diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000000000000000000000000000000000000..4773cc57619bc4665a68643eacdb11d3e9868626 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,36 @@ +--- +engines: + brakeman: + enabled: true + bundler-audit: + enabled: true + csslint: + enabled: true + duplication: + enabled: true + config: + languages: + - ruby + - javascript + eslint: + enabled: true + channel: "eslint-2" + fixme: + enabled: true + rubocop: + enabled: true +ratings: + paths: + - Gemfile.lock + - "**.erb" + - "**.haml" + - "**.rb" + - "**.css" + - "**.js" +exclude_paths: +- config/ +- db/ +- features/ +- script/ +- spec/ +- vendor/ diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000000000000000000000000000000000000..62ba89fdae6d4c186f44d24f596fb1a50f478e45 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,258 @@ +{ + "env": { + "browser": true, + "jasmine": true, + "jquery": true + }, + + "globals": { + "_": false, + "autosize": false, + "Backbone": false, + "Bloodhound": false, + "gon": false, + "Handlebars": false, + "HandlebarsTemplates": false, + "ImagePaths": false, + "jsxc": false, + "L": false, + "Routes": false, + "OSM": false, + "qq": false, + "blueimp": false, + + "loginAs": true, + "logout": true, + "spec": true, + "context": true, + "factory": true, + "stubView": true, + + "app": true, + "Diaspora": true, + "Keycodes": true, + "PosixBracketExpressions": true + }, + + "rules": { + "accessor-pairs": 0, + "array-bracket-spacing": [2, "never"], + "array-callback-return": 0, + "arrow-body-style": 0, + "arrow-parens": 0, + "arrow-spacing": 0, + "block-scoped-var": 0, + "block-spacing": [2, "always"], + "brace-style": [2, "1tbs", {"allowSingleLine": true}], + "callback-return": 0, + "camelcase": 2, + "comma-dangle": [2, "never"], + "comma-spacing": [2, {"before": false, "after": true}], + "comma-style": [2, "last"], + "complexity": [1, {"max": 20}], + "computed-property-spacing": [2, "never"], + "consistent-return": 2, + "consistent-this": 0, + "constructor-super": 0, + "curly": [2, "all"], + "default-case": 0, + "dot-location": [2, "property"], + "dot-notation": 2, + "eol-last": 2, + "eqeqeq": [2, "allow-null"], + "func-names": 0, + "func-style": 0, + "generator-star-spacing": 0, + "global-require": 0, + "guard-for-in": 1, + "handle-callback-err": 0, + "id-blacklist": 0, + "id-length": 0, + "id-match": 0, + "indent": [2, 2, {"SwitchCase": 1, "VariableDeclarator": {"var": 2, "let": 2, "const": 3}}], + "init-declarations": 0, + "jsx-quotes": 0, + "key-spacing": [2, {"beforeColon": false, "afterColon": true}], + "keyword-spacing": 2, + "linebreak-style": 0, + "lines-around-comment": 0, + "max-depth": 0, + "max-len": [1, {"code": 120, "ignoreUrls": true}], + "max-lines": 0, + "max-nested-callbacks": 0, + "max-params": 0, + "max-statements": 0, + "max-statements-per-line": 0, + "new-cap": [2, {"capIsNew": false}], + "new-parens": 2, + "newline-after-var": 0, + "newline-before-return": 0, + "newline-per-chained-call": 0, + "no-alert": 0, + "no-array-constructor": 2, + "no-bitwise": 0, + "no-caller": 2, + "no-case-declarations": 2, + "no-catch-shadow": 0, + "no-class-assign": 2, + "no-cond-assign": 2, + "no-confusing-arrow": 2, + "no-console": 2, + "no-const-assign": 2, + "no-constant-condition": 2, + "no-continue": 0, + "no-control-regex": 2, + "no-debugger": 2, + "no-delete-var": 2, + "no-div-regex": 0, + "no-dupe-args": 2, + "no-dupe-class-members": 2, + "no-dupe-keys": 2, + "no-duplicate-case": 2, + "no-duplicate-imports": 0, + "no-else-return": 2, + "no-empty": 2, + "no-empty-character-class": 2, + "no-empty-function": 1, + "no-empty-pattern": 2, + "no-eq-null": 0, + "no-eval": 2, + "no-ex-assign": 2, + "no-extend-native": 2, + "no-extra-bind": 2, + "no-extra-boolean-cast": 2, + "no-extra-label": 0, + "no-extra-parens": 0, + "no-extra-semi": 2, + "no-fallthrough": 2, + "no-floating-decimal": 0, + "no-func-assign": 2, + "no-implicit-coercion": 0, + "no-implicit-globals": 0, + "no-implied-eval": 0, + "no-inline-comments": 0, + "no-inner-declarations": 2, + "no-invalid-regexp": 2, + "no-invalid-this": 0, + "no-irregular-whitespace": 2, + "no-iterator": 0, + "no-label-var": 0, + "no-labels": 0, + "no-lone-blocks": 0, + "no-lonely-if": 2, + "no-loop-func": 2, + "no-magic-numbers": 0, + "no-mixed-operators": 0, + "no-mixed-requires": 0, + "no-mixed-spaces-and-tabs": 2, + "no-multi-spaces": 1, + "no-multi-str": 0, + "no-multiple-empty-lines": [1, {"max": 1}], + "no-native-reassign": 2, + "no-negated-condition": 0, + "no-negated-in-lhs": 2, + "no-nested-ternary": 0, + "no-new": 0, + "no-new-func": 0, + "no-new-object": 0, + "no-new-require": 0, + "no-new-symbol": 0, + "no-new-wrappers": 0, + "no-obj-calls": 2, + "no-octal": 2, + "no-octal-escape": 0, + "no-param-reassign": 0, + "no-path-concat": 0, + "no-plusplus": 0, + "no-process-env": 0, + "no-process-exit": 0, + "no-proto": 2, + "no-prototype-builtins": 0, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-restricted-globals": 0, + "no-restricted-imports": 0, + "no-restricted-modules": 0, + "no-restricted-syntax": 0, + "no-return-assign": 2, + "no-script-url": 0, + "no-self-assign": 2, + "no-self-compare": 2, + "no-sequences": 2, + "no-shadow": 1, + "no-shadow-restricted-names": 2, + "no-spaced-func": 1, + "no-sparse-arrays": 2, + "no-sync": 0, + "no-ternary": 0, + "no-this-before-super": 2, + "no-throw-literal": 2, + "no-trailing-spaces": 2, + "no-undef": 2, + "no-undef-init": 0, + "no-undefined": 0, + "no-underscore-dangle": 0, + "no-unexpected-multiline": 2, + "no-unmodified-loop-condition": 1, + "no-unneeded-ternary": 1, + "no-unreachable": 2, + "no-unsafe-finally": 1, + "no-unused-expressions": 0, + "no-unused-labels": 2, + "no-unused-vars": 2, + "no-use-before-define": [2, {"functions": false, "classes": true}], + "no-useless-call": 1, + "no-useless-computed-key": 0, + "no-useless-concat": 0, + "no-useless-constructor": 0, + "no-useless-escape": 0, + "no-useless-rename": 0, + "no-var": 0, + "no-void": 0, + "no-warning-comments": 0, + "no-whitespace-before-property": 2, + "no-with": 2, + "object-curly-newline": 0, + "object-curly-spacing": [2, "never"], + "object-property-newline": 0, + "object-shorthand": 0, + "one-var": 0, + "one-var-declaration-per-line": 0, + "operator-assignment": 0, + "operator-linebreak": 0, + "padded-blocks": [2, "never"], + "prefer-arrow-callback": 0, + "prefer-const": 0, + "prefer-reflect": 0, + "prefer-rest-params": 0, + "prefer-spread": 0, + "prefer-template": 0, + "quote-props": 0, + "quotes": [2, "double", "avoid-escape"], + "radix": [2, "always"], + "require-jsdoc": 0, + "require-yield": 0, + "rest-spread-spacing": 0, + "semi": [2, "always"], + "semi-spacing": [2, {"before": false, "after": true}], + "sort-imports": 0, + "sort-vars": 0, + "space-before-blocks": [2, "always"], + "space-before-function-paren": [2, "never"], + "space-in-parens": [2, "never"], + "space-infix-ops": [2, {"int32Hint": true}], + "space-unary-ops": [2, {"words": true, "nonwords": false}], + "spaced-comment": [2, "always", {"markers": ["="]}], + "strict": 0, + "template-curly-spacing": 0, + "unicode-bom": 0, + "use-isnan": 2, + "valid-jsdoc": 0, + "valid-typeof": 2, + "vars-on-top": 0, + "wrap-iife": 0, + "wrap-regex": 0, + "yield-star-spacing": 0, + "yoda": [2, "never"] + } +} diff --git a/.gitignore b/.gitignore index 1e6da2c170c56129c3a5884679eda7bcde0b4cd9..46f688972ddd256a940e3614114ae16bddb58ed9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,13 @@ -# xmpp certificates, keys and user data -config/vines/*.crt -config/vines/*.key +# XMPP certificates, keys and user data +config/certs/*.crt +config/certs/*.key +config/prosody.cfg.lua -#trademark sillyness +# Trademark sillyness app/views/home/_show.* app/views/terms/terms.* app/assets/images/custom/ - # Configuration files config/diaspora.yml config/heroku.yml @@ -21,8 +21,9 @@ vendor/cache/ config/database.yml .rvmrc_custom .rvmrc.local +config/oidc_key.pem -#Mailing list stuff +# Mailing list stuff config/email_offset config/mailing_list.csv @@ -42,9 +43,9 @@ public/500.html app/assets/images/branding-*.png app/assets/images/branding/logos-*.png app/assets/images/icons-*.png -app/assets/images/social_media_logos-*.png +app/assets/images/social-media-logos-*.png -#Documentation +# Documentation .yardoc/ doc/ @@ -69,15 +70,18 @@ tmp/ *.swp *~ *# +*.bak +*.save +*.autosave nbproject patches-* capybara-*.html dump.rdb -#Rubinius's JIT +# Rubinius's JIT *.rbc -#IDE +# IDE diaspora.iml # Dolphin's directory's preferences files diff --git a/.haml-lint.yml b/.haml-lint.yml new file mode 100644 index 0000000000000000000000000000000000000000..bf61f7f60adc40a0b7a8431e522e4f92c30d162b --- /dev/null +++ b/.haml-lint.yml @@ -0,0 +1,5 @@ +linters: + LineLength: + max: 120 + SpaceInsideHashAttributes: + style: no_space diff --git a/.hound.yml b/.hound.yml deleted file mode 100644 index 9c0f49ddb2f926de0b5a592f986a25fbaa96ecd5..0000000000000000000000000000000000000000 --- a/.hound.yml +++ /dev/null @@ -1,9 +0,0 @@ -java_script: - enabled: true - config_file: config/.jshint.json - ignore_file: config/.jshint_ignore -ruby: - enabled: true - config_file: .rubocop.yml -scss: - enabled: false diff --git a/.jshintignore b/.jshintignore deleted file mode 120000 index e650afb0573525cf100cf912bca925ae911c2884..0000000000000000000000000000000000000000 --- a/.jshintignore +++ /dev/null @@ -1 +0,0 @@ -config/.jshint_ignore \ No newline at end of file diff --git a/.jshintrc b/.jshintrc deleted file mode 120000 index 2c12c8897ed69beb7360822f4c002c08c6fe532d..0000000000000000000000000000000000000000 --- a/.jshintrc +++ /dev/null @@ -1 +0,0 @@ -config/.jshint.json \ No newline at end of file diff --git a/.pronto.yml b/.pronto.yml new file mode 100644 index 0000000000000000000000000000000000000000..c5f358b4a1b691894c01ee7cb2f7906d9f756e04 --- /dev/null +++ b/.pronto.yml @@ -0,0 +1,4 @@ +all: + exclude: + - "vendor/**/*" +consolidate_comments: true diff --git a/.ruby-version b/.ruby-version index 879b416e609a820dafeff67d679a7e3849fe8a09..bb576dbde10fdad22759c170d482813d5e873c1e 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.1 +2.3 diff --git a/.scss-lint.yml b/.scss-lint.yml new file mode 100644 index 0000000000000000000000000000000000000000..1fc197bb911e9b9f395443ba54a6d4f3a588b574 --- /dev/null +++ b/.scss-lint.yml @@ -0,0 +1,231 @@ +scss_files: 'app/assets/stylesheets/**/*.scss' +plugin_directories: ['.scss-linters'] + +# List of gem names to load custom linters from (make sure they are already +# installed) +plugin_gems: [] + +linters: + BangFormat: + enabled: true + space_before_bang: true + space_after_bang: false + + BemDepth: + enabled: false + max_elements: 1 + + BorderZero: + enabled: true + convention: zero # or `none` + + ColorKeyword: + enabled: true + + ColorVariable: + enabled: true + + Comment: + enabled: true + + DebugStatement: + enabled: true + + DeclarationOrder: + enabled: true + + DisableLinterReason: + enabled: true + + DuplicateProperty: + enabled: true + + ElsePlacement: + enabled: true + style: same_line # or 'new_line' + + EmptyLineBetweenBlocks: + enabled: true + ignore_single_line_blocks: true + + EmptyRule: + enabled: true + + ExtendDirective: + enabled: false + + FinalNewline: + enabled: true + present: true + + HexLength: + enabled: true + style: short # or 'long' + + HexNotation: + enabled: true + style: lowercase # or 'uppercase' + + HexValidation: + enabled: true + + IdSelector: + enabled: true + + ImportantRule: + enabled: true + + ImportPath: + enabled: true + leading_underscore: false + filename_extension: false + + Indentation: + enabled: true + allow_non_nested_indentation: false + character: space # or 'tab' + width: 2 + + LeadingZero: + enabled: true + style: exclude_zero # or 'include_zero' + + MergeableSelector: + enabled: true + force_nesting: true + + NameFormat: + enabled: true + allow_leading_underscore: true + convention: hyphenated_lowercase # or 'camel_case', or 'snake_case', or a regex pattern + + NestingDepth: + enabled: true + max_depth: 3 + ignore_parent_selectors: false + + PlaceholderInExtend: + enabled: true + + PropertyCount: + enabled: false + include_nested: false + max_properties: 10 + + PropertySortOrder: + enabled: true + ignore_unspecified: false + min_properties: 2 + separate_groups: false + + PropertySpelling: + enabled: true + extra_properties: [] + + PropertyUnits: + enabled: true + global: [ + 'ch', 'em', 'ex', 'rem', # Font-relative lengths + 'cm', 'in', 'mm', 'pc', 'pt', 'px', 'q', # Absolute lengths + 'vh', 'vw', 'vmin', 'vmax', # Viewport-percentage lengths + 'deg', 'grad', 'rad', 'turn', # Angle + 'ms', 's', # Duration + 'Hz', 'kHz', # Frequency + 'dpi', 'dpcm', 'dppx', # Resolution + '%'] # Other + properties: {} + + QualifyingElement: + enabled: true + allow_element_with_attribute: false + allow_element_with_class: false + allow_element_with_id: false + + SelectorDepth: + enabled: true + max_depth: 3 + + SelectorFormat: + enabled: true + convention: hyphenated_lowercase # or 'strict_BEM', or 'hyphenated_BEM', or 'snake_case', or 'camel_case', or a regex pattern + + Shorthand: + enabled: true + allowed_shorthands: [1, 2, 3] + + SingleLinePerProperty: + enabled: true + allow_single_line_rule_sets: true + + SingleLinePerSelector: + enabled: true + + SpaceAfterComma: + enabled: true + + SpaceAfterPropertyColon: + enabled: true + style: one_space # or 'no_space', or 'at_least_one_space', or 'aligned' + + SpaceAfterPropertyName: + enabled: true + + SpaceAfterVariableName: + enabled: true + + SpaceAroundOperator: + enabled: true + style: one_space # or 'no_space' + + SpaceBeforeBrace: + enabled: true + style: space # or 'new_line' + allow_single_line_padding: false + + SpaceBetweenParens: + enabled: true + spaces: 0 + + StringQuotes: + enabled: true + style: single_quotes # or double_quotes + + TrailingSemicolon: + enabled: true + + TrailingWhitespace: + enabled: true + + TrailingZero: + enabled: false + + TransitionAll: + enabled: false + + UnnecessaryMantissa: + enabled: true + + UnnecessaryParentReference: + enabled: true + + UrlFormat: + enabled: true + + UrlQuotes: + enabled: true + + VariableForProperty: + enabled: false + properties: [] + + VendorPrefix: + enabled: true + identifier_list: base + additional_identifiers: [] + excluded_identifiers: [] + + ZeroUnit: + enabled: true + + Compass::*: + enabled: false diff --git a/.travis.yml b/.travis.yml index 6d57bbc8c337bc5ea2739600a5a32cef83348eb3..1bcd8421a8497e6f2462c9bb119625ecc15c03bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,14 @@ language: ruby rvm: + - 2.3.1 - 2.1 - - 2.0 env: - - DB=postgres BUILD_TYPE=other - - DB=mysql BUILD_TYPE=other - - DB=postgres BUILD_TYPE=cucumber + - DB=postgresql BUILD_TYPE=cucumber - DB=mysql BUILD_TYPE=cucumber + - DB=postgresql BUILD_TYPE=other + - DB=mysql BUILD_TYPE=other sudo: false cache: @@ -19,11 +19,17 @@ cache: branches: only: - 'master' - - 'stable' + - 'next-minor' - 'develop' -before_install: gem install bundler -bundler_args: "--without development production heroku --jobs 3 --retry 3" +before_install: + - gem install bundler + - mkdir travis-phantomjs + - wget http://cifiles.diasporafoundation.org/phantomjs-2.1.1-linux-x86_64.tar.bz2 -O $PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 + - tar -xvf $PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C $PWD/travis-phantomjs + - export PATH=$PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH + +bundler_args: "--deployment --without development production --with mysql postgresql --jobs 3 --retry 3" script: "./script/ci/build.sh" diff --git a/Changelog.md b/Changelog.md index a62e25875d8096c70961cc65a44d8207e4df331b..9a162a2a40b79ffce53fada64f887d971f0e7427 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,208 @@ +# 0.6.0.0 + +## Warning: This release contains long migrations + +This diaspora\* releases comes with a few database cleanup migrations and they could possible take a while. While you should always do that, it is especially important this time to make sure you run the migrations inside a detachable environment like `screen` or `tmux`. A interrupted SSH session could possibly harm your database. Also, please make a backup. + +## The DB environment variable is gone + +With Bundler 1.10 supporting optional groups, we removed the DB environment variable. When updating to this release, please update +bundler and select the database support you want: + +```sh +gem install bundler +bundle install --with mysql # For MySQL and MariaDB +bundle install --with postgresql # For PostgreSQL +``` + +For production setups we now additionally recommend adding the `--deployment` flag. +If you set the DB environment variable anywhere, that's no longer necessary. + +## Supported Ruby versions + +This release recommends using Ruby 2.3, while retaining Ruby 2.1 as an officially supported version. +Ruby 2.0 is no longer officially supported. + +## Configuration changes + +Please note that the default listen parameter for production setups got +changed. diaspora\* will no longer listen on `0.0.0.0:3000` as it will now +bind to an UNIX socket at `unix:tmp/diaspora.sock`. Please change your local +`diaspora.yml` if necessary. + +## Redis namespace support dropped + +We dropped support for Redis namespaces in this release. If you previously set +a custom namespace, please note that diaspora\* will no longer use the +configured value. By default, Redis supports up to 8 databases which can be +selected via the Redis URL in `diaspora.yml`. Please check the examples +provided in our configuration example file. + +## Terms of Use design changes + +With the port to Bootstrap 3, app/views/terms/default.haml has a new structure. If you have created a customised app/views/terms/terms.haml or app/views/terms/terms.erb file, you will need to edit those files to base your customisations on the new default.haml file. + +## API authentication + +This release makes diaspora\* a OpenID Connect provider. This means you can authenticate to third parties with your diaspora\* account and let +them act as your diaspora\* account on your behalf. This feature is still considered in early development, we still expect edge cases and advanced +features of the specificiation to not be handled correctly or be missing. But we expect a basic OpenID Connect compliant client to work. Please submit issues! +We will also most likely still change the authorization scopes we offer and started with a very minimal set. +Most work still required is on documentation as well as designing and implementing the data API for all of Diaspora's functionality. +Contributions are very welcome, the hard work is done! + +## Vines got replaced by Prosody + +Due to many issues with Vines, we decided to remove Vines and offer a Prosody +example configuration instead. [Check the +wiki](https://wiki.diasporafoundation.org/Integration/Chat#Vines_to_Prosody) +for more information on how to migrate to Prosody if you've been using Vines +before. + +## Sidekiq queue changes + +We've decreased the amount of sidekiq queues from 13 to 5 in PR [#6950](https://github.com/diaspora/diaspora/pull/6950). +The new queues are organized according to priority for the jobs they will process. When upgrading please make sure to +empty the sidekiq queues before shutting down the server for an update. + +If you run your sidekiq with a custom queue configuration, please make sure to update that for the new queues. + +The new queues are: `urgent, high, medium, low, default`. + +When you upgrade to the new version, some jobs may persist in the old queues. To move them to the default queue, +so they're processed, run: + +``` +bin/rake migrations:legacy_queues +``` + +Note that this will retry all dead jobs, if you want to prevent that empty the dead queue first. + +The command will report queues that still have jobs and launch sidekiq process for that queues. + +## Refactor +* Improve bookmarklet [#5904](https://github.com/diaspora/diaspora/pull/5904) +* Update listen configuration to listen on unix sockets by default [#5974](https://github.com/diaspora/diaspora/pull/5974) +* Port to Bootstrap 3 [#6015](https://github.com/diaspora/diaspora/pull/6015) +* Use a fixed width for the mobile drawer [#6057](https://github.com/diaspora/diaspora/pull/6057) +* Replace jquery.autoresize with autosize [#6104](https://github.com/diaspora/diaspora/pull/6104) +* Improve mobile conversation design [#6087](https://github.com/diaspora/diaspora/pull/6087) +* Replace remaining faceboxes with Bootstrap modals [#6106](https://github.com/diaspora/diaspora/pull/6106) [#6161](https://github.com/diaspora/diaspora/pull/6161) +* Rewrite header using Bootstrap 3 [#6109](https://github.com/diaspora/diaspora/pull/6109) [#6130](https://github.com/diaspora/diaspora/pull/6130) [#6132](https://github.com/diaspora/diaspora/pull/6132) +* Use upstream CSS mappings for Entypo [#6158](https://github.com/diaspora/diaspora/pull/6158) +* Replace some mobile icons with Entypo [#6218](https://github.com/diaspora/diaspora/pull/6218) +* Refactor publisher backbone view [#6228](https://github.com/diaspora/diaspora/pull/6228) +* Replace MBP.autogrow with autosize on mobile [#6261](https://github.com/diaspora/diaspora/pull/6261) +* Improve mobile drawer transition [#6233](https://github.com/diaspora/diaspora/pull/6233) +* Remove unused header icons and an unused favicon [#6283](https://github.com/diaspora/diaspora/pull/6283) +* Replace mobile icons for post interactions with Entypo icons [#6291](https://github.com/diaspora/diaspora/pull/6291) +* Replace jquery.autocomplete with typeahead.js [#6293](https://github.com/diaspora/diaspora/pull/6293) +* Redesign sidebars on stream pages [#6309](https://github.com/diaspora/diaspora/pull/6309) +* Improve ignored users styling [#6349](https://github.com/diaspora/diaspora/pull/6349) +* Use Blueimp image gallery instead of lightbox [#6301](https://github.com/diaspora/diaspora/pull/6301) +* Unify mobile and desktop header design [#6285](https://github.com/diaspora/diaspora/pull/6285) +* Add white background and box-shadow to stream elements [#6324](https://github.com/diaspora/diaspora/pull/6324) +* Override Bootstrap list group design [#6345](https://github.com/diaspora/diaspora/pull/6345) +* Clean up publisher code [#6336](https://github.com/diaspora/diaspora/pull/6336) +* Port conversations to new design [#6431](https://github.com/diaspora/diaspora/pull/6431) +* Hide cancel button in publisher on small screens [#6435](https://github.com/diaspora/diaspora/pull/6435) +* Replace mobile background with color [#6415](https://github.com/diaspora/diaspora/pull/6415) +* Port flash messages to backbone [#6395](https://github.com/diaspora/diaspora/pull/6395) +* Change login/registration/forgot password button color [#6504](https://github.com/diaspora/diaspora/pull/6504) +* A note regarding ignoring users was added to the failure messages on commenting/liking [#6646](https://github.com/diaspora/diaspora/pull/6646) +* Replace sidetiq with sidekiq-cron [#6616](https://github.com/diaspora/diaspora/pull/6616) +* Refactor mobile comment section [#6509](https://github.com/diaspora/diaspora/pull/6509) +* Set vertical resize as default for all textareas [#6654](https://github.com/diaspora/diaspora/pull/6654) +* Unifiy max-widths and page layouts [#6675](https://github.com/diaspora/diaspora/pull/6675) +* Enable autosizing for all textareas [#6674](https://github.com/diaspora/diaspora/pull/6674) +* Stream faces are gone [#6686](https://github.com/diaspora/diaspora/pull/6686) +* Refactor mobile javascript and add tests [#6394](https://github.com/diaspora/diaspora/pull/6394) +* Dropped `parent_author_signature` from relayables [#6586](https://github.com/diaspora/diaspora/pull/6586) +* Attached ShareVisibilities to the User, not the Contact [#6723](https://github.com/diaspora/diaspora/pull/6723) +* Refactor mentions input, now based on typeahead.js [#6728](https://github.com/diaspora/diaspora/pull/6728) +* Optimized the pod up checks [#6727](https://github.com/diaspora/diaspora/pull/6727) +* Prune and do not create aspect visibilities for public posts [#6732](https://github.com/diaspora/diaspora/pull/6732) +* Optimized mobile login and registration forms [#6764](https://github.com/diaspora/diaspora/pull/6764) +* Redesign stream pages [#6535](https://github.com/diaspora/diaspora/pull/6535) +* Improve search and mentions suggestions [#6788](https://github.com/diaspora/diaspora/pull/6788) +* Redesign back to top button [#6782](https://github.com/diaspora/diaspora/pull/6782) +* Adjusted Facebook integration for a successful review [#6778](https://github.com/diaspora/diaspora/pull/6778) +* Redirect to the sign-in page instead of the stream on account deletion [#6784](https://github.com/diaspora/diaspora/pull/6784) +* Removed own unicorn killer by a maintained third-party gem [#6792](https://github.com/diaspora/diaspora/pull/6792) +* Removed deprecated `REDISTOGO_URL` environment variable [#6863](https://github.com/diaspora/diaspora/pull/6863) +* Use Poltergeist instead of Selenium [#6768](https://github.com/diaspora/diaspora/pull/6768) +* Redesigned the landing page and added dedicated notes for podmins [#6268](https://github.com/diaspora/diaspora/pull/6268) +* Moved the entire federation implementation into its own gem. 🎉 [#6873](https://github.com/diaspora/diaspora/pull/6873) +* Remove `StatusMessage#raw_message` [#6921](https://github.com/diaspora/diaspora/pull/6921) +* Extract photo export into a service class [#6922](https://github.com/diaspora/diaspora/pull/6922) +* Use handlebars template for aspect membership dropdown [#6864](https://github.com/diaspora/diaspora/pull/6864) +* Extract relayable signatures into their own tables [#6932](https://github.com/diaspora/diaspora/pull/6932) +* Remove outdated columns from posts table [#6940](https://github.com/diaspora/diaspora/pull/6940) +* Remove some unused routes [#6781](https://github.com/diaspora/diaspora/pull/6781) +* Consolidate sidekiq queues [#6950](https://github.com/diaspora/diaspora/pull/6950) +* Don't re-render the whole comment stream when adding comments [#6406](https://github.com/diaspora/diaspora/pull/6406) +* Drop legacy invitation system [#6976](https://github.com/diaspora/diaspora/pull/6976) +* More consistent and updated meta tags throughout [#6998](https://github.com/diaspora/diaspora/pull/6998) + +## Bug fixes +* Destroy Participation when removing interactions with a post [#5852](https://github.com/diaspora/diaspora/pull/5852) +* Improve accessibility of a couple pages [#6227](https://github.com/diaspora/diaspora/pull/6227) +* Capitalize "Powered by diaspora" [#6254](https://github.com/diaspora/diaspora/pull/6254) +* Display username and avatar for NSFW posts in mobile view [#6245](https://github.com/diaspora/diaspora/pull/6245) +* Prevent multiple comment boxes on mobile [#6363](https://github.com/diaspora/diaspora/pull/6363) +* Correctly display location in post preview [#6429](https://github.com/diaspora/diaspora/pull/6429) +* Do not fail when submitting an empty comment in the mobile view [#6543](https://github.com/diaspora/diaspora/pull/6543) +* Limit flash message width on small devices [#6529](https://github.com/diaspora/diaspora/pull/6529) +* Add navbar on mobile when not logged in [#6483](https://github.com/diaspora/diaspora/pull/6483) +* Fix timeago tooltips for reshares [#6648](https://github.com/diaspora/diaspora/pull/6648) +* "Getting started" is now turned off after first visit on mobile [#6681](https://github.com/diaspora/diaspora/pull/6681) +* Fixed a 500 when liking on mobile without JS enabled [#6683](https://github.com/diaspora/diaspora/pull/6683) +* Fixed profile image upload in the mobile UI [#6684](https://github.com/diaspora/diaspora/pull/6684) +* Fixed eye not stopping all processes when trying to exit `script/server` [#6693](https://github.com/diaspora/diaspora/pull/6693) +* Do not change contacts count when marking notifications on the contacts page as read [#6718](https://github.com/diaspora/diaspora/pull/6718) +* Fix typeahead for non-latin characters [#6741](https://github.com/diaspora/diaspora/pull/6741) +* Fix upload size error on mobile [#6803](https://github.com/diaspora/diaspora/pull/6803) +* Connection tester handles invalid NodeInfo implementations [#6890](https://github.com/diaspora/diaspora/pull/6890) +* Do not allow to change email to an already used one [#6905](https://github.com/diaspora/diaspora/pull/6905) +* Correctly filter mentions on the server side [#6902](https://github.com/diaspora/diaspora/pull/6902) +* Add aspects to the aspect membership dropdown when creating them on the getting started page [#6864](https://github.com/diaspora/diaspora/pull/6864) +* Strip markdown from message preview in conversations list [#6923](https://github.com/diaspora/diaspora/pull/6923) +* Improve tag stream performance [#6903](https://github.com/diaspora/diaspora/pull/6903) +* Only show mutual contacts in conversations auto suggestions [#7001](https://github.com/diaspora/diaspora/pull/7001) + +## Features +* Support color themes [#6033](https://github.com/diaspora/diaspora/pull/6033) +* Add mobile services and privacy settings pages [#6086](https://github.com/diaspora/diaspora/pull/6086) +* Optionally make your extended profile details public [#6162](https://github.com/diaspora/diaspora/pull/6162) +* Add admin dashboard showing latest diaspora\* version [#6216](https://github.com/diaspora/diaspora/pull/6216) +* Display poll & location on mobile [#6238](https://github.com/diaspora/diaspora/pull/6238) +* Update counts on contacts page dynamically [#6240](https://github.com/diaspora/diaspora/pull/6240) +* Add support for relay based public post federation [#6207](https://github.com/diaspora/diaspora/pull/6207) +* Bigger mobile publisher [#6261](https://github.com/diaspora/diaspora/pull/6261) +* Backend information panel & health checks for known pods [#6290](https://github.com/diaspora/diaspora/pull/6290) +* Allow users to view a posts locations on an OpenStreetMap [#6256](https://github.com/diaspora/diaspora/pull/6256) +* Redesign and unify error pages [#6428](https://github.com/diaspora/diaspora/pull/6428) +* Redesign and refactor report admin interface [#6378](https://github.com/diaspora/diaspora/pull/6378) +* Add permalink icon to stream elements [#6457](https://github.com/diaspora/diaspora/pull/6457) +* Move reshare count to interactions for stream elements [#6487](https://github.com/diaspora/diaspora/pull/6487) +* Posts of ignored users are now visible on that profile page [#6617](https://github.com/diaspora/diaspora/pull/6617) +* Add white color theme [#6631](https://github.com/diaspora/diaspora/pull/6631) +* Add answer counts to poll [#6641](https://github.com/diaspora/diaspora/pull/6641) +* Check for collapsible posts after images in posts have loaded [#6671](https://github.com/diaspora/diaspora/pull/6671) +* Add reason for post report to email sent to admins [#6679](https://github.com/diaspora/diaspora/pull/6679) +* Add links to the single post view of the related post to photos in the photo stream [#6621](https://github.com/diaspora/diaspora/pull/6621) +* Add a note for people with disabled JavaScript [#6777](https://github.com/diaspora/diaspora/pull/6777) +* Do not include conversation subject in notification mail [#6910](https://github.com/diaspora/diaspora/pull/6910) +* Add 'Be excellent to each other!' to the sidebar [#6914](https://github.com/diaspora/diaspora/pull/6914) +* Expose Sidekiq dead queue configuration options +* Properly support pluralization in timeago strings [#6926](https://github.com/diaspora/diaspora/pull/6926) +* Return all contacts in people search [#6951](https://github.com/diaspora/diaspora/pull/6951) +* Make screenreaders read alerts [#6973](https://github.com/diaspora/diaspora/pull/6973) +* Display message when there are no posts in a stream [#6974](https://github.com/diaspora/diaspora/pull/6974) +* Add bootstrap-markdown editor to the publisher [#6551](https://github.com/diaspora/diaspora/pull/6551) +* Don't create notifications for ignored users [#6984](https://github.com/diaspora/diaspora/pull/6984) +* Fetch missing persons when receiving a mention for them [#6992](https://github.com/diaspora/diaspora/pull/6992) + # 0.5.10.2 Update to Rails 4.2.7.1 which fixes [CVE-2016-6316](https://groups.google.com/forum/#!topic/ruby-security-ann/8B2iV2tPRSE) and [CVE-2016-6317](https://groups.google.com/forum/#!topic/ruby-security-ann/WccgKSKiPZA). @@ -193,6 +398,7 @@ and on a pod that received that data. * Update perfect-scrollbar [#6085](https://github.com/diaspora/diaspora/pull/6085) * Remove top margin for first heading in a post [#6110](https://github.com/diaspora/diaspora/pull/6110) * Add link to pod statistics in right navigation [#6117](https://github.com/diaspora/diaspora/pull/6117) +* Update to Rails 4.2.3 [#6140](https://github.com/diaspora/diaspora/pull/6140) * Refactor person related URL generation [#6168](https://github.com/diaspora/diaspora/pull/6168) * Move webfinger and HCard generation out of the core and embed the `diaspora_federation-rails` gem [#6151](https://github.com/diaspora/diaspora/pull/6151/) * Refactor rspec tests to to use `let` instead of before blocks [#6199](https://github.com/diaspora/diaspora/pull/6199) diff --git a/Gemfile b/Gemfile index 72d68ce10a73193d86cd9a5d98b7719f84ad22b2..66efbfd37b8e0e0e946dcadb74154429071aa03f 100644 --- a/Gemfile +++ b/Gemfile @@ -9,22 +9,23 @@ gem "responders", "2.2.0" # Appserver gem "unicorn", "5.1.0", require: false +gem "unicorn-worker-killer", "0.4.4" # Federation -gem "diaspora_federation-rails", "0.0.13" +gem "diaspora_federation-rails", "0.1.4" # API and JSON -gem "acts_as_api", "0.4.2" +gem "acts_as_api", "0.4.3" gem "json", "1.8.3" gem "json-schema", "2.6.2" # Authentication -gem "devise", "3.5.6" +gem "devise", "4.2.0" gem "devise_lastseenable", "0.0.6" -gem "devise-token_authenticatable", "0.4.6" +gem "devise-token_authenticatable", "0.5.2" # Captcha @@ -32,16 +33,16 @@ gem "simple_captcha2", "0.4.0", require: "simple_captcha" # Background processing -gem "sidekiq", "3.4.2" +gem "sidekiq", "4.1.4" gem "sinatra", "1.4.7" # Scheduled processing -gem "sidetiq", "0.6.3" +gem "sidekiq-cron", "0.4.2" # Compression -gem "uglifier", "3.0.0" +gem "uglifier", "3.0.1" # Configuration @@ -53,19 +54,23 @@ gem "rack-cors", "0.4.0", require: "rack/cors" # CSS -gem "bootstrap-sass", "2.3.2.2" +gem "bootstrap-sass", "3.3.7" gem "compass-rails", "2.0.5" -gem "sass-rails", "5.0.4" -gem "autoprefixer-rails", "6.3.6.2" +gem "sass-rails", "5.0.6" +gem "autoprefixer-rails", "6.4.0.2" +gem "bootstrap-switch-rails", "3.3.3" # Database -ENV["DB"] ||= "mysql" +group :mysql, optional: true do + gem "mysql2", "0.4.4" +end +group :postgresql, optional: true do + gem "pg", "0.18.4" +end -gem "mysql2", "0.4.4" if ENV["DB"] == "all" || ENV["DB"] == "mysql" -gem "pg", "0.18.4" if ENV["DB"] == "all" || ENV["DB"] == "postgres" -gem "activerecord-import", "0.13.0" +gem "activerecord-import", "0.15.0" # File uploading @@ -79,40 +84,39 @@ gem "uuid", "2.3.8" # Icons -gem "entypo-rails", "2.2.3" +gem "entypo-rails", "3.0.0.pre.rc2" # JavaScript gem "backbone-on-rails", "1.2.0.0" -gem "handlebars_assets", "0.23.0" +gem "handlebars_assets", "0.23.1" gem "jquery-rails", "4.1.1" gem "jquery-ui-rails", "5.0.5" gem "js_image_paths", "0.1.0" -gem "js-routes", "1.2.6" +gem "js-routes", "1.2.9" source "https://rails-assets.org" do - gem "rails-assets-jquery", "1.12.0" # Should be kept in sync with jquery-rails + gem "rails-assets-jquery", "2.2.1" # Should be kept in sync with jquery-rails - gem "rails-assets-markdown-it", "6.0.5" + gem "rails-assets-markdown-it", "7.0.0" gem "rails-assets-markdown-it-hashtag", "0.4.0" - gem "rails-assets-markdown-it-diaspora-mention", "0.4.0" - gem "rails-assets-markdown-it-sanitizer", "0.4.1" + gem "rails-assets-markdown-it-diaspora-mention", "1.0.0" + gem "rails-assets-markdown-it-sanitizer", "0.4.2" gem "rails-assets-markdown-it--markdown-it-for-inline", "0.1.1" gem "rails-assets-markdown-it-sub", "1.0.0" gem "rails-assets-markdown-it-sup", "1.0.0" - gem "rails-assets-highlightjs", "9.4.0" + gem "rails-assets-highlightjs", "9.6.0" + gem "rails-assets-bootstrap-markdown", "2.10.0" # jQuery plugins - gem "rails-assets-jeresig--jquery.hotkeys", "0.2.0" gem "rails-assets-jquery-placeholder", "2.3.1" gem "rails-assets-jquery-textchange", "0.2.3" - gem "rails-assets-perfect-scrollbar", "0.6.11" - gem "rails-assets-jakobmattsson--jquery-elastic", "1.6.11" + gem "rails-assets-perfect-scrollbar", "0.6.12" + gem "rails-assets-autosize", "3.0.17" + gem "rails-assets-blueimp-gallery", "2.21.3" end -gem "facebox-rails", "0.2.0" - # Localization gem "http_accept_language", "2.0.5" @@ -122,33 +126,37 @@ gem "rails-i18n", "4.0.8" # Mail gem "markerb", "1.1.0" -gem "messagebus_ruby_api", "1.0.3" + +# Map +gem "leaflet-rails", "0.7.7" # Parsing gem "nokogiri", "1.6.8" gem "redcarpet", "3.3.4" -gem "twitter-text", "1.13.4" -gem "roxml", "3.1.6" +gem "twitter-text", "1.14.0" gem "ruby-oembed", "0.10.1" gem "open_graph_reader", "0.6.1" # Services gem "omniauth", "1.3.1" -gem "omniauth-facebook", "3.0.0" +gem "omniauth-facebook", "4.0.0" gem "omniauth-tumblr", "1.2" gem "omniauth-twitter", "1.2.1" gem "twitter", "5.16.0" gem "omniauth-wordpress", "0.2.2" +# OpenID Connect +gem "openid_connect", "0.12.0" + # Serializers gem "active_model_serializers", "0.9.5" # XMPP chat dependencies -gem "diaspora-vines", "0.2.0.develop.4" -gem "rails-assets-diaspora_jsxc", "0.1.4", source: "https://rails-assets.org" +gem "diaspora-prosody-config", "0.0.5" +gem "rails-assets-diaspora_jsxc", "0.1.5.develop.1", source: "https://rails-assets.org" # Tags @@ -160,12 +168,12 @@ gem "addressable", "2.3.8", require: "addressable/uri" gem "faraday", "0.9.2" gem "faraday_middleware", "0.10.0" gem "faraday-cookie_jar", "0.0.6" -gem "typhoeus", "1.0.2" +gem "typhoeus", "1.1.0" # Views -gem "gon", "6.0.1" -gem "haml", "4.0.7" +gem "gon", "6.1.0" +gem "hamlit", "2.5.0" gem "mobile-fu", "1.3.1" gem "will_paginate", "3.1.0" gem "rails-timeago", "2.11.0" @@ -185,6 +193,8 @@ gem "rubyzip", "1.2.0", require: "zip" # https://github.com/discourse/discourse/pull/238 gem "minitest" +gem "versionist", "1.5.0" + # Windows and OSX have an execjs compatible runtime built-in, Linux users should # install Node.js or use "therubyracer". # @@ -208,7 +218,7 @@ group :production do # we don"t install these on travis to speed up test runs # Process management - gem "eye", "0.7" + gem "eye", "0.8.1" # Redirects @@ -223,20 +233,24 @@ end group :development do # Automatic test runs gem "guard", "2.14.0", require: false - gem "listen", "~> 3.0.0", require: false gem "guard-cucumber", "2.1.2", require: false - gem "guard-rspec", "4.7.2", require: false + gem "guard-rspec", "4.7.3", require: false gem "guard-rubocop", "1.2.0", require: false gem "rb-fsevent", "0.9.7", require: false gem "rb-inotify", "0.9.7", require: false # Linters - gem "jshintrb", "0.3.0" - gem "rubocop", "0.40.0" + gem "rubocop", "0.40.0" + gem "haml_lint", "0.18.1" + gem "pronto", "0.7.0" + gem "pronto-eslint", "0.7.0" + gem "pronto-rubocop", "0.7.0" + gem "pronto-haml", "0.7.0" + gem "pronto-scss", "0.7.0", require: false # Preloading environment - gem "spring", "1.7.1" + gem "spring", "1.7.2" gem "spring-commands-rspec", "1.0.4" gem "spring-commands-cucumber", "1.0.1" @@ -245,7 +259,7 @@ group :development do gem "pry-byebug" # test coverage - gem "simplecov", "0.11.2", require: false + gem "simplecov", "0.12.0", require: false gem "turbo_dev_assets", "0.0.2" end @@ -254,14 +268,17 @@ group :test do # RSpec (unit tests, some integration tests) gem "fixture_builder", "0.4.1" - gem "fuubar", "2.0.0" - gem "test_after_commit", "1.0.0" + gem "fuubar", "2.1.1" + gem "test_after_commit", "1.1.0" # Cucumber (integration tests) gem "capybara", "2.7.1" gem "database_cleaner", "1.5.3" - gem "selenium-webdriver", "2.47.1" + gem "poltergeist", "1.10.0" + + gem "cucumber-api-steps", "0.13", require: false + gem "json_spec", "1.1.4" # General helpers @@ -270,15 +287,18 @@ group :test do gem "webmock", "2.1.0", require: false gem "shoulda-matchers", "3.1.1" - gem "diaspora_federation-test", "0.0.13" + gem "diaspora_federation-test", "0.1.4" + + # Coverage + gem 'coveralls', require: false end group :development, :test do # RSpec (unit tests, some integration tests) - gem "rspec-rails", "3.4.2" + gem "rspec-rails", "3.5.1" # Cucumber (integration tests) - gem "cucumber-rails", "1.4.3", require: false + gem "cucumber-rails", "1.4.4", require: false # Jasmine (client side application tests (JS)) gem "jasmine", "2.4.0" diff --git a/Gemfile.lock b/Gemfile.lock index 252d02825df74449d7e7ca4f7ef2e5e9f75ce2e1..b8906af729c8f484a948ec3fe0b4e19a02e50b22 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -34,8 +34,8 @@ GEM activemodel (= 4.2.7.1) activesupport (= 4.2.7.1) arel (~> 6.0) - activerecord-import (0.13.0) - activerecord (>= 3.0) + activerecord-import (0.15.0) + activerecord (>= 3.2) activesupport (4.2.7.1) i18n (~> 0.7) json (~> 1.7, >= 1.7.7) @@ -44,7 +44,7 @@ GEM tzinfo (~> 1.1) acts-as-taggable-on (3.5.0) activerecord (>= 3.2, < 5) - acts_as_api (0.4.2) + acts_as_api (0.4.3) activemodel (>= 3.0.0) activesupport (>= 3.0.0) rack (>= 1.1.0) @@ -55,7 +55,8 @@ GEM fog (>= 1.8.0) unf ast (2.3.0) - autoprefixer-rails (6.3.6.2) + attr_required (1.0.1) + autoprefixer-rails (6.4.0.2) execjs backbone-on-rails (1.2.0.0) eco @@ -63,8 +64,11 @@ GEM jquery-rails railties bcrypt (3.1.11) - bootstrap-sass (2.3.2.2) - sass (~> 3.2) + bindata (2.3.1) + bootstrap-sass (3.3.7) + autoprefixer-rails (>= 5.2.1) + sass (>= 3.3.4) + bootstrap-switch-rails (3.3.3) buftok (0.2.0) builder (3.2.2) byebug (9.0.5) @@ -81,18 +85,33 @@ GEM json (>= 1.7) mime-types (>= 1.16) mimemagic (>= 0.3.0) - celluloid (0.16.0) - timers (~> 4.0.0) - celluloid-io (0.16.2) - celluloid (>= 0.16.0) - nio4r (>= 1.1.0) - childprocess (0.5.9) - ffi (~> 1.0, >= 1.0.11) - chunky_png (1.3.5) + celluloid (0.17.3) + celluloid-essentials + celluloid-extras + celluloid-fsm + celluloid-pool + celluloid-supervision + timers (>= 4.1.1) + celluloid-essentials (0.20.5) + timers (>= 4.1.1) + celluloid-extras (0.20.5) + timers (>= 4.1.1) + celluloid-fsm (0.20.5) + timers (>= 4.1.1) + celluloid-io (0.17.3) + celluloid (>= 0.17.2) + nio4r (>= 1.1) + timers (>= 4.1.1) + celluloid-pool (0.20.5) + timers (>= 4.1.1) + celluloid-supervision (0.20.6) + timers (>= 4.1.1) + chunky_png (1.3.6) + cliver (0.3.2) coderay (1.1.1) - coffee-rails (4.1.1) + coffee-rails (4.2.1) coffee-script (>= 2.2.0) - railties (>= 4.0.0, < 5.1.x) + railties (>= 4.0.0, < 5.2.x) coffee-script (2.4.1) coffee-script-source execjs @@ -113,8 +132,15 @@ GEM compass (~> 1.0.0) sass-rails (< 5.1) sprockets (< 2.13) + concurrent-ruby (1.0.2) configurate (0.3.1) connection_pool (2.2.0) + coveralls (0.8.15) + json (>= 1.8, < 3) + simplecov (~> 0.12.0) + term-ansicolor (~> 1.3) + thor (~> 0.19.1) + tins (>= 1.6.0, < 2) crack (0.4.3) safe_yaml (~> 1.0.0) cucumber (2.4.0) @@ -125,50 +151,47 @@ GEM gherkin (~> 4.0) multi_json (>= 1.7.5, < 2.0) multi_test (>= 0.1.2) + cucumber-api-steps (0.13) + cucumber (>= 1.2.1) + jsonpath (>= 0.1.2) + rspec (>= 2.12.0) cucumber-core (1.5.0) gherkin (~> 4.0) - cucumber-rails (1.4.3) + cucumber-rails (1.4.4) capybara (>= 1.1.2, < 3) cucumber (>= 1.3.8, < 3) mime-types (>= 1.16, < 4) nokogiri (~> 1.5) - railties (>= 3, < 5) + railties (>= 3, < 5.1) cucumber-wire (0.0.1) database_cleaner (1.5.3) - devise (3.5.6) + devise (4.2.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 3.2.6, < 5) + railties (>= 4.1.0, < 5.1) responders - thread_safe (~> 0.1) warden (~> 1.2.3) - devise-token_authenticatable (0.4.6) - devise (>= 3.5.2, < 4.0.0) + devise-token_authenticatable (0.5.2) + devise (>= 4.0.0, < 4.3.0) devise_lastseenable (0.0.6) devise rails (>= 3.0.4) - diaspora-vines (0.2.0.develop.4) - activerecord (~> 4.1) - bcrypt (~> 3.1) - em-hiredis (~> 0.3.0) - eventmachine (~> 1.0.8) - http_parser.rb (~> 0.6) - nokogiri (~> 1.6) - diaspora_federation (0.0.13) + diaspora-prosody-config (0.0.5) + diaspora_federation (0.1.4) faraday (~> 0.9.0) faraday_middleware (~> 0.10.0) - nokogiri (~> 1.6, >= 1.6.7.2) + nokogiri (~> 1.6, >= 1.6.8) typhoeus (~> 1.0) valid (~> 1.0) - diaspora_federation-rails (0.0.13) - diaspora_federation (= 0.0.13) + diaspora_federation-rails (0.1.4) + diaspora_federation (= 0.1.4) rails (~> 4.2) - diaspora_federation-test (0.0.13) - diaspora_federation (= 0.0.13) - factory_girl (~> 4.5, >= 4.5.0) + diaspora_federation-test (0.1.4) + diaspora_federation (= 0.1.4) + factory_girl (~> 4.7) diff-lcs (1.2.5) docile (1.1.5) - domain_name (0.5.20160310) + domain_name (0.5.20160615) unf (>= 0.0.5, < 1.0.0) eco (1.0.0) coffee-script @@ -176,27 +199,24 @@ GEM execjs eco-source (1.1.0.rc.1) ejs (1.1.1) - em-hiredis (0.3.1) - eventmachine (~> 1.0) - hiredis (~> 0.6.0) - entypo-rails (2.2.3) - railties (>= 3.1, <= 5) + entypo-rails (3.0.0.pre.rc2) + railties (>= 4.1, <= 5) equalizer (0.0.10) erubis (2.7.0) + eslintrb (2.1.0) + execjs + multi_json (>= 1.3) + rake ethon (0.9.0) ffi (>= 1.3.0) - eventmachine (1.0.9.1) excon (0.49.0) execjs (2.7.0) - eye (0.7) - celluloid (~> 0.16.0) - celluloid-io (~> 0.16.0) + eye (0.8.1) + celluloid (~> 0.17.3) + celluloid-io (~> 0.17.0) sigar (~> 0.7.3) state_machine thor - facebox-rails (0.2.0) - railties (>= 3.0, < 5.0) - thor (>= 0.14, < 2.0) factory_girl (4.7.0) activesupport (>= 3.0.0) factory_girl_rails (4.7.0) @@ -209,7 +229,7 @@ GEM http-cookie (~> 1.0.0) faraday_middleware (0.10.0) faraday (>= 0.7.4, < 0.10) - ffi (1.9.10) + ffi (1.9.14) fission (0.5.0) CFPropertyList (~> 2.2) fixture_builder (0.4.1) @@ -342,16 +362,20 @@ GEM fog-xml (0.1.2) fog-core nokogiri (~> 1.5, >= 1.5.11) - font-awesome-rails (4.6.3.0) + font-awesome-rails (4.6.3.1) railties (>= 3.2, < 5.1) formatador (0.2.5) - fuubar (2.0.0) + fuubar (2.1.1) rspec (~> 3.0) ruby-progressbar (~> 1.4) + get_process_mem (0.2.1) gherkin (4.0.0) + gitlab (3.6.1) + httparty + terminal-table globalid (0.3.7) activesupport (>= 4.1.0) - gon (6.0.1) + gon (6.1.0) actionpack (>= 3.0) json multi_json @@ -370,7 +394,7 @@ GEM cucumber (~> 2.0) guard-compat (~> 1.0) nenv (~> 0.1) - guard-rspec (4.7.2) + guard-rspec (4.7.3) guard (~> 2.1) guard-compat (~> 1.1) rspec (>= 2.99.0, < 4.0) @@ -379,7 +403,16 @@ GEM rubocop (~> 0.20) haml (4.0.7) tilt - handlebars_assets (0.23.0) + haml_lint (0.18.1) + haml (~> 4.0) + rake (>= 10, < 12) + rubocop (>= 0.36.0) + sysexits (~> 1.1) + hamlit (2.5.0) + temple (~> 0.7.6) + thor + tilt + handlebars_assets (0.23.1) execjs (~> 2.0) multi_json (~> 1.0) sprockets (>= 2.0.0) @@ -387,7 +420,6 @@ GEM hashdiff (0.3.0) hashie (3.4.4) hike (1.2.3) - hiredis (0.6.1) hitimes (1.2.4) http (1.0.4) addressable (~> 2.3) @@ -399,6 +431,10 @@ GEM http-form_data (1.0.1) http_accept_language (2.0.5) http_parser.rb (0.6.0) + httparty (0.13.7) + json (~> 1.8) + multi_xml (>= 0.5.2) + httpclient (2.8.1) i18n (0.7.0) i18n-inflector (2.6.7) i18n (>= 0.4.1) @@ -406,7 +442,6 @@ GEM actionpack (>= 3.0.0) i18n-inflector (~> 2.6) railties (>= 3.0.0) - ice_cube (0.11.1) inflecto (0.0.2) ipaddress (0.8.3) jasmine (2.4.0) @@ -422,26 +457,35 @@ GEM thor (>= 0.14, < 2.0) jquery-ui-rails (5.0.5) railties (>= 3.2.16) - js-routes (1.2.6) + js-routes (1.2.9) railties (>= 3.2) sprockets-rails js_image_paths (0.1.0) rails (~> 4.0) - jshintrb (0.3.0) - execjs - multi_json (>= 1.3) - rake json (1.8.3) + json-jwt (1.6.3) + activesupport + bindata + multi_json (>= 1.3) + securecompare + url_safe_base64 json-schema (2.6.2) addressable (~> 2.3.8) - jwt (1.5.1) + json_spec (1.1.4) + multi_json (~> 1.0) + rspec (>= 2.0, < 4.0) + jsonpath (0.5.8) + multi_json + jwt (1.5.4) kaminari (0.16.3) actionpack (>= 3.0.0) activesupport (>= 3.0.0) kgio (2.10.0) - listen (3.0.8) + leaflet-rails (0.7.7) + listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) little-plugger (1.1.4) logging (2.1.0) little-plugger (~> 1.1) @@ -458,7 +502,6 @@ GEM markerb (1.1.0) memoizable (0.4.2) thread_safe (~> 0.3, >= 0.3.1) - messagebus_ruby_api (1.0.3) method_source (0.8.2) mime-types (3.1) mime-types-data (~> 3.2015) @@ -478,24 +521,26 @@ GEM naught (1.1.0) nenv (0.3.0) nested_form (0.3.2) - nio4r (1.2.0) + nio4r (1.2.1) nokogiri (1.6.8) mini_portile2 (~> 2.1.0) pkg-config (~> 1.1.7) - notiffany (0.1.0) + notiffany (0.1.1) nenv (~> 0.1) shellany (~> 0.0) oauth (0.5.1) - oauth2 (1.1.0) + oauth2 (1.2.0) faraday (>= 0.8, < 0.10) - jwt (~> 1.0, < 1.5.2) + jwt (~> 1.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) + octokit (4.3.0) + sawyer (~> 0.7.0, >= 0.5.3) omniauth (1.3.1) hashie (>= 1.2, < 4) rack (>= 1.0, < 3) - omniauth-facebook (3.0.0) + omniauth-facebook (4.0.0) omniauth-oauth2 (~> 1.2) omniauth-oauth (1.1.0) oauth @@ -514,13 +559,48 @@ GEM open_graph_reader (0.6.1) faraday (~> 0.9.0) nokogiri (~> 1.6) + openid_connect (0.12.0) + activemodel + attr_required (>= 1.0.0) + json (>= 1.4.3) + json-jwt (>= 1.5.0) + rack-oauth2 (>= 1.3.1) + swd (>= 1.0.0) + tzinfo + validate_email + validate_url + webfinger (>= 1.0.1) orm_adapter (0.5.0) parser (2.3.1.2) ast (~> 2.2) + pg (0.18.4) phantomjs (2.1.1.0) pkg-config (1.1.7) + poltergeist (1.10.0) + capybara (~> 2.1) + cliver (~> 0.3.1) + websocket-driver (>= 0.2.0) powerpack (0.1.1) - pry (0.10.3) + pronto (0.7.0) + gitlab (~> 3.6, >= 3.4.0) + httparty (~> 0.13.7) + octokit (~> 4.3, >= 4.1.0) + rainbow (~> 2.1) + rugged (~> 0.24, >= 0.23.0) + thor (~> 0.19.0) + pronto-eslint (0.7.0) + eslintrb (~> 2.0, >= 2.0.0) + pronto (~> 0.7.0) + pronto-haml (0.7.0) + haml_lint (~> 0.16, >= 0.15.0) + pronto (~> 0.7.0) + pronto-rubocop (0.7.0) + pronto (~> 0.7.0) + rubocop (~> 0.38, >= 0.35.0) + pronto-scss (0.7.0) + pronto (~> 0.7.0) + scss_lint (~> 0.43, >= 0.43.0) + pry (0.10.4) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) @@ -536,6 +616,12 @@ GEM activesupport rack-mobile-detect (0.4.0) rack + rack-oauth2 (1.4.0) + activesupport (>= 2.3) + attr_required (>= 0.0.5) + httpclient (>= 2.4) + multi_json (>= 1.3.6) + rack (>= 1.1) rack-piwik (0.3.0) rack-pjax (0.8.0) nokogiri (~> 1.5) @@ -558,7 +644,13 @@ GEM bundler (>= 1.3.0, < 2.0) railties (= 4.2.7.1) sprockets-rails - rails-assets-diaspora_jsxc (0.1.4) + rails-assets-autosize (3.0.17) + rails-assets-blueimp-gallery (2.21.3) + rails-assets-bootstrap (3.3.7) + rails-assets-jquery (>= 1.9.1, < 4) + rails-assets-bootstrap-markdown (2.10.0) + rails-assets-bootstrap (~> 3) + rails-assets-diaspora_jsxc (0.1.5.develop.1) rails-assets-favico.js (~> 0.3.9) rails-assets-jquery (>= 1.11) rails-assets-jquery-colorbox (~> 1.6.3) @@ -566,15 +658,11 @@ GEM rails-assets-jquery.slimscroll (~> 1.3.6) rails-assets-jquery.ui (~> 1.11.4) rails-assets-favico.js (0.3.10) - rails-assets-highlightjs (9.4.0) - rails-assets-jakobmattsson--jquery-elastic (1.6.11) - rails-assets-jquery (>= 1.2.6) + rails-assets-highlightjs (9.6.0) rails-assets-jasmine (2.4.1) rails-assets-jasmine-ajax (3.2.0) rails-assets-jasmine (~> 2) - rails-assets-jeresig--jquery.hotkeys (0.2.0) - rails-assets-jquery (>= 1.4.2) - rails-assets-jquery (1.12.0) + rails-assets-jquery (2.2.1) rails-assets-jquery-colorbox (1.6.4) rails-assets-jquery (>= 1.3.2) rails-assets-jquery-fullscreen-plugin (0.5.0) @@ -582,17 +670,17 @@ GEM rails-assets-jquery (>= 1.6) rails-assets-jquery-textchange (0.2.3) rails-assets-jquery - rails-assets-jquery.slimscroll (1.3.7) + rails-assets-jquery.slimscroll (1.3.8) rails-assets-jquery.ui (1.11.4) rails-assets-jquery (>= 1.6) rails-assets-markdown-it--markdown-it-for-inline (0.1.1) - rails-assets-markdown-it (6.0.5) - rails-assets-markdown-it-diaspora-mention (0.4.0) + rails-assets-markdown-it (7.0.0) + rails-assets-markdown-it-diaspora-mention (1.0.0) rails-assets-markdown-it-hashtag (0.4.0) - rails-assets-markdown-it-sanitizer (0.4.1) + rails-assets-markdown-it-sanitizer (0.4.2) rails-assets-markdown-it-sub (1.0.0) rails-assets-markdown-it-sup (1.0.0) - rails-assets-perfect-scrollbar (0.6.11) + rails-assets-perfect-scrollbar (0.6.12) rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) rails-dom-testing (1.0.7) @@ -637,37 +725,34 @@ GEM nokogiri (>= 1.4.1) trollop redcarpet (3.3.4) - redis (3.2.2) + redis (3.3.1) redis-namespace (1.5.2) redis (~> 3.0, >= 3.0.4) remotipart (1.2.1) request_store (1.3.1) responders (2.2.0) railties (>= 4.2.0, < 5.1) - roxml (3.1.6) - activesupport (>= 2.3.0) - nokogiri (>= 1.3.3) - rspec (3.4.0) - rspec-core (~> 3.4.0) - rspec-expectations (~> 3.4.0) - rspec-mocks (~> 3.4.0) - rspec-core (3.4.4) - rspec-support (~> 3.4.0) - rspec-expectations (3.4.0) + rspec (3.5.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-core (3.5.2) + rspec-support (~> 3.5.0) + rspec-expectations (3.5.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.4.0) - rspec-mocks (3.4.1) + rspec-support (~> 3.5.0) + rspec-mocks (3.5.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.4.0) - rspec-rails (3.4.2) - actionpack (>= 3.0, < 4.3) - activesupport (>= 3.0, < 4.3) - railties (>= 3.0, < 4.3) - rspec-core (~> 3.4.0) - rspec-expectations (~> 3.4.0) - rspec-mocks (~> 3.4.0) - rspec-support (~> 3.4.0) - rspec-support (3.4.1) + rspec-support (~> 3.5.0) + rspec-rails (3.5.1) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-support (~> 3.5.0) + rspec-support (3.5.0) rubocop (0.40.0) parser (>= 2.3.1.0, < 3.0) powerpack (~> 0.1) @@ -676,40 +761,44 @@ GEM unicode-display_width (~> 1.0, >= 1.0.1) ruby-oembed (0.10.1) ruby-progressbar (1.8.1) + ruby_dep (1.3.1) rubyzip (1.2.0) + rufus-scheduler (3.2.1) + rugged (0.24.0) safe_yaml (1.0.4) sass (3.4.22) - sass-rails (5.0.4) - railties (>= 4.0.0, < 5.0) + sass-rails (5.0.6) + railties (>= 4.0.0, < 6) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - selenium-webdriver (2.47.1) - childprocess (~> 0.5) - multi_json (~> 1.0) - rubyzip (~> 1.0) - websocket (~> 1.0) + sawyer (0.7.0) + addressable (>= 2.3.5, < 2.5) + faraday (~> 0.8, < 0.10) + scss_lint (0.49.0) + rake (>= 0.9, < 12) + sass (~> 3.4.20) + securecompare (1.0.0) shellany (0.0.1) shoulda-matchers (3.1.1) activesupport (>= 4.0.0) - sidekiq (3.4.2) - celluloid (~> 0.16.0) + sidekiq (4.1.4) + concurrent-ruby (~> 1.0) connection_pool (~> 2.2, >= 2.2.0) - json (~> 1.0) redis (~> 3.2, >= 3.2.1) - redis-namespace (~> 1.5, >= 1.5.2) - sidetiq (0.6.3) - celluloid (>= 0.14.1) - ice_cube (= 0.11.1) - sidekiq (>= 3.0.0) + sinatra (>= 1.4.7) + sidekiq-cron (0.4.2) + redis-namespace (>= 1.5.2) + rufus-scheduler (>= 2.0.24) + sidekiq (>= 4.0.0) sigar (0.7.3) simple_captcha2 (0.4.0) rails (>= 4.1) simple_oauth (0.3.1) - simplecov (0.11.2) + simplecov (0.12.0) docile (~> 1.1.0) - json (~> 1.8) + json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.0) sinatra (1.4.7) @@ -719,7 +808,7 @@ GEM sinon-rails (1.15.0) railties (>= 3.1) slop (3.6.0) - spring (1.7.1) + spring (1.7.2) spring-commands-cucumber (1.0.1) spring (>= 0.9.1) spring-commands-rspec (1.0.4) @@ -734,15 +823,27 @@ GEM activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) state_machine (1.2.0) + swd (1.0.1) + activesupport (>= 3) + attr_required (>= 0.0.5) + httpclient (>= 2.4) + i18n + json (>= 1.4.3) + sysexits (1.2.0) systemu (2.6.5) - test_after_commit (1.0.0) + temple (0.7.7) + term-ansicolor (1.3.2) + tins (~> 1.0) + terminal-table (1.6.0) + test_after_commit (1.1.0) activerecord (>= 3.2) thor (0.19.1) thread_safe (0.3.5) tilt (1.4.1) timecop (0.8.1) - timers (4.0.4) + timers (4.1.1) hitimes + tins (1.12.0) trollop (2.1.2) turbo_dev_assets (0.0.2) twitter (5.16.0) @@ -756,104 +857,135 @@ GEM memoizable (~> 0.4.0) naught (~> 1.0) simple_oauth (~> 0.3.0) - twitter-text (1.13.4) + twitter-text (1.14.0) unf (~> 0.1.0) - typhoeus (1.0.2) + typhoeus (1.1.0) ethon (>= 0.9.0) tzinfo (1.2.2) thread_safe (~> 0.1) - uglifier (3.0.0) + uglifier (3.0.1) execjs (>= 0.3.0, < 3) unf (0.1.4) unf_ext unf_ext (0.0.7.2) - unicode-display_width (1.0.5) + unicode-display_width (1.1.0) unicorn (5.1.0) kgio (~> 2.6) raindrops (~> 0.7) + unicorn-worker-killer (0.4.4) + get_process_mem (~> 0) + unicorn (>= 4, < 6) + url_safe_base64 (0.2.2) uuid (2.3.8) macaddr (~> 1.0) - valid (1.1.0) + valid (1.2.0) + validate_email (0.1.6) + activemodel (>= 3.0) + mail (>= 2.2.5) + validate_url (1.0.2) + activemodel (>= 3.0.0) + addressable + versionist (1.5.0) + activesupport (>= 3) + railties (>= 3) + yard (~> 0.7) warden (1.2.6) rack (>= 1.0) + webfinger (1.0.2) + activesupport + httpclient (>= 2.4) + multi_json webmock (2.1.0) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff - websocket (1.2.3) + websocket-driver (0.6.4) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.2) will_paginate (3.1.0) xml-simple (1.1.5) xpath (2.0.0) nokogiri (~> 1.3) + yard (0.8.7.6) PLATFORMS ruby DEPENDENCIES active_model_serializers (= 0.9.5) - activerecord-import (= 0.13.0) + activerecord-import (= 0.15.0) acts-as-taggable-on (= 3.5.0) - acts_as_api (= 0.4.2) + acts_as_api (= 0.4.3) addressable (= 2.3.8) asset_sync (= 1.1.0) - autoprefixer-rails (= 6.3.6.2) + autoprefixer-rails (= 6.4.0.2) backbone-on-rails (= 1.2.0.0) - bootstrap-sass (= 2.3.2.2) + bootstrap-sass (= 3.3.7) + bootstrap-switch-rails (= 3.3.3) capybara (= 2.7.1) carrierwave (= 0.11.2) compass-rails (= 2.0.5) configurate (= 0.3.1) - cucumber-rails (= 1.4.3) + coveralls + cucumber-api-steps (= 0.13) + cucumber-rails (= 1.4.4) database_cleaner (= 1.5.3) - devise (= 3.5.6) - devise-token_authenticatable (= 0.4.6) + devise (= 4.2.0) + devise-token_authenticatable (= 0.5.2) devise_lastseenable (= 0.0.6) - diaspora-vines (= 0.2.0.develop.4) - diaspora_federation-rails (= 0.0.13) - diaspora_federation-test (= 0.0.13) - entypo-rails (= 2.2.3) - eye (= 0.7) - facebox-rails (= 0.2.0) + diaspora-prosody-config (= 0.0.5) + diaspora_federation-rails (= 0.1.4) + diaspora_federation-test (= 0.1.4) + entypo-rails (= 3.0.0.pre.rc2) + eye (= 0.8.1) factory_girl_rails (= 4.7.0) faraday (= 0.9.2) faraday-cookie_jar (= 0.0.6) faraday_middleware (= 0.10.0) fixture_builder (= 0.4.1) fog (= 1.38.0) - fuubar (= 2.0.0) - gon (= 6.0.1) + fuubar (= 2.1.1) + gon (= 6.1.0) guard (= 2.14.0) guard-cucumber (= 2.1.2) - guard-rspec (= 4.7.2) + guard-rspec (= 4.7.3) guard-rubocop (= 1.2.0) - haml (= 4.0.7) - handlebars_assets (= 0.23.0) + haml_lint (= 0.18.1) + hamlit (= 2.5.0) + handlebars_assets (= 0.23.1) http_accept_language (= 2.0.5) i18n-inflector-rails (= 1.0.7) jasmine (= 2.4.0) jasmine-jquery-rails (= 2.0.3) jquery-rails (= 4.1.1) jquery-ui-rails (= 5.0.5) - js-routes (= 1.2.6) + js-routes (= 1.2.9) js_image_paths (= 0.1.0) - jshintrb (= 0.3.0) json (= 1.8.3) json-schema (= 2.6.2) - listen (~> 3.0.0) + json_spec (= 1.1.4) + leaflet-rails (= 0.7.7) logging-rails (= 0.5.0) markerb (= 1.1.0) - messagebus_ruby_api (= 1.0.3) mini_magick (= 4.5.1) minitest mobile-fu (= 1.3.1) mysql2 (= 0.4.4) nokogiri (= 1.6.8) omniauth (= 1.3.1) - omniauth-facebook (= 3.0.0) + omniauth-facebook (= 4.0.0) omniauth-tumblr (= 1.2) omniauth-twitter (= 1.2.1) omniauth-wordpress (= 0.2.2) open_graph_reader (= 0.6.1) + openid_connect (= 0.12.0) + pg (= 0.18.4) + poltergeist (= 1.10.0) + pronto (= 0.7.0) + pronto-eslint (= 0.7.0) + pronto-haml (= 0.7.0) + pronto-rubocop (= 0.7.0) + pronto-scss (= 0.7.0) pry pry-byebug quiet_assets (= 1.1.0) @@ -864,22 +996,23 @@ DEPENDENCIES rack-rewrite (= 1.5.1) rack-ssl (= 1.4.1) rails (= 4.2.7.1) - rails-assets-diaspora_jsxc (= 0.1.4)! - rails-assets-highlightjs (= 9.4.0)! - rails-assets-jakobmattsson--jquery-elastic (= 1.6.11)! + rails-assets-autosize (= 3.0.17)! + rails-assets-blueimp-gallery (= 2.21.3)! + rails-assets-bootstrap-markdown (= 2.10.0)! + rails-assets-diaspora_jsxc (= 0.1.5.develop.1)! + rails-assets-highlightjs (= 9.6.0)! rails-assets-jasmine-ajax (= 3.2.0)! - rails-assets-jeresig--jquery.hotkeys (= 0.2.0)! - rails-assets-jquery (= 1.12.0)! + rails-assets-jquery (= 2.2.1)! rails-assets-jquery-placeholder (= 2.3.1)! rails-assets-jquery-textchange (= 0.2.3)! - rails-assets-markdown-it (= 6.0.5)! + rails-assets-markdown-it (= 7.0.0)! rails-assets-markdown-it--markdown-it-for-inline (= 0.1.1)! - rails-assets-markdown-it-diaspora-mention (= 0.4.0)! + rails-assets-markdown-it-diaspora-mention (= 1.0.0)! rails-assets-markdown-it-hashtag (= 0.4.0)! - rails-assets-markdown-it-sanitizer (= 0.4.1)! + rails-assets-markdown-it-sanitizer (= 0.4.2)! rails-assets-markdown-it-sub (= 1.0.0)! rails-assets-markdown-it-sup (= 1.0.0)! - rails-assets-perfect-scrollbar (= 0.6.11)! + rails-assets-perfect-scrollbar (= 0.6.12)! rails-i18n (= 4.0.8) rails-timeago (= 2.11.0) rails_admin (= 0.8.1) @@ -888,32 +1021,32 @@ DEPENDENCIES redcarpet (= 3.3.4) remotipart (= 1.2.1) responders (= 2.2.0) - roxml (= 3.1.6) - rspec-rails (= 3.4.2) + rspec-rails (= 3.5.1) rubocop (= 0.40.0) ruby-oembed (= 0.10.1) rubyzip (= 1.2.0) - sass-rails (= 5.0.4) - selenium-webdriver (= 2.47.1) + sass-rails (= 5.0.6) shoulda-matchers (= 3.1.1) - sidekiq (= 3.4.2) - sidetiq (= 0.6.3) + sidekiq (= 4.1.4) + sidekiq-cron (= 0.4.2) simple_captcha2 (= 0.4.0) - simplecov (= 0.11.2) + simplecov (= 0.12.0) sinatra (= 1.4.7) sinon-rails (= 1.15.0) - spring (= 1.7.1) + spring (= 1.7.2) spring-commands-cucumber (= 1.0.1) spring-commands-rspec (= 1.0.4) - test_after_commit (= 1.0.0) + test_after_commit (= 1.1.0) timecop (= 0.8.1) turbo_dev_assets (= 0.0.2) twitter (= 5.16.0) - twitter-text (= 1.13.4) - typhoeus (= 1.0.2) - uglifier (= 3.0.0) + twitter-text (= 1.14.0) + typhoeus (= 1.1.0) + uglifier (= 3.0.1) unicorn (= 5.1.0) + unicorn-worker-killer (= 0.4.4) uuid (= 2.3.8) + versionist (= 1.5.0) webmock (= 2.1.0) will_paginate (= 3.1.0) diff --git a/README.md b/README.md index bdacd7bb755a514d7a7c1e25639e67af6ac4d75e..c91fc94fe12066498443dc60794d449005e87519 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,17 @@ # diaspora* ### A privacy-aware, distributed, open source social network -**master:** [](http://travis-ci.org/diaspora/diaspora) -**stable:** [](http://travis-ci.org/diaspora/diaspora) | -**develop:** [](http://travis-ci.org/diaspora/diaspora) | -[](https://gemnasium.com/diaspora/diaspora) -[](https://codeclimate.com/github/diaspora/diaspora) +**master:** [](http://travis-ci.org/diaspora/diaspora) +**next-minor:** [](http://travis-ci.org/diaspora/diaspora) +[](https://coveralls.io/github/diaspora/diaspora?branch=next-minor)| +**develop:** [](http://travis-ci.org/diaspora/diaspora) +[](https://coveralls.io/github/diaspora/diaspora?branch=develop) | +[](https://gemnasium.com/diaspora/diaspora) +[](https://codeclimate.com/github/diaspora/diaspora) [Project site](https://diasporafoundation.org) | [Wiki](https://wiki.diasporafoundation.org) | -[Bugtracker](http://github.com/diaspora/diaspora/issues) | +[Bugtracker](https://github.com/diaspora/diaspora/issues) | [Discussions](https://www.loomio.org/groups/194) | [Mailing lists](https://wiki.diasporafoundation.org/How_We_Communicate#Mailing_Lists) | [License](/COPYRIGHT) | @@ -17,7 +19,6 @@ ## Installation - You don't have to install diaspora* to use the network. There are many servers connected to diaspora*s network which are open to anyone, and you can create an account on one of these servers. Have a look at our [tips for finding a home](https://wiki.diasporafoundation.org/Choosing_a_pod), or you can just go straight to the [list of open servers](http://podupti.me) to sign up. Want to own your data and install diaspora*? Whether you just want to try it out, want to install it on your server or want to contribute and need a development setup, our [installation guides](https://wiki.diasporafoundation.org/Installation) will get you started! @@ -36,5 +37,4 @@ Everyone interacting in diaspora’s codebases, issue trackers, chat rooms, mail ## Security -Found a security issue? Please disclose it responsibly. We have a team of developers listening to [security@diasporafoundation.org](mailto:security@diasporafoundation.org). The PGP fingerprint is [AB0D AB02 0FC5 D398 03AB 3CE1 6F70 243F 27AD 886A](http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x6F70243F27AD886A) - +Found a security issue? Please disclose it responsibly. We have a team of developers listening to [security@diasporafoundation.org](mailto:security@diasporafoundation.org). The PGP fingerprint is [AB0D AB02 0FC5 D398 03AB 3CE1 6F70 243F 27AD 886A](https://pgp.mit.edu/pks/lookup?op=get&search=0x6F70243F27AD886A). diff --git a/app/assets/images/ajax-loader.gif b/app/assets/images/ajax-loader.gif deleted file mode 100644 index e40f19a2818e4c81726bf965fc8dc108d52dc599..0000000000000000000000000000000000000000 Binary files a/app/assets/images/ajax-loader.gif and /dev/null differ diff --git a/app/assets/images/mobile/asterisk_white_mobile.png b/app/assets/images/branding/logos/asterisk_white_mobile.png similarity index 100% rename from app/assets/images/mobile/asterisk_white_mobile.png rename to app/assets/images/branding/logos/asterisk_white_mobile.png diff --git a/app/assets/images/branding/logos/header-logo.png b/app/assets/images/branding/logos/header-logo.png deleted file mode 100644 index 0e47dd91e2c930d7cca30172833dfaf79e2fae03..0000000000000000000000000000000000000000 Binary files a/app/assets/images/branding/logos/header-logo.png and /dev/null differ diff --git a/app/assets/images/branding/logos/header-logo_hover.png b/app/assets/images/branding/logos/header-logo_hover.png deleted file mode 100644 index dae58b94328b60fd0f82ad352b806ff5937f870c..0000000000000000000000000000000000000000 Binary files a/app/assets/images/branding/logos/header-logo_hover.png and /dev/null differ diff --git a/app/assets/images/branding/logos/powered_by_diaspora.png b/app/assets/images/branding/logos/powered_by_diaspora.png deleted file mode 100644 index 3979f5be721b8a28f7ece55d0a7e3c1648c342cc..0000000000000000000000000000000000000000 Binary files a/app/assets/images/branding/logos/powered_by_diaspora.png and /dev/null differ diff --git a/app/assets/images/branding/logos/white2x.png b/app/assets/images/branding/logos/white2x.png deleted file mode 100644 index fa0aafb9561888d358a4795b6fcf08db45ce5112..0000000000000000000000000000000000000000 Binary files a/app/assets/images/branding/logos/white2x.png and /dev/null differ diff --git a/app/assets/images/dandelion.jpg b/app/assets/images/dandelion.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5766b5840cdf1edd7955a3353494fbb1b37e81ff Binary files /dev/null and b/app/assets/images/dandelion.jpg differ diff --git a/app/assets/images/favicon.ico b/app/assets/images/favicon.ico deleted file mode 100644 index c07db736300e1af7689b4e9945f08be4767dbc29..0000000000000000000000000000000000000000 Binary files a/app/assets/images/favicon.ico and /dev/null differ diff --git a/app/assets/images/fonts/Roboto-Bold.ttf b/app/assets/images/fonts/Roboto-Bold.ttf deleted file mode 100644 index 91ec21227866ca9d1cf77ec13660b7b85ec900dd..0000000000000000000000000000000000000000 Binary files a/app/assets/images/fonts/Roboto-Bold.ttf and /dev/null differ diff --git a/app/assets/images/fonts/Roboto-Light.ttf b/app/assets/images/fonts/Roboto-Light.ttf deleted file mode 100644 index d43e943312e0f2c653815dd791d93f94f0abd73f..0000000000000000000000000000000000000000 Binary files a/app/assets/images/fonts/Roboto-Light.ttf and /dev/null differ diff --git a/app/assets/images/fonts/Roboto-Regular.ttf b/app/assets/images/fonts/Roboto-Regular.ttf deleted file mode 100644 index 7d9a6c4c32d7e920b549caf531e390733496b6e0..0000000000000000000000000000000000000000 Binary files a/app/assets/images/fonts/Roboto-Regular.ttf and /dev/null differ diff --git a/app/assets/images/fonts/diaspora-custom.ttf b/app/assets/images/fonts/diaspora-custom.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4b21e9b84da8b55ed39b28e17a22e3a4021def56 Binary files /dev/null and b/app/assets/images/fonts/diaspora-custom.ttf differ diff --git a/app/assets/images/fonts/svg-icons/compose_mobile.svg b/app/assets/images/fonts/svg-icons/compose_mobile.svg new file mode 100644 index 0000000000000000000000000000000000000000..ff020cd60bbd05e663e22b50ba0ce2abc9605c51 --- /dev/null +++ b/app/assets/images/fonts/svg-icons/compose_mobile.svg @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + viewBox="0 0 744.09448819 1052.3622047" + height="40px" + width="40px"> + <g + style="display:inline" + id="layer1" + transform="matrix(4.9383994,0,0,5.2618096,-1527.6262,-2214.8726)"> + <path + id="path3511" + d="m 278.125,520.93362 0,-100 79.0625,0.0138 c 43.48437,0.008 81.17062,0.36221 83.74721,0.7881 3.3747,0.55781 6.95755,2.85698 12.8125,8.22198 l 8.12779,7.44764 0,16.13926 0,16.13926 -10,0 -10,0 -0.0158,-10.3125 -0.0157,-10.3125 -6.77054,-5.9375 -6.77057,-5.9375 -66.3387,0 -66.33869,0 0,83.75 0,83.75 24.54911,0 24.54912,0 -0.77696,6.5625 c -0.47778,4.0355 -1.59948,7.16416 -2.91302,8.125 -1.57019,1.14856 -10.18586,1.5625 -32.52216,1.5625 l -30.38609,0 0,-100 z m 75.01385,98.75856 c -0.95897,-0.59267 0.76874,-9.48251 5.61079,-28.86997 l 6.99644,-28.01359 39.00196,-39.14467 c 21.45108,-21.52956 40.5209,-39.95144 42.37738,-40.9375 1.87165,-0.99411 6.78352,-1.79283 11.02537,-1.79283 l 7.64993,0 12.71105,12.39542 12.71105,12.39542 0,12.61571 0,12.6157 -39.44885,39.44886 -39.44886,39.44885 -19.28755,4.7892 c -18.3445,4.55503 -36.89916,6.90323 -39.89871,5.0494 z m 33.55295,-18.06936 c 3.68049,-0.97963 6.89841,-1.98775 7.15094,-2.24027 0.25252,-0.25253 -3.66299,-4.55375 -8.70115,-9.55828 l -9.16028,-9.09915 -2.11015,8.40052 c -2.09814,8.35273 -2.09435,8.41733 0.66474,11.35425 3.24463,3.45376 3.41414,3.46969 12.1559,1.14293 z m 66.1351,-79.11794 -5.26283,-5.36242 -24.7019,24.67873 -24.70189,24.67874 5.26282,5.36243 5.26282,5.36242 24.70191,-24.67873 24.70189,-24.67875 -5.26282,-5.36242 z" + style="fill:#fefefe" + inkscape:connector-curvature="0" /> + </g> +</svg> diff --git a/app/assets/images/header-bg-long.jpg b/app/assets/images/header-bg-long.jpg deleted file mode 100644 index da0492bc7d2276baa906aec3050ec80a5d35e2f3..0000000000000000000000000000000000000000 Binary files a/app/assets/images/header-bg-long.jpg and /dev/null differ diff --git a/app/assets/images/header-bg.png b/app/assets/images/header-bg.png deleted file mode 100644 index fa7d7d8aa9d6b856ddacae05c327d8f15fb412a7..0000000000000000000000000000000000000000 Binary files a/app/assets/images/header-bg.png and /dev/null differ diff --git a/app/assets/images/icons/mail_grey.png b/app/assets/images/icons/mail_grey.png deleted file mode 100644 index 3f503af5337413e358b57c93fdd1b432c0cefbd7..0000000000000000000000000000000000000000 Binary files a/app/assets/images/icons/mail_grey.png and /dev/null differ diff --git a/app/assets/images/icons/mail_grey_hover.png b/app/assets/images/icons/mail_grey_hover.png deleted file mode 100644 index a4dbff8389e80f9ddc7f7be38b45fadbaff4ba38..0000000000000000000000000000000000000000 Binary files a/app/assets/images/icons/mail_grey_hover.png and /dev/null differ diff --git a/app/assets/images/icons/notifications_grey.png b/app/assets/images/icons/notifications_grey.png deleted file mode 100644 index 78ad7c77977cb6286a73538ba86a54baba508e73..0000000000000000000000000000000000000000 Binary files a/app/assets/images/icons/notifications_grey.png and /dev/null differ diff --git a/app/assets/images/icons/notifications_grey_hover.png b/app/assets/images/icons/notifications_grey_hover.png deleted file mode 100644 index 4558a55a952727b50099902d9492a5c198bcc62a..0000000000000000000000000000000000000000 Binary files a/app/assets/images/icons/notifications_grey_hover.png and /dev/null differ diff --git a/app/assets/images/img/glyphicons-halflings-blue.png b/app/assets/images/img/glyphicons-halflings-blue.png deleted file mode 100644 index a8dca0fccdf2d4e3170190183661d702c050399e..0000000000000000000000000000000000000000 Binary files a/app/assets/images/img/glyphicons-halflings-blue.png and /dev/null differ diff --git a/app/assets/images/img/glyphicons-halflings-red.png b/app/assets/images/img/glyphicons-halflings-red.png deleted file mode 100644 index 30c315fe08b5520b7668be08f762cfd477d090ac..0000000000000000000000000000000000000000 Binary files a/app/assets/images/img/glyphicons-halflings-red.png and /dev/null differ diff --git a/app/assets/images/landing/cog.png b/app/assets/images/landing/cog.png deleted file mode 100644 index 06e6939605d8c7ae1f21e204783e6bc03d1be8cb..0000000000000000000000000000000000000000 Binary files a/app/assets/images/landing/cog.png and /dev/null differ diff --git a/app/assets/images/landing/pen_write.png b/app/assets/images/landing/pen_write.png deleted file mode 100644 index 34a2fdffc679506d78782c0f706e02c94a08bf4e..0000000000000000000000000000000000000000 Binary files a/app/assets/images/landing/pen_write.png and /dev/null differ diff --git a/app/assets/images/landing/smiley_laughing.png b/app/assets/images/landing/smiley_laughing.png deleted file mode 100644 index e2e6dc0b84f57fb1a6830e6ae088751f775c4700..0000000000000000000000000000000000000000 Binary files a/app/assets/images/landing/smiley_laughing.png and /dev/null differ diff --git a/app/assets/images/mobile/arrow-left.png b/app/assets/images/mobile/arrow-left.png deleted file mode 100644 index 8ae1a3d0e36242e8abc4b1f2c43aafd8f1609cf0..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/arrow-left.png and /dev/null differ diff --git a/app/assets/images/mobile/arrow-right.png b/app/assets/images/mobile/arrow-right.png deleted file mode 100644 index 9683d7bbaa1f6dfafa256d271c27a7ea7f0483ea..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/arrow-right.png and /dev/null differ diff --git a/app/assets/images/mobile/arrow_down_small.png b/app/assets/images/mobile/arrow_down_small.png deleted file mode 100644 index 392d821251b2884743c8c383df05663f9b70c52a..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/arrow_down_small.png and /dev/null differ diff --git a/app/assets/images/mobile/arrow_up_small.png b/app/assets/images/mobile/arrow_up_small.png deleted file mode 100644 index 970a8e5969ecd9fc7411e789f5063421bda73dfe..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/arrow_up_small.png and /dev/null differ diff --git a/app/assets/images/mobile/camera.png b/app/assets/images/mobile/camera.png deleted file mode 100644 index cc4d3bd54fe2f1c9f57d342bfc6da111bc6418d3..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/camera.png and /dev/null differ diff --git a/app/assets/images/mobile/check_yes_ok.png b/app/assets/images/mobile/check_yes_ok.png deleted file mode 100644 index da33bf6fd5204d6c41818a00f2ceab94ed91cd12..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/check_yes_ok.png and /dev/null differ diff --git a/app/assets/images/mobile/compose_mobile.png b/app/assets/images/mobile/compose_mobile.png deleted file mode 100644 index 22bfd6f770f035edb125f192b74bfede5e05fdc1..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/compose_mobile.png and /dev/null differ diff --git a/app/assets/images/mobile/deletelabel.png b/app/assets/images/mobile/deletelabel.png deleted file mode 100644 index b3e53ee3a767e955a4e48b6e83edc8287d8d5ab2..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/deletelabel.png and /dev/null differ diff --git a/app/assets/images/mobile/hatched-light.jpg b/app/assets/images/mobile/hatched-light.jpg deleted file mode 100644 index 0282e7eb764ab1a5ac36419d6328cabdfda378f4..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/hatched-light.jpg and /dev/null differ diff --git a/app/assets/images/mobile/heart_mobile_grey.png b/app/assets/images/mobile/heart_mobile_grey.png deleted file mode 100644 index 9e5ce387c799b31842aaafe0aa52b505fb503d3f..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/heart_mobile_grey.png and /dev/null differ diff --git a/app/assets/images/mobile/heart_mobile_red.png b/app/assets/images/mobile/heart_mobile_red.png deleted file mode 100644 index e2b5dc42b4980044bd89fdcda16985f7da83e37f..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/heart_mobile_red.png and /dev/null differ diff --git a/app/assets/images/mobile/mail_white.png b/app/assets/images/mobile/mail_white.png deleted file mode 100644 index ad215505f1d920bd669c551dfc2494c59ad8f93c..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/mail_white.png and /dev/null differ diff --git a/app/assets/images/mobile/menu.png b/app/assets/images/mobile/menu.png deleted file mode 100644 index 59b11180c08c522bba8e41576307b22f7a3f0973..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/menu.png and /dev/null differ diff --git a/app/assets/images/mobile/notifications_white.png b/app/assets/images/mobile/notifications_white.png deleted file mode 100644 index 3f94e2848dbcdc8955a0bfb2369eee1612c071b1..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/notifications_white.png and /dev/null differ diff --git a/app/assets/images/mobile/pencil_mobile_grey.png b/app/assets/images/mobile/pencil_mobile_grey.png deleted file mode 100644 index da72cc3d4da1dfa52402f4f2ba36ca166bd5b622..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/pencil_mobile_grey.png and /dev/null differ diff --git a/app/assets/images/mobile/pencil_mobile_grey_active.png b/app/assets/images/mobile/pencil_mobile_grey_active.png deleted file mode 100644 index 5d4147ea0376a3d93818bc58d11baac8ac851dd8..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/pencil_mobile_grey_active.png and /dev/null differ diff --git a/app/assets/images/mobile/reshare_mobile.png b/app/assets/images/mobile/reshare_mobile.png deleted file mode 100644 index 91883ea03128cc87f3b14068551e6fdf52c09b93..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/reshare_mobile.png and /dev/null differ diff --git a/app/assets/images/mobile/reshare_mobile_active.png b/app/assets/images/mobile/reshare_mobile_active.png deleted file mode 100644 index 71a1feb5b77275bbf0b0678a09e56970f7f14f74..0000000000000000000000000000000000000000 Binary files a/app/assets/images/mobile/reshare_mobile_active.png and /dev/null differ diff --git a/app/assets/images/social_media_logos/Readme.txt b/app/assets/images/social-media-logos/Readme.txt similarity index 100% rename from app/assets/images/social_media_logos/Readme.txt rename to app/assets/images/social-media-logos/Readme.txt diff --git a/app/assets/images/social_media_logos/facebook-16x16.png b/app/assets/images/social-media-logos/facebook-16x16.png similarity index 100% rename from app/assets/images/social_media_logos/facebook-16x16.png rename to app/assets/images/social-media-logos/facebook-16x16.png diff --git a/app/assets/images/social_media_logos/facebook-24x24.png b/app/assets/images/social-media-logos/facebook-24x24.png similarity index 100% rename from app/assets/images/social_media_logos/facebook-24x24.png rename to app/assets/images/social-media-logos/facebook-24x24.png diff --git a/app/assets/images/social_media_logos/facebook-32x32.png b/app/assets/images/social-media-logos/facebook-32x32.png similarity index 100% rename from app/assets/images/social_media_logos/facebook-32x32.png rename to app/assets/images/social-media-logos/facebook-32x32.png diff --git a/app/assets/images/social_media_logos/tumblr-16x16.png b/app/assets/images/social-media-logos/tumblr-16x16.png similarity index 100% rename from app/assets/images/social_media_logos/tumblr-16x16.png rename to app/assets/images/social-media-logos/tumblr-16x16.png diff --git a/app/assets/images/social_media_logos/tumblr-24x24.png b/app/assets/images/social-media-logos/tumblr-24x24.png similarity index 100% rename from app/assets/images/social_media_logos/tumblr-24x24.png rename to app/assets/images/social-media-logos/tumblr-24x24.png diff --git a/app/assets/images/social_media_logos/tumblr-32x32.png b/app/assets/images/social-media-logos/tumblr-32x32.png similarity index 100% rename from app/assets/images/social_media_logos/tumblr-32x32.png rename to app/assets/images/social-media-logos/tumblr-32x32.png diff --git a/app/assets/images/social_media_logos/twitter-16x16.png b/app/assets/images/social-media-logos/twitter-16x16.png similarity index 100% rename from app/assets/images/social_media_logos/twitter-16x16.png rename to app/assets/images/social-media-logos/twitter-16x16.png diff --git a/app/assets/images/social_media_logos/twitter-24x24.png b/app/assets/images/social-media-logos/twitter-24x24.png similarity index 100% rename from app/assets/images/social_media_logos/twitter-24x24.png rename to app/assets/images/social-media-logos/twitter-24x24.png diff --git a/app/assets/images/social_media_logos/twitter-32x32.png b/app/assets/images/social-media-logos/twitter-32x32.png similarity index 100% rename from app/assets/images/social_media_logos/twitter-32x32.png rename to app/assets/images/social-media-logos/twitter-32x32.png diff --git a/app/assets/images/social_media_logos/wordpress-16x16.png b/app/assets/images/social-media-logos/wordpress-16x16.png similarity index 100% rename from app/assets/images/social_media_logos/wordpress-16x16.png rename to app/assets/images/social-media-logos/wordpress-16x16.png diff --git a/app/assets/images/social_media_logos/wordpress-24x24.png b/app/assets/images/social-media-logos/wordpress-24x24.png similarity index 100% rename from app/assets/images/social_media_logos/wordpress-24x24.png rename to app/assets/images/social-media-logos/wordpress-24x24.png diff --git a/app/assets/images/social_media_logos/wordpress-32x32.png b/app/assets/images/social-media-logos/wordpress-32x32.png similarity index 100% rename from app/assets/images/social_media_logos/wordpress-32x32.png rename to app/assets/images/social-media-logos/wordpress-32x32.png diff --git a/app/assets/images/static-loader.png b/app/assets/images/static-loader.png deleted file mode 100644 index 1b370993518adffc5b67c2ac0bf02f013d1affbe..0000000000000000000000000000000000000000 Binary files a/app/assets/images/static-loader.png and /dev/null differ diff --git a/app/assets/javascripts/api/authorization_page.js b/app/assets/javascripts/api/authorization_page.js new file mode 100644 index 0000000000000000000000000000000000000000..d61b941ece68ee4aae19ad8b5eabb3069660fb05 --- /dev/null +++ b/app/assets/javascripts/api/authorization_page.js @@ -0,0 +1,5 @@ +$(document).ready(function() { + $("#js-app-logo").error(function () { + $(this).attr("src", ImagePaths.get("user/default.png")); + }); +}); diff --git a/app/assets/javascripts/app/app.js b/app/assets/javascripts/app/app.js index 00730479373344de2d20d1ff6072e77150dd6d34..1046bd66ab5df8a7648700537f1ee6a88354215d 100644 --- a/app/assets/javascripts/app/app.js +++ b/app/assets/javascripts/app/app.js @@ -46,8 +46,8 @@ var app = { app.router = new app.Router(); this.setupDummyPreloads(); - this.setupFacebox(); this.setupUser(); + this.setupAspects(); this.setupHeader(); this.setupBackboneLinks(); this.setupGlobalViews(); @@ -66,7 +66,7 @@ var app = { }, parsePreload : function(prop) { - if(!app.hasPreload(prop)) { return } + if(!app.hasPreload(prop)) { return; } var preload = window.gon.preloads[prop]; delete window.gon.preloads[prop]; //prevent dirty state across navigates @@ -84,6 +84,10 @@ var app = { app.currentUser = app.user(window.gon.user) || new app.models.User(); }, + setupAspects: function() { + app.aspects = new app.collections.Aspects(app.currentUser.get("aspects")); + }, + setupHeader: function() { if(app.currentUser.authenticated()) { app.header = new app.views.Header(); @@ -92,12 +96,6 @@ var app = { } }, - setupFacebox: function() { - $.facebox.settings.closeImage = ImagePaths.get('facebox/closelabel.png'); - $.facebox.settings.loadingImage = ImagePaths.get('facebox/loading.gif'); - $.facebox.settings.opacity = 0.75; - }, - setupBackboneLinks: function() { Backbone.history.start({pushState: true}); @@ -110,12 +108,6 @@ var app = { evt.preventDefault(); var link = $(this); - if(link.data("stream-title") && link.data("stream-title").length) { - $(".stream_title").text(link.data("stream-title")); - } else { - $(".stream_title").text(link.text()); - } - $("html, body").animate({scrollTop: 0}); // app.router.navigate doesn't tell us if it changed the page, @@ -127,16 +119,14 @@ var app = { setupGlobalViews: function() { app.hovercard = new app.views.Hovercard(); - $('.aspect_membership_dropdown').each(function(){ - new app.views.AspectMembership({el: this}); - }); app.sidebar = new app.views.Sidebar(); app.backToTop = new app.views.BackToTop({el: $(document)}); + app.flashMessages = new app.views.FlashMessages({el: $("#flash-container")}); }, /* mixpanel wrapper function */ instrument : function(type, name, object, callback) { - if(!window.mixpanel) { return } + if(!window.mixpanel) { return; } window.mixpanel[type](name, object, callback); }, @@ -150,6 +140,9 @@ var app = { // add placeholder support for old browsers $("input, textarea").placeholder(); + // init autosize plugin + autosize($("textarea")); + // setup remote forms $(document).on("ajax:success", "form[data-remote]", function() { $(this).clearForm(); diff --git a/app/assets/javascripts/app/collections/aspect_memberships.js b/app/assets/javascripts/app/collections/aspect_memberships.js index dc3c0410bd506e45a16be286ac37f7c57ed0e631..5c53b6ead9d3c8c8259fa7592206fdcbe204830f 100644 --- a/app/assets/javascripts/app/collections/aspect_memberships.js +++ b/app/assets/javascripts/app/collections/aspect_memberships.js @@ -1,6 +1,10 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.collections.AspectMemberships = Backbone.Collection.extend({ - model: app.models.AspectMembership + model: app.models.AspectMembership, + + findByAspectId: function(id) { + return this.find(function(membership) { return membership.belongsToAspect(id); }); + } }); // @license-end diff --git a/app/assets/javascripts/app/collections/aspect_selections.js b/app/assets/javascripts/app/collections/aspect_selections.js new file mode 100644 index 0000000000000000000000000000000000000000..bfe3fb94e8964d538dc6d2378bc31448881cf62b --- /dev/null +++ b/app/assets/javascripts/app/collections/aspect_selections.js @@ -0,0 +1,31 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later + +app.collections.AspectSelections = Backbone.Collection.extend({ + model: app.models.AspectSelection, + + selectedGetAttribute: function(attribute) { + return _.pluck(_.filter(this.toJSON(), function(a) { + return a.selected; + }), attribute); + }, + + allSelected: function() { + return this.length === _.filter(this.toJSON(), function(a) { return a.selected; }).length; + }, + + selectAll: function() { + this.map(function(a) { a.set({"selected": true}); }); + }, + + deselectAll: function() { + this.map(function(a) { a.set({"selected": false}); }); + }, + + toSentence: function() { + var separator = Diaspora.I18n.t("comma") + " "; + var pattern = new RegExp(Diaspora.I18n.t("comma") + "\\s([^" + Diaspora.I18n.t("comma") + "]+)$"); + return this.selectedGetAttribute("name").join(separator).replace(pattern, " " + Diaspora.I18n.t("and") + " $1") + || Diaspora.I18n.t("my_aspects"); + } +}); +// @license-end diff --git a/app/assets/javascripts/app/collections/aspects.js b/app/assets/javascripts/app/collections/aspects.js index 7b25d33b5618a39e3930b754eb50adc82924ab88..4cecea647dc0e9c56cd886b572e53348f29f3bef 100644 --- a/app/assets/javascripts/app/collections/aspects.js +++ b/app/assets/javascripts/app/collections/aspects.js @@ -1,29 +1,7 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.collections.Aspects = Backbone.Collection.extend({ - model: app.models.AspectSelection, - - selectedAspects: function(attribute){ - return _.pluck(_.filter(this.toJSON(), function(a){ - return a.selected; - }), attribute); - }, - - allSelected: function(){ - return this.length === _.filter(this.toJSON(), function(a){ return a.selected; }).length; - }, - - selectAll: function(){ - this.map(function(a){ a.set({ 'selected' : true })} ); - }, - - deselectAll: function(){ - this.map(function(a){ a.set({ 'selected' : false })} ); - }, - - toSentence: function(){ - var separator = Diaspora.I18n.t("comma") + ' '; - return this.selectedAspects('name').join(separator).replace(/,\s([^,]+)$/, ' ' + Diaspora.I18n.t("and") + ' $1') || Diaspora.I18n.t("my_aspects"); - } + model: app.models.Aspect, + url: "/aspects" }); // @license-end diff --git a/app/assets/javascripts/app/collections/comments.js b/app/assets/javascripts/app/collections/comments.js index f096363e0537e38e26e94c60cf3d6d94cc8cd016..9ecf4f047391b90d3422aed60aa8f80513e227cf 100644 --- a/app/assets/javascripts/app/collections/comments.js +++ b/app/assets/javascripts/app/collections/comments.js @@ -2,19 +2,20 @@ app.collections.Comments = Backbone.Collection.extend({ model: app.models.Comment, - url: function() { return _.result(this.post, 'url') + '/comments'; }, + url: function() { + return _.result(this.post, "url") + "/comments"; + }, initialize : function(models, options) { this.post = options.post; }, - make : function(text){ + make : function(text) { var self = this; - - var comment = new app.models.Comment({text: text }); + var comment = new app.models.Comment({ "text": text }); var deferred = comment.save({}, { - url: '/posts/'+this.post.id+'/comments', + url: "/posts/"+ this.post.id +"/comments", success: function() { comment.set({author: app.currentUser.toJSON(), parent: self.post }); self.add(comment); diff --git a/app/assets/javascripts/app/collections/pods.js b/app/assets/javascripts/app/collections/pods.js new file mode 100644 index 0000000000000000000000000000000000000000..1264d09c44e6da9616428c2b6f4321c45a636ffc --- /dev/null +++ b/app/assets/javascripts/app/collections/pods.js @@ -0,0 +1,10 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later +app.collections.Pods = Backbone.Collection.extend({ + model: app.models.Pod, + + comparator: function(model) { + var host = model.get("host") || ""; + return host.toLowerCase(); + } +}); +// @license-end diff --git a/app/assets/javascripts/app/collections/posts.js b/app/assets/javascripts/app/collections/posts.js index fc5fe1bbe156eba0a39daca8d940ccee9414c418..d05ed6bbcbe25b3c2c00e931aac373eb6e7f0479 100644 --- a/app/assets/javascripts/app/collections/posts.js +++ b/app/assets/javascripts/app/collections/posts.js @@ -5,4 +5,3 @@ app.collections.Posts = Backbone.Collection.extend({ url : "/posts" }); // @license-end - diff --git a/app/assets/javascripts/app/collections/reshares.js b/app/assets/javascripts/app/collections/reshares.js index 28ce59c2406e1d3ca1e60ee03667c4b2a0bfb291..1aee510539413cea1620de0d44ab705d126fda9d 100644 --- a/app/assets/javascripts/app/collections/reshares.js +++ b/app/assets/javascripts/app/collections/reshares.js @@ -5,4 +5,3 @@ app.collections.Reshares = Backbone.Collection.extend({ url : "/reshares" }); // @license-end - diff --git a/app/assets/javascripts/app/helpers/handlebars-helpers.js b/app/assets/javascripts/app/helpers/handlebars-helpers.js index d27f4df96cde50636213f784d0d1cd63871e5f78..0a75ebbb629afb45c219eb6c937fd0e29915a389 100644 --- a/app/assets/javascripts/app/helpers/handlebars-helpers.js +++ b/app/assets/javascripts/app/helpers/handlebars-helpers.js @@ -47,7 +47,7 @@ Handlebars.registerHelper("sharingMessage", function(person) { var icon = "circle"; if( person.is_sharing ) { i18nScope = "people.helper.is_sharing"; - icon = "entypo check"; + icon = "entypo-check"; } var title = Diaspora.I18n.t(i18nScope, {name: _.escape(person.name)}); @@ -60,11 +60,8 @@ Handlebars.registerHelper("sharingMessage", function(person) { // allow hovercards for users that are not the current user. // returns the html class name used to trigger hovercards. -Handlebars.registerHelper('hovercardable', function(person) { - if( app.currentUser.get('guid') !== person.guid ) { - return 'hovercardable'; - } - return ''; +Handlebars.registerHelper("hovercardable", function(person) { + return app.currentUser.get("guid") === person.guid ? "" : "hovercardable"; }); Handlebars.registerHelper('personImage', function(person, size, imageClass) { @@ -78,10 +75,11 @@ Handlebars.registerHelper('personImage', function(person, size, imageClass) { size = ( !_.isString(size) ) ? "small" : size; imageClass = ( !_.isString(imageClass) ) ? size : imageClass; - return _.template('<img src="<%= src %>" class="avatar <%= img_class %>" title="<%= title %>" alt="<%= title %>" />')({ - 'src': avatar[size], - 'img_class': imageClass, - 'title': _.escape(name) + return _.template("<img src=\"<%= src %>\" class=\"<%= imageClass %>\" " + + "title=\"<%= title %>\" alt=\"<%= title %>\" />")({ + src: avatar[size], + imageClass: imageClass + " avatar img-responsive center-block", + title: _.escape(name) }); }); @@ -120,7 +118,7 @@ Handlebars.registerHelper("isCurrentProfilePage", function(id, diasporaHandle, o Handlebars.registerHelper('aspectMembershipIndicator', function(contact,in_aspect) { if(!app.aspect || !app.aspect.get('id')) return '<div class="aspect_membership_dropdown placeholder"></div>'; - var html = '<i class="entypo '; + var html = "<i class=\"entypo-"; if( in_aspect === 'in_aspect' ) { html += 'circled-cross contact_remove-from-aspect" '; html += 'title="' + Diaspora.I18n.t('contacts.remove_contact') + '" '; diff --git a/app/assets/javascripts/app/helpers/locations.js b/app/assets/javascripts/app/helpers/locations.js new file mode 100644 index 0000000000000000000000000000000000000000..4909dbe9c50c39b992a2b5367e44ada65aca08b3 --- /dev/null +++ b/app/assets/javascripts/app/helpers/locations.js @@ -0,0 +1,25 @@ +(function() { + app.helpers.locations = { + getTiles: function() { + // If the mapbox option is enabled in the diaspora.yml, the mapbox tiles with the podmin's credentials are used. + if (gon.appConfig.map.mapbox.enabled) { + return L.tileLayer("https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}", { + id: gon.appConfig.map.mapbox.id, + accessToken: gon.appConfig.map.mapbox.access_token, + attribution: "Map data © <a href='http://openstreetmap.org'>OpenStreetMap</a> contributors, " + + "<a href='http://creativecommons.org/licenses/by-sa/2.0/''>CC-BY-SA</a>, " + + "Imagery © <a href='https://www.mapbox.com'>Mapbox</a>", + maxZoom: 18 + }); + } + + // maptiles from the Heidelberg University are used by default. + return L.tileLayer("http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}", { + attribution: "Map data © <a href='http://openstreetmap.org'>OpenStreetMap</a> contributors, " + + "rendering <a href='http://giscience.uni-hd.de/'>" + + "GIScience Research Group @ Heidelberg University</a>", + maxZoom: 18 + }); + } + }; +})(); diff --git a/app/assets/javascripts/app/helpers/modal_helper.js b/app/assets/javascripts/app/helpers/modal_helper.js new file mode 100644 index 0000000000000000000000000000000000000000..01aaac4b7984cabd619707cd026dbdbe3235e1c2 --- /dev/null +++ b/app/assets/javascripts/app/helpers/modal_helper.js @@ -0,0 +1,13 @@ +(function(){ + app.helpers.showModal = function(id){ + $(id).modal(); + var modalBody = $(id).find(".modal-body"); + + var url = $(id).attr("href"); + + modalBody.load(url, function(){ + $(id).find("#modalWaiter").remove(); + $(id).trigger("modal:loaded"); + }); + }; +})(); diff --git a/app/assets/javascripts/app/helpers/text_formatter.js b/app/assets/javascripts/app/helpers/text_formatter.js index 163f938ed62779104a6f2cf09a962cc35770fe25..ea237832c5690eee98b25b8de7d28c9073dcf23e 100644 --- a/app/assets/javascripts/app/helpers/text_formatter.js +++ b/app/assets/javascripts/app/helpers/text_formatter.js @@ -26,7 +26,12 @@ array[index][1] = attribute[1].replace(/^www\./, "http://www."); } }); - tokens[idx].attrPush([ "target", "_blank" ]); + tokens[idx].attrPush(["target", "_blank"]); + tokens[idx].attrPush(["rel", "noopener noreferrer"]); + }); + + md.use(inlinePlugin, "responsive_images", "image", function (tokens, idx) { + tokens[idx].attrPush(["class", "img-responsive"]); }); var hashtagPlugin = window.markdownitHashtag; @@ -49,7 +54,7 @@ var supPlugin = window.markdownitSup; md.use(supPlugin); var sanitizerPlugin = window.markdownitSanitizer; - md.use(sanitizerPlugin); + md.use(sanitizerPlugin, {imageClass: "img-responsive"}); var hljs = window.hljs; md.set({ @@ -76,7 +81,6 @@ // Bootstrap table markup md.renderer.rules.table_open = function () { return "<table class=\"table table-striped\">\n"; }; - return md.render(text); }; })(); diff --git a/app/assets/javascripts/app/models.js b/app/assets/javascripts/app/models.js index 286e990c6bd90b8e0cc85f17bfeb6d5a25f08e80..87dfe98438199fb9f94382eb49d1d2982a13e2fb 100644 --- a/app/assets/javascripts/app/models.js +++ b/app/assets/javascripts/app/models.js @@ -5,7 +5,6 @@ // Requires: // this = model with "created_at" attribute app.models.formatDateMixin = { - timeOf: function(field) { return app.helpers.dateFormatter.parse(this.get(field)) / 1000; }, @@ -13,7 +12,5 @@ app.models.formatDateMixin = { createdAt: function() { return this.timeOf("created_at"); } - }; // @license-end - diff --git a/app/assets/javascripts/app/models/aspect_membership.js b/app/assets/javascripts/app/models/aspect_membership.js index ddb503702a9603e676b71d77128013beb1b0c78f..bfae08b50ebccb4ab6ea39c691397b7c79882b83 100644 --- a/app/assets/javascripts/app/models/aspect_membership.js +++ b/app/assets/javascripts/app/models/aspect_membership.js @@ -5,7 +5,11 @@ * (only valid for the context of the current user) */ app.models.AspectMembership = Backbone.Model.extend({ - urlRoot: "/aspect_memberships" + urlRoot: "/aspect_memberships", + + belongsToAspect: function(aspectId) { + var aspect = this.get("aspect"); + return aspect && aspect.id === aspectId; + } }); // @license-end - diff --git a/app/assets/javascripts/app/models/comment.js b/app/assets/javascripts/app/models/comment.js index f2778f718cb80b5d0e356df42cfef7cf8cb88534..d382b731fef641f325da8377809df9c9b5480dec 100644 --- a/app/assets/javascripts/app/models/comment.js +++ b/app/assets/javascripts/app/models/comment.js @@ -4,4 +4,3 @@ app.models.Comment = Backbone.Model.extend({ urlRoot: "/comments" }); // @license-end - diff --git a/app/assets/javascripts/app/models/contact.js b/app/assets/javascripts/app/models/contact.js index 5457f2c4e6f989a78355e4023ac771fe3a974be2..2c72ae41d92e5643b694ed2c4f1bcdee3cfa1275 100644 --- a/app/assets/javascripts/app/models/contact.js +++ b/app/assets/javascripts/app/models/contact.js @@ -2,12 +2,15 @@ app.models.Contact = Backbone.Model.extend({ initialize : function() { - this.aspect_memberships = new app.collections.AspectMemberships(this.get('aspect_memberships')); - if( this.get('person') ) this.person = new app.models.Person(this.get('person')); + this.aspectMemberships = new app.collections.AspectMemberships(this.get("aspect_memberships")); + if (this.get("person")) { + this.person = new app.models.Person(this.get("person")); + this.person.contact = this; + } }, inAspect : function(id) { - return this.aspect_memberships.any(function(membership){ return membership.get('aspect').id === id; }); + return this.aspectMemberships.any(function(membership) { return membership.belongsToAspect(id); }); } }); // @license-end diff --git a/app/assets/javascripts/app/models/person.js b/app/assets/javascripts/app/models/person.js index 8c9a7241a04174b381f3d99955bc8fcd9e5ba39d..4d70fada456f93b606e2a904abae3a30bd834608 100644 --- a/app/assets/javascripts/app/models/person.js +++ b/app/assets/javascripts/app/models/person.js @@ -6,8 +6,13 @@ app.models.Person = Backbone.Model.extend({ }, initialize: function() { - if( this.get('profile') ) - this.profile = new app.models.Profile(this.get('profile')); + if (this.get("profile")) { + this.profile = new app.models.Profile(this.get("profile")); + } + if (this.get("contact")) { + this.contact = new app.models.Contact(this.get("contact")); + this.contact.person = this; + } }, isSharing: function() { diff --git a/app/assets/javascripts/app/models/pod.js b/app/assets/javascripts/app/models/pod.js new file mode 100644 index 0000000000000000000000000000000000000000..5ea497df5a405c8a906c4bddbd779f0d79d1cec0 --- /dev/null +++ b/app/assets/javascripts/app/models/pod.js @@ -0,0 +1,15 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later +app.models.Pod = Backbone.Model.extend({ + urlRoot: Routes.adminPods(), + + recheck: function() { + var self = this, + url = Routes.adminPodRecheck(this.id).toString(); + + return $.ajax({url: url, method: "POST", dataType: "json"}) + .done(function(newAttributes) { + self.set(newAttributes); + }); + } +}); +// @license-end diff --git a/app/assets/javascripts/app/models/post/interactions.js b/app/assets/javascripts/app/models/post/interactions.js index d992440f74706dde724fee665b2ae4af038591a8..e837f96bc8c3b87ea460ab537781ef3fdf707257 100644 --- a/app/assets/javascripts/app/models/post/interactions.js +++ b/app/assets/javascripts/app/models/post/interactions.js @@ -32,7 +32,7 @@ app.models.Post.Interactions = Backbone.Model.extend({ }, likesCount : function(){ - return (this.get("fetched") ? this.likes.models.length : this.get("likes_count") ); + return this.get("fetched") ? this.likes.models.length : this.get("likes_count"); }, resharesCount : function(){ @@ -44,12 +44,15 @@ app.models.Post.Interactions = Backbone.Model.extend({ }, userLike : function(){ - return this.likes.select(function(like){ return like.get("author").guid === app.currentUser.get("guid")})[0]; + return this.likes.select(function(like){ + return like.get("author") && like.get("author").guid === app.currentUser.get("guid"); + })[0]; }, userReshare : function(){ return this.reshares.select(function(reshare){ - return reshare.get("author") && reshare.get("author").guid === app.currentUser.get("guid")})[0]; + return reshare.get("author") && reshare.get("author").guid === app.currentUser.get("guid"); + })[0]; }, toggleLike : function() { @@ -62,10 +65,15 @@ app.models.Post.Interactions = Backbone.Model.extend({ like : function() { var self = this; - this.likes.create({}, {success : function(){ - self.trigger("change"); - self.set({"likes_count" : self.get("likes_count") + 1}); - }}); + this.likes.create({}, { + success: function() { + self.trigger("change"); + self.set({"likes_count" : self.get("likes_count") + 1}); + }, + error: function() { + app.flashMessages.error(Diaspora.I18n.t("failed_to_like")); + } + }); app.instrument("track", "Like"); }, @@ -84,11 +92,7 @@ app.models.Post.Interactions = Backbone.Model.extend({ var self = this; this.comments.make(text).fail(function () { - var flash = new Diaspora.Widgets.FlashMessages(); - flash.render({ - success: false, - notice: Diaspora.I18n.t("failed_to_post_message") - }); + app.flashMessages.error(Diaspora.I18n.t("failed_to_comment")); }).done(function() { self.trigger('change'); //updates after sync }); @@ -99,16 +103,11 @@ app.models.Post.Interactions = Backbone.Model.extend({ }, reshare : function(){ - var interactions = this - , reshare = this.post.reshare() - , flash = new Diaspora.Widgets.FlashMessages(); + var interactions = this; - reshare.save() + this.post.reshare().save() .done(function(reshare) { - flash.render({ - success: true, - notice: Diaspora.I18n.t("reshares.successful") - }); + app.flashMessages.success(Diaspora.I18n.t("reshares.successful")); interactions.reshares.add(reshare); if (app.stream && /^\/(?:stream|activity|aspects)/.test(app.stream.basePath())) { app.stream.addNow(reshare); @@ -116,10 +115,7 @@ app.models.Post.Interactions = Backbone.Model.extend({ interactions.trigger("change"); }) .fail(function(){ - flash.render({ - success: false, - notice: Diaspora.I18n.t("reshares.duplicate") - }); + app.flashMessages.error(Diaspora.I18n.t("reshares.duplicate")); }); app.instrument("track", "Reshare"); diff --git a/app/assets/javascripts/app/models/status_message.js b/app/assets/javascripts/app/models/status_message.js index f8469662af01ef98c1d7c9e1893e9a0aaabe90b7..d233b09ebfa171c33b5a922b8967bf992a2b6dc3 100644 --- a/app/assets/javascripts/app/models/status_message.js +++ b/app/assets/javascripts/app/models/status_message.js @@ -21,4 +21,3 @@ app.models.StatusMessage = app.models.Post.extend({ } }); // @license-end - diff --git a/app/assets/javascripts/app/models/stream_aspects.js b/app/assets/javascripts/app/models/stream_aspects.js index e64d3ea5b3a3911074682a959e02228b6559cb4e..a3d18a5c73105fac8e4cd852ad0f822be18579fa 100644 --- a/app/assets/javascripts/app/models/stream_aspects.js +++ b/app/assets/javascripts/app/models/stream_aspects.js @@ -17,7 +17,7 @@ app.models.StreamAspects = app.models.Stream.extend({ }, fetch: function() { - if(this.isFetching()){ return false } + if(this.isFetching()) { return false; } var url = this.url(); var ids = this.aspects_ids; this.deferred = this.items.fetch(this._fetchOpts({url : url, data : { 'a_ids': ids }})) @@ -26,10 +26,9 @@ app.models.StreamAspects = app.models.Stream.extend({ fetchDone: function() { this.triggerFetchedEvents(); - if (app.aspects) { - app.aspects.trigger('aspectStreamFetched'); + if (app.aspectSelections) { + app.aspectSelections.trigger("aspectStreamFetched"); } } }); // @license-end - diff --git a/app/assets/javascripts/app/pages/admin_dashboard.js b/app/assets/javascripts/app/pages/admin_dashboard.js new file mode 100644 index 0000000000000000000000000000000000000000..4826c12ea6f102c5e806d52fa4f9735029d60cf5 --- /dev/null +++ b/app/assets/javascripts/app/pages/admin_dashboard.js @@ -0,0 +1,75 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later + +app.pages.AdminDashboard = Backbone.View.extend({ + initialize: function() { + this.updatePodStatus(); + }, + + updatePodStatus: function() { + var self = this, + tagName = ""; + $.get("https://api.github.com/repos/diaspora/diaspora/releases/latest") + .done(function(data) { + // the response might be malformed + try { + /* jshint camelcase: false */ + tagName = data.tag_name; + /* jshint camelcase: true */ + if(tagName.charAt(0) !== "v") { + self.updatePodStatusFail(); + return; + } + } catch(e) { + self.updatePodStatusFail(); + return; + } + + // split version into components + self.latestVersion = tagName.slice(1).split(".").map(Number); + if(self.podUpToDate() === null) { + self.updatePodStatusFail(); + } else { + self.updatePodStatusSuccess(); + } + }) + .fail(function() { + self.updatePodStatusFail(); + }); + }, + + updatePodStatusSuccess: function() { + $("#pod-status .alert").removeClass("alert-info"); + var podStatusMessage = Diaspora.I18n.t("admins.dashboard.up_to_date"); + if(this.podUpToDate()) { + $("#pod-status .alert").addClass("alert-success"); + } else { + podStatusMessage = Diaspora.I18n.t("admins.dashboard.outdated"); + $("#pod-status .alert").addClass("alert-danger"); + } + $("#pod-status .alert") + .html("<strong>" + podStatusMessage + "</strong>") + .append(" ") + .append(Diaspora.I18n.t("admins.dashboard.compare_versions", { + latestVersion: "v" + this.latestVersion.join("."), + podVersion: "v" + gon.podVersion + })); + }, + + updatePodStatusFail: function() { + $("#pod-status .alert") + .removeClass("alert-info") + .addClass("alert-warning") + .text(Diaspora.I18n.t("admins.dashboard.error")); + }, + + podUpToDate: function() { + var podVersion = gon.podVersion.split(/\.|\-/).map(Number); + if(this.latestVersion.length < 4 || podVersion.length < 4) { return null; } + for(var i = 0; i < 4; i++) { + if(this.latestVersion[i] < podVersion[i]) { return true; } + if(this.latestVersion[i] > podVersion[i]) { return false; } + } + return true; + } +}); +// @license-end diff --git a/app/assets/javascripts/app/pages/admin_pods.js b/app/assets/javascripts/app/pages/admin_pods.js new file mode 100644 index 0000000000000000000000000000000000000000..27fb1979ed4db73df3ee0b4043c25cf16b599aa6 --- /dev/null +++ b/app/assets/javascripts/app/pages/admin_pods.js @@ -0,0 +1,52 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later + +app.pages.AdminPods = app.views.Base.extend({ + templateName: "pod_table", + + tooltipSelector: "th i", + + initialize: function() { + this.pods = new app.collections.Pods(app.parsePreload("pods")); + this.rows = []; // contains the table row views + }, + + postRenderTemplate: function() { + var self = this; + this._showMessages(); + + // avoid reflowing the page for every entry + var fragment = document.createDocumentFragment(); + this.pods.each(function(pod) { + self.rows.push(new app.views.PodEntry({ + parent: fragment, + model: pod + }).render()); + }); + this.$("tbody").append(fragment); + + return this; + }, + + _showMessages: function() { + var msgs = document.createDocumentFragment(); + if( gon.uncheckedCount && gon.uncheckedCount > 0 ) { + var unchecked = $("<div class='alert alert-info' role='alert' />") + .append(Diaspora.I18n.t("admin.pods.unchecked", {count: gon.uncheckedCount})); + msgs.appendChild(unchecked[0]); + } + if( gon.versionFailedCount && gon.versionFailedCount > 0 ) { + var versionFailed = $("<div class='alert alert-warning' role='alert' />") + .append(Diaspora.I18n.t("admin.pods.version_failed", {count: gon.versionFailedCount})); + msgs.appendChild(versionFailed[0]); + } + if( gon.errorCount && gon.errorCount > 0 ) { + var errors = $("<div class='alert alert-danger' role='alert' />") + .append(Diaspora.I18n.t("admin.pods.errors", {count: gon.errorCount})); + msgs.appendChild(errors[0]); + } + + $("#pod-alerts").html(msgs); + } +}); + +// @license-end diff --git a/app/assets/javascripts/app/pages/contacts.js b/app/assets/javascripts/app/pages/contacts.js index 96cfb60f6b1da212a21d80d30b04f0a46fd8a530..eca20fa330ae908d3b09eae6180a094f91043944 100644 --- a/app/assets/javascripts/app/pages/contacts.js +++ b/app/assets/javascripts/app/pages/contacts.js @@ -8,17 +8,20 @@ app.pages.Contacts = Backbone.View.extend({ "click #contacts_visibility_toggle" : "toggleContactVisibility", "click #chat_privilege_toggle" : "toggleChatPrivilege", "click #change_aspect_name" : "showAspectNameForm", - "keyup #contact_list_search" : "searchContactList" + "click .conversation_button": "showMessageModal", + "click #invitations-button": "showInvitationsModal" }, initialize: function(opts) { - this.visibility_toggle = $("#contacts_visibility_toggle .entypo"); - this.chat_toggle = $("#chat_privilege_toggle .entypo"); + this.visibilityToggle = $("#contacts_visibility_toggle i"); + this.chatToggle = $("#chat_privilege_toggle i"); this.stream = opts.stream; this.stream.render(); - $("#people_stream.contacts .header .entypo").tooltip({"placement": "bottom"}); + $("#people_stream.contacts .header i").tooltip({"placement": "bottom"}); $(document).on("ajax:success", "form.edit_aspect", this.updateAspectName); app.events.on("aspect:create", function(){ window.location.reload() }); + app.events.on("aspect_membership:create", this.addAspectMembership, this); + app.events.on("aspect_membership:destroy", this.removeAspectMembership, this); this.aspectCreateView = new app.views.AspectCreate({ el: $("#newAspectContainer") }); this.aspectCreateView.render(); @@ -27,14 +30,14 @@ app.pages.Contacts = Backbone.View.extend({ }, toggleChatPrivilege: function() { - if (this.chat_toggle.hasClass("enabled")) { - this.chat_toggle.tooltip("destroy") + if (this.chatToggle.hasClass("enabled")) { + this.chatToggle.tooltip("destroy") .removeClass("enabled") .removeAttr("data-original-title") .attr("title", Diaspora.I18n.t("contacts.aspect_chat_is_not_enabled")) .tooltip({"placement": "bottom"}); } else { - this.chat_toggle.tooltip("destroy") + this.chatToggle.tooltip("destroy") .addClass("enabled") .removeAttr("data-original-title") .attr("title", Diaspora.I18n.t("contacts.aspect_chat_is_enabled")) @@ -43,17 +46,17 @@ app.pages.Contacts = Backbone.View.extend({ }, toggleContactVisibility: function() { - if (this.visibility_toggle.hasClass("lock-open")) { - this.visibility_toggle.removeClass("lock-open") - .addClass("lock") + if (this.visibilityToggle.hasClass("entypo-lock-open")) { + this.visibilityToggle.removeClass("entypo-lock-open") + .addClass("entypo-lock") .tooltip("destroy") .removeAttr("data-original-title") .attr("title", Diaspora.I18n.t("contacts.aspect_list_is_not_visible")) .tooltip({"placement": "bottom"}); } else { - this.visibility_toggle.removeClass("lock") - .addClass("lock-open") + this.visibilityToggle.removeClass("entypo-lock") + .addClass("entypo-lock-open") .tooltip("destroy") .removeAttr("data-original-title") .attr("title", Diaspora.I18n.t("contacts.aspect_list_is_visible")) @@ -75,13 +78,17 @@ app.pages.Contacts = Backbone.View.extend({ $(".header > h3").show(); }, - searchContactList: function(e) { - this.stream.search($(e.target).val()); + showMessageModal: function(){ + app.helpers.showModal("#conversationModal"); + }, + + showInvitationsModal: function() { + app.helpers.showModal("#invitationsModal"); }, setupAspectSorting: function() { - $("#aspect_nav .nav").sortable({ - items: "li.aspect[data-aspect-id]", + $("#aspect_nav .list-group").sortable({ + items: "a.aspect[data-aspect-id]", update: function() { $("#aspect_nav .ui-sortable").addClass("syncing"); var data = JSON.stringify({ ordered_aspect_ids: $(this).sortable("toArray", { attribute: "data-aspect-id" }) }); @@ -92,7 +99,51 @@ app.pages.Contacts = Backbone.View.extend({ revert: true, helper: "clone" }); + }, + + updateBadgeCount: function(selector, change) { + var count = parseInt($("#aspect_nav " + selector + " .badge").text(), 10); + $("#aspect_nav " + selector + " .badge").text(count + change); + }, + + addAspectMembership: function(data) { + if(data.startSharing) { + this.updateBadgeCount(".all_aspects", 1); + + var contact = this.stream.collection.find(function(c) { + return c.get("person").id === data.membership.personId; + }); + + if(contact && contact.person.get("relationship") === "sharing") { + contact.person.set({relationship: "mutual"}); + this.updateBadgeCount(".only_sharing", -1); + } + else if(contact && contact.person.get("relationship") === "not_sharing") { + contact.person.set({relationship: "receiving"}); + this.updateBadgeCount(".all_contacts", 1); + } + } + this.updateBadgeCount("[data-aspect-id='" + data.membership.aspectId + "']", 1); + }, + + removeAspectMembership: function(data) { + if(data.stopSharing) { + this.updateBadgeCount(".all_aspects", -1); + + var contact = this.stream.collection.find(function(c) { + return c.get("person").id === data.membership.personId; + }); + + if(contact && contact.person.get("relationship") === "mutual") { + contact.person.set({relationship: "sharing"}); + this.updateBadgeCount(".only_sharing", 1); + } + else if(contact && contact.person.get("relationship") === "receiving") { + contact.person.set({relationship: "not_sharing"}); + this.updateBadgeCount(".all_contacts", -1); + } + } + this.updateBadgeCount("[data-aspect-id='" + data.membership.aspectId + "']", -1); } }); // @license-end - diff --git a/app/assets/javascripts/app/pages/getting_started.js b/app/assets/javascripts/app/pages/getting_started.js new file mode 100644 index 0000000000000000000000000000000000000000..4cf3044c4bb88e21d3692d1bec59288c0e5423fa --- /dev/null +++ b/app/assets/javascripts/app/pages/getting_started.js @@ -0,0 +1,20 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later +app.pages.GettingStarted = app.views.Base.extend({ + el: "#hello-there", + + templateName: false, + + subviews: { + ".aspect_membership_dropdown": "aspectMembershipView" + }, + + initialize: function(opts) { + this.inviter = opts.inviter; + app.events.on("aspect:create", this.render, this); + }, + + aspectMembershipView: function() { + return new app.views.AspectMembership({person: this.inviter, dropdownMayCreateNewAspect: true}); + } +}); +// @license-end diff --git a/app/assets/javascripts/app/pages/profile.js b/app/assets/javascripts/app/pages/profile.js index c50a8a717204cd0d785405b1d39535ba50e35de6..b987ea3876e6fb2bf8d4a5a6d24f3d7efa272073 100644 --- a/app/assets/javascripts/app/pages/profile.js +++ b/app/assets/javascripts/app/pages/profile.js @@ -4,45 +4,49 @@ app.pages.Profile = app.views.Base.extend({ templateName: false, events: { - 'click #block_user_button': 'blockPerson', - 'click #unblock_user_button': 'unblockPerson' + "click #block_user_button": "blockPerson", + "click #unblock_user_button": "unblockPerson" }, subviews: { - '#profile': 'sidebarView', - '.profile_header': 'headerView', - '#main_stream': 'streamView' + "#profile": "sidebarView", + ".profile_header": "headerView", + "#main_stream": "streamView" }, - tooltipSelector: '.profile_button .profile-header-icon, .sharing_message_container', + tooltipSelector: ".profile_button .profile-header-icon, .sharing_message_container", initialize: function(opts) { if( !this.model ) { this._populateModel(opts); } - if( app.hasPreload('photos') ) - this.photos = app.parsePreload('photos'); // we don't interact with it, so no model - if( app.hasPreload('contacts') ) - this.contacts = app.parsePreload('contacts'); // we don't interact with it, so no model + if (app.hasPreload("photos_count")) { + this.photos = app.parsePreload("photos_count"); + } + if (app.hasPreload("contacts_count")) { + this.contacts = app.parsePreload("contacts_count"); + } - this.streamCollection = _.has(opts, 'streamCollection') ? opts.streamCollection : null; - this.streamViewClass = _.has(opts, 'streamView') ? opts.streamView : null; + this.streamCollection = _.has(opts, "streamCollection") ? opts.streamCollection : null; + this.streamViewClass = _.has(opts, "streamView") ? opts.streamView : null; - this.model.on('change', this.render, this); - this.model.on('sync', this._done, this); + this.model.on("change", this.render, this); + this.model.on("sync", this._done, this); // bind to global events - var id = this.model.get('id'); - app.events.on('person:block:'+id, this.reload, this); - app.events.on('person:unblock:'+id, this.reload, this); - app.events.on('aspect:create', this.reload, this); - app.events.on('aspect_membership:update', this.reload, this); + var id = this.model.get("id"); + app.events.on("person:block:"+id, this.reload, this); + app.events.on("person:unblock:"+id, this.reload, this); + app.events.on("aspect:create", this.reload, this); + app.events.on("aspect_membership:update", this.reload, this); + + app.router.renderAspectMembershipDropdowns(this.$el); }, _populateModel: function(opts) { - if( app.hasPreload('person') ) { - this.model = new app.models.Person(app.parsePreload('person')); + if( app.hasPreload("person") ) { + this.model = new app.models.Person(app.parsePreload("person")); } else if(opts && opts.person_id) { this.model = new app.models.Person({guid: opts.person_id}); this.model.fetch(); @@ -52,14 +56,18 @@ app.pages.Profile = app.views.Base.extend({ }, sidebarView: function() { - if( !this.model.has('profile') ) return false; + if(!this.model.has("profile")){ + return false; + } return new app.views.ProfileSidebar({ - model: this.model, + model: this.model }); }, headerView: function() { - if( !this.model.has('profile') ) return false; + if(!this.model.has("profile")){ + return false; + } return new app.views.ProfileHeader({ model: this.model, photos: this.photos, @@ -68,12 +76,7 @@ app.pages.Profile = app.views.Base.extend({ }, streamView: function() { - if( !this.model.has('profile') ) return false; - if( this.model.isBlocked() ) { - $('#main_stream').empty().html( - '<div class="dull">'+ - Diaspora.I18n.t('profile.ignoring', {name: this.model.get('name')}) + - '</div>'); + if(!this.model.has("profile")){ return false; } @@ -96,14 +99,13 @@ app.pages.Profile = app.views.Base.extend({ }, blockPerson: function() { - if( !confirm(Diaspora.I18n.t('ignore_user')) ) return; + if(!confirm(Diaspora.I18n.t("ignore_user"))){ + return; + } var block = this.model.block(); block.fail(function() { - Diaspora.page.flashMessages.render({ - success: false, - notice: Diaspora.I18n.t('ignore_failed') - }); + app.flashMessages.error(Diaspora.I18n.t("ignore_failed")); }); return false; @@ -112,22 +114,18 @@ app.pages.Profile = app.views.Base.extend({ unblockPerson: function() { var block = this.model.unblock(); block.fail(function() { - Diaspora.page.flashMessages.render({ - success: false, - notice: Diaspora.I18.t('unblock_failed') - }); + app.flashMessages.error(Diaspora.I18.t("unblock_failed")); }); return false; }, reload: function() { - this.$('#profile').addClass('loading'); + this.$("#profile").addClass("loading"); this.model.fetch(); }, _done: function() { - this.$('#profile').removeClass('loading'); + this.$("#profile").removeClass("loading"); } }); // @license-end - diff --git a/app/assets/javascripts/app/pages/settings.js b/app/assets/javascripts/app/pages/settings.js index c111d56814daf355f585aa584e4fa8304fcd330f..517d17663e381fc15922f1ce9e93d38478a03226 100644 --- a/app/assets/javascripts/app/pages/settings.js +++ b/app/assets/javascripts/app/pages/settings.js @@ -1,7 +1,9 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.pages.Settings = Backbone.View.extend({ initialize: function() { - $(".settings_visibilty").tooltip({placement: "top"}); + $(".settings-visibility").tooltip({placement: "top"}); + $(".profile-visibility-hint").tooltip({placement: "top"}); + $("[name='profile[public_details]']").bootstrapSwitch(); } }); // @license-end diff --git a/app/assets/javascripts/app/pages/single-post-viewer.js b/app/assets/javascripts/app/pages/single-post-viewer.js index 0eb0cc0d8233b202c259f3bc2c78289cfd49cc2c..c5a30f1c9f4ecea06e8b4ae010147c3669ca3f76 100644 --- a/app/assets/javascripts/app/pages/single-post-viewer.js +++ b/app/assets/javascripts/app/pages/single-post-viewer.js @@ -12,16 +12,6 @@ app.pages.SinglePostViewer = app.views.Base.extend({ this.model = new app.models.Post({ id : gon.post.id }); this.model.preloadOrFetch().done(_.bind(this.initViews, this)); this.model.interactions.fetch(); //async, yo, might want to throttle this later. - this.setupLightbox(); - }, - - setupLightbox : function(){ - this.lightbox = Diaspora.BaseWidget.instantiate("Lightbox"); - this.lightbox.set({ - imageParent: '.photo_attachments', - imageSelector: 'img.stream-photo' - }); - this.$el.delegate("a.stream-photo-link", "click", this.lightbox.lightboxImageClicked); }, initViews : function() { @@ -37,7 +27,6 @@ app.pages.SinglePostViewer = app.views.Base.extend({ //... and converts html to plain text document.title = $('<div>').html(html_title).text(); } - }, - + } }); // @license-end diff --git a/app/assets/javascripts/app/router.js b/app/assets/javascripts/app/router.js index 2fefe63a81c7148f5fb9f192c2d7da1051916e0f..160123505b2d1f96c6067259461f429c45bbddb5 100644 --- a/app/assets/javascripts/app/router.js +++ b/app/assets/javascripts/app/router.js @@ -2,31 +2,34 @@ app.Router = Backbone.Router.extend({ routes: { - "help/:section": "help", - "help/": "help", - "help": "help", - "contacts": "contacts", - "conversations": "conversations", - "user/edit": "settings", - "users/sign_up": "registration", - - "posts/:id": "singlePost", - "p/:id": "singlePost", - - "activity": "stream", - "stream": "stream", - "aspects": "aspects", - "commented": "stream", - "liked": "stream", - "mentions": "stream", - "public": "stream", - "followed_tags": "followed_tags", - "tags/:name": "followed_tags", - "people/:id/photos": "photos", - "people/:id/contacts": "profile", - - "people/:id": "profile", - "u/:name": "profile" + "activity(/)": "stream", + "admin/pods(/)": "adminPods", + "admins/dashboard(/)": "adminDashboard", + "aspects(/)": "aspects", + "commented(/)": "stream", + "community_spotlight(/)": "spotlight", + "contacts(/)": "contacts", + "conversations(/)": "conversations", + "followed_tags(/)": "followed_tags", + "getting_started(/)": "gettingStarted", + "help(/)": "help", + "help/:section(/)": "help", + "liked(/)": "stream", + "mentions(/)": "stream", + "notifications(/)": "notifications", + "p/:id(/)": "singlePost", + "people(/)": "peopleSearch", + "people/:id(/)": "profile", + "people/:id/contacts(/)": "profile", + "people/:id/photos(/)": "photos", + "posts/:id(/)": "singlePost", + "profile/edit(/)": "settings", + "public(/)": "stream", + "stream(/)": "stream", + "tags/:name(/)": "followed_tags", + "u/:name(/)": "profile", + "user/edit(/)": "settings", + "users/sign_up(/)": "registration" }, initialize: function() { @@ -36,19 +39,55 @@ app.Router = Backbone.Router.extend({ this.route(/^bookmarklet(?:\?(.*))?/, "bookmarklet"); }, - help: function(section) { - app.help = new app.views.Help(); - $("#help").prepend(app.help.el); - app.help.render(section); + adminDashboard: function() { + app.page = new app.pages.AdminDashboard(); + }, + + adminPods: function() { + this.renderPage(function() { + return new app.pages.AdminPods({ + el: $("#pod-list") + }); + }); + }, + + aspects: function() { + app.aspectSelections = app.aspectSelections || + new app.collections.AspectSelections(app.currentUser.get("aspects")); + this.aspectsList = this.aspectsList || new app.views.AspectsList({collection: app.aspectSelections}); + this.aspectsList.render(); + /* eslint-disable camelcase */ + this.aspects_stream(); + /* eslint-enable camelcase */ }, - contacts: function() { + /* eslint-disable camelcase */ + aspects_stream: function() { + /* eslint-enable camelcase */ + var ids = app.aspectSelections.selectedGetAttribute("id"); + /* eslint-disable camelcase */ + app.stream = new app.models.StreamAspects([], {aspects_ids: ids}); + /* eslint-enable camelcase */ + app.stream.fetch(); + this._initializeStreamView(); + app.publisher.setSelectedAspects(ids); + }, + + bookmarklet: function() { + var contents = (window.gon) ? gon.preloads.bookmarklet : {}; + app.bookmarklet = new app.views.Bookmarklet( + _.extend({}, {el: $("#bookmarklet")}, contents) + ).render(); + }, + + contacts: function(params) { app.aspect = new app.models.Aspect(gon.preloads.aspect); - app.contacts = new app.collections.Contacts(app.parsePreload('contacts')); + this._loadContacts(); var stream = new app.views.ContactStream({ collection: app.contacts, - el: $('.stream.contacts #contact_stream'), + el: $(".stream.contacts #contact_stream"), + urlParams: params }); app.page = new app.pages.Contacts({stream: stream}); @@ -58,119 +97,150 @@ app.Router = Backbone.Router.extend({ app.conversations = new app.views.Conversations(); }, - registration: function() { - app.page = new app.pages.Registration(); - }, + /* eslint-disable camelcase */ + followed_tags: function(name) { + /* eslint-enable camelcase */ + this.stream(); - settings: function() { - app.page = new app.pages.Settings(); + app.tagFollowings = new app.collections.TagFollowings(); + this.followedTagsView = new app.views.TagFollowingList({collection: app.tagFollowings}); + $("#tags_list").replaceWith(this.followedTagsView.render().el); + this.followedTagsView.setupAutoSuggest(); + + app.tagFollowings.reset(gon.preloads.tagFollowings); + + if (name) { + var followedTagsAction = new app.views.TagFollowingAction( + {tagText: decodeURIComponent(name).toLowerCase()} + ); + $("#author_info").prepend(followedTagsAction.render().el); + app.tags = new app.views.Tags({hashtagName: name}); + } + this._hideInactiveStreamLists(); }, - singlePost : function(id) { - this.renderPage(function(){ return new app.pages.SinglePostViewer({ id: id })}); + gettingStarted: function() { + this.renderPage(function() { + return new app.pages.GettingStarted({inviter: new app.models.Person(app.parsePreload("inviter"))}); + }); }, - renderPage : function(pageConstructor){ - app.page && app.page.unbind && app.page.unbind(); //old page might mutate global events $(document).keypress, so unbind before creating - app.page = pageConstructor(); //create new page after the world is clean (like that will ever happen) - app.page.render(); + help: function(section) { + app.help = new app.views.Help(); + $("#help").prepend(app.help.el); + app.help.render(section); + }, - if( !$.contains(document, app.page.el) ) { - // view element isn't already attached to the DOM, insert it - $("#container").empty().append(app.page.el); - } + notifications: function() { + this._loadContacts(); + this.renderAspectMembershipDropdowns($(document)); + new app.views.Notifications({el: "#notifications_container"}); }, - stream : function() { - app.stream = new app.models.Stream(); - app.stream.fetch(); - this._initializeStreamView(); + peopleSearch: function() { + this._loadContacts(); + this.renderAspectMembershipDropdowns($(document)); + $(".invitations-link").click(function() { + app.helpers.showModal("#invitationsModal"); + }); }, - photos : function(guid) { + photos: function(guid) { + this._loadContacts(); this.renderPage(function() { return new app.pages.Profile({ + /* eslint-disable camelcase */ person_id: guid, - el: $('body > .container-fluid'), + /* eslint-enable camelcase */ + el: $("body > #profile_container"), streamCollection: app.collections.Photos, streamView: app.views.Photos }); }); }, - followed_tags : function(name) { - this.stream(); - - app.tagFollowings = new app.collections.TagFollowings(); - this.followedTagsView = new app.views.TagFollowingList({collection: app.tagFollowings}); - $("#tags_list").replaceWith(this.followedTagsView.render().el); - this.followedTagsView.setupAutoSuggest(); - - app.tagFollowings.reset(gon.preloads.tagFollowings); + profile: function() { + this._loadContacts(); + this.renderPage(function() { + return new app.pages.Profile({ + el: $("body > #profile_container") + }); + }); + }, - if(name) { - var followedTagsAction = new app.views.TagFollowingAction( - {tagText: decodeURIComponent(name).toLowerCase()} - ); - $("#author_info").prepend(followedTagsAction.render().el); - app.tags = new app.views.Tags({hashtagName: name}); - } - this._hideInactiveStreamLists(); + registration: function() { + app.page = new app.pages.Registration(); }, - aspects: function() { - app.aspects = app.aspects || new app.collections.Aspects(app.currentUser.get("aspects")); - this.aspectsList = this.aspectsList || new app.views.AspectsList({ collection: app.aspects }); - this.aspectsList.render(); - this.aspects_stream(); + settings: function() { + app.page = new app.pages.Settings(); }, - aspects_stream : function(){ - var ids = app.aspects.selectedAspects('id'); - app.stream = new app.models.StreamAspects([], { aspects_ids: ids }); - app.stream.fetch(); - this._initializeStreamView(); - app.publisher.setSelectedAspects(ids); + singlePost: function(id) { + this.renderPage(function() { return new app.pages.SinglePostViewer({id: id}); }); }, - bookmarklet: function() { - var contents = (window.gon) ? gon.preloads.bookmarklet : {}; - app.bookmarklet = new app.views.Bookmarklet( - _.extend({}, {el: $('#bookmarklet')}, contents) - ).render(); + spotlight: function() { + $("#invitations-button").click(function() { + app.helpers.showModal("#invitationsModal"); + }); }, - profile: function() { - this.renderPage(function() { return new app.pages.Profile({ - el: $('body > .container-fluid') - }); }); + stream: function() { + app.stream = new app.models.Stream(); + app.stream.fetch(); + this._initializeStreamView(); }, _hideInactiveStreamLists: function() { - if(this.aspectsList && Backbone.history.fragment !== "aspects") { + if (this.aspectsList && Backbone.history.fragment !== "aspects") { this.aspectsList.hideAspectsList(); } - if(this.followedTagsView && Backbone.history.fragment !== "followed_tags") { + if (this.followedTagsView && Backbone.history.fragment !== "followed_tags") { this.followedTagsView.hideFollowedTags(); } }, _initializeStreamView: function() { - if(app.page) { + if (app.page) { app.page.unbindInfScroll(); app.page.remove(); } - app.page = new app.views.Stream({model : app.stream}); - app.publisher = app.publisher || new app.views.Publisher({collection : app.stream.items}); + app.page = new app.views.Stream({model: app.stream}); app.shortcuts = app.shortcuts || new app.views.StreamShortcuts({el: $(document)}); - - var streamFacesView = new app.views.StreamFaces({collection : app.stream.items}); + if ($("#publisher").length !== 0) { + app.publisher = app.publisher || new app.views.Publisher({collection: app.stream.items}); + } $("#main_stream").html(app.page.render().el); - $("#selected_aspect_contacts .content").html(streamFacesView.render().el); this._hideInactiveStreamLists(); + }, + + _loadContacts: function() { + app.contacts = new app.collections.Contacts(app.parsePreload("contacts")); + }, + + renderAspectMembershipDropdowns: function($context) { + $context.find(".aspect_membership_dropdown.placeholder").each(function() { + var personId = $(this).data("personId"); + var view = new app.views.AspectMembership({person: app.contacts.findWhere({"person_id": personId}).person}); + $(this).html(view.render().$el); + }); + }, + + renderPage: function(pageConstructor) { + // old page might mutate global events $(document).keypress, so unbind before creating + app.page && app.page.unbind && app.page.unbind(); + // create new page after the world is clean (like that will ever happen) + app.page = pageConstructor(); + app.page.render(); + + if (!$.contains(document, app.page.el)) { + // view element isn"t already attached to the DOM, insert it + $("#container").empty().append(app.page.el); + } } }); // @license-end diff --git a/app/assets/javascripts/app/views.js b/app/assets/javascripts/app/views.js index 1d787462aab82e0fda9bfbcefa2795d4964e8761..ebd8901a94c96f19815940a08590bfeddb9b794d 100644 --- a/app/assets/javascripts/app/views.js +++ b/app/assets/javascripts/app/views.js @@ -61,16 +61,20 @@ app.views.Base = Backbone.View.extend({ // add placeholder support for old browsers this.$("input, textarea").placeholder(); + // init autosize plugin + autosize(this.$("textarea")); + this.postRenderTemplate(); }, - postRenderTemplate : $.noop, //hella callbax yo + postRenderTemplate: $.noop, //hella callbax yo renderSubviews : function(){ var self = this; _.each(this.subviews, function(property, selector){ var view = _.isFunction(self[property]) ? self[property]() : self[property]; - if(view) { + if (view && self.$(selector).length > 0) { + self.$(selector).empty(); self.$(selector).html(view.render().el); view.delegateEvents(); } @@ -116,38 +120,30 @@ app.views.Base = Backbone.View.extend({ var report = new app.models.Report(); report.save(data, { success: function() { - Diaspora.page.flashMessages.render({ - success: true, - notice: Diaspora.I18n.t('report.status.created') - }); + app.flashMessages.success(Diaspora.I18n.t("report.status.created")); }, error: function() { - Diaspora.page.flashMessages.render({ - success: false, - notice: Diaspora.I18n.t('report.status.exists') - }); + app.flashMessages.error(Diaspora.I18n.t("report.status.exists")); } }); }, + destroyConfirmMsg: function() { return Diaspora.I18n.t("confirm_dialog"); }, + destroyModel: function(evt) { evt && evt.preventDefault(); var self = this; - var url = this.model.urlRoot + '/' + this.model.id; + var url = this.model.urlRoot + "/" + this.model.id; - if (confirm(Diaspora.I18n.t("confirm_dialog"))) { - this.$el.addClass('deleting'); + if( confirm(_.result(this, "destroyConfirmMsg")) ) { + this.$el.addClass("deleting"); this.model.destroy({ url: url }) .done(function() { self.remove(); }) .fail(function() { - self.$el.removeClass('deleting'); - var flash = new Diaspora.Widgets.FlashMessages(); - flash.render({ - success: false, - notice: Diaspora.I18n.t('failed_to_remove') - }); + self.$el.removeClass("deleting"); + app.flashMessages.error(Diaspora.I18n.t("failed_to_remove")); }); } }, @@ -161,7 +157,6 @@ app.views.Base = Backbone.View.extend({ }); app.views.StaticContentView = app.views.Base.extend({ - initialize : function(options) { this.templateName = options.templateName; this.data = options.data; diff --git a/app/assets/javascripts/app/views/aspect_create_view.js b/app/assets/javascripts/app/views/aspect_create_view.js index 4ef77c808237b168ead751b74dfe93e006068126..8c7d030f9710b5e51add1049c3eb76d743aaf94a 100644 --- a/app/assets/javascripts/app/views/aspect_create_view.js +++ b/app/assets/javascripts/app/views/aspect_create_view.js @@ -4,24 +4,23 @@ app.views.AspectCreate = app.views.Base.extend({ templateName: "aspect_create_modal", events: { - "click .btn.creation": "createAspect" + "click .btn.btn-primary": "createAspect", + "keypress input#aspect_name": "inputKeypress" }, initialize: function(opts) { - this._personId = _.has(opts, "personId") ? opts.personId : null; + if (opts && opts.person) { + this.person = opts.person; + this._personId = opts.person.id; + } }, presenter: function() { return _.extend(this.defaultPresenter(), { - addPersonId: this._personId !== null, personId : this._personId }); }, - postRenderTemplate: function() { - this.modal = this.$(".modal"); - }, - _contactsVisible: function() { return this.$("#aspect_contacts_visible").is(":checked"); }, @@ -30,34 +29,59 @@ app.views.AspectCreate = app.views.Base.extend({ return this.$("#aspect_name").val(); }, + inputKeypress: function(evt) { + if(evt.which === Keycodes.ENTER) { + evt.preventDefault(); + this.createAspect(); + } + }, + + postRenderTemplate: function() { + this.$(".modal").on("hidden.bs.modal", null, this, function(e) { + e.data.ensureEventsOrder(); + }); + }, + createAspect: function() { - var aspect = new app.models.Aspect({ - "person_id": this._personId, - "name": this._name(), - "contacts_visible": this._contactsVisible() + this._eventsCounter = 0; + + this.$(".modal").modal("hide"); + + this.listenToOnce(app.aspects, "sync", function(response) { + var aspectName = response.get("name"), + membership = response.get("aspect_membership"); + + this._newAspectId = response.get("id"); + + if (membership) { + if (!this.person.contact) { + this.person.contact = new app.models.Contact(); + } + this.person.contact.aspectMemberships.add([membership]); + } + + this.ensureEventsOrder(); + app.flashMessages.success(Diaspora.I18n.t("aspects.create.success", {"name": aspectName})); }); - var self = this; - aspect.on("sync", function(response) { - var aspectId = response.get("id"), - aspectName = response.get("name"); - - self.modal.modal("hide"); - app.events.trigger("aspect:create", aspectId); - Diaspora.page.flashMessages.render({ - "success": true, - "notice": Diaspora.I18n.t("aspects.create.success", {"name": aspectName}) - }); + this.listenToOnce(app.aspects, "error", function() { + app.flashMessages.error(Diaspora.I18n.t("aspects.create.failure")); + this.stopListening(app.aspects, "sync"); }); - aspect.on("error", function() { - self.modal.modal("hide"); - Diaspora.page.flashMessages.render({ - "success": false, - "notice": Diaspora.I18n.t("aspects.create.failure") - }); + app.aspects.create({ + "person_id": this._personId || null, + "name": this._name(), + "contacts_visible": this._contactsVisible() }); - return aspect.save(); + }, + + // ensure that we trigger the aspect:create event only after both hidden.bs.modal and and aspects sync happens + ensureEventsOrder: function() { + this._eventsCounter++; + if (this._eventsCounter > 1) { + app.events.trigger("aspect:create", this._newAspectId); + } } }); // @license-end diff --git a/app/assets/javascripts/app/views/aspect_membership_view.js b/app/assets/javascripts/app/views/aspect_membership_view.js index 4d8d5236733727516c17c927a6d6fe700af70c56..30529837e381f2999f9819eb11c7b69907e62e63 100644 --- a/app/assets/javascripts/app/views/aspect_membership_view.js +++ b/app/assets/javascripts/app/views/aspect_membership_view.js @@ -1,7 +1,5 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later -//= require ./aspects_dropdown_view - /** * this view lets the user (de-)select aspect memberships in the context * of another users profile or the contact page. @@ -9,90 +7,120 @@ * updates to the list of aspects are immediately propagated to the server, and * the results are dislpayed as flash messages. */ -app.views.AspectMembership = app.views.AspectsDropdown.extend({ +app.views.AspectMembership = app.views.Base.extend({ + templateName: "aspect_membership_dropdown", + className: "btn-group aspect_dropdown aspect_membership_dropdown", + + subviews: { + ".newAspectContainer": "aspectCreateView" + }, events: { - "click ul.aspect_membership.dropdown-menu > li.aspect_selector": "_clickHandler", - "keypress ul.aspect_membership.dropdown-menu > li.aspect_selector": "_clickHandler", - "click ul.aspect_membership.dropdown-menu > li.newItem": "showModal" + "click ul.aspect_membership.dropdown-menu > li.aspect_selector" + : "_clickHandler", + "keypress ul.aspect_membership.dropdown-menu > li.aspect_selector" + : "_clickHandler" }, - initialize: function() { + initialize: function(opts) { + _.extend(this, opts); this.list_item = null; this.dropdown = null; - if (this.$(".newAspectContainer").length > 0) { - this.aspectCreateView = new app.views.AspectCreate({ - el: this.$(".newAspectContainer"), - personId: this.$("ul.dropdown-menu").data("person_id") - }); - this.aspectCreateView.render(); - } + }, + + presenter: function() { + var aspectMembershipsLength = this.person.contact ? this.person.contact.aspectMemberships.length : 0; + + return _.extend(this.defaultPresenter(), { + aspects: this.aspectsPresenter(), + dropdownMayCreateNewAspect: this.dropdownMayCreateNewAspect + }, aspectMembershipsLength === 0 ? { + extraButtonClass: "btn-default", + noAspectIsSelected: true + } : { // this.contact.aspectMemberships.length > 0 + aspectMembershipsLength: aspectMembershipsLength, + allAspectsAreSelected: aspectMembershipsLength === app.aspects.length, + onlyOneAspectIsSelected: aspectMembershipsLength === 1, + firstMembershipName: this.person.contact.aspectMemberships.at(0).get("aspect").name, + extraButtonClass: "btn-success" + }); + }, + + aspectsPresenter: function() { + return _.map(app.aspects.models, function(aspect) { + return _.extend( + this.person.contact ? + {membership: this.person.contact.aspectMemberships.findByAspectId(aspect.attributes.id)} : {}, + aspect.attributes // id, name + ); + }, this); + }, + + aspectCreateView: function() { + return new app.views.AspectCreate({ + person: this.person + }); }, // decide what to do when clicked // -> addMembership // -> removeMembership _clickHandler: function(evt) { - var promise = null; this.list_item = $(evt.target).closest('li.aspect_selector'); this.dropdown = this.list_item.parent(); this.list_item.addClass('loading'); - if( this.list_item.is('.selected') ) { - var membership_id = this.list_item.data('membership_id'); - promise = this.removeMembership(membership_id); + if (this.list_item.is(".selected")) { + this.removeMembership(this.list_item.data("membership_id")); } else { - var aspect_id = this.list_item.data('aspect_id'); - var person_id = this.dropdown.data('person_id'); - promise = this.addMembership(person_id, aspect_id); + this.addMembership(this.list_item.data("aspect_id")); } - promise && promise.always(function() { - // trigger a global event - app.events.trigger('aspect_membership:update'); - }); - return false; // stop the event }, // return the (short) name of the person associated with the current dropdown _name: function() { - return this.dropdown.data('person-short-name'); + return this.person.name || this.person.get("name"); + }, + + _personId: function() { + return this.person.id; }, // create a membership for the given person in the given aspect - addMembership: function(person_id, aspect_id) { - var aspect_membership = new app.models.AspectMembership({ - 'person_id': person_id, - 'aspect_id': aspect_id - }); + addMembership: function(aspectId) { + if (!this.person.contact) { + this.person.contact = new app.models.Contact(); + } - aspect_membership.on('sync', this._successSaveCb, this); - aspect_membership.on('error', function() { + this.listenToOnce(this.person.contact.aspectMemberships, "sync", this._successSaveCb); + this.listenToOnce(this.person.contact.aspectMemberships, "error", function() { this._displayError('aspect_dropdown.error'); - }, this); + }); - return aspect_membership.save(); + return this.person.contact.aspectMemberships.create({"aspect_id": aspectId, "person_id": this._personId()}); }, - _successSaveCb: function(aspect_membership) { - var aspect_id = aspect_membership.get('aspect_id'); - var membership_id = aspect_membership.get('id'); - var li = this.dropdown.find('li[data-aspect_id="'+aspect_id+'"]'); + _successSaveCb: function(aspectMembership) { + var aspectId = aspectMembership.get("aspect_id"), + startSharing = false; // the user didn't have this person in any aspects before, congratulate them // on their newly found friendship ;) - if( this.dropdown.find('li.selected').length === 0 ) { - var msg = Diaspora.I18n.t('aspect_dropdown.started_sharing_with', { 'name': this._name() }); - Diaspora.page.flashMessages.render({ 'success':true, 'notice':msg }); + if( this.dropdown.find("li.selected").length === 0 ) { + var msg = Diaspora.I18n.t("aspect_dropdown.started_sharing_with", { "name": this._name() }); + startSharing = true; + app.flashMessages.success(msg); } - li.attr('data-membership_id', membership_id) // just to be sure... - .data('membership_id', membership_id); - - this.updateSummary(li); - this._done(); + app.events.trigger("aspect_membership:create", { + membership: {aspectId: aspectId, personId: this._personId()}, + startSharing: startSharing + }); + this.render(); + app.events.trigger("aspect_membership:update"); }, // show an error flash msg @@ -101,39 +129,39 @@ app.views.AspectMembership = app.views.AspectsDropdown.extend({ this.dropdown.closest('.aspect_membership_dropdown').removeClass('open'); // close the dropdown var msg = Diaspora.I18n.t(msg_id, { 'name': this._name() }); - Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg }); + app.flashMessages.error(msg); }, // remove the membership with the given id - removeMembership: function(membership_id) { - var aspect_membership = new app.models.AspectMembership({ - 'id': membership_id + removeMembership: function(membershipId) { + var membership = this.person.contact.aspectMemberships.get(membershipId); + this.listenToOnce(membership, "sync", this._successDestroyCb); + this.listenToOnce(membership, "error", function() { + this._displayError("aspect_dropdown.error_remove"); }); - aspect_membership.on('sync', this._successDestroyCb, this); - aspect_membership.on('error', function() { - this._displayError('aspect_dropdown.error_remove'); - }, this); - - return aspect_membership.destroy(); + return membership.destroy(); }, - _successDestroyCb: function(aspect_membership) { - var membership_id = aspect_membership.get('id'); - var li = this.dropdown.find('li[data-membership_id="'+membership_id+'"]'); - - li.removeAttr('data-membership_id') - .removeData('membership_id'); - this.updateSummary(li); + _successDestroyCb: function(aspectMembership) { + var membershipId = aspectMembership.get("id"), + aspectId = aspectMembership.get("aspect").id, + stopSharing = false; + this.render(); // we just removed the last aspect, inform the user with a flash message // that he is no longer sharing with that person - if( this.dropdown.find('li.selected').length === 0 ) { - var msg = Diaspora.I18n.t('aspect_dropdown.stopped_sharing_with', { 'name': this._name() }); - Diaspora.page.flashMessages.render({ 'success':true, 'notice':msg }); + if (this.$el.find("li.selected").length === 0) { + var msg = Diaspora.I18n.t("aspect_dropdown.stopped_sharing_with", { "name": this._name() }); + stopSharing = true; + app.flashMessages.success(msg); } - this._done(); + app.events.trigger("aspect_membership:destroy", { + membership: {aspectId: aspectId, personId: this._personId()}, + stopSharing: stopSharing + }); + app.events.trigger("aspect_membership:update"); }, // cleanup tasks after aspect selection @@ -142,15 +170,5 @@ app.views.AspectMembership = app.views.AspectsDropdown.extend({ this.list_item.removeClass('loading'); } }, - - // refresh the button text to reflect the current aspect selection status - updateSummary: function(target) { - this._toggleCheckbox(target); - this._updateButton('green'); - }, - - showModal: function() { - this.$("#newAspectModal").modal("show"); - } }); // @license-end diff --git a/app/assets/javascripts/app/views/aspect_view.js b/app/assets/javascripts/app/views/aspect_view.js index 66cc4a945ff57940c82c40195f01d0e77bb9a2d3..69367a6eb4ec2b9aff7b8410f6fd7c3f075be701 100644 --- a/app/assets/javascripts/app/views/aspect_view.js +++ b/app/assets/javascripts/app/views/aspect_view.js @@ -8,7 +8,7 @@ app.views.Aspect = app.views.Base.extend({ className: 'hoverable', events: { - 'click .entypo.check+a': 'toggleAspect' + "click .aspect-item": "toggleAspect" }, toggleAspect: function(evt) { diff --git a/app/assets/javascripts/app/views/aspects_dropdown_view.js b/app/assets/javascripts/app/views/aspects_dropdown_view.js index 70e446704c838a216e50db5709f1da731dc6c29d..ae9d7d897b3809f9906b55f36883ff9d50ae4347 100644 --- a/app/assets/javascripts/app/views/aspects_dropdown_view.js +++ b/app/assets/javascripts/app/views/aspects_dropdown_view.js @@ -1,6 +1,6 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later -/* +/* * Aspects view for the publishers aspect dropdown and the aspect membership dropdown. */ app.views.AspectsDropdown = app.views.Base.extend({ @@ -31,7 +31,7 @@ app.views.AspectsDropdown = app.views.Base.extend({ var button = this.$('.btn.dropdown-toggle'), selectedAspects = this.$(".dropdown-menu > li.selected").length, buttonText; - + if (selectedAspects === 0) { button.removeClass(inAspectClass).addClass('btn-default'); buttonText = Diaspora.I18n.t("aspect_dropdown.select_aspects"); diff --git a/app/assets/javascripts/app/views/aspects_list_view.js b/app/assets/javascripts/app/views/aspects_list_view.js index c0e5646f7233c72dcd99a1dae6fda7539f217066..488863d88f779aff6b0c5f059820d55389bd3da3 100644 --- a/app/assets/javascripts/app/views/aspects_list_view.js +++ b/app/assets/javascripts/app/views/aspects_list_view.js @@ -15,7 +15,6 @@ app.views.AspectsList = app.views.Base.extend({ initialize: function() { this.collection.on("change", this.toggleSelector, this); - this.collection.on("change", this.updateStreamTitle, this); this.collection.on("aspectStreamFetched", this.updateAspectList, this); app.events.on("aspect:create", function(id) { window.location = "/contacts?a_id=" + id }); }, @@ -26,12 +25,11 @@ app.views.AspectsList = app.views.Base.extend({ postRenderTemplate: function() { this.collection.each(this.appendAspect, this); - this.updateStreamTitle(); this.toggleSelector(); }, appendAspect: function(aspect) { - $("#aspects_list > *:last").before(new app.views.Aspect({ + $("#aspects_list > .hoverable:last").before(new app.views.Aspect({ model: aspect, attributes: {'data-aspect_id': aspect.get('id')} }).render().el); }, @@ -58,17 +56,13 @@ app.views.AspectsList = app.views.Base.extend({ } }, - updateStreamTitle: function() { - $('.stream_title').text(this.collection.toSentence()); - }, - updateAspectList: function() { this.collection.each(function(aspect) { - var element = this.$("li[data-aspect_id="+aspect.get('id')+"]"); - if (aspect.get('selected')) { - element.find('.entypo.check').addClass('selected'); + var element = this.$("li[data-aspect_id="+aspect.get("id")+"]"); + if (aspect.get("selected")) { + element.find(".entypo-check").addClass("selected"); } else { - element.find('.entypo.check').removeClass('selected'); + element.find(".entypo-check").removeClass("selected"); } }); }, diff --git a/app/assets/javascripts/app/views/bookmarklet_view.js b/app/assets/javascripts/app/views/bookmarklet_view.js index c8e982fc30cd01f9d3f474ec2c6479505698cfa4..c85ffdf7c2ad5671849cba616864635cf86c09d8 100644 --- a/app/assets/javascripts/app/views/bookmarklet_view.js +++ b/app/assets/javascripts/app/views/bookmarklet_view.js @@ -1,15 +1,15 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.Bookmarklet = Backbone.View.extend({ - separator: ' - ', + separator: "\n\n", initialize: function(opts) { // init a standalone publisher app.publisher = new app.views.Publisher({standalone: true}); - app.publisher.on('publisher:add', this._postSubmit, this); - app.publisher.on('publisher:sync', this._postSuccess, this); - app.publisher.on('publisher:error', this._postError, this); + app.publisher.on("publisher:add", this._postSubmit, this); + app.publisher.on("publisher:sync", this._postSuccess, this); + app.publisher.on("publisher:error", this._postError, this); this.param_contents = opts; }, @@ -25,24 +25,28 @@ app.views.Bookmarklet = Backbone.View.extend({ var p = this.param_contents; if( p.content ) return p.content; - var contents = p.title + this.separator + p.url; - if( p.notes ) contents += this.separator + p.notes; + var contents = "### " + p.title + this.separator; + if( p.notes ) { + var notes = p.notes.toString().replace(/(?:\r\n|\r|\n)/g, "\n> "); + contents += "> " + notes + this.separator; + } + contents += p.url; return contents; }, _postSubmit: function() { - this.$('h4').text(Diaspora.I18n.t('bookmarklet.post_submit')); + this.$("h4").text(Diaspora.I18n.t("bookmarklet.post_submit")); }, _postSuccess: function() { - this.$('h4').text(Diaspora.I18n.t('bookmarklet.post_success')); + this.$("h4").text(Diaspora.I18n.t("bookmarklet.post_success")); app.publisher.close(); this.$("#publisher").addClass("hidden"); _.delay(window.close, 2000); }, _postError: function() { - this.$('h4').text(Diaspora.I18n.t('bookmarklet.post_something')); + this.$("h4").text(Diaspora.I18n.t("bookmarklet.post_something")); } }); // @license-end diff --git a/app/assets/javascripts/app/views/comment_stream_view.js b/app/assets/javascripts/app/views/comment_stream_view.js index 5810c07cdc9245ce5fafd83f26e43c0e81ba8d3d..6878eec1a84c4d60774f4b03cf20b6d8fe01c024 100644 --- a/app/assets/javascripts/app/views/comment_stream_view.js +++ b/app/assets/javascripts/app/views/comment_stream_view.js @@ -21,16 +21,10 @@ app.views.CommentStream = app.views.Base.extend({ setupBindings: function() { this.model.comments.bind('add', this.appendComment, this); - this.model.bind("commentsExpanded", this.storeTextareaValue, this); - this.model.bind("commentsExpanded", this.render, this); }, postRenderTemplate : function() { this.model.comments.each(this.appendComment, this); - - // add autoexpanders to new comment textarea - this.$("textarea").autoResize({'extraSpace' : 10}); - this.$('textarea').val(this.textareaValue); }, presenter: function(){ @@ -43,7 +37,7 @@ app.views.CommentStream = app.views.Base.extend({ createComment: function(evt) { if(evt){ evt.preventDefault(); } - + var commentText = $.trim(this.$('.comment_box').val()); this.$(".comment_box").val(""); this.$(".comment_box").css("height", ""); @@ -56,40 +50,61 @@ app.views.CommentStream = app.views.Base.extend({ }, keyDownOnCommentBox: function(evt) { - if(evt.keyCode === 13 && evt.ctrlKey) { + if(evt.which === Keycodes.ENTER && evt.ctrlKey) { this.$("form").submit(); return false; } }, - + + _insertPoint: 0, // An index of the comment added in the last call of this.appendComment + + // This adjusts this._insertPoint according to timestamp value + _moveInsertPoint: function(timestamp, commentBlocks) { + if (commentBlocks.length === 0) { + this._insertPoint = 0; + return; + } + + if (this._insertPoint > commentBlocks.length) { + this._insertPoint = commentBlocks.length; + } + + while (this._insertPoint > 0 && timestamp < commentBlocks.eq(this._insertPoint - 1).find("time").attr("datetime")) { + this._insertPoint--; + } + while (this._insertPoint < commentBlocks.length && + timestamp > commentBlocks.eq(this._insertPoint).find("time").attr("datetime")) { + this._insertPoint++; + } + }, + appendComment: function(comment) { // Set the post as the comment's parent, so we can check // on post ownership in the Comment view. comment.set({parent : this.model.toJSON()}); - this.$(".comments").append(new app.views.Comment({ - model: comment - }).render().el); + var commentHtml = new app.views.Comment({model: comment}).render().el; + var commentBlocks = this.$(".comments div.comment.media"); + this._moveInsertPoint(comment.get("created_at"), commentBlocks); + if (this._insertPoint === commentBlocks.length) { + this.$(".comments").append(commentHtml); + } else { + commentBlocks.eq(this._insertPoint).before(commentHtml); + } + this._insertPoint++; }, commentTextareaFocused: function(){ this.$("form").removeClass('hidden').addClass("open"); }, - storeTextareaValue: function(){ - this.textareaValue = this.$('textarea').val(); - }, - expandComments: function(evt){ if(evt){ evt.preventDefault(); } var self = this; this.model.comments.fetch({ success : function(resp){ - self.model.set({ - comments : resp.models, - all_comments_loaded : true - }); + self.$("div.comment.show_comments").addClass("hidden"); self.model.trigger("commentsExpanded", self); } diff --git a/app/assets/javascripts/app/views/contact_stream_view.js b/app/assets/javascripts/app/views/contact_stream_view.js index ad93301bd809be1ff5c92f97dee0d5e0ebd022cf..cbc254c37605b0b255843fee8d7dac7e34e50977 100644 --- a/app/assets/javascripts/app/views/contact_stream_view.js +++ b/app/assets/javascripts/app/views/contact_stream_view.js @@ -1,77 +1,79 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.ContactStream = Backbone.View.extend({ - initialize: function() { - this.itemCount = 0; - this.perPage = 25; - this.query = ''; - this.resultList = this.collection.toArray(); + initialize: function(opts) { + this.page = 1; var throttledScroll = _.throttle(_.bind(this.infScroll, this), 200); $(window).scroll(throttledScroll); - this.on('renderContacts', this.renderContacts, this); + this.on("fetchContacts", this.fetchContacts, this); + this.urlParams = opts.urlParams; }, render: function() { - if( _.isEmpty(this.resultList) ) { - var content = document.createDocumentFragment(); - content = '<div id="no_contacts" class="well">' + - ' <h4>' + - Diaspora.I18n.t('contacts.search_no_results') + - ' </h4>' + - '</div>'; - this.$el.html(content); - } else { - this.$el.html(''); - this.renderContacts(); - } + this.fetchContacts(); }, - renderContacts: function() { + fetchContacts: function() { this.$el.addClass("loading"); - var content = document.createDocumentFragment(); - _.rest(_.first(this.resultList , this.itemCount + this.perPage), this.itemCount).forEach( function(item) { - var view = new app.views.Contact({model: item}); - content.appendChild(view.render().el); + $("#paginate .loader").removeClass("hidden"); + $.ajax(this._fetchUrl(), { + context: this + }).success(function(response) { + if (response.length === 0) { + this.onEmptyResponse(); + } else { + this.appendContactViews(response); + this.page++; + } }); + }, - var size = _.size(this.resultList); - if( this.itemCount + this.perPage >= size ){ - this.itemCount = size; - this.off('renderContacts'); - } else { - this.itemCount += this.perPage; + _fetchUrl: function() { + var url = Routes.contacts({format: "json", page: this.page}); + if (this.urlParams) { + url += "&" + this.urlParams; } - this.$el.append(content); - this.$el.removeClass("loading"); + return url; }, - search: function(query) { - query = query.trim(); - if( query || this.query ) { - this.off('renderContacts'); - this.on('renderContacts', this.renderContacts, this); - this.itemCount = 0; - if( query ) { - this.query = query; - var regex = new RegExp(query,'i'); - this.resultList = this.collection.filter(function(contact) { - return regex.test(contact.get('person').name) || - regex.test(contact.get('person').diaspora_id); - }); - } else { - this.resultList = this.collection.toArray(); - this.query = ''; - } - this.render(); + onEmptyResponse: function() { + if (this.collection.length === 0) { + var content = document.createDocumentFragment(); + content = "<div id='no_contacts' class='well'>" + + " <h4>" + + Diaspora.I18n.t("contacts.search_no_results") + + " </h4>" + + "</div>"; + this.$el.html(content); } + this.off("fetchContacts"); + this.$el.removeClass("loading"); + $("#paginate .loader").addClass("hidden"); + }, + + appendContactViews: function(contacts) { + var content = document.createDocumentFragment(); + contacts.forEach(function(contactData) { + var contact = new app.models.Contact(contactData); + this.collection.add(contact); + var view = new app.views.Contact({model: contact}); + content.appendChild(view.render().el); + }.bind(this)); + this.$el.append(content); + this.$el.removeClass("loading"); + $("#paginate .loader").addClass("hidden"); }, infScroll: function() { - if( this.$el.hasClass('loading') ) return; + if (this.$el.hasClass("loading")) { + return; + } var distanceTop = $(window).height() + $(window).scrollTop(), distanceBottom = $(document).height() - distanceTop; - if(distanceBottom < 300) this.trigger('renderContacts'); + if (distanceBottom < 300) { + this.trigger("fetchContacts"); + } } }); // @license-end diff --git a/app/assets/javascripts/app/views/contact_view.js b/app/assets/javascripts/app/views/contact_view.js index 840edfe46c7b789c60aae1ee4c3f48e3ef579892..1a0a676d60e0f5fc8a9ed5408da1677c57084088 100644 --- a/app/assets/javascripts/app/views/contact_view.js +++ b/app/assets/javascripts/app/views/contact_view.js @@ -3,6 +3,10 @@ app.views.Contact = app.views.Base.extend({ templateName: 'contact', + subviews: { + ".aspect_membership_dropdown": "AspectMembershipView" + }, + events: { "click .contact_add-to-aspect" : "addContactToAspect", "click .contact_remove-from-aspect" : "removeContactFromAspect" @@ -10,6 +14,12 @@ app.views.Contact = app.views.Base.extend({ tooltipSelector: '.contact_add-to-aspect, .contact_remove-from-aspect', + initialize: function() { + this.AspectMembershipView = new app.views.AspectMembership( + {person: _.extend(this.model.get("person"), {contact: this.model})} + ); + }, + presenter: function() { return _.extend(this.defaultPresenter(), { person_id : this.model.get('person_id'), @@ -18,52 +28,51 @@ app.views.Contact = app.views.Base.extend({ }); }, - postRenderTemplate: function() { - var self = this; - var dropdownEl = this.$('.aspect_membership_dropdown.placeholder'); - if( dropdownEl.length === 0 ) { - return; - } - - // TODO render me client side!!! - var href = this.model.person.url() + '/aspect_membership_button?size=small'; - - $.get(href, function(resp) { - dropdownEl.html(resp); - new app.views.AspectMembership({el: $('.aspect_dropdown',dropdownEl)}); - - // UGLY (re-)attach the facebox - self.$('a[rel*=facebox]').facebox(); - }); - }, - addContactToAspect: function(){ var self = this; - this.model.aspect_memberships.create({ - 'person_id': this.model.get('person_id'), - 'aspect_id': app.aspect.get('id') + // do we create the first aspect membership for this person? + var startSharing = this.model.aspectMemberships.length === 0; + this.model.aspectMemberships.create({ + "person_id": this.model.get("person_id"), + "aspect_id": app.aspect.get("id") },{ success: function(){ + app.events.trigger("aspect_membership:create", { + membership: { + aspectId: app.aspect.get("id"), + personId: self.model.get("person_id") + }, + startSharing: startSharing + }); self.render(); }, error: function(){ - var msg = Diaspora.I18n.t('contacts.error_add', { 'name': self.model.get('person').name }); - Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg }); + var msg = Diaspora.I18n.t("contacts.error_add", { "name": self.model.get("person").name }); + app.flashMessages.error(msg); } }); }, removeContactFromAspect: function(){ var self = this; - this.model.aspect_memberships - .find(function(membership){ return membership.get('aspect').id === app.aspect.id; }) + // do we destroy the last aspect membership for this person? + var stopSharing = this.model.aspectMemberships.length <= 1; + this.model.aspectMemberships + .find(function(membership){ return membership.get("aspect").id === app.aspect.id; }) .destroy({ success: function(){ + app.events.trigger("aspect_membership:destroy", { + membership: { + aspectId: app.aspect.get("id"), + personId: self.model.get("person_id") + }, + stopSharing: stopSharing + }); self.render(); }, error: function(){ - var msg = Diaspora.I18n.t('contacts.error_remove', { 'name': self.model.get('person').name }); - Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg }); + var msg = Diaspora.I18n.t("contacts.error_remove", { "name": self.model.get("person").name }); + app.flashMessages.error(msg); } }); } diff --git a/app/assets/javascripts/app/views/content_view.js b/app/assets/javascripts/app/views/content_view.js index e93f6bfa6466dc577ae086536bd5f3a7c8663e44..76fb627395d50c71c844f767da351d836c99a21e 100644 --- a/app/assets/javascripts/app/views/content_view.js +++ b/app/assets/javascripts/app/views/content_view.js @@ -29,7 +29,6 @@ app.views.Content = app.views.Base.extend({ return photos; }, - expandPost: function(evt) { var el = $(this.el).find('.collapsible'); el.removeClass('collapsed').addClass('opened'); @@ -40,8 +39,8 @@ app.views.Content = app.views.Base.extend({ }, location: function(){ - var address = this.model.get('address')? this.model.get('address') : ''; - return address; + var location = this.model.get("location")? this.model.get("location") : ""; + return location; }, collapseOversized : function() { @@ -73,6 +72,25 @@ app.views.Content = app.views.Base.extend({ postRenderTemplate : function(){ _.defer(_.bind(this.collapseOversized, this)); + + // run collapseOversized again after all contained images are loaded + var self = this; + _.defer(function() { + self.$("img").each(function() { + this.addEventListener("load", function() { + // only fire if the top of the post is in viewport + var rect = self.el.getBoundingClientRect(); + if(rect.top > 0) { + self.collapseOversized.call(self); + } + }); + }); + }); + + var photoAttachments = this.$(".photo_attachments"); + if(photoAttachments.length > 0) { + new app.views.Gallery({ el: photoAttachments }); + } } }); @@ -82,6 +100,10 @@ app.views.StatusMessage = app.views.Content.extend({ app.views.ExpandedStatusMessage = app.views.StatusMessage.extend({ postRenderTemplate : function(){ + var photoAttachments = this.$(".photo_attachments"); + if(photoAttachments.length > 0) { + new app.views.Gallery({ el: photoAttachments }); + } } }); @@ -147,4 +169,5 @@ app.views.SPVOpenGraph = app.views.OpenGraph.extend({ // override with nothing } }); + // @license-end diff --git a/app/assets/javascripts/app/views/conversations_form_view.js b/app/assets/javascripts/app/views/conversations_form_view.js index 5289241dc8848fbbbcdc1cf8c96f6da86f6662e3..53dbee68127be007bbf3ac17d489ada0da376c54 100644 --- a/app/assets/javascripts/app/views/conversations_form_view.js +++ b/app/assets/javascripts/app/views/conversations_form_view.js @@ -33,6 +33,7 @@ app.views.ConversationsForm = Backbone.View.extend({ emptyText: Diaspora.I18n.t("no_results"), preFill: this.prefill }).focus(); + $("#contact_ids").attr("aria-labelledby", "toLabel"); }, displayNoContactsMessage: function() { @@ -42,7 +43,7 @@ app.views.ConversationsForm = Backbone.View.extend({ }, keyDown : function(evt) { - if( evt.keyCode === 13 && evt.ctrlKey ) { + if(evt.which === Keycodes.ENTER && evt.ctrlKey) { $(evt.target).parents("form").submit(); } } diff --git a/app/assets/javascripts/app/views/conversations_view.js b/app/assets/javascripts/app/views/conversations_view.js index cd4addf4161c65cf889cd4ed1e4c37b3959b5926..d5ed22a3a32ebb38641ce570d78be2c3defbb8e6 100644 --- a/app/assets/javascripts/app/views/conversations_view.js +++ b/app/assets/javascripts/app/views/conversations_view.js @@ -24,10 +24,10 @@ app.views.Conversations = Backbone.View.extend({ $(".control-icons a").tooltip({placement: "bottom"}); var conv = $(".conversation-wrapper .stream_element.selected"), - cBadge = $("#conversations_badge .badge_count"); + cBadge = $("#conversations-link .badge"); if(conv.hasClass("unread") ){ - var unreadCount = parseInt(conv.find(".unread_message_count").text(), 10); + var unreadCount = parseInt(conv.find(".unread-message-count").text(), 10); if(cBadge.text() !== "") { cBadge.text().replace(/\d+/, function(num){ @@ -40,7 +40,7 @@ app.views.Conversations = Backbone.View.extend({ }); } conv.removeClass("unread"); - conv.find(".unread_message_count").remove(); + conv.find(".unread-message-count").remove(); var pos = $("#first_unread").offset().top - 50; $("html").animate({scrollTop:pos}); @@ -50,7 +50,7 @@ app.views.Conversations = Backbone.View.extend({ }, keyDown : function(evt) { - if( evt.keyCode === 13 && evt.ctrlKey ) { + if(evt.which === Keycodes.ENTER && evt.ctrlKey) { $(evt.target).parents("form").submit(); } } diff --git a/app/assets/javascripts/app/views/feedback_view.js b/app/assets/javascripts/app/views/feedback_view.js index 938469bbb04c98ec893ec49b31b3432f0705e692..70bf4ca6d166191c9e98de3e7b22a02373624ccd 100644 --- a/app/assets/javascripts/app/views/feedback_view.js +++ b/app/assets/javascripts/app/views/feedback_view.js @@ -11,13 +11,13 @@ app.views.Feedback = app.views.Base.extend({ "click .post_report" : "report", "click .block_user" : "blockUser", - "click .hide_post" : "hidePost", + "click .hide_post" : "hidePost" }, tooltipSelector : ".label", initialize : function() { - this.model.interactions.on('change', this.render, this); + this.model.interactions.on("change", this.render, this); this.initViews && this.initViews(); // I don't know why this was failing with $.noop... :( }, @@ -47,7 +47,7 @@ app.views.Feedback = app.views.Base.extend({ blockUser: function(evt) { if(evt) { evt.preventDefault(); } - if(!confirm(Diaspora.I18n.t('ignore_user'))) { return; } + if(!confirm(Diaspora.I18n.t("ignore_user"))) { return; } this.model.blockAuthor() .done(function() { @@ -55,16 +55,13 @@ app.views.Feedback = app.views.Base.extend({ document.location.href = "/stream"; }) .fail(function() { - Diaspora.page.flashMessages.render({ - success: false, - notice: Diaspora.I18n.t('hide_post_failed') - }); + app.flashMessages.error(Diaspora.I18n.t("hide_post_failed")); }); }, hidePost : function(evt) { if(evt) { evt.preventDefault(); } - if(!confirm(Diaspora.I18n.t('hide_post'))) { return; } + if(!confirm(Diaspora.I18n.t("hide_post"))) { return; } $.ajax({ url : "/share_visibilities/42", @@ -77,11 +74,8 @@ app.views.Feedback = app.views.Base.extend({ document.location.href = "/stream"; }) .fail(function() { - Diaspora.page.flashMessages.render({ - success: false, - notice: Diaspora.I18n.t('ignore_post_failed') - }); + app.flashMessages.error(Diaspora.I18n.t("ignore_post_failed")); }); - }, + } }); // @license-end diff --git a/app/assets/javascripts/app/views/flash_messages_view.js b/app/assets/javascripts/app/views/flash_messages_view.js new file mode 100644 index 0000000000000000000000000000000000000000..cb5b214b23637c19620252568bcd78fe970d6936 --- /dev/null +++ b/app/assets/javascripts/app/views/flash_messages_view.js @@ -0,0 +1,20 @@ +app.views.FlashMessages = app.views.Base.extend({ + templateName: "flash_messages", + + _flash: function(message, error){ + this.presenter = { + message: message, + alertLevel: error ? "alert-danger" : "alert-success" + }; + + this.renderTemplate(); + }, + + success: function(message){ + this._flash(message, false); + }, + + error: function(message){ + this._flash(message, true); + } +}); diff --git a/app/assets/javascripts/app/views/gallery_view.js b/app/assets/javascripts/app/views/gallery_view.js new file mode 100644 index 0000000000000000000000000000000000000000..6af5774190842026782a5931762ec03c7ad28173 --- /dev/null +++ b/app/assets/javascripts/app/views/gallery_view.js @@ -0,0 +1,42 @@ +app.views.Gallery = app.views.Base.extend({ + events: { + "click a.gallery-picture": "showGallery" + }, + + pictures: function(){ + return this.$el.find("a.gallery-picture"); + }, + + showGallery: function(event){ + event = event || window.event; + var target = event.target || event.srcElement; + var link = target.src ? target.parentNode : target; + var links = this.pictures(); + blueimp.Gallery(links, this.options(event, link)); + }, + + preventHideControls: function(){ + var lightbox = $("#blueimp-gallery"); + var onEvent = function(ev){ + if($(ev.target).hasClass("slide-content")){ + ev.preventDefault(); + ev.stopPropagation(); + } + }; + + lightbox.find(".slide").click(onEvent); + }, + + options: function(event, link) { + return { + index: link, + event: event, + hidePageScrollbars: false, + disableScroll: true, + continuous: true, + toggleControlsOnReturn: false, + onopened: this.preventHideControls, + slideshowInterval: 2000 + }; + } +}); diff --git a/app/assets/javascripts/app/views/header_view.js b/app/assets/javascripts/app/views/header_view.js index 814ef3a879b551a8babbd98e9705be05d0d23530..5b682c3b347289caaea546f5fcb0d953a55a5817 100644 --- a/app/assets/javascripts/app/views/header_view.js +++ b/app/assets/javascripts/app/views/header_view.js @@ -6,48 +6,18 @@ app.views.Header = app.views.Base.extend({ className: "dark-header", - events: { - "click ul.dropdown li:first-child": "toggleUserDropdown", - "focusin #q": "toggleSearchActive", - "focusout #q": "toggleSearchActive" - }, - - initialize: function(){ - $(document.body).click($.proxy(this.hideUserDropdown, this)); - - return this; + presenter: function() { + return _.extend({}, this.defaultPresenter(), { + podname: gon.appConfig.settings.podname + }); }, postRenderTemplate: function(){ - new app.views.Notifications({ el: '#notification_dropdown' }); - new app.views.NotificationDropdown({ el: '#notification_badge' }); - new app.views.Search({ el: '#header-search-form' }); + new app.views.Notifications({ el: "#notification-dropdown" }); + this.notificationDropdown = new app.views.NotificationDropdown({ el: "#notification-dropdown" }); + new app.views.Search({ el: "#header-search-form" }); }, menuElement: function(){ return this.$("ul.dropdown"); }, - - toggleUserDropdown: function(evt){ - if(evt){ evt.preventDefault(); } - - this.menuElement().toggleClass("active"); - - if($.browser.msie){ - this.$("header").toggleClass('ie-user-menu-active'); - } - }, - - hideUserDropdown: function(evt){ - if(this.menuElement().hasClass("active") && !$(evt.target).parents("#user_menu").length){ - this.menuElement().removeClass("active"); - } - }, - - toggleSearchActive: function(ev){ - // jQuery produces two events for focus/blur (for bubbling) - // don't rely on which event arrives first, by allowing for both variants - var is_active = (_.indexOf(['focus','focusin'], ev.type) !== -1); - $(ev.target).toggleClass('active', is_active); - return false; - } }); // @license-end diff --git a/app/assets/javascripts/app/views/help_view.js b/app/assets/javascripts/app/views/help_view.js index f1ec4618f7a437ba0b17b202fc31860bfd939110..48731e55c201b25d9a9f76292e5b06557ee95032 100644 --- a/app/assets/javascripts/app/views/help_view.js +++ b/app/assets/javascripts/app/views/help_view.js @@ -210,15 +210,15 @@ app.views.Help = app.views.StaticContentView.extend({ }, chatEnabled: function(){ - return gon.chatEnabled; + return gon.appConfig.chat.enabled; }, getChatIcons: function(){ - return '<div class="help-chat-icons">' + - ' <i class="entypo lock-open"></i>' + - ' <i class="entypo chat"></i>' + - ' <i class="entypo trash"></i>' + - '</div>'; + return "<div class=\"help-chat-icons\">" + + " <i class=\"entypo-lock-open\"></i>" + + " <i class=\"entypo-chat\"></i>" + + " <i class=\"entypo-trash\"></i>" + + "</div>"; } }); // @license-end diff --git a/app/assets/javascripts/app/views/hovercard_view.js b/app/assets/javascripts/app/views/hovercard_view.js index 2389521548763a7f4ee238df3a8edfeb3002c7e9..93f9ffa6232a750b7bc421c8e9aab1cc585a0abe 100644 --- a/app/assets/javascripts/app/views/hovercard_view.js +++ b/app/assets/javascripts/app/views/hovercard_view.js @@ -4,13 +4,15 @@ app.views.Hovercard = app.views.Base.extend({ templateName: 'hovercard', id: 'hovercard_container', + subviews: { + "#hovercard_dropdown_container": "aspectMembershipDropdown" + }, + events: { 'mouseleave': '_mouseleaveHandler' }, initialize: function() { - this.render(); - $(document) .on('mouseenter', '.hovercardable', _.bind(this._mouseenterHandler, this)) .on('mouseleave', '.hovercardable', _.bind(this._mouseleaveHandler, this)); @@ -18,18 +20,18 @@ app.views.Hovercard = app.views.Base.extend({ this.showMe = false; this.parent = null; // current 'hovercardable' element that caused HC to appear - // cache some element references - this.avatar = this.$('.avatar'); - this.avatarLink = this.$("a.person_avatar"); - this.dropdown_container = this.$('#hovercard_dropdown_container'); - this.hashtags = this.$('.hashtags'); - this.person_link = this.$('a.person'); - this.person_handle = this.$('div.handle'); this.active = true; }, postRenderTemplate: function() { - this.$el.appendTo($('body')); + this.$el.appendTo($("body")); + + // cache some element references + this.avatar = this.$(".avatar"); + this.avatarLink = this.$("a.person_avatar"); + this.hashtags = this.$(".hashtags"); + this.personLink = this.$("a.person"); + this.personID = this.$("div.handle"); }, deactivate: function() { @@ -73,7 +75,6 @@ app.views.Hovercard = app.views.Base.extend({ this.$el.hide(); } - this.dropdown_container.unbind().empty(); return false; }, @@ -102,6 +103,12 @@ app.views.Hovercard = app.views.Base.extend({ throw new Error("received data is not a person object"); } + if (app.currentUser.authenticated()) { + self.aspectMembershipDropdown = new app.views.AspectMembership({person: new app.models.Person(person)}); + } + + self.render(); + self._populateHovercardWith(person); if( !self.showMe ) { // mouse has left element @@ -112,29 +119,20 @@ app.views.Hovercard = app.views.Base.extend({ }, _populateHovercardWith: function(person) { - var self = this; - - this.avatar.attr('src', person.avatar); - this.avatarLink.attr("href", person.url); - this.person_link.attr('href', person.url); - this.person_link.text(person.name); - this.person_handle.text(person.handle); - - // set hashtags - this.hashtags.empty(); - this.hashtags.html( $(_.map(person.tags, function(tag){ - return $('<a/>',{href: "/tags/"+tag.substring(1)}).text(tag)[0] ; - })) ); - - if(!app.currentUser.authenticated()){ return; } - // set aspect dropdown - // TODO render me client side!!! - var href = this.href(); - href += "/aspect_membership_button"; - $.ajax(href, {preventGlobalErrorHandling: true}).done(function(response){ - self.dropdown_container.html(response); - }); - new app.views.AspectMembership({el: self.dropdown_container}); + this.avatarLink.attr("href", this.href()); + this.personLink.attr("href", this.href()); + this.personLink.text(person.name); + this.personID.text(person.diaspora_id); + + if (person.profile) { + this.avatar.attr("src", person.profile.avatar); + + // set hashtags + this.hashtags.empty(); + this.hashtags.html($(_.map(person.profile.tags, function(tag) { + return $("<a/>", {href: "/tags/" + tag.substring(1)}).text(tag)[0]; + }))); + } }, _positionHovercard: function() { diff --git a/app/assets/javascripts/app/views/infinite_stream_view.js b/app/assets/javascripts/app/views/infinite_stream_view.js index 1716eefb76cf1f694485c1dd5e670bf4d0deaafa..d5783d5595c4b64d70089c686e815de6fd415796 100644 --- a/app/assets/javascripts/app/views/infinite_stream_view.js +++ b/app/assets/javascripts/app/views/infinite_stream_view.js @@ -16,6 +16,7 @@ app.views.InfScroll = app.views.Base.extend({ this.showLoader(); this.bind("loadMore", this.fetchAndshowLoader, this); this.stream.bind("fetched", this.finishedLoading, this); + this.stream.bind("allItemsLoaded", this.showNoPostsInfo, this); this.stream.bind("allItemsLoaded", this.unbindInfScroll, this); this.collection.bind("add", this.addPostView, this); @@ -29,10 +30,6 @@ app.views.InfScroll = app.views.Base.extend({ this.prependedPosts = document.createDocumentFragment(); }, - postRenderTemplate : function() { - if(this.stream.isFetching()) { this.showLoader() } - }, - createPostView : function(post){ var postView = new this.postClass({ model: post, stream: this.stream }); if (this.collection.at(0).id === post.id) { @@ -54,6 +51,13 @@ app.views.InfScroll = app.views.Base.extend({ } }, + showNoPostsInfo: function() { + if (this.postViews.length === 0) { + var noPostsInfo = new app.views.NoPostsInfo(); + this.$el.append(noPostsInfo.render().el); + } + }, + unbindInfScroll : function() { $(window).unbind("scroll"); }, @@ -86,6 +90,7 @@ app.views.InfScroll = app.views.Base.extend({ this.$el.prepend(this.prependedPosts); this.$el.append(this.appendedPosts); this._resetPostFragments(); + this.postRenderTemplate(); }, finishedLoading: function() { diff --git a/app/assets/javascripts/app/views/likes_info_view.js b/app/assets/javascripts/app/views/likes_info_view.js index a672645dda6c2bfdb9825eb75698652b9abfc462..9300ac9adbebed566a4aefec7e819e9d00032559 100644 --- a/app/assets/javascripts/app/views/likes_info_view.js +++ b/app/assets/javascripts/app/views/likes_info_view.js @@ -5,26 +5,32 @@ app.views.LikesInfo = app.views.Base.extend({ templateName : "likes-info", events : { - "click .expand_likes" : "showAvatars" + "click .expand-likes" : "showAvatars" }, tooltipSelector : ".avatar", initialize : function() { this.model.interactions.bind('change', this.render, this); + this.displayAvatars = false; }, presenter : function() { return _.extend(this.defaultPresenter(), { likes : this.model.interactions.likes.toJSON(), likesCount : this.model.interactions.likesCount(), - likes_fetched : this.model.interactions.get("fetched"), + displayAvatars : this.model.interactions.get("fetched") && this.displayAvatars }); }, showAvatars : function(evt){ if(evt) { evt.preventDefault() } - this.model.interactions.fetch(); + this.displayAvatars = true; + if(!this.model.interactions.get("fetched")){ + this.model.interactions.fetch(); + } else { + this.model.interactions.trigger("change"); + } } }); // @license-end diff --git a/app/assets/javascripts/app/views/location_stream.js b/app/assets/javascripts/app/views/location_stream.js index fd6fae94646fcae4d828252d07a72ac0d736d40b..925ee1f2f0be3155195313057ffd5af5f9c1fb9e 100644 --- a/app/assets/javascripts/app/views/location_stream.js +++ b/app/assets/javascripts/app/views/location_stream.js @@ -1,7 +1,31 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.LocationStream = app.views.Content.extend({ - templateName: "status-message-location" + events: { + "click .near-from": "toggleMap" + }, + templateName: "status-message-location", + + toggleMap: function () { + var mapContainer = this.$el.find(".mapContainer"); + + if (mapContainer.hasClass("empty")) { + var location = this.model.get("location"); + mapContainer.css("height", "150px"); + + if (location.lat) { + var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); + var tiles = app.helpers.locations.getTiles(); + + tiles.addTo(map); + + L.marker(location).addTo(map); + mapContainer.removeClass("empty"); + return map; + } + } else { + mapContainer.toggle(); + } + } }); // @license-end - diff --git a/app/assets/javascripts/app/views/location_view.js b/app/assets/javascripts/app/views/location_view.js deleted file mode 100644 index 0fe6be15d7992ad42896a35b3ac6af5112f18068..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/app/views/location_view.js +++ /dev/null @@ -1,27 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later - -app.views.Location = Backbone.View.extend({ - - el: "#location", - - initialize: function(){ - this.render(); - this.getLocation(); - }, - - render: function(){ - $(this.el).append('<img alt="ajax-loader" src="'+ImagePaths.get('ajax-loader.gif')+'">'); - }, - - getLocation: function(){ - var element = this.el; - - var locator = new OSM.Locator(); - locator.getAddress(function(address, latlng){ - $(element).html('<input id="location_address" type="text" class="input-block-level" value="' + address + '"/>'); - $('#location_coords').val(latlng.latitude + "," + latlng.longitude); - }); - }, -}); -// @license-end - diff --git a/app/assets/javascripts/app/views/locator.js b/app/assets/javascripts/app/views/locator.js new file mode 100644 index 0000000000000000000000000000000000000000..364f3fa395a9320525a0d693d589c60cba847a80 --- /dev/null +++ b/app/assets/javascripts/app/views/locator.js @@ -0,0 +1,33 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later + +app.views.Location = Backbone.View.extend({ + + el: "#location", + + initialize: function(){ + this.render(); + this.getLocation(); + }, + + render: function() { + $("<div class=\"loader\"><div class=\"spinner\"></div></div>").appendTo(this.el); + }, + + getLocation: function(){ + var element = this.el ; + + var locator = new OSM.Locator(); + locator.getAddress(function(address, latlng){ + $(element).empty(); + $("<input/>", + { id: "location_address", + value: address, + type: "text", + class: "input-block-level form-control" + }).appendTo($(element)); + + $("#location_coords").val(latlng.latitude + "," + latlng.longitude); + }); + } +}); +// @license-end diff --git a/app/assets/javascripts/app/views/no_posts_info_view.js b/app/assets/javascripts/app/views/no_posts_info_view.js new file mode 100644 index 0000000000000000000000000000000000000000..57894b9f04b9dc2529bfb52958a03fbb63e68b4c --- /dev/null +++ b/app/assets/javascripts/app/views/no_posts_info_view.js @@ -0,0 +1,3 @@ +app.views.NoPostsInfo = app.views.Base.extend({ + templateName: "no_posts_info" +}); diff --git a/app/assets/javascripts/app/views/notification_dropdown_view.js b/app/assets/javascripts/app/views/notification_dropdown_view.js index 117c29d84d516e58099838cf75023ecf6fbcb2b3..3fec6a793a4f885a667aac6ecc0208e74e208067 100644 --- a/app/assets/javascripts/app/views/notification_dropdown_view.js +++ b/app/assets/javascripts/app/views/notification_dropdown_view.js @@ -1,8 +1,8 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.NotificationDropdown = app.views.Base.extend({ - events:{ - "click #notifications-badge": "toggleDropdown" + events: { + "click #notifications-link": "toggleDropdown" }, initialize: function(){ @@ -12,49 +12,46 @@ app.views.NotificationDropdown = app.views.Base.extend({ this.perPage = 5; this.hasMoreNotifs = true; this.badge = this.$el; - this.dropdown = $('#notification_dropdown'); - this.dropdownNotifications = this.dropdown.find('.notifications'); - this.ajaxLoader = this.dropdown.find('.ajax_loader'); + this.dropdown = $("#notification-dropdown"); + this.dropdownNotifications = this.dropdown.find(".notifications"); + this.ajaxLoader = this.dropdown.find(".ajax-loader"); this.perfectScrollbarInitialized = false; }, toggleDropdown: function(evt){ - evt.preventDefault(); evt.stopPropagation(); + if (!$("#notifications-link .entypo-bell:visible").length) { return true; } + evt.preventDefault(); if(this.dropdownShowing()){ this.hideDropdown(evt); } else{ this.showDropdown(); } }, dropdownShowing: function(){ - return this.dropdown.css('display') === 'block'; + return this.dropdown.hasClass("dropdown-open"); }, showDropdown: function(){ this.resetParams(); this.ajaxLoader.show(); - this.badge.addClass('active'); - this.dropdown.css('display', 'block'); - this.dropdownNotifications.addClass('loading'); + this.dropdown.addClass("dropdown-open"); + this.updateScrollbar(); + this.dropdownNotifications.addClass("loading"); this.getNotifications(); }, hideDropdown: function(evt){ - var inDropdown = $(evt.target).parents().is(this.dropdown); + var inDropdown = $(evt.target).parents().is($(".dropdown-menu", this.dropdown)); var inHovercard = $.contains(app.hovercard.el, evt.target); if(!inDropdown && !inHovercard && this.dropdownShowing()){ - this.badge.removeClass('active'); - this.dropdown.css('display', 'none'); - if(this.perfectScrollbarInitialized) { - this.dropdownNotifications.perfectScrollbar("destroy"); - this.perfectScrollbarInitialized = false; - } + this.dropdown.removeClass("dropdown-open"); + this.destroyScrollbar(); } }, dropdownScroll: function(){ - var isLoading = ($('.loading').length === 1); + var isLoading = ($(".loading").length === 1); if (this.isBottom() && this.hasMoreNotifs && !isLoading){ - this.dropdownNotifications.addClass('loading'); + this.dropdownNotifications.addClass("loading"); this.getNotifications(); } }, @@ -71,7 +68,7 @@ app.views.NotificationDropdown = app.views.Base.extend({ }, isBottom: function(){ - var bottom = this.dropdownNotifications.prop('scrollHeight') - this.dropdownNotifications.height(); + var bottom = this.dropdownNotifications.prop("scrollHeight") - this.dropdownNotifications.height(); var currentPosition = this.dropdownNotifications.scrollTop(); return currentPosition + 50 >= bottom; }, @@ -89,21 +86,21 @@ app.views.NotificationDropdown = app.views.Base.extend({ hideAjaxLoader: function(){ var self = this; - this.ajaxLoader.find('img').fadeTo(200, 0, function(){ - self.ajaxLoader.hide(300, function(){ - self.ajaxLoader.find('img').css('opacity', 1); + this.ajaxLoader.find(".spinner").fadeTo(200, 0, function(){ + self.ajaxLoader.hide(200, function(){ + self.ajaxLoader.find(".spinner").css("opacity", 1); }); }); }, renderNotifications: function(){ var self = this; - this.dropdownNotifications.find('.media.stream_element').remove(); + this.dropdownNotifications.find(".media.stream_element").remove(); $.each(self.notifications, function(index, notifications){ $.each(notifications, function(index, notification){ if($.inArray(notification, notifications) === -1){ var node = self.dropdownNotifications.append(notification.note_html); - $(node).find('.unread-toggle .entypo').tooltip('destroy').tooltip(); + $(node).find(".unread-toggle .entypo-eye").tooltip("destroy").tooltip(); $(node).find(self.avatars.selector).error(self.avatars.fallback); } }); @@ -113,15 +110,27 @@ app.views.NotificationDropdown = app.views.Base.extend({ app.helpers.timeago(this.dropdownNotifications); - if(this.perfectScrollbarInitialized) { - this.dropdownNotifications.perfectScrollbar("destroy"); - } - this.dropdownNotifications.perfectScrollbar(); - this.perfectScrollbarInitialized = true; + this.updateScrollbar(); this.dropdownNotifications.removeClass("loading"); this.dropdownNotifications.scroll(function(){ self.dropdownScroll(); }); + }, + + updateScrollbar: function() { + if(this.perfectScrollbarInitialized) { + this.dropdownNotifications.perfectScrollbar("update"); + } else { + this.dropdownNotifications.perfectScrollbar(); + this.perfectScrollbarInitialized = true; + } + }, + + destroyScrollbar: function() { + if(this.perfectScrollbarInitialized) { + this.dropdownNotifications.perfectScrollbar("destroy"); + this.perfectScrollbarInitialized = false; + } } }); // @license-end diff --git a/app/assets/javascripts/app/views/notifications_view.js b/app/assets/javascripts/app/views/notifications_view.js index 808ce6749e75edac49f274a5d2cbbb0999bfb3a3..3af3e717d189301e192f8368e01ed76f9b9dfa49 100644 --- a/app/assets/javascripts/app/views/notifications_view.js +++ b/app/assets/javascripts/app/views/notifications_view.js @@ -8,19 +8,19 @@ app.views.Notifications = Backbone.View.extend({ }, initialize: function() { - $(".unread-toggle .entypo").tooltip(); + $(".unread-toggle .entypo-eye").tooltip(); app.helpers.timeago($(document)); }, toggleUnread: function(evt) { var note = $(evt.target).closest(".stream_element"); var unread = note.hasClass("unread"); - - if (unread){ this.setRead(note.data("guid")); } - else { this.setUnread(note.data("guid")); } + var guid = note.data("guid"); + if (unread){ this.setRead(guid); } + else { this.setUnread(guid); } }, - getAllUnread: function(){ return $('.media.stream_element.unread'); }, + getAllUnread: function(){ return $(".media.stream_element.unread"); }, setRead: function(guid) { this.setUnreadStatus(guid, false); }, @@ -37,8 +37,9 @@ app.views.Notifications = Backbone.View.extend({ }, clickSuccess: function(data) { - var type = $('.stream_element[data-guid=' + data["guid"] + ']').data('type'); - this.updateView(data["guid"], type, data["unread"]); + var guid = data.guid; + var type = $(".stream_element[data-guid=" + guid + "]").data("type"); + this.updateView(guid, type, data.unread); }, markAllRead: function(evt){ @@ -51,43 +52,44 @@ app.views.Notifications = Backbone.View.extend({ updateView: function(guid, type, unread) { var change = unread ? 1 : -1, - all_notes = $('ul.nav > li:eq(0) .badge'), - type_notes = $('ul.nav > li[data-type=' + type + '] .badge'), - header_badge = $('#notification_badge .badge_count'), - note = $('.stream_element[data-guid=' + guid + ']'), - markAllReadLink = $('a#mark_all_read_link'), - translationKey = unread ? 'notifications.mark_read' : 'notifications.mark_unread'; + allNotes = $("#notifications_container .list-group > a:eq(0) .badge"), + typeNotes = $("#notifications_container .list-group > a[data-type=" + type + "] .badge"), + headerBadge = $(".notifications-link .badge"), + note = $(".notifications .stream_element[data-guid=" + guid + "]"), + markAllReadLink = $("a#mark_all_read_link"), + translationKey = unread ? "notifications.mark_read" : "notifications.mark_unread"; if(unread){ note.removeClass("read").addClass("unread"); } else { note.removeClass("unread").addClass("read"); } - $(".unread-toggle .entypo", note) - .tooltip('destroy') + $(".unread-toggle .entypo-eye", note) + .tooltip("destroy") .removeAttr("data-original-title") - .attr('title',Diaspora.I18n.t(translationKey)) + .attr("title",Diaspora.I18n.t(translationKey)) .tooltip(); - [all_notes, type_notes, header_badge].forEach(function(element){ + [allNotes, typeNotes, headerBadge].forEach(function(element){ element.text(function(i, text){ - return parseInt(text) + change }); + return parseInt(text) + change; + }); }); - [all_notes, type_notes].forEach(function(badge) { + [allNotes, typeNotes].forEach(function(badge) { if(badge.text() > 0) { - badge.addClass('badge-important').removeClass('badge-default'); + badge.removeClass("hidden"); } else { - badge.removeClass('badge-important').addClass('badge-default'); + badge.addClass("hidden"); } }); - if(header_badge.text() > 0){ - header_badge.removeClass('hidden'); - markAllReadLink.removeClass('disabled'); + if(headerBadge.text() > 0){ + headerBadge.removeClass("hidden"); + markAllReadLink.removeClass("disabled"); } else{ - header_badge.addClass('hidden'); - markAllReadLink.addClass('disabled'); + headerBadge.addClass("hidden"); + markAllReadLink.addClass("disabled"); } } }); diff --git a/app/assets/javascripts/app/views/photo_view.js b/app/assets/javascripts/app/views/photo_view.js index 286d3fe9805aa20ebdc3cd8f6522e785c1d4ecaf..ecf30fe1c9ff4af8a91022613435e78620389d5a 100644 --- a/app/assets/javascripts/app/views/photo_view.js +++ b/app/assets/javascripts/app/views/photo_view.js @@ -4,7 +4,7 @@ app.views.Photo = app.views.Base.extend({ templateName: "photo", - className : "photo loaded", + className : "photo loaded col-md-4 col-sm-6 clearfix", events: { "click .remove_post": "destroyModel" @@ -19,7 +19,7 @@ app.views.Photo = app.views.Base.extend({ presenter : function() { return _.extend(this.defaultPresenter(), { - authorIsCurrentUser : app.currentUser.isAuthorOf(this.model), + authorIsCurrentUser : app.currentUser.isAuthorOf(this.model) }); } }); diff --git a/app/assets/javascripts/app/views/photo_viewer.js b/app/assets/javascripts/app/views/photo_viewer.js deleted file mode 100644 index d9a5874000826bf1cf37f2df020c14e9a1d57fee..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/app/views/photo_viewer.js +++ /dev/null @@ -1,10 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later - -app.views.PhotoViewer = app.views.Base.extend({ - templateName : "photo-viewer", - - presenter : function(){ - return { photos : this.model.get("photos") }; //json array of attributes, not backbone models, yet. - } -}); -// @license-end diff --git a/app/assets/javascripts/app/views/photos_view.js b/app/assets/javascripts/app/views/photos_view.js index 5d5969ef15b47b2fad42157aee20a745520e05da..8a31fc815279e17292cf2d016e6fd669d975fa0b 100644 --- a/app/assets/javascripts/app/views/photos_view.js +++ b/app/assets/javascripts/app/views/photos_view.js @@ -1,26 +1,24 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.Photos = app.views.InfScroll.extend({ + className: "clearfix row", + + postClass : app.views.Photo, + initialize : function() { this.stream = this.model; this.collection = this.stream.items; // viable for extraction this.stream.fetch(); - - this.setupLightbox(); this.setupInfiniteScroll(); }, - postClass : app.views.Photo, - - setupLightbox : function(){ - this.lightbox = Diaspora.BaseWidget.instantiate("Lightbox"); - this.lightbox.set({ - imageParent: '#main_stream', - imageSelector: 'img.photo' - }); - $(this.el).delegate("a.photo-link", "click", this.lightbox.lightboxImageClicked); + postRenderTemplate: function(){ + var photoAttachments = $("#main_stream > div"); + if(photoAttachments.length > 0) { + new app.views.Gallery({ el: photoAttachments }); + } } }); // @license-end diff --git a/app/assets/javascripts/app/views/pod_entry_view.js b/app/assets/javascripts/app/views/pod_entry_view.js new file mode 100644 index 0000000000000000000000000000000000000000..112b6708fae08bd575148e883217008d7542bd35 --- /dev/null +++ b/app/assets/javascripts/app/views/pod_entry_view.js @@ -0,0 +1,84 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later + +app.views.PodEntry = app.views.Base.extend({ + templateName: "pod_table_entry", + + tagName: "tr", + + events: { + "click .more": "toggleMore", + "click .recheck": "recheckPod" + }, + + tooltipSelector: ".ssl-status i, .actions i", + + className: function() { + if( this.model.get("offline") ) { return "bg-danger"; } + if( this.model.get("status")==="version_failed" ) { return "bg-warning"; } + if( this.model.get("status")==="no_errors" ) { return "bg-success"; } + }, + + initialize: function(opts) { + this.parent = opts.parent; + this.rendered = false; + this.model.on("change", this.render, this); + }, + + presenter: function() { + return _.extend({}, this.defaultPresenter(), { + /* jshint camelcase: false */ + is_unchecked: (this.model.get("status")==="unchecked"), + has_no_errors: (this.model.get("status")==="no_errors"), + has_errors: (this.model.get("status")!=="no_errors"), + status_text: Diaspora.I18n.t("admin.pods.states."+this.model.get("status")), + pod_url: (this.model.get("ssl") ? "https" : "http") + "://" + this.model.get("host") + + (this.model.get("port") ? ":" + this.model.get("port") : ""), + response_time_fmt: this._fmtResponseTime() + /* jshint camelcase: true */ + }); + }, + + postRenderTemplate: function() { + if( !this.rendered ) { + this.parent.appendChild(this.el); + } + + this.rendered = true; + return this; + }, + + toggleMore: function() { + this.$(".details").toggle(); + return false; + }, + + recheckPod: function() { + var self = this; + this.$el.addClass("checking"); + + this.model.recheck() + .done(function(){ + app.flashMessages.success(Diaspora.I18n.t("admin.pods.recheck.success")); + }) + .fail(function(){ + app.flashMessages.error(Diaspora.I18n.t("admin.pods.recheck.failure")); + }) + .always(function(){ + self.$el + .removeClass("bg-danger bg-warning bg-success") + .addClass(_.result(self, "className")) + .removeClass("checking"); + }); + + return false; + }, + + _fmtResponseTime: function() { + if( this.model.get("response_time")===-1 ) { + return Diaspora.I18n.t("admin.pods.not_available"); + } + return Diaspora.I18n.t("admin.pods.ms", {count: this.model.get("response_time")}); + } +}); + +// @license-end diff --git a/app/assets/javascripts/app/views/poll_view.js b/app/assets/javascripts/app/views/poll_view.js index 14355716dc3c6b5dcba8b3cd4c2c03d40eb53f09..751e47538876884608130477b36f0c181c5d1114 100644 --- a/app/assets/javascripts/app/views/poll_view.js +++ b/app/assets/javascripts/app/views/poll_view.js @@ -89,8 +89,8 @@ app.views.Poll = app.views.Base.extend({ }, toggleElements: function() { - this.$('.percentage').toggle(); - this.$('.progress').toggle(); + this.$(".poll-result").toggle(); + this.$(".progress").toggle(); }, clickSubmit: function(evt) { @@ -117,4 +117,3 @@ app.views.Poll = app.views.Base.extend({ }); // @license-end - diff --git a/app/assets/javascripts/app/views/preview_post_view.js b/app/assets/javascripts/app/views/preview_post_view.js new file mode 100644 index 0000000000000000000000000000000000000000..1f8fe398174d188e0259e0505ce7d953650ebcc6 --- /dev/null +++ b/app/assets/javascripts/app/views/preview_post_view.js @@ -0,0 +1,41 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later + +app.views.PreviewPost = app.views.Post.extend({ + templateName: "stream-element", + className: "stream_element loaded", + + subviews: { + ".feedback": "feedbackView", + ".post-content": "postContentView", + ".oembed": "oEmbedView", + ".opengraph": "openGraphView", + ".poll": "pollView", + ".status-message-location": "postLocationStreamView" + }, + + tooltipSelector: [ + ".timeago", + ".delete", + ".permalink" + ].join(", "), + + initialize: function() { + this.model.set("preview", true); + this.oEmbedView = new app.views.OEmbed({model: this.model}); + this.openGraphView = new app.views.OpenGraph({model: this.model}); + this.pollView = new app.views.Poll({model: this.model}); + }, + + feedbackView: function() { + return new app.views.Feedback({model: this.model}); + }, + + postContentView: function() { + return new app.views.StatusMessage({model: this.model}); + }, + + postLocationStreamView: function() { + return new app.views.LocationStream({model: this.model}); + } +}); +// @license-end diff --git a/app/assets/javascripts/app/views/profile_header_view.js b/app/assets/javascripts/app/views/profile_header_view.js index c9e4bc6557f15c16071a2738591d26340dc91ea0..9067368957418d38f7b3e3f65a5096c0b6806797 100644 --- a/app/assets/javascripts/app/views/profile_header_view.js +++ b/app/assets/javascripts/app/views/profile_header_view.js @@ -3,10 +3,20 @@ app.views.ProfileHeader = app.views.Base.extend({ templateName: 'profile_header', + subviews: { + ".aspect_membership_dropdown": "aspectMembershipView" + }, + + events: { + "click #mention_button": "showMentionModal", + "click #message_button": "showMessageModal" + }, + initialize: function(opts) { - app.events.on('aspect:create', this.postRenderTemplate, this); this.photos = _.has(opts, 'photos') ? opts.photos : null; this.contacts = _.has(opts, 'contacts') ? opts.contacts : null; + $("#mentionModal").on("modal:loaded", this.mentionModalLoaded.bind(this)); + $("#mentionModal").on("hidden.bs.modal", this.mentionModalHidden); }, presenter: function() { @@ -24,6 +34,10 @@ app.views.ProfileHeader = app.views.Base.extend({ }); }, + aspectMembershipView: function() { + return new app.views.AspectMembership({person: this.model, dropdownMayCreateNewAspect: true}); + }, + _hasTags: function() { return (this.model.get('profile')['tags'].length > 0); }, @@ -33,30 +47,40 @@ app.views.ProfileHeader = app.views.Base.extend({ }, _shouldShowPhotos: function() { - return (this.photos && this.photos.count > 0); + return (this.photos && this.photos > 0); }, _shouldShowContacts: function() { - return (this.contacts && this.contacts.count > 0); + return (this.contacts && this.contacts > 0); }, - postRenderTemplate: function() { - var dropdownEl = this.$('.aspect_membership_dropdown.placeholder'); - if( dropdownEl.length === 0 ) { - return; - } + showMentionModal: function() { + app.helpers.showModal("#mentionModal"); + }, - // TODO render me client side!!! - var href = this.model.url() + '/aspect_membership_button?create=true&size=normal'; + mentionModalLoaded: function() { + app.publisher = new app.views.Publisher({ + standalone: true, + prefillMention: _.extend({handle: this.model.get("diaspora_id")}, this.model.attributes) + }); + app.publisher.open(); + $("#publisher").bind("ajax:success", function() { + $("#mentionModal").modal("hide"); + app.publisher.clear(); + app.publisher.remove(); + location.reload(); + }); + }, - $.get(href, function(resp) { - dropdownEl.html(resp); - new app.views.AspectMembership({el: $('.aspect_dropdown',dropdownEl)}); + mentionModalHidden: function() { + app.publisher.clear(); + app.publisher.remove(); + $("#mentionModal .modal-body").empty(); + }, - // UGLY (re-)attach the facebox - self.$('a[rel*=facebox]').facebox(); - }); - } + showMessageModal: function(){ + app.helpers.showModal("#conversationModal"); + }, }); // @license-end diff --git a/app/assets/javascripts/app/views/profile_sidebar_view.js b/app/assets/javascripts/app/views/profile_sidebar_view.js index a8b0d4074f8525363425dacae58900d4cb75b4a6..f19f7970a0b81697149e3a67502eb04f30345e1e 100644 --- a/app/assets/javascripts/app/views/profile_sidebar_view.js +++ b/app/assets/javascripts/app/views/profile_sidebar_view.js @@ -1,17 +1,7 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.ProfileSidebar = app.views.Base.extend({ - templateName: 'profile_sidebar', - - presenter: function() { - return _.extend({}, this.defaultPresenter(), { - show_profile_info: this._shouldShowProfileInfo(), - }); - }, - - _shouldShowProfileInfo: function() { - return (this.model.isSharing() || this.model.get('is_own_profile')); - } + templateName: "profile_sidebar" }); // @license-end diff --git a/app/assets/javascripts/app/views/publisher/aspect_selector_view.js b/app/assets/javascripts/app/views/publisher/aspect_selector_view.js index 7145de4ad56e885e70fc78e3de7914f55ba395dd..5e65e63ec0765ac4f905462f522e535fab8698ad 100644 --- a/app/assets/javascripts/app/views/publisher/aspect_selector_view.js +++ b/app/assets/javascripts/app/views/publisher/aspect_selector_view.js @@ -32,15 +32,15 @@ app.views.PublisherAspectSelector = app.views.AspectsDropdown.extend({ this._updateSelectedAspectIds(); this._updateButton('btn-default'); - + // update the globe or lock icon - var icon = this.$('#visibility-icon'); - if (target.find('.text').text().trim() === Diaspora.I18n.t('stream.public')) { - icon.removeClass('lock'); - icon.addClass('globe'); + var icon = this.$("#visibility-icon"); + if (target.find(".text").text().trim() === Diaspora.I18n.t("stream.public")) { + icon.removeClass("entypo-lock"); + icon.addClass("entypo-globe"); } else { - icon.removeClass('globe'); - icon.addClass('lock'); + icon.removeClass("entypo-globe"); + icon.addClass("entypo-lock"); } }, diff --git a/app/assets/javascripts/app/views/publisher/getting_started_view.js b/app/assets/javascripts/app/views/publisher/getting_started_view.js index 6d36a83a7af3ca5393eb5995b86114876aa69abe..5ba089efc2b35be17ef6ba71be7933971fd10daa 100644 --- a/app/assets/javascripts/app/views/publisher/getting_started_view.js +++ b/app/assets/javascripts/app/views/publisher/getting_started_view.js @@ -11,70 +11,67 @@ app.views.PublisherGettingStarted = Backbone.View.extend({ initialize: function(opts) { - this.el_first_msg = opts.el_first_msg; - this.el_visibility = opts.el_visibility; - this.el_stream = opts.el_stream; + this.firstMessage = opts.firstMessageEl; + this.visibility = opts.visibilityEl; + this.stream = opts.streamEl; }, // initiate all the popover message boxes show: function() { - this._addPopover(this.el_first_msg, { - trigger: 'manual', - offset: 30, - id: 'first_message_explain', - placement: 'right', + app.publisher.open(); + this._addPopover(this.firstMessage, { + trigger: "manual", + id: "first_message_explain", + placement: "left", html: true, - container: 'body' + container: "body" }, 600); - this._addPopover(this.el_visibility, { - trigger: 'manual', - offset: 10, - id: 'message_visibility_explain', - placement: 'bottom', + this._addPopover(this.visibility, { + trigger: "manual", + id: "message_visibility_explain", + placement: "bottom", html: true, - container: 'body' + container: "body" }, 1000); - this._addPopover(this.el_stream, { - trigger: 'manual', - offset: -5, - id: 'stream_explain', - placement: 'left', + this._addPopover(this.stream, { + trigger: "manual", + id: "stream_explain", + placement: "left", html: true, - container: 'body' + container: "body" }, 1400); // hide some popovers when a post is created - this.$('.button.creation').click(function() { - this.el_visibility.popover('hide'); - this.el_first_msg.popover('hide'); + this.$("#submit").click(function() { + this.visibility.popover("hide"); + this.firstMessage.popover("hide"); }); }, _addPopover: function(el, opts, timeout) { el.popover(opts); el.click(function() { - el.popover('hide'); + el.popover("hide"); }); // show the popover after the given timeout setTimeout(function() { - el.popover('show'); + el.popover("show"); // disable 'getting started' when the last popover is closed - var popup = el.data('popover').$tip[0]; - var close = $(popup).find('.close'); + var popup = el.data("bs.popover").$tip[0]; + var close = $(popup).find(".close"); close.click(function() { - if( $('.popover').length === 1 ) { - $.get('/getting_started_completed', {success: function() { + if( $(".popover").length <= 1 ) { + $.get("/getting_started_completed", {success: function() { $("#welcome-to-diaspora, #welcome-to-diaspora~br").remove(); }}); } - el.popover('hide'); + el.popover("hide"); return false; }); }, timeout); } }); // @license-end - diff --git a/app/assets/javascripts/app/views/publisher/mention_view.js b/app/assets/javascripts/app/views/publisher/mention_view.js new file mode 100644 index 0000000000000000000000000000000000000000..b8f6143f55c5e3334849a95d6c89c130648149da --- /dev/null +++ b/app/assets/javascripts/app/views/publisher/mention_view.js @@ -0,0 +1,223 @@ +//= require ../search_base_view + +app.views.PublisherMention = app.views.SearchBase.extend({ + triggerChar: "@", + invisibleChar: "\u200B", // zero width space + mentionRegex: /@([^@\s]+)$/, + + templates: { + mentionItemSyntax: _.template("@{<%= name %> ; <%= handle %>}"), + mentionItemHighlight: _.template("<strong><span><%= name %></span></strong>") + }, + + events: { + "keydown #status_message_fake_text": "onInputBoxKeyDown", + "input #status_message_fake_text": "onInputBoxInput", + "click #status_message_fake_text": "onInputBoxClick", + "blur #status_message_fake_text": "onInputBoxBlur", + }, + + initialize: function() { + this.mentionedPeople = []; + + // contains the 'fake text' displayed to the user + // also has a data-messageText attribute with the original text + this.inputBox = this.$("#status_message_fake_text"); + // contains the mentions displayed to the user + this.mentionsBox = this.$(".mentions-box"); + this.typeaheadInput = this.$(".typeahead-mention-box"); + this.bindTypeaheadEvents(); + + app.views.SearchBase.prototype.initialize.call(this, { + typeaheadInput: this.typeaheadInput, + customSearch: true, + autoselect: true, + remoteRoute: "/contacts" + }); + }, + + bindTypeaheadEvents: function() { + var self = this; + // Process mention when the user selects a result. + this.typeaheadInput.on("typeahead:select", function(evt, person) { self.onSuggestionSelection(person); }); + }, + + addPersonToMentions: function(person) { + if(!(person && person.name && person.handle)) { return; } + // This is needed for processing preview + /* jshint camelcase: false */ + person.diaspora_id = person.handle; + /* jshint camelcase: true */ + this.mentionedPeople.push(person); + this.ignorePersonForSuggestions(person); + }, + + cleanMentionedPeople: function() { + var inputText = this.inputBox.val(); + this.mentionedPeople = this.mentionedPeople.filter(function(person) { + return person.name && inputText.indexOf(person.name) > -1; + }); + this.ignoreDiasporaIds = this.mentionedPeople.map(function(person) { return person.handle; }); + }, + + onSuggestionSelection: function(person) { + var messageText = this.inputBox.val(); + var caretPosition = this.inputBox[0].selectionStart; + var triggerCharPosition = messageText.lastIndexOf(this.triggerChar, caretPosition); + + if(triggerCharPosition === -1) { return; } + + this.addPersonToMentions(person); + this.closeSuggestions(); + + messageText = messageText.substring(0, triggerCharPosition) + + this.invisibleChar + person.name + messageText.substring(caretPosition); + + this.inputBox.val(messageText); + this.updateMessageTexts(); + + this.inputBox.focus(); + var newCaretPosition = triggerCharPosition + person.name.length + 1; + this.inputBox[0].setSelectionRange(newCaretPosition, newCaretPosition); + }, + + /** + * Replaces every combination of this.invisibleChar + mention.name by the + * correct syntax for both hidden text and visible one. + * + * For instance, the text "Hello \u200Buser1" will be tranformed to + * "Hello @{user1 ; user1@pod.tld}" in the hidden element and + * "Hello <strong><span>user1</span></strong>" in the element visible to the user. + */ + updateMessageTexts: function() { + var fakeMessageText = this.inputBox.val(), + mentionBoxText = _.escape(fakeMessageText), + messageText = fakeMessageText; + + this.mentionedPeople.forEach(function(person) { + var mentionName = this.invisibleChar + person.name; + messageText = messageText.replace(mentionName, this.templates.mentionItemSyntax(person)); + var textHighlight = this.templates.mentionItemHighlight({name: _.escape(person.name)}); + mentionBoxText = mentionBoxText.replace(mentionName, textHighlight); + }, this); + + this.inputBox.data("messageText", messageText); + this.mentionsBox.find(".mentions").html(mentionBoxText); + }, + + updateTypeaheadInput: function() { + var messageText = this.inputBox.val(); + var caretPosition = this.inputBox[0].selectionStart; + var result = this.mentionRegex.exec(messageText.substring(0,caretPosition)); + + if(result === null) { + this.closeSuggestions(); + return; + } + + // result[1] is the string between the last '@' and the current caret position + this.typeaheadInput.typeahead("val", result[1]); + this.typeaheadInput.typeahead("open"); + }, + + /** + * Let us prefill the publisher with a mention list + * @param persons List of people to mention in a post; + * JSON object of form { handle: <diaspora handle>, name: <name>, ... } + */ + prefillMention: function(persons) { + persons.forEach(function(person) { + this.addPersonToMentions(person); + var text = this.invisibleChar + person.name; + if(this.inputBox.val().length !== 0) { + text = this.inputBox.val() + " " + text; + } + this.inputBox.val(text); + this.updateMessageTexts(); + }, this); + }, + + /** + * Selects next or previous result when result dropdown is open and + * user press up and down arrows. + */ + onArrowKeyDown: function(e) { + if(!this.isVisible() || (e.which !== Keycodes.UP && e.which !== Keycodes.DOWN)) { + return; + } + + e.preventDefault(); + e.stopPropagation(); + + this.typeaheadInput.typeahead("activate"); + this.typeaheadInput.typeahead("open"); + this.typeaheadInput.trigger($.Event("keydown", {keyCode: e.keyCode, which: e.which})); + }, + + /** + * Listens for user input and opens results dropdown when input contains the trigger char + */ + onInputBoxInput: function() { + this.cleanMentionedPeople(); + this.updateMessageTexts(); + this.updateTypeaheadInput(); + }, + + onInputBoxKeyDown: function(e) { + // This also matches HOME/END on OSX which is CMD+LEFT, CMD+RIGHT + if(e.which === Keycodes.LEFT || e.which === Keycodes.RIGHT || + e.which === Keycodes.HOME || e.which === Keycodes.END) { + _.defer(_.bind(this.updateTypeaheadInput, this)); + return; + } + + if(!this.isVisible) { + return true; + } + + switch(e.which) { + case Keycodes.ESC: + case Keycodes.SPACE: + this.closeSuggestions(); + break; + case Keycodes.UP: + case Keycodes.DOWN: + this.onArrowKeyDown(e); + break; + case Keycodes.RETURN: + case Keycodes.TAB: + if(this.$(".tt-cursor").length === 1) { + this.$(".tt-cursor").click(); + return false; + } + break; + } + return true; + }, + + onInputBoxClick: function() { + this.updateTypeaheadInput(); + }, + + onInputBoxBlur: function() { + this.closeSuggestions(); + }, + + reset: function() { + this.inputBox.val(""); + this.onInputBoxInput(); + }, + + closeSuggestions: function() { + this.typeaheadInput.typeahead("val", ""); + this.typeaheadInput.typeahead("close"); + }, + + isVisible: function() { + return this.$(".tt-menu").is(":visible"); + }, + + getTextForSubmit: function() { + return this.mentionedPeople.length ? this.inputBox.data("messageText") : this.inputBox.val(); + } +}); diff --git a/app/assets/javascripts/app/views/publisher/services_view.js b/app/assets/javascripts/app/views/publisher/services_view.js index 1ed4c988bcb6709e7e75c5a92434f177efa71e41..8fd17a9e85a40af3499a82bf3f50e452aaa41ab1 100644 --- a/app/assets/javascripts/app/views/publisher/services_view.js +++ b/app/assets/javascripts/app/views/publisher/services_view.js @@ -37,7 +37,7 @@ app.views.PublisherServices = Backbone.View.extend({ // keep track of character count _createCounter: function() { // remove any obsolete counters - this.input.siblings('.counter').remove(); + $("#publisher .counter").remove(); // create new counter var min = 40000; @@ -47,7 +47,13 @@ app.views.PublisherServices = Backbone.View.extend({ var num = parseInt($(value).attr('maxchar')); if (min > num) { min = num; } }); - this.input.charCount({allowed: min, warning: min/10 }); + var counter = $("<div class='counter pull-right'></div>"); + $("#publisher-images").after(counter); + this.input.charCount({ + allowed: min, + warning: min / 10, + counter: counter + }); } }, diff --git a/app/assets/javascripts/app/views/publisher/uploader_view.js b/app/assets/javascripts/app/views/publisher/uploader_view.js index 00580f57a0abc7eaabe80d89994175a32f69f0fa..5f1fedc0cca14aac6b9afc8fe0e2225c4f20053b 100644 --- a/app/assets/javascripts/app/views/publisher/uploader_view.js +++ b/app/assets/javascripts/app/views/publisher/uploader_view.js @@ -6,7 +6,7 @@ app.views.PublisherUploader = Backbone.View.extend({ - allowedExtensions: ['jpg', 'jpeg', 'png', 'gif', 'tif', 'tiff'], + allowedExtensions: ["jpg", "jpeg", "png", "gif", "tif", "tiff"], sizeLimit: 4194304, // bytes initialize: function(opts) { @@ -18,14 +18,14 @@ app.views.PublisherUploader = Backbone.View.extend({ //debug: true, - action: '/photos', + action: "/photos", params: { photo: { pending: true }}, allowedExtensions: this.allowedExtensions, sizeLimit: this.sizeLimit, messages: { - typeError: Diaspora.I18n.t('photo_uploader.invalid_ext'), - sizeError: Diaspora.I18n.t('photo_uploader.size_error'), - emptyError: Diaspora.I18n.t('photo_uploader.empty') + typeError: Diaspora.I18n.t("photo_uploader.invalid_ext"), + sizeError: Diaspora.I18n.t("photo_uploader.size_error"), + emptyError: Diaspora.I18n.t("photo_uploader.empty") }, onProgress: _.bind(this.progressHandler, this), onSubmit: _.bind(this.submitHandler, this), @@ -33,22 +33,22 @@ app.views.PublisherUploader = Backbone.View.extend({ }); - this.el_info = $('<div id="fileInfo" />'); - this.publisher.el_wrapper.before(this.el_info); + this.info = $("<div id=\"fileInfo\" />"); + this.publisher.wrapperEl.before(this.info); - this.publisher.el_photozone.on('click', '.x', _.bind(this._removePhoto, this)); + this.publisher.photozoneEl.on("click", ".x", _.bind(this._removePhoto, this)); }, progressHandler: function(id, fileName, loaded, total) { var progress = Math.round(loaded / total * 100); - this.el_info.text(fileName + ' ' + progress + '%').fadeTo(200, 1); - this.publisher.el_photozone - .find('li.loading').first().find('.bar') - .width(progress + '%'); + this.info.text(fileName + " " + progress + "%").fadeTo(200, 1); + this.publisher.photozoneEl + .find("li.loading").first().find(".progress-bar") + .width(progress + "%"); }, submitHandler: function() { - this.$el.addClass('loading'); + this.$el.addClass("loading"); this._addPhotoPlaceholder(); }, @@ -57,32 +57,34 @@ app.views.PublisherUploader = Backbone.View.extend({ var publisher = this.publisher; publisher.setButtonsEnabled(false); - publisher.el_wrapper.addClass('with_attachments'); - publisher.el_photozone.append( - '<li class="publisher_photo loading" style="position:relative;">' + - ' <div class="progress progress-striped active"><div class="bar"></div></div>' + - ' <img src="'+Handlebars.helpers.imageUrl('ajax-loader2.gif')+'" class="ajax-loader" alt="" />'+ - '</li>' + publisher.wrapperEl.addClass("with_attachments"); + publisher.photozoneEl.append( + "<li class=\"publisher_photo loading\" style=\"position:relative;\">" + + " <div class=\"progress\">" + + " <div class=\"progress-bar progress-bar-striped active\" role=\"progressbar\"></div>"+ + " </div>" + + " <img src=\"\"+Handlebars.helpers.imageUrl(\"ajax-loader2.gif\")+\"\" class=\"ajax-loader\" alt=\"\" />"+ + "</li>" ); }, uploadCompleteHandler: function(_id, fileName, response) { if (response.success){ - this.el_info.text(Diaspora.I18n.t('photo_uploader.completed', {file: fileName})).fadeTo(2000, 0); + this.info.text(Diaspora.I18n.t("photo_uploader.completed", {file: fileName})).fadeTo(2000, 0); var id = response.data.photo.id, url = response.data.photo.unprocessed_image.url; this._addFinishedPhoto(id, url); - this.trigger('change'); + this.trigger("change"); } else { this._cancelPhotoUpload(); - this.trigger('change'); - this.el_info.text(Diaspora.I18n.t('photo_uploader.error', {file: fileName})); - this.publisher.el_wrapper.find('#photodropzone_container').first().after( - '<div id="upload_error">' + - Diaspora.I18n.t('photo_uploader.error', {file: fileName}) + - '</div>' + this.trigger("change"); + this.info.text(Diaspora.I18n.t("photo_uploader.error", {file: fileName})); + this.publisher.wrapperEl.find("#photodropzone_container").first().after( + "<div id=\"upload_error\">" + + Diaspora.I18n.t("photo_uploader.error", {file: fileName}) + + "</div>" ); } }, @@ -93,58 +95,58 @@ app.views.PublisherUploader = Backbone.View.extend({ var publisher = this.publisher; // add form input element - publisher.$('.content_creation form').append( - '<input type="hidden", value="'+id+'" name="photos[]" />' + publisher.$(".content_creation form").append( + "<input type=\"hidden\", value=\""+id+"\" name=\"photos[]\" />" ); // replace placeholder - var placeholder = publisher.el_photozone.find('li.loading').first(); + var placeholder = publisher.photozoneEl.find("li.loading").first(); placeholder - .removeClass('loading') + .removeClass("loading") .prepend( - '<div class="x"></div>'+ - '<div class="circle"></div>' + "<div class=\"x\"></div>"+ + "<div class=\"circle\"></div>" ) - .find('img').attr({'src': url, 'data-id': id}).removeClass('ajax-loader'); + .find("img").attr({"src": url, "data-id": id}).removeClass("ajax-loader"); placeholder - .find('div.progress').remove(); + .find("div.progress").remove(); // no more placeholders? enable buttons - if( publisher.el_photozone.find('li.loading').length === 0 ) { - this.$el.removeClass('loading'); + if( publisher.photozoneEl.find("li.loading").length === 0 ) { + this.$el.removeClass("loading"); publisher.setButtonsEnabled(true); } }, _cancelPhotoUpload: function() { var publisher = this.publisher; - var placeholder = publisher.el_photozone.find('li.loading').first(); + var placeholder = publisher.photozoneEl.find("li.loading").first(); placeholder - .removeClass('loading') - .find('img').remove(); + .removeClass("loading") + .find("img").remove(); }, // remove an already uploaded photo _removePhoto: function(evt) { var self = this; - var photo = $(evt.target).parents('.publisher_photo'); - var img = photo.find('img'); + var photo = $(evt.target).parents(".publisher_photo"); + var img = photo.find("img"); - photo.addClass('dim'); + photo.addClass("dim"); $.ajax({ - url: '/photos/'+img.attr('data-id'), - dataType: 'json', - type: 'DELETE', + url: "/photos/"+img.attr("data-id"), + dataType: "json", + type: "DELETE", success: function() { $.when(photo.fadeOut(400)).then(function(){ photo.remove(); - if( self.publisher.$('.publisher_photo').length === 0 ) { + if( self.publisher.$(".publisher_photo").length === 0 ) { // no more photos left... - self.publisher.el_wrapper.removeClass('with_attachments'); + self.publisher.wrapperEl.removeClass("with_attachments"); } - self.trigger('change'); + self.trigger("change"); }); } }); diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index fece5dd08e6c0877000f676d1ec6bd477c90684d..95aab180aef56dc146cc3968ef894df70b721a65 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -5,9 +5,11 @@ * the COPYRIGHT file. */ -//= require ./publisher/services_view //= require ./publisher/aspect_selector_view //= require ./publisher/getting_started_view +//= require ./publisher/mention_view +//= require ./publisher/poll_creator_view +//= require ./publisher/services_view //= require ./publisher/uploader_view //= require jquery-textchange @@ -18,10 +20,8 @@ app.views.Publisher = Backbone.View.extend({ events : { "keydown #status_message_fake_text" : "keyDown", "focus textarea" : "open", - "click #hide_publisher" : "clear", "submit form" : "createStatusMessage", "click #submit" : "createStatusMessage", - "click .post_preview_button" : "createPostPreview", "textchange #status_message_fake_text": "handleTextchange", "click #locator" : "showLocation", "click #poll_creator" : "togglePollCreator", @@ -31,70 +31,62 @@ app.views.Publisher = Backbone.View.extend({ initialize : function(opts){ this.standalone = opts ? opts.standalone : false; + this.prefillMention = opts && opts.prefillMention ? opts.prefillMention : undefined; this.disabled = false; // init shortcut references to the various elements - this.el_input = this.$('#status_message_fake_text'); - this.el_hiddenInput = this.$('#status_message_text'); - this.el_wrapper = this.$('#publisher_textarea_wrapper'); - this.el_submit = this.$('input[type=submit], button#submit'); - this.el_preview = this.$('button.post_preview_button'); - this.el_photozone = this.$('#photodropzone'); - - // init mentions plugin - Mentions.initialize(this.el_input); - - // init autoresize plugin - this.el_input.autoResize({ 'extraSpace' : 10, 'maxHeight' : Infinity }); + this.inputEl = this.$("#status_message_fake_text"); + this.hiddenInputEl = this.$("#status_message_text"); + this.wrapperEl = this.$("#publisher_textarea_wrapper"); + this.submitEl = this.$("input[type=submit], button#submit"); + this.photozoneEl = this.$("#photodropzone"); // if there is data in the publisher we ask for a confirmation // before the user is able to leave the page - $(window).on('beforeunload', _.bind(this._beforeUnload, this)); + $(window).on("beforeunload", _.bind(this._beforeUnload, this)); + $(window).unload(this.clear.bind(this)); // sync textarea content - if( this.el_hiddenInput.val() === "" ) { - this.el_hiddenInput.val( this.el_input.val() ); + if( this.hiddenInputEl.val() === "" ) { + this.hiddenInputEl.val( this.inputEl.val() ); } - if( this.el_input.val() === "" ) { - this.el_input.val( this.el_hiddenInput.val() ); + if( this.inputEl.val() === "" ) { + this.inputEl.val( this.hiddenInputEl.val() ); } // hide close and preview buttons and manage services link // in case publisher is standalone // (e.g. bookmarklet, mentions popup) if( this.standalone ) { - this.$("#hide_publisher").hide(); - this.el_preview.hide(); this.$(".question_mark").hide(); } // this has to be here, otherwise for some reason the callback for the // textchange event won't be called in Backbone... - this.el_input.bind('textchange', $.noop); + this.inputEl.bind("textchange", $.noop); - var _this = this; - $('body').on('click', function(event){ - // if the click event is happened outside the publisher view, then try to close the box - if( _this.el && $(event.target).closest('#publisher').attr('id') !== _this.el.id){ - _this.tryClose(); - } - }); + $("body").click(function(event) { + var $target = $(event.target); + if ($target.closest("#publisher").length === 0 && !$target.hasClass("dropdown-backdrop")) { + this.tryClose(); + } + }.bind(this)); // close publisher on post - this.on('publisher:add', function() { + this.on("publisher:add", function() { this.close(); this.showSpinner(true); }); // open publisher on post error - this.on('publisher:error', function() { + this.on("publisher:error", function() { this.open(); this.showSpinner(false); }); // resetting the poll view - this.on('publisher:sync', function() { - this.view_poll_creator.render(); + this.on("publisher:sync", function() { + this.viewPollCreator.render(); }); this.initSubviews(); @@ -103,56 +95,96 @@ app.views.Publisher = Backbone.View.extend({ }, initSubviews: function() { - var form = this.$('.content_creation form'); + this.mention = new app.views.PublisherMention({ el: this.$("#publisher_textarea_wrapper") }); + if(this.prefillMention) { + this.mention.prefillMention([this.prefillMention]); + } + + var form = this.$(".content_creation form"); this.view_services = new app.views.PublisherServices({ - el: this.$('#publisher_service_icons'), - input: this.el_input, + el: this.$("#publisher-service-icons"), + input: this.inputEl, form: form }); - this.view_aspect_selector = new app.views.PublisherAspectSelector({ - el: this.$('.public_toggle .aspect_dropdown'), + this.viewAspectSelector = new app.views.PublisherAspectSelector({ + el: this.$(".public_toggle .aspect_dropdown"), form: form }); - this.view_getting_started = new app.views.PublisherGettingStarted({ - el_first_msg: this.el_input, - el_visibility: this.$('.public_toggle .aspect_dropdown > .dropdown-toggle'), - el_stream: $('#gs-shim') + this.viewGettingStarted = new app.views.PublisherGettingStarted({ + firstMessageEl: this.inputEl, + visibilityEl: this.$(".public_toggle .aspect_dropdown > .dropdown-toggle"), + streamEl: $("#main_stream") }); - this.view_uploader = new app.views.PublisherUploader({ - el: this.$('#file-upload'), + this.viewUploader = new app.views.PublisherUploader({ + el: this.$("#file-upload"), publisher: this }); - this.view_uploader.on('change', this.checkSubmitAvailability, this); + this.viewUploader.on("change", this.checkSubmitAvailability, this); + + var self = this; + var mdEditorOptions = { + onPreview: function() { + self.wrapperEl.addClass("markdown-preview"); + return self.createPostPreview(); + }, + + onHidePreview: function() { + self.wrapperEl.removeClass("markdown-preview"); + }, + + onPostPreview: function() { + var photoAttachments = self.wrapperEl.find(".photo_attachments"); + if (photoAttachments.length > 0) { + new app.views.Gallery({el: photoAttachments}); + } + }, + + onChange: function() { + self.inputEl.trigger("textchange"); + } + }; - this.view_poll_creator = new app.views.PublisherPollCreator({ - el: this.$('#poll_creator_container') + if (!this.standalone) { + mdEditorOptions.onClose = function() { + self.clear(); + }; + } + this.markdownEditor = new Diaspora.MarkdownEditor(this.inputEl, mdEditorOptions); + + this.viewPollCreator = new app.views.PublisherPollCreator({ + el: this.$("#poll_creator_container") }); - this.view_poll_creator.on('change', this.checkSubmitAvailability, this); - this.view_poll_creator.render(); + this.viewPollCreator.on("change", this.checkSubmitAvailability, this); + this.viewPollCreator.render(); + + if (this.prefillMention) { + this.handleTextchange(); + } }, // set the selected aspects in the dropdown by their ids setSelectedAspects: function(ids) { - this.view_aspect_selector.updateAspectsSelector(ids); + this.viewAspectSelector.updateAspectsSelector(ids); }, // inject content into the publisher textarea setText: function(txt) { - this.el_input.val(txt); - this.el_hiddenInput.val(txt); + this.inputEl.val(txt); + this.hiddenInputEl.val(txt); this.prefillText = txt; - this.el_input.trigger('input'); + this.inputEl.trigger("input"); + autosize.update(this.inputEl); this.handleTextchange(); }, // show the "getting started" popups around the publisher triggerGettingStarted: function() { - this.view_getting_started.show(); + this.viewGettingStarted.show(); }, createStatusMessage : function(evt) { @@ -164,7 +196,7 @@ app.views.Publisher = Backbone.View.extend({ // Auto-adding a poll answer always leaves an empty box when the user starts // typing in the last box. We'll delete the last one to avoid submitting an // empty poll answer and failing validation. - this.view_poll_creator.removeLastAnswer(); + this.viewPollCreator.removeLastAnswer(); //add missing mentions at end of post: this.handleTextchange(); @@ -172,10 +204,13 @@ app.views.Publisher = Backbone.View.extend({ var serializedForm = $(evt.target).closest("form").serializeObject(); // disable input while posting, must be after the form is serialized this.setInputEnabled(false); + this.wrapperEl.addClass("submitting"); // lulz this code should be killed. var statusMessage = new app.models.Post(); - if( app.publisher ) app.publisher.trigger('publisher:add'); + if( app.publisher ) { + app.publisher.trigger("publisher:add"); + } statusMessage.save({ "status_message" : { @@ -192,9 +227,9 @@ app.views.Publisher = Backbone.View.extend({ url : "/status_messages", success : function() { if( app.publisher ) { - app.publisher.$el.trigger('ajax:success'); - app.publisher.trigger('publisher:sync'); - self.view_poll_creator.trigger('publisher:sync'); + app.publisher.$el.trigger("ajax:success"); + app.publisher.trigger("publisher:sync"); + self.viewPollCreator.trigger("publisher:sync"); } if(app.stream && !self.standalone){ @@ -208,20 +243,25 @@ app.views.Publisher = Backbone.View.extend({ if( self.standalone ) self.setEnabled(false); }, error: function(model, resp) { - if( app.publisher ) app.publisher.trigger('publisher:error'); + if( app.publisher ) { + app.publisher.trigger("publisher:error"); + } self.setInputEnabled(true); - Diaspora.page.flashMessages.render({ 'success':false, 'notice':resp.responseText }); + app.flashMessages.error(resp.responseText); self.setButtonsEnabled(true); self.setInputEnabled(true); + self.wrapperEl.removeClass("submitting"); + self.handleTextchange(); + autosize.update(self.inputEl); } }); }, // creates the location showLocation: function(){ - if($('#location').length === 0){ - $('#location_container').append('<div id="location"></div>'); - this.el_wrapper.addClass('with_location'); + if($("#location").length === 0){ + this.$(".location-container").append("<div id=\"location\"></div>"); + this.wrapperEl.addClass("with-location"); this.view_locator = new app.views.Location(); } }, @@ -230,36 +270,30 @@ app.views.Publisher = Backbone.View.extend({ destroyLocation: function(){ if(this.view_locator){ this.view_locator.remove(); - this.el_wrapper.removeClass('with_location'); + this.wrapperEl.removeClass("with-location"); delete this.view_locator; } }, togglePollCreator: function(){ - this.view_poll_creator.$el.toggle(); - this.el_input.focus(); + this.wrapperEl.toggleClass("with-poll"); + this.inputEl.focus(); }, // avoid submitting form when pressing Enter key avoidEnter: function(evt){ - if(evt.keyCode === 13) + if(evt.which === Keycodes.ENTER) { return false; + } }, - createPostPreview : function(evt) { - if(evt){ evt.preventDefault(); } - - //add missing mentions at end of post: - this.handleTextchange(); - - var serializedForm = $(evt.target).closest("form").serializeObject(); - + getUploadedPhotos: function() { var photos = []; - $('li.publisher_photo img').each(function(){ - var file = $(this).attr('src').substring("/uploads/images/".length); + $("li.publisher_photo img").each(function() { + var file = $(this).attr("src").substring("/uploads/images/".length); photos.push( { - "sizes":{ + "sizes": { "small" : "/uploads/images/thumb_small_" + file, "medium" : "/uploads/images/thumb_medium_" + file, "large" : "/uploads/images/scaled_full_" + file @@ -267,94 +301,72 @@ app.views.Publisher = Backbone.View.extend({ } ); }); + return photos; + }, - var mentioned_people = [], - regexp = new RegExp("@{\(\[\^\;\]\+\); \(\[\^\}\]\+\)}", "g"), - user; - - var getMentionedUser = function(handle) { - return Mentions.contacts.filter(function(user) { - return user.handle === handle; - })[0]; - }; - - while( (user = regexp.exec(serializedForm["status_message[text]"])) ){ - // user[1]: name, user[2]: handle - var mentioned_user = getMentionedUser(user[2]); - if(mentioned_user){ - mentioned_people.push({ - "id":mentioned_user["id"], - "guid":mentioned_user["guid"], - "name":user[1], - "diaspora_id":user[2], - "avatar":mentioned_user["avatar"] - }); - } - } - - var date = (new Date()).toISOString(); - + getPollData: function(serializedForm) { var poll; - var poll_question = serializedForm["poll_question"]; - var poll_answers_arry = _.flatten([serializedForm["poll_answers[]"]]); - var poll_answers = _.map(poll_answers_arry, function(answer){ - if(answer) return { 'answer' : answer }; + var pollQuestion = serializedForm.poll_question; + var pollAnswersArray = _.flatten([serializedForm["poll_answers[]"]]); + var pollAnswers = _.map(pollAnswersArray, function(answer){ + if (answer) { + return {"answer": answer, "vote_count": 0}; + } }); - poll_answers = _.without(poll_answers, undefined); + pollAnswers = _.without(pollAnswers, undefined); - if(poll_question && poll_answers.length) { + if(pollQuestion && pollAnswers.length) { poll = { - 'question': poll_question, - 'poll_answers' : poll_answers, - 'participation_count': '0' + "question": pollQuestion, + "poll_answers": pollAnswers, + "participation_count": "0" }; } - - var previewMessage = { - "id" : 0, - "text" : serializedForm["status_message[text]"], - "public" : serializedForm["aspect_ids[]"] === "public", - "created_at" : date, - "interacted_at" : date, - "post_type" : "StatusMessage", - "author" : app.currentUser ? app.currentUser.attributes : {}, - "mentioned_people" : mentioned_people, - "photos" : photos, - "frame_name" : "status", - "title" : serializedForm["status_message[text]"], - "address" : $("#location_address").val(), - "interactions" : {"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":0}, - 'poll': poll, - }; - if(app.stream) { - this.removePostPreview(); - app.stream.addNow(previewMessage); - this.recentPreview=previewMessage; - this.modifyPostPreview($('.stream_element:first',$('.stream_container'))); - } + return poll; }, - modifyPostPreview : function(post) { - post.addClass('post_preview'); - $('.collapsible',post).removeClass('collapsed').addClass('opened'); - $('a.delete.remove_post',post).hide(); - $('a.like, a.focus_comment_textarea',post).removeAttr("href"); - $('a.like',post).addClass("like_preview"); - $('a.like',post).removeClass("like"); - $('a.focus_comment_textarea',post).addClass("focus_comment_textarea_preview"); - $('a.focus_comment_textarea',post).removeClass("focus_comment_textarea"); - $('a',$('span.details.grey',post)).removeAttr("href"); - }, + createPostPreview: function() { + //add missing mentions at end of post: + this.handleTextchange(); - removePostPreview : function() { - if(app.stream && this.recentPreview){ - app.stream.items.remove(this.recentPreview); - delete this.recentPreview; + var serializedForm = $("#new_status_message").serializeObject(); + var text = this.mention.getTextForSubmit(); + var photos = this.getUploadedPhotos(); + var mentionedPeople = this.mention.mentionedPeople; + var poll = this.getPollData(serializedForm); + var locationCoords = serializedForm["location[coords]"]; + if(!locationCoords || locationCoords === "") { + locationCoords = ["", ""]; + } else { + locationCoords = locationCoords.split(","); } + var location = { + "address": $("#location_address").val(), + "lat": locationCoords[0], + "lng": locationCoords[1] + }; + + var previewMessage = { + "id": 0, + "text": text, + "public": serializedForm["aspect_ids[]"] === "public", + "created_at": new Date().toISOString(), + "interacted_at": new Date().toISOString(), + "author": app.currentUser ? app.currentUser.attributes : {}, + "mentioned_people": mentionedPeople, + "photos": photos, + "title": serializedForm["status_message[text]"], + "location": location, + "interactions": {"likes": [], "reshares": [], "comments_count": 0, "likes_count": 0, "reshares_count": 0}, + "poll": poll + }; + + var previewPost = new app.views.PreviewPost({model: new app.models.Post(previewMessage)}).render().el; + return $("<div/>").append(previewPost).html(); }, keyDown : function(evt) { - if( evt.keyCode === 13 && evt.ctrlKey ) { + if(evt.which === Keycodes.ENTER && evt.ctrlKey) { this.$("form").submit(); this.open(); return false; @@ -362,29 +374,28 @@ app.views.Publisher = Backbone.View.extend({ }, clear : function() { - // clear text(s) - this.el_input.val(''); - this.el_hiddenInput.val(''); - this.el_input.trigger('keyup') - .trigger('keydown'); - // remove mentions - this.el_input.mentionsInput('reset'); + this.mention.reset(); + + // clear text(s) + this.inputEl.val(""); + this.hiddenInputEl.val(""); + this.inputEl.trigger("keyup") + .trigger("keydown"); + autosize.update(this.inputEl); // remove photos - this.el_photozone.find('li').remove(); + this.photozoneEl.find("li").remove(); this.$("input[name='photos[]']").remove(); - this.el_wrapper.removeClass("with_attachments"); + this.wrapperEl.removeClass("with_attachments"); // empty upload-photo - this.$('#fileInfo').empty(); + this.$("#fileInfo").empty(); - // close publishing area (CSS) + // remove preview and close publishing area (CSS) + this.markdownEditor.hidePreview(); this.close(); - // remove preview - this.removePostPreview(); - // disable submitting this.checkSubmitAvailability(); @@ -393,6 +404,7 @@ app.views.Publisher = Backbone.View.extend({ // enable input this.setInputEnabled(true); + this.wrapperEl.removeClass("submitting"); // enable buttons this.setButtonsEnabled(true); @@ -401,11 +413,11 @@ app.views.Publisher = Backbone.View.extend({ this.destroyLocation(); // clear poll form - this.view_poll_creator.clearInputs(); + this.viewPollCreator.clearInputs(); // force textchange plugin to update lastValue - this.el_input.data('lastValue', ''); - this.el_hiddenInput.data('lastValue', ''); + this.inputEl.data("lastValue", ""); + this.hiddenInputEl.data("lastValue", ""); return this; }, @@ -421,27 +433,27 @@ app.views.Publisher = Backbone.View.extend({ if( this.disabled ) return; // visually 'open' the publisher - this.$el.removeClass('closed'); - this.el_wrapper.addClass('active'); - - // fetch contacts for mentioning - Mentions.fetchContacts(); + this.$el.removeClass("closed"); + this.wrapperEl.addClass("active"); + autosize.update(this.inputEl); return this; }, close : function() { $(this.el).addClass("closed"); - this.el_wrapper.removeClass("active"); - this.el_input.css('height', ''); - this.view_poll_creator.$el.hide(); + this.wrapperEl.removeClass("active"); + this.inputEl.css("height", ""); + this.wrapperEl.removeClass("with-poll"); return this; }, showSpinner: function(bool) { - if (bool) - this.$('#publisher_spinner').removeClass('hidden'); - else - this.$('#publisher_spinner').addClass('hidden'); + if (bool) { + this.$("#publisher_spinner").removeClass("hidden"); + } + else { + this.$("#publisher_spinner").addClass("hidden"); + } }, checkSubmitAvailability: function() { @@ -461,44 +473,38 @@ app.views.Publisher = Backbone.View.extend({ setButtonsEnabled: function(bool) { if (bool) { - this.el_submit.removeProp('disabled'); - this.el_preview.removeProp('disabled'); + this.submitEl.removeAttr("disabled"); } else { - this.el_submit.prop('disabled', true); - this.el_preview.prop('disabled', true); + this.submitEl.prop("disabled", true); } }, setInputEnabled: function(bool) { if (bool) { - this.el_input.removeProp('disabled'); - this.el_hiddenInput.removeProp('disabled'); + this.inputEl.removeAttr("disabled"); + this.hiddenInputEl.removeAttr("disabled"); } else { - this.el_input.prop('disabled', true); - this.el_hiddenInput.prop('disabled', true); + this.inputEl.prop("disabled", true); + this.hiddenInputEl.prop("disabled", true); } }, // determine submit availability _submittable: function() { - var onlyWhitespaces = ($.trim(this.el_input.val()) === ''), - isPhotoAttached = (this.el_photozone.children().length > 0), - isValidPoll = this.view_poll_creator.validatePoll(); + var onlyWhitespaces = ($.trim(this.inputEl.val()) === ""), + isPhotoAttached = (this.photozoneEl.children().length > 0), + isValidPoll = this.viewPollCreator.validatePoll(); return (!onlyWhitespaces || isPhotoAttached) && isValidPoll && !this.disabled; }, handleTextchange: function() { - var self = this; - this.checkSubmitAvailability(); - this.el_input.mentionsInput("val", function(value){ - self.el_hiddenInput.val(value); - }); + this.hiddenInputEl.val(this.mention.getTextForSubmit()); }, _beforeUnload: function(e) { - if(this._submittable() && this.el_input.val() !== this.prefillText){ + if(this._submittable() && this.inputEl.val() !== this.prefillText){ var confirmationMessage = Diaspora.I18n.t("confirm_unload"); (e || window.event).returnValue = confirmationMessage; //Gecko + IE return confirmationMessage; //Webkit, Safari, Chrome, etc. @@ -516,9 +522,9 @@ $.fn.serializeObject = function() if (!o[this.name].push) { o[this.name] = [o[this.name]]; } - o[this.name].push(this.value || ''); + o[this.name].push(this.value || ""); } else { - o[this.name] = this.value || ''; + o[this.name] = this.value || ""; } }); return o; diff --git a/app/assets/javascripts/app/views/reshares_info_view.js b/app/assets/javascripts/app/views/reshares_info_view.js new file mode 100644 index 0000000000000000000000000000000000000000..b91027e8467e55d6f7a4e6eaf9aa633bf6b679d0 --- /dev/null +++ b/app/assets/javascripts/app/views/reshares_info_view.js @@ -0,0 +1,36 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later + +app.views.ResharesInfo = app.views.Base.extend({ + + templateName : "reshares-info", + + events : { + "click .expand-reshares" : "showAvatars" + }, + + tooltipSelector : ".avatar", + + initialize : function() { + this.model.interactions.bind("change", this.render, this); + this.displayAvatars = false; + }, + + presenter : function() { + return _.extend(this.defaultPresenter(), { + reshares : this.model.interactions.reshares.toJSON(), + resharesCount : this.model.interactions.resharesCount(), + displayAvatars : this.model.interactions.get("fetched") && this.displayAvatars + }); + }, + + showAvatars : function(evt){ + if(evt) { evt.preventDefault() } + this.displayAvatars = true; + if(!this.model.interactions.get("fetched")){ + this.model.interactions.fetch(); + } else { + this.model.interactions.trigger("change"); + } + } +}); +// @license-end diff --git a/app/assets/javascripts/app/views/search_base_view.js b/app/assets/javascripts/app/views/search_base_view.js new file mode 100644 index 0000000000000000000000000000000000000000..72b032337db6ecb0663908f9b8b212160da25d7f --- /dev/null +++ b/app/assets/javascripts/app/views/search_base_view.js @@ -0,0 +1,125 @@ +app.views.SearchBase = app.views.Base.extend({ + initialize: function(options) { + this.ignoreDiasporaIds = []; + this.typeaheadInput = options.typeaheadInput; + this.setupBloodhound(options); + if(options.customSearch) { this.setupCustomSearch(); } + this.setupTypeahead(); + // TODO: Remove this as soon as corejavascript/typeahead.js has its first release + this.setupMouseSelectionEvents(); + if(options.autoselect) { this.setupAutoselect(); } + }, + + bloodhoundTokenizer: function(str) { + if(typeof str !== "string") { return []; } + return str.split(/[\s\.:,;\?\!#@\-_\[\]\{\}\(\)]+/).filter(function(s) { return s !== ""; }); + }, + + setupBloodhound: function(options) { + var bloodhoundOptions = { + datumTokenizer: function(datum) { + // hashtags + if(typeof datum.handle === "undefined") { return [datum.name]; } + // people + if(datum.name === datum.handle) { return [datum.handle]; } + return this.bloodhoundTokenizer(datum.name).concat(datum.handle); + }.bind(this), + queryTokenizer: Bloodhound.tokenizers.whitespace, + sufficient: 5 + }; + + // Allow bloodhound to look for remote results if there is a route given in the options + if(options.remoteRoute) { + bloodhoundOptions.remote = { + url: options.remoteRoute + ".json?q=%QUERY", + wildcard: "%QUERY", + transform: this.transformBloodhoundResponse + }; + } + + this.bloodhound = new Bloodhound(bloodhoundOptions); + }, + + setupCustomSearch: function() { + var self = this; + this.bloodhound.customSearch = function(query, sync, async) { + var _async = function(datums) { + var results = datums.filter(function(datum) { + return datum.handle !== undefined && self.ignoreDiasporaIds.indexOf(datum.handle) === -1; + }); + async(results); + }; + + self.bloodhound.search(query, sync, _async); + }; + }, + + setupTypeahead: function() { + this.typeaheadInput.typeahead({ + hint: false, + highlight: true, + minLength: 2 + }, { + async: true, + display: "name", + limit: 5, + source: this.bloodhound.customSearch !== undefined ? this.bloodhound.customSearch : this.bloodhound, + templates: { + /* jshint camelcase: false */ + suggestion: HandlebarsTemplates.search_suggestion_tpl + /* jshint camelcase: true */ + } + }); + }, + + transformBloodhoundResponse: function(response) { + return response.map(function(data) { + // person + if(data.handle) { + data.person = true; + return data; + } + + // hashtag + return { + hashtag: true, + name: data.name, + url: Routes.tag(data.name.substring(1)) + }; + }); + }, + + _deselectAllSuggestions: function() { + this.$(".tt-suggestion").removeClass("tt-cursor"); + }, + + _selectSuggestion: function(suggestion) { + this._deselectAllSuggestions(); + suggestion.addClass("tt-cursor"); + }, + + // TODO: Remove this as soon as corejavascript/typeahead.js has its first release + setupMouseSelectionEvents: function() { + var self = this, + selectSuggestion = function(e) { self._selectSuggestion($(e.target).closest(".tt-suggestion")); }, + deselectAllSuggestions = function() { self._deselectAllSuggestions(); }; + + this.typeaheadInput.on("typeahead:render", function() { + self.$(".tt-menu .tt-suggestion").off("mouseover").on("mouseover", selectSuggestion); + self.$(".tt-menu .tt-suggestion *").off("mouseover").on("mouseover", selectSuggestion); + self.$(".tt-menu .tt-suggestion").off("mouseleave").on("mouseleave", deselectAllSuggestions); + }); + }, + + // Selects the first result when the result dropdown opens + setupAutoselect: function() { + var self = this; + this.typeaheadInput.on("typeahead:render", function() { + self._selectSuggestion(self.$(".tt-menu .tt-suggestion").first()); + }); + }, + + ignorePersonForSuggestions: function(person) { + if(person.handle) { this.ignoreDiasporaIds.push(person.handle); } + }, +}); diff --git a/app/assets/javascripts/app/views/search_view.js b/app/assets/javascripts/app/views/search_view.js index aed2e54ca48787c829cb51164f4bcbc9bcdc1593..254bcb071a1c7c657b373c28db03bc7b08091be3 100644 --- a/app/assets/javascripts/app/views/search_view.js +++ b/app/assets/javascripts/app/views/search_view.js @@ -1,72 +1,35 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later -app.views.Search = app.views.Base.extend({ - initialize: function(){ - this.searchFormAction = this.$el.attr('action'); - this.searchInput = this.$('input[type="search"]'); - this.searchInputName = this.$('input[type="search"]').attr('name'); - this.searchInputHandle = this.$('input[type="search"]').attr('handle'); - this.options = { - cacheLength: 15, - delay: 800, - extraParams: {limit: 4}, - formatItem: this.formatItem, - formatResult: this.formatResult, - max: 5, - minChars: 2, - onSelect: this.selectItemCallback, - parse: this.parse, - scroll: false, - context: this - }; - - var self = this; - this.searchInput.autocomplete(self.searchFormAction + '.json', - $.extend(self.options, { element: self.searchInput })); - }, - - formatItem: function(row){ - if(typeof row.search !== 'undefined') { return Diaspora.I18n.t('search_for', row); } - else { - var item = ''; - if (row.avatar) { item += '<img src="' + row.avatar + '" class="avatar"/>'; } - item += row.name; - if (row.handle) { item += '<div class="search_handle">' + row.handle + '</div>'; } - return item; - } +app.views.Search = app.views.SearchBase.extend({ + events: { + "focusin #q": "toggleSearchActive", + "focusout #q": "toggleSearchActive", + "keypress #q": "inputKeypress" }, - formatResult: function(row){ return Handlebars.Utils.escapeExpression(row.name); }, - - parse: function(data) { - var self = this.context; - - var results = data.map(function(person){ - person.name = self.formatResult(person); - return {data : person, value : person.name}; + initialize: function() { + this.searchInput = this.$("#q"); + app.views.SearchBase.prototype.initialize.call(this, { + typeaheadInput: this.searchInput, + remoteRoute: this.$el.attr("action") }); - - results.push({ - data: { - name: self.searchInput.val(), - url: self.searchFormAction + '?' + self.searchInputName + '=' + self.searchInput.val(), - search: true - }, - value: self.searchInput.val() - }); - - return results; + this.searchInput.on("typeahead:select", this.suggestionSelected); }, - selectItemCallback: function(evt, data, formatted){ - var self = this.context; + toggleSearchActive: function(evt) { + // jQuery produces two events for focus/blur (for bubbling) + // don't rely on which event arrives first, by allowing for both variants + var isActive = (_.indexOf(["focus","focusin"], evt.type) !== -1); + $(evt.target).toggleClass("active", isActive); + }, - if(data.search === true){ - window.location = self.searchFormAction + '?' + self.searchInputName + '=' + data.name; - } - else{ // The actual result - self.options.element.val(formatted); - window.location = data.url ? data.url : '/tags/' + data.name.substring(1); + inputKeypress: function(evt) { + if(evt.which === Keycodes.ENTER && $(".tt-suggestion.tt-cursor").length === 0) { + $(evt.target).closest("form").submit(); } + }, + + suggestionSelected: function(evt, datum) { + window.location = datum.url; } }); // @license-ends diff --git a/app/assets/javascripts/app/views/sidebar.js b/app/assets/javascripts/app/views/sidebar.js index d73dbf100dcf9de505ead55f82be24de0078c692..f5ce24b80fdd5f7087039a0baafd8355719d4874 100644 --- a/app/assets/javascripts/app/views/sidebar.js +++ b/app/assets/javascripts/app/views/sidebar.js @@ -1,15 +1,19 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.Sidebar = app.views.Base.extend({ - el: '.rightBar', + el: ".info-bar", events: { - 'click input#invite_code': 'selectInputText' + "click input#invite_code": "selectInputText", + "click .section .title": "toggleSection" }, selectInputText: function(event) { event.target.select(); + }, + + toggleSection: function(e) { + $(e.target).closest(".section").toggleClass("collapsed"); } }); // @license-end - diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js index ebb0a9dbf632b52bd28fd3483568290330531bfd..63ef065f6725a36c29218d3770c8891a4bbb52af 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js @@ -8,19 +8,19 @@ app.views.SinglePostCommentStream = app.views.CommentStream.extend({ }, highlightPermalinkComment: function() { - if(document.location.hash){ + if (document.location.hash && $(document.location.hash).length > 0) { var element = $(document.location.hash); - var headerSize = 50; + var headerSize = 60; $(".highlighted").removeClass("highlighted"); element.addClass("highlighted"); var pos = element.offset().top - headerSize; - $("html").animate({scrollTop:pos}); + window.scroll(0, pos); } }, postRenderTemplate: function() { app.views.CommentStream.prototype.postRenderTemplate.apply(this); - this.$(".new_comment_form_wrapper").removeClass('hidden'); + this.$(".new-comment-form-wrapper").removeClass("hidden"); _.defer(this.highlightPermalinkComment); }, diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js index 967b72f9f6ed8ee4e845cddf33ed69cb59648a79..c58cf08af7cea105044d447dbde26676962a5965 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js @@ -1,17 +1,17 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.SinglePostContent = app.views.Base.extend({ - templateName: 'single-post-viewer/single-post-content', + templateName: "single-post-viewer/single-post-content", tooltipSelector: "time, .post_scope", + className: "framed-content", subviews : { "#single-post-actions" : "singlePostActionsView", - '#single-post-moderation': "singlePostModerationView", - '#real-post-content' : 'postContentView', + "#single-post-moderation": "singlePostModerationView", + "#real-post-content" : "postContentView", ".oembed" : "oEmbedView", ".opengraph" : "openGraphView", - ".status-message-location" : "postLocationStreamView", - '.poll': 'pollView', + ".poll": "pollView", }, initialize : function() { @@ -23,8 +23,25 @@ app.views.SinglePostContent = app.views.Base.extend({ this.pollView = new app.views.Poll({ model: this.model }); }, - postLocationStreamView : function(){ - return new app.views.LocationStream({ model : this.model}); + map : function(){ + if (this.$(".mapContainer").length < 1){ return; } + + // find and set height of mapContainer to max size of the container + // which is necessary to have all necessary tiles prerendered + var mapContainer = this.$(".mapContainer"); + mapContainer.css("height", "200px"); + + // get location data and render map + var location = this.model.get("location"); + + var map = L.map(mapContainer[0]).setView([location.lat, location.lng], 14); + var tiles = app.helpers.locations.getTiles(); + + tiles.addTo(map); + + // put marker on map + L.marker(location).addTo(map); + return map; }, presenter : function() { @@ -37,6 +54,10 @@ app.views.SinglePostContent = app.views.Base.extend({ showPost : function() { return (app.currentUser.get("showNsfw")) || !this.model.get("nsfw"); + }, + + postRenderTemplate : function(){ + _.defer(_.bind(this.map, this)); } }); // @license-end diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_interactions.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_interactions.js index b8c4a8661a0f766b7d4da926b36dc9f467d9022e..9549a74a5d639653d8f1d3d0ba50149269f89b61 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_interactions.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_interactions.js @@ -3,6 +3,7 @@ app.views.SinglePostInteractions = app.views.Base.extend({ templateName: "single-post-viewer/single-post-interactions", tooltipSelector: ".avatar.micro", + className: "framed-content", subviews: { '#comments': 'commentStreamView' diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_moderation.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_moderation.js index 8604d1adc91141cc518294bd61736a8fa1a53556..823783da3d59ea965fc98ebb774cbf0a506cf90c 100644 --- a/app/assets/javascripts/app/views/single-post-viewer/single_post_moderation.js +++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_moderation.js @@ -1,7 +1,7 @@ app.views.SinglePostModeration = app.views.Feedback.extend({ templateName: "single-post-viewer/single-post-moderation", - className: 'control-icons', + className: "control-icons", events: function() { return _.defaults({ @@ -19,7 +19,7 @@ app.views.SinglePostModeration = app.views.Feedback.extend({ renderPluginWidgets : function() { app.views.Base.prototype.renderPluginWidgets.apply(this); - this.$('a').tooltip({placement: 'bottom'}); + this.$("a").tooltip({placement: "bottom"}); }, authorIsCurrentUser: function() { @@ -28,7 +28,7 @@ app.views.SinglePostModeration = app.views.Feedback.extend({ destroyModel: function(evt) { if(evt) { evt.preventDefault(); } - var url = this.model.urlRoot + '/' + this.model.id; + var url = this.model.urlRoot + "/" + this.model.id; if (confirm(Diaspora.I18n.t("remove_post"))) { this.model.destroy({ url: url }) @@ -37,11 +37,7 @@ app.views.SinglePostModeration = app.views.Feedback.extend({ document.location.href = "/stream"; }) .fail(function() { - var flash = new Diaspora.Widgets.FlashMessages(); - flash.render({ - success: false, - notice: Diaspora.I18n.t('failed_to_remove') - }); + app.flashMessages.error(Diaspora.I18n.t("failed_to_remove")); }); } }, diff --git a/app/assets/javascripts/app/views/stream/shortcuts.js b/app/assets/javascripts/app/views/stream/shortcuts.js index b09c6e753bc0294a1a56d44a7dee68eb8cb8b573..dd62588c9f799f5270be7cf7febddb3cafef89ff 100644 --- a/app/assets/javascripts/app/views/stream/shortcuts.js +++ b/app/assets/javascripts/app/views/stream/shortcuts.js @@ -1,7 +1,7 @@ // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later app.views.StreamShortcuts = Backbone.View.extend({ - _headerSize: 50, + _headerSize: 60, events: { "keydown": "_onHotkeyDown", @@ -57,35 +57,35 @@ app.views.StreamShortcuts = Backbone.View.extend({ gotoNext: function() { // select next post: take the first post under the header - var stream_elements = this.$('div.stream_element.loaded'); + var streamElements = this.$("div.stream_element.loaded"); var posUser = window.pageYOffset; - for (var i = 0; i < stream_elements.length; i++) { - if(stream_elements[i].offsetTop>posUser+this._headerSize){ - this.selectPost(stream_elements[i]); + for (var i = 0; i < streamElements.length; i++) { + if (Math.round($(streamElements[i]).offset().top) > posUser + this._headerSize) { + this.selectPost(streamElements[i]); return; } } // standard: last post - if(stream_elements[stream_elements.length-1]){ - this.selectPost(stream_elements[stream_elements.length-1]); + if (streamElements[streamElements.length - 1]) { + this.selectPost(streamElements[streamElements.length - 1]); } }, gotoPrev: function() { // select previous post: take the first post above the header - var stream_elements = this.$('div.stream_element.loaded'); + var streamElements = this.$("div.stream_element.loaded"); var posUser = window.pageYOffset; - for (var i = stream_elements.length-1; i >=0; i--) { - if(stream_elements[i].offsetTop<posUser+this._headerSize){ - this.selectPost(stream_elements[i]); + for (var i = streamElements.length - 1; i >= 0; i--) { + if (Math.round($(streamElements[i]).offset().top) < posUser + this._headerSize) { + this.selectPost(streamElements[i]); return; } } // standard: first post - if(stream_elements[0]){ - this.selectPost(stream_elements[0]); + if (streamElements[0]) { + this.selectPost(streamElements[0]); } }, @@ -118,7 +118,7 @@ app.views.StreamShortcuts = Backbone.View.extend({ var selected=this.$('div.stream_element.loaded.shortcut_selected'); selected.removeClass('shortcut_selected').removeClass('highlighted'); //move to new post - window.scrollTo(window.pageXOffset, element.offsetTop-this._headerSize); + window.scrollTo(window.pageXOffset, Math.round($(element).offset().top - this._headerSize)); //add the selection and selected-class to new post element.className+=" shortcut_selected highlighted"; }, diff --git a/app/assets/javascripts/app/views/stream_faces_view.js b/app/assets/javascripts/app/views/stream_faces_view.js deleted file mode 100644 index 6ad00d057de1f24dfa82e9cc6c2e6a302296597f..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/app/views/stream_faces_view.js +++ /dev/null @@ -1,33 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later - -app.views.StreamFaces = app.views.Base.extend({ - - templateName : "stream-faces", - - className : "stream-faces", - - tooltipSelector : ".avatar", - - initialize : function(){ - this.updatePeople(); - app.stream.items.bind("add", this.updatePeople, this); - app.stream.items.bind("remove", this.updatePeople, this); - }, - - presenter : function() { - return {people : this.people}; - }, - - updatePeople : function(){ - if(this.people && this.people.length >= 15) { return } - this.people = _(this.collection.models).chain() - .map(function(post){ return post.get("author") }) - .compact() - .uniq(false, function(person){ return person.id }) - .value() - .slice(0,15); - - this.render(); - } -}); -// @license-end diff --git a/app/assets/javascripts/app/views/stream_post_views.js b/app/assets/javascripts/app/views/stream_post_views.js index 4fe9bdb82a75b60b7c00ddc4986be9dd943d0e40..b298cd0adcec15ee9fdb06d6848612b25c574243 100644 --- a/app/assets/javascripts/app/views/stream_post_views.js +++ b/app/assets/javascripts/app/views/stream_post_views.js @@ -7,6 +7,7 @@ app.views.StreamPost = app.views.Post.extend({ subviews : { ".feedback" : "feedbackView", ".likes" : "likesInfoView", + ".reshares" : "resharesInfoView", ".comments" : "commentStreamView", ".post-content" : "postContentView", ".oembed" : "oEmbedView", @@ -29,13 +30,20 @@ app.views.StreamPost = app.views.Post.extend({ "click .destroy_participation": "destroyParticipation" }, - tooltipSelector : ".timeago, .post_scope, .post_report, .block_user, .delete, .create_participation, .destroy_participation", + tooltipSelector : [".timeago", + ".post_scope", + ".post_report", + ".block_user", + ".delete", + ".create_participation", + ".destroy_participation", + ".permalink"].join(", "), initialize : function(){ - var personId = this.model.get('author').id; - app.events.on('person:block:'+personId, this.remove, this); + var personId = this.model.get("author").id; + app.events.on("person:block:"+personId, this.remove, this); - this.model.on('remove', this.remove, this); + this.model.on("remove", this.remove, this); //subviews this.commentStreamView = new app.views.CommentStream({model : this.model}); this.oEmbedView = new app.views.OEmbed({model : this.model}); @@ -48,6 +56,10 @@ app.views.StreamPost = app.views.Post.extend({ return new app.views.LikesInfo({model : this.model}); }, + resharesInfoView : function(){ + return new app.views.ResharesInfo({model : this.model}); + }, + feedbackView : function(){ if(!app.currentUser.authenticated()) { return null } return new app.views.Feedback({model : this.model}); @@ -78,14 +90,11 @@ app.views.StreamPost = app.views.Post.extend({ blockUser: function(evt){ if(evt) { evt.preventDefault(); } - if(!confirm(Diaspora.I18n.t('ignore_user'))) { return } + if(!confirm(Diaspora.I18n.t("ignore_user"))) { return } this.model.blockAuthor() .fail(function() { - Diaspora.page.flashMessages.render({ - success: false, - notice: Diaspora.I18n.t('ignore_failed') - }); + app.flashMessages.error(Diaspora.I18n.t("ignore_failed")); }); }, @@ -97,7 +106,7 @@ app.views.StreamPost = app.views.Post.extend({ hidePost : function(evt) { if(evt) { evt.preventDefault(); } - if(!confirm(Diaspora.I18n.t('confirm_dialog'))) { return } + if(!confirm(Diaspora.I18n.t("confirm_dialog"))) { return } var self = this; $.ajax({ @@ -110,10 +119,7 @@ app.views.StreamPost = app.views.Post.extend({ self.remove(); }) .fail(function() { - Diaspora.page.flashMessages.render({ - success: false, - notice: Diaspora.I18n.t('hide_post_failed') - }); + app.flashMessages.error(Diaspora.I18n.t("hide_post_failed")); }); }, @@ -137,7 +143,7 @@ app.views.StreamPost = app.views.Post.extend({ focusCommentTextarea: function(evt){ evt.preventDefault(); - this.$(".new_comment_form_wrapper").removeClass("hidden"); + this.$(".new-comment-form-wrapper").removeClass("hidden"); this.$(".comment_box").focus(); return this; diff --git a/app/assets/javascripts/app/views/stream_view.js b/app/assets/javascripts/app/views/stream_view.js index d9ed0530634ff8b08ad7ba716549d01ee45dd865..45e2091ff754c1494f139c327ef2fd88c6a63941 100644 --- a/app/assets/javascripts/app/views/stream_view.js +++ b/app/assets/javascripts/app/views/stream_view.js @@ -9,18 +9,13 @@ app.views.Stream = app.views.InfScroll.extend({ this.postViews = []; this.setupNSFW(); - this.setupLightbox(); this.setupInfiniteScroll(); this.markNavSelected(); + this.initInvitationModal(); }, postClass : app.views.StreamPost, - setupLightbox : function(){ - this.lightbox = Diaspora.BaseWidget.instantiate("Lightbox"); - this.$el.delegate("a.stream-photo-link", "click", this.lightbox.lightboxImageClicked); - }, - setupNSFW : function(){ function reRenderPostViews() { _.map(this.postViews, function(view){ view.render() }); @@ -33,6 +28,12 @@ app.views.Stream = app.views.InfScroll.extend({ var streamSelection = $("#stream_selection"); streamSelection.find("[data-stream]").removeClass("selected"); streamSelection.find("[data-stream='" + activeStream + "']").addClass("selected"); + }, + + initInvitationModal : function() { + $(".invitations-link").click(function() { + app.helpers.showModal("#invitationsModal"); + }); } }); // @license-end diff --git a/app/assets/javascripts/app/views/tag_following_action_view.js b/app/assets/javascripts/app/views/tag_following_action_view.js index 37d95ff2a78c43ae19694ca60534d47499f0a3ec..e62754c0c1219bae6b8ab5700f578d204b63ca5f 100644 --- a/app/assets/javascripts/app/views/tag_following_action_view.js +++ b/app/assets/javascripts/app/views/tag_following_action_view.js @@ -43,12 +43,12 @@ app.views.TagFollowingAction = app.views.Base.extend({ }, mouseIn : function(){ - this.$("input").removeClass("green").addClass("btn-danger"); + this.$("input").removeClass("btn-success").addClass("btn-danger"); this.$("input").val( Diaspora.I18n.t('stream.tags.stop_following', {tag: this.model.attributes.name} ) ); }, mouseOut : function() { - this.$("input").removeClass("btn-danger").addClass("green"); + this.$("input").removeClass("btn-danger").addClass("btn-success"); this.$("input").val( Diaspora.I18n.t('stream.tags.following', {"tag" : this.model.attributes.name} ) ); }, diff --git a/app/assets/javascripts/app/views/tag_following_list_view.js b/app/assets/javascripts/app/views/tag_following_list_view.js index 3ccdf3a6e15ee0765c81250693fda3a14dec74f2..0504ab270df934054eef22f1928f9e6905273c44 100644 --- a/app/assets/javascripts/app/views/tag_following_list_view.js +++ b/app/assets/javascripts/app/views/tag_following_list_view.js @@ -46,7 +46,7 @@ app.views.TagFollowingList = app.views.Base.extend({ }); this.$("input").bind('keydown', function(evt){ - if(evt.keyCode === 13 || evt.keyCode === 9 || evt.keyCode === 32){ + if(evt.which === Keycodes.ENTER || evt.which === Keycodes.TAB || evt.which === Keycodes.SPACE) { evt.preventDefault(); if( $('li.as-result-item.active').length === 0 ){ $('li.as-result-item').first().click(); diff --git a/app/assets/javascripts/app/views/tag_following_view.js b/app/assets/javascripts/app/views/tag_following_view.js index 838fd896d93fc11d4918b11902ded80b47aa6bb7..ef6d08e5df18663008350aaedc1b992e0a237134 100644 --- a/app/assets/javascripts/app/views/tag_following_view.js +++ b/app/assets/javascripts/app/views/tag_following_view.js @@ -9,7 +9,7 @@ app.views.TagFollowing = app.views.Base.extend({ tagName: "li", events : { - "click .delete_tag_following": "destroyModel" + "click .delete-tag-following": "destroyModel" }, initialize : function(){ @@ -31,6 +31,6 @@ app.views.TagFollowing = app.views.Base.extend({ tag : this.model }); } - + }); // @license-end diff --git a/app/assets/javascripts/app/views/tags_view.js b/app/assets/javascripts/app/views/tags_view.js index e420281fb7f9fca2558f6b2518ab246e0f8fbc50..3913f87984c5bc98ddc183a63d3c422ccacb55c7 100644 --- a/app/assets/javascripts/app/views/tags_view.js +++ b/app/assets/javascripts/app/views/tags_view.js @@ -2,7 +2,9 @@ app.views.Tags = Backbone.View.extend({ initialize: function(opts) { - app.publisher.setText("#"+ opts.hashtagName + " "); + if(app.publisher) { + app.publisher.setText("#"+ opts.hashtagName + " "); + } } }); // @license-end diff --git a/app/assets/javascripts/aspects-dropdown.js b/app/assets/javascripts/aspects-dropdown.js deleted file mode 100644 index 6c1ea03bcc06ed17eaa87e90f6e4048693d9a019..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/aspects-dropdown.js +++ /dev/null @@ -1,78 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later - -// Copyright (c) 2010-2012, Diaspora Inc. This file is -// licensed under the Affero General Public License version 3 or later. See -// the COPYRIGHT file. - -var AspectsDropdown = { - updateNumber: function(dropdown, personId, number, inAspectClass){ - var button = dropdown.parents(".dropdown").children('.button.toggle'), - selectedAspects = dropdown.children(".selected").length, - allAspects = dropdown.children().length, - replacement, - message, - isInPublisher = dropdown.closest('#publisher').length; - - if (number === 0) { - button.removeClass(inAspectClass); - if (isInPublisher) { - replacement = Diaspora.I18n.t("aspect_dropdown.select_aspects"); - } else { - replacement = Diaspora.I18n.t("aspect_dropdown.add_to_aspect"); - /* flash message prompt */ - message = Diaspora.I18n.t("aspect_dropdown.stopped_sharing_with", {name: dropdown.data('person-short-name')}); - Diaspora.page.flashMessages.render({success: true, notice: message}); - } - } else if (selectedAspects === allAspects) { - replacement = Diaspora.I18n.t('aspect_dropdown.all_aspects'); - } else if (number === 1) { - button.addClass(inAspectClass); - replacement = dropdown.find(".selected").first().text(); - /* flash message prompt */ - if (!isInPublisher) { - message = Diaspora.I18n.t("aspect_dropdown.started_sharing_with", {name: dropdown.data('person-short-name')}); - Diaspora.page.flashMessages.render({success: true, notice: message}); - } - } else { - replacement = Diaspora.I18n.t('aspect_dropdown.toggle', { count: number.toString()}); - } - - // if we are in the publisher, we add the visibility icon - if (isInPublisher) { - var icon = $('#visibility-icon'); - if (replacement.trim() === Diaspora.I18n.t('stream.public')) { - icon.removeClass('lock'); - icon.addClass('globe'); - } else { - icon.removeClass('globe'); - icon.addClass('lock'); - } - button.find('.text').text(replacement); - } else { - button.text(replacement + ' â–¼'); - } - }, - - toggleCheckbox: function(check) { - if(!check.hasClass('radio')){ - var selectedAspects = check.closest(".dropdown").find("li.radio"); - AspectsDropdown.uncheckGroup(selectedAspects); - } - - check.toggleClass('selected'); - }, - - toggleRadio: function(check) { - var selectedAspects = check.closest(".dropdown").find("li"); - - AspectsDropdown.uncheckGroup(selectedAspects); - AspectsDropdown.toggleCheckbox(check); - }, - - uncheckGroup: function(elements){ - $.each(elements, function(index, value) { - $(value).removeClass('selected'); - }); - } -}; -// @license-end diff --git a/app/assets/javascripts/bookmarklet.js b/app/assets/javascripts/bookmarklet.js new file mode 100644 index 0000000000000000000000000000000000000000..4755490e403f9a82b15041a071ad73d0a61a7a9d --- /dev/null +++ b/app/assets/javascripts/bookmarklet.js @@ -0,0 +1,56 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later + +var bookmarklet = function(url, width, height, opts) { + var maxLen = 1900; // max GET request length, see #3076 + var maxTitleLen = 128; // cut title after this length, if too long + + // calculate popup dimensions & placement + var dim = function() { + var w = window, + winTop = (w.screenTop ? w.screenTop : w.screenY), + winLeft = (w.screenLeft ? w.screenLeft : w.screenX), + top = (winTop + (w.innerHeight / 2) - (height / 2)), + left = (winLeft + (w.innerWidth / 2) - (width / 2)); + return "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left; + }; + + // prepare url parameters + var params = function() { + var w = window, + d = document, + href = w.location.href, + title = d.title, + sel = w.getSelection ? w.getSelection() : + d.getSelection ? d.getSelection() : + d.selection.createRange().text, + notes = sel.toString(), + len = maxLen - href.length; + + if( (title+notes).length > len ) { + // shorten the text to fit in a GET request + if( title.length > maxTitleLen ) title = title.substr(0, maxTitleLen) + " ..."; + if( notes.length > (len-maxTitleLen) ) notes = notes.substr(0, len-maxTitleLen) + " ..."; + } + + return "url=" + encodeURIComponent(href) + + "&title=" + encodeURIComponent(title) + + "¬es=" + encodeURIComponent(notes); + }; + + // popup (or redirect) action + var act = function() { + var popupOpts = (opts || "location=yes,links=no,scrollbars=yes,toolbar=no"), + jumpUrl = url + "?jump=yes"; + + (window.open(url + "?" + params(), "diaspora_bookmarklet", popupOpts + "," + dim()) || + (window.location.href = jumpUrl + "&" + params())); + }; + + if( /Firefox/.test(navigator.userAgent) ) { + setTimeout(act, 0); + } else { + act(); + } +}; + +// @license-end diff --git a/app/assets/javascripts/browser_detection.js b/app/assets/javascripts/browser_detection.js deleted file mode 100644 index 6a8e5adabeaacecacfb6f360d05cbe4b0678c7ff..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/browser_detection.js +++ /dev/null @@ -1,9 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later - -jQuery.browser = {}; -jQuery.browser.mozilla = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase()); -jQuery.browser.webkit = /webkit/.test(navigator.userAgent.toLowerCase()); -jQuery.browser.opera = /opera/.test(navigator.userAgent.toLowerCase()); -jQuery.browser.msie = /msie/.test(navigator.userAgent.toLowerCase()); -// @license-end - diff --git a/app/assets/javascripts/contact-list.js b/app/assets/javascripts/contact-list.js index 0e8bda50e65a84766d8c3f25687a22999bebf745..3dfa85dc50c075151f3926e6e0513b723cd2f2f0 100644 --- a/app/assets/javascripts/contact-list.js +++ b/app/assets/javascripts/contact-list.js @@ -15,9 +15,15 @@ var List = { }); streamEl.html(string); - $('.aspect_membership_dropdown').each(function(){ - new app.views.AspectMembership({el: this}); - }); + + if (data.contacts) { + var contacts = new app.collections.Contacts(data.contacts); + $(".aspect_membership_dropdown.placeholder").each(function() { + var personId = $(this).data("personId"); + var view = new app.views.AspectMembership({person: contacts.findWhere({"person_id": personId}).person}); + $(this).html(view.render().$el); + }); + } }, startSearchDelay: function (theSearch) { @@ -25,4 +31,3 @@ var List = { } }; // @license-end - diff --git a/app/assets/javascripts/diaspora.js b/app/assets/javascripts/diaspora.js index 157a6ab5e77a504431e0c361c6ca572ad6939d28..b05b2860109b1a2c141158ae2b313ef94675e182 100644 --- a/app/assets/javascripts/diaspora.js +++ b/app/assets/javascripts/diaspora.js @@ -49,7 +49,7 @@ $.extend(Diaspora.Widgets[Widget].prototype, Diaspora.EventBroker.extend(Diaspora.BaseWidget)); var widget = new Diaspora.Widgets[Widget](), - args = Array.prototype.slice.call(arguments, 1); + args = Array.prototype.slice.call(arguments, 1); widget.publish("widget/ready", args); @@ -70,7 +70,6 @@ $.extend(this, { directionDetector: this.instantiate("DirectionDetector"), events: function() { return Diaspora.page.eventsContainer.data("events"); }, - flashMessages: this.instantiate("FlashMessages"), header: this.instantiate("Header", body.find("header")), timeAgo: this.instantiate("TimeAgo") }); @@ -86,7 +85,7 @@ Diaspora.page = new Page(); } - if(!$.mobile)//why does this need this? + if(!$.mobile) // why does this need this? $.extend(Diaspora.page, new Diaspora.BasePage($(document.body))); Diaspora.page.publish("page/ready", [$(document.body)]); }; diff --git a/app/assets/javascripts/helpers/i18n.js b/app/assets/javascripts/helpers/i18n.js index 9be574c459e155380a64b165755c86d322dafaca..42bd7a8864a747700a1409da679786f0b815b746 100644 --- a/app/assets/javascripts/helpers/i18n.js +++ b/app/assets/javascripts/helpers/i18n.js @@ -20,12 +20,11 @@ Diaspora.I18n = { updateLocale: function(locale, data) { locale.data = $.extend(locale.data, data); - var rule = this._resolve(locale, ['pluralization_rule']); - if (rule !== "") { - /* jshint evil:true */ - // TODO change this to `locale.pluralizationKey = rule`? + var rule = locale.data.pluralization_rule; + if (typeof rule !== "undefined") { + /* eslint-disable no-eval */ eval("locale.pluralizationKey = "+rule); - /* jshint evil:false */ + /* eslint-enable no-eval */ } }, @@ -46,14 +45,9 @@ Diaspora.I18n = { : locale.data[nextNamespace]; if(typeof translatedMessage === "undefined") { - if (typeof locale.fallback === "undefined") { - return ""; - } else { - return this._resolve(locale.fallback, originalItems); - } + throw new Error("Missing translation: " + originalItems.join(".")); } } - return translatedMessage; }, @@ -68,7 +62,7 @@ Diaspora.I18n = { return _.template(this._resolve(locale, items))(views || {}); } catch (e) { if (typeof locale.fallback === "undefined") { - return ""; + throw e; } else { return this._render(locale.fallback, originalItems, views); } @@ -77,10 +71,12 @@ Diaspora.I18n = { reset: function() { this.locale.data = {}; + this.locale.fallback.data = {}; - if( arguments.length > 0 && !(_.isEmpty(arguments[0])) ) + if(arguments.length > 0 && !(_.isEmpty(arguments[0]))) { this.locale.data = arguments[0]; + this.locale.fallback.data = arguments[0]; + } } }; // @license-end - diff --git a/app/assets/javascripts/helpers/markdown_editor.js b/app/assets/javascripts/helpers/markdown_editor.js new file mode 100644 index 0000000000000000000000000000000000000000..55df134808d336a5d7202c275ec31fa5fd3c275f --- /dev/null +++ b/app/assets/javascripts/helpers/markdown_editor.js @@ -0,0 +1,162 @@ +Diaspora.MarkdownEditor = function(element, opts) { + this.initialize(element, opts); +}; + +Diaspora.MarkdownEditor.prototype = { + constructor: Diaspora.MarkdownEditor, + + initialize: function(element, opts) { + this.options = { + resize: "none", + onHidePreview: $.noop, + onPostPreview: $.noop + }; + + $.extend(this.options, opts); + + this.options.fullscreen = {enable: false, icons: {}}; + this.options.language = this.localize(); + this.options.hiddenButtons = ["cmdPreview"]; + this.options.onShow = this.onShow.bind(this); + + $(element).markdown(this.options); + }, + + /** + * Attach the $.fn.markdown instance to the current MarkdownEditor instance + * and initializes the preview and edit tabs after the editor is shown. + * @param instance + */ + onShow: function(instance) { + this.instance = instance; + + if (_.isFunction(this.options.onPreview)) { + instance.$editor.find(".md-header").remove(".write-preview-tabs").prepend(this.createTabsElement()); + } + + if (_.isFunction(this.options.onClose)) { + instance.$editor.find(".md-header").remove(".md-cancel").append(this.createCloseElement()); + } + + // Monkey patch to change icons. Will have to PR upstream + var icons = { + cmdUrl: ["glyphicon-link", "entypo-link"], + cmdImage: ["glyphicon-picture", "entypo-picture"], + cmdList: ["glyphicon-list", "entypo-list"], + cmdListO: ["glyphicon-th-list", "entypo-numbered-list"], + cmdCode: ["glyphicon-asterisk", "entypo-code"], + cmdQuote: ["glyphicon-comment", "entypo-comment"] + }; + + Object.keys(icons).forEach(function(key) { + instance.$editor.find("[data-handler='bootstrap-markdown-" + key + "']").find(".glyphicon") + .removeClass("glyphicon").removeClass(icons[key][0]) + .addClass(icons[key][1]); + }); + }, + + /** + * Creates write and preview tabs inside the markdown editor header. + * @returns {jQuery} The created tabs + */ + createTabsElement: function() { + var self = this; + + var tabElement = $("<ul class='nav nav-tabs btn-group write-preview-tabs'></ul>"); + + var writeTab = $("<li class='active full-height' role='presentation'></li>"); + this.writeLink = $("<a class='full-height md-write-tab' href='#'></a>") + .attr("title", Diaspora.I18n.t("publisher.markdown_editor.tooltips.write")); + + this.writeLink.append($("<i class='visible-sm visible-xs visible-md diaspora-custom-compose'></i>")); + this.writeLink.append($("<span class='hidden-sm hidden-xs hidden-md tab-help-text'></span>") + .text(Diaspora.I18n.t("publisher.markdown_editor.write"))); + + this.writeLink.click(function(evt) { + evt.preventDefault(); + self.hidePreview(); + }); + + writeTab.append(this.writeLink); + + var previewTab = $("<li class='full-height' role='presentation'></li>"); + this.previewLink = $("<a class='full-height md-preview-tab' href='#'></a>") + .attr("title", Diaspora.I18n.t("publisher.markdown_editor.tooltips.preview")); + + this.previewLink.append($("<i class='visible-sm visible-xs visible-md entypo-search'>")); + this.previewLink.append($("<span class='hidden-sm hidden-xs hidden-md tab-help-text'></span>") + .text(Diaspora.I18n.t("publisher.markdown_editor.preview"))); + + this.previewLink.click(function(evt) { + evt.preventDefault(); + self.showPreview(); + }); + + previewTab.append(this.previewLink); + + return tabElement.append(writeTab).append(previewTab); + }, + + /** + * Creates a cancel button that executes {options#onClose} on click. + * @returns {jQuery} The created cancel button + */ + createCloseElement: function() { + var self = this; + var button = $("<a class='md-cancel btn btn-sm btn-link hidden-xs pull-right'></a>") + .attr("title", Diaspora.I18n.t("publisher.markdown_editor.tooltips.cancel")); + + button.click(function() { + self.hidePreview(); + self.options.onClose(); + }); + + return button.append($("<i class='entypo-cross'></i>")); + }, + + hidePreview: function() { + if (this.writeLink) { + this.writeLink.tab("show"); + this.instance.hidePreview(); + this.options.onHidePreview(); + } + }, + + showPreview: function() { + if (this.previewLink) { + this.previewLink.tab("show"); + this.instance.showPreview(); + this.options.onPostPreview(); + } + }, + + localize: function() { + var locale = Diaspora.I18n.language; + + $.fn.markdown.messages[locale] = { + "Bold": Diaspora.I18n.t("publisher.markdown_editor.tooltips.bold"), + "Italic": Diaspora.I18n.t("publisher.markdown_editor.tooltips.italic"), + "Heading": Diaspora.I18n.t("publisher.markdown_editor.tooltips.heading"), + "URL/Link": Diaspora.I18n.t("publisher.markdown_editor.tooltips.insert_link"), + "Image": Diaspora.I18n.t("publisher.markdown_editor.tooltips.insert_image"), + "Ordered List": Diaspora.I18n.t("publisher.markdown_editor.tooltips.insert_ordered_list"), + "Unordered List": Diaspora.I18n.t("publisher.markdown_editor.tooltips.insert_unordered_list"), + "Preview": Diaspora.I18n.t("publisher.markdown_editor.tooltips.preview"), + "Quote": Diaspora.I18n.t("publisher.markdown_editor.tooltips.quote"), + "Code": Diaspora.I18n.t("publisher.markdown_editor.tooltips.code"), + "strong text": Diaspora.I18n.t("publisher.markdown_editor.texts.strong"), + "emphasized text": Diaspora.I18n.t("publisher.markdown_editor.texts.italic"), + "heading text": Diaspora.I18n.t("publisher.markdown_editor.texts.heading"), + "enter link description here": Diaspora.I18n.t("publisher.markdown_editor.texts.insert_link_description_text"), + "Insert Hyperlink": Diaspora.I18n.t("publisher.markdown_editor.texts.insert_link_help_text"), + "enter image description here": Diaspora.I18n.t("publisher.markdown_editor.texts.insert_image_description_text"), + "Insert Image Hyperlink": Diaspora.I18n.t("publisher.markdown_editor.texts.insert_image_help_text"), + "enter image title here": Diaspora.I18n.t("publisher.markdown_editor.texts.insert_image_title"), + "list text here": Diaspora.I18n.t("publisher.markdown_editor.texts.list"), + "quote here": Diaspora.I18n.t("publisher.markdown_editor.texts.quote"), + "code text here": Diaspora.I18n.t("publisher.markdown_editor.texts.code") + }; + + return locale; + } +}; diff --git a/app/assets/javascripts/jasmine-load-all.js b/app/assets/javascripts/jasmine-load-all.js index 793b86e0e9248742c6384c187be7b117b44cae92..37920dc4006f2afc8fff9a74e9baa85fe7ecbc30 100644 --- a/app/assets/javascripts/jasmine-load-all.js +++ b/app/assets/javascripts/jasmine-load-all.js @@ -1,4 +1,4 @@ -//= require jquery +//= require jquery2 //= require handlebars.runtime //= require templates //= require main diff --git a/app/assets/javascripts/jsxc.js b/app/assets/javascripts/jsxc.js index cf75c913bf64a927e2c3757ca64907dceb5f6288..d2774dafbc0f8a1099916628c768a3c1f8cc25c6 100644 --- a/app/assets/javascripts/jsxc.js +++ b/app/assets/javascripts/jsxc.js @@ -12,7 +12,6 @@ $(document).ready(function() { var jid = app.currentUser.get('diaspora_id'); jsxc.init({ root: '/assets/diaspora_jsxc', - logoutElement: $('.user-menu-item [data-method=delete]'), rosterAppend: 'body', otr: { debug: true, diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index beaf399ee7eabeea048c5b36e77bc9e8de559bd3..e5b5a8688e5f204cbe1b3e085fd0e888cc2bb0dc 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -6,19 +6,13 @@ //= require js-routes //= require underscore //= require backbone -//= require jquery.hotkeys //= require jquery.remotipart -//= require jquery.autoresize -//= require jquery.charcount +//= require autosize +//= require charcount //= require jquery-placeholder //= require rails-timeago -//= require jquery.facebox -//= require browser_detection //= require jquery.events.input -//= require jakobmattsson-jquery-elastic -//= require jquery.mentionsInput //= require jquery.infinitescroll-custom -//= require jquery.autocomplete-custom //= require jquery-ui/core //= require jquery-ui/widget //= require jquery-ui/mouse @@ -36,15 +30,18 @@ //= require markdown-it-sup //= require highlightjs //= require clear-form +//= require typeahead.bundle.js //= require app/app //= require diaspora //= require_tree ./helpers //= require_tree ./pages //= require_tree ./widgets -//= require aspects-dropdown -//= require mentions -//= require bootstrap-tooltip -//= require bootstrap-popover -//= require bootstrap-dropdown -//= require bootstrap-modal +//= require bootstrap //= require osmlocator +//= require bootstrap-switch +//= require blueimp-gallery +//= require blueimp-gallery/blueimp-gallery-indicator +//= require leaflet +//= require api/authorization_page +// = require bootstrap-markdown/bootstrap-markdown +// = require helpers/markdown_editor diff --git a/app/assets/javascripts/mentions.js b/app/assets/javascripts/mentions.js deleted file mode 100644 index 33058ae6703d8784df3ded4a9f7e311dabb5d2a7..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/mentions.js +++ /dev/null @@ -1,49 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later - -var Mentions = { - initialize: function(mentionsInput) { - return mentionsInput.mentionsInput(Mentions.options); - }, - - // pre-fetch the list of contacts for the current user. - // called by the initializer of the publisher, for faster ('offline') - // execution of the filtering for mentions - fetchContacts : function(){ - Mentions.contacts || $.getJSON("/contacts", function(data) { - Mentions.contacts = Mentions.createList(data); - }); - }, - - // creates a list of mentions out of a list of contacts - // @see _contactToMention - createList: function(contacts) { - return _.map(contacts, Mentions._contactToMention); - }, - - // takes a given contact object and modifies to fit the format - // expected by the jQuery.mentionsInput plugin. - // @see http://podio.github.com/jquery-mentions-input/ - _contactToMention: function(contact) { - contact.value = contact.name; - return contact; - }, - - // default options for jQuery.mentionsInput - // @see http://podio.github.com/jquery-mentions-input/ - options: { - elastic: false, - minChars: 1, - - onDataRequest: function(mode, query, callback) { - var filteredResults = _.filter(Mentions.contacts, function(item) { return item.name.toLowerCase().indexOf(query.toLowerCase()) > -1 }); - - callback.call(this, filteredResults.slice(0,5)); - }, - - templates: { - mentionItemSyntax: _.template("@{<%= name %> ; <%= handle %>}") - } - } -}; -// @license-end - diff --git a/app/assets/javascripts/mobile/mobile.js b/app/assets/javascripts/mobile/mobile.js index 5a97bd54f63f3e08de5355282989662195948fc3..fad57b3f0ee09f2ac01df3ce40fa227eca385865 100644 --- a/app/assets/javascripts/mobile/mobile.js +++ b/app/assets/javascripts/mobile/mobile.js @@ -4,302 +4,25 @@ * licensed under the Affero General Public License version 3 or later. See * the COPYRIGHT file. */ -//= require jquery.charcount +//= require jquery-textchange +//= require charcount //= require js-routes -//= require mbp-helper +//= require autosize +//= require keycodes //= require jquery.autoSuggest.custom //= require fileuploader-custom //= require rails-timeago //= require underscore +//= require bootstrap //= require diaspora //= require helpers/i18n //= require widgets/timeago +//= require mobile/mobile_application //= require mobile/mobile_file_uploader //= require mobile/profile_aspects //= require mobile/tag_following - -$(document).ready(function(){ - - $('.shield a').click(function(){ - $(this).parents('.shield_wrapper').remove(); - return false; - }); - var showLoader = function(link){ - link.addClass('loading'); - }; - - var removeLoader = function(link){ - link.removeClass('loading') - .toggleClass('active') - .toggleClass('inactive'); - }; - - /* Drawer menu */ - $('#menu_badge').bind("tap click", function(evt){ - evt.preventDefault(); - $("#app").toggleClass('draw'); - }); - - /* Show / hide aspects in the drawer */ - $('#all_aspects').bind("tap click", function(evt){ - evt.preventDefault(); - $("#all_aspects + li").toggleClass('hide'); - }); - - /* Show / hide followed tags in the drawer */ - $('#followed_tags').bind("tap click", function(evt){ - evt.preventDefault(); - $("#followed_tags + li").toggleClass('hide'); - }); - - /* Heart toggle */ - $(".like_action", ".stream").bind("tap click", function(evt){ - evt.preventDefault(); - var link = $(this), - likeCounter = $(this).closest(".stream_element").find("like_count"), - href = link.attr("href"); - - if(!link.hasClass("loading")){ - if(link.hasClass('inactive')) { - $.ajax({ - url: href, - dataType: 'json', - type: 'POST', - beforeSend: showLoader(link), - success: function(data){ - removeLoader(link); - link.attr("href", href + "/" + data["id"]); - - if(likeCounter){ - likeCounter.text(parseInt(likeCounter.text) + 1); - } - } - }); - } - else if(link.hasClass("active")){ - $.ajax({ - url: link.attr("href"), - dataType: 'json', - type: 'DELETE', - beforeSend: showLoader(link), - complete: function(){ - removeLoader(link); - link.attr("href", href.replace(/\/\d+$/, '')); - - if(likeCounter){ - likeCounter.text(parseInt(likeCounter.text) - 1); - } - } - }); - } - } - }); - - /* Reshare */ - $(".reshare_action", ".stream").bind("tap click", function(evt){ - evt.preventDefault(); - - var link = $(this), - href = link.attr("href"), - confirmText = link.attr('title'); - - if(!link.hasClass("loading")) { - if(link.hasClass('inactive')) { - if(confirm(confirmText)) { - $.ajax({ - url: href + "&provider_display_name=mobile", - dataType: 'json', - type: 'POST', - beforeSend: showLoader(link), - success: function(){ - removeLoader(link); - }, - error: function(){ - removeLoader(link); - alert(Diaspora.I18n.t('failed_to_reshare')); - } - }); - } - } - } - }); - - /* Show comments */ - $("a.show_comments", ".stream").bind("tap click", function(evt){ - evt.preventDefault(); - var link = $(this), - parent = link.closest(".bottom_bar").first(), - commentsContainer = function(){ return parent.find(".comment_container").first(); }, - existingCommentsContainer = commentsContainer(); - - if( link.hasClass('active') ) { - existingCommentsContainer.hide(); - if(!link.hasClass('bottom_collapse')){ - link.removeClass('active'); - } else { - parent.find(".show_comments").first().removeClass('active'); - } - - $('html,body').scrollTop(parent.offset().top - parent.closest(".stream_element").height() - 8); - - } else if( existingCommentsContainer.length > 0) { - - if(!existingCommentsContainer.hasClass('noComments')) { - $.ajax({ - url: link.attr('href'), - success: function(data){ - parent.append($(data).find('.comments_container').html()); - link.addClass('active'); - existingCommentsContainer.show(); - scrollToOffset(parent, commentsContainer()); - commentsContainer().find('time.timeago').timeago(); - } - }); - } else { - existingCommentsContainer.show(); - existingCommentsContainer.find('time.timeago').timeago(); - } - - link.addClass('active'); - - } else { - $.ajax({ - url: link.attr('href'), - success: function(data){ - parent.append(data); - link.addClass('active'); - scrollToOffset(parent, commentsContainer()); - commentsContainer().find('time.timeago').timeago(); - } - }); - } - }); - - var scrollToOffset = function(parent, commentsContainer){ - var commentCount = commentsContainer.find("li.comment").length; - if( commentCount > 3 ) { - var lastComment = commentsContainer.find("li:nth-child("+(commentCount-4)+")"); - $('html,body').animate({ - scrollTop: lastComment.offset().top - }, 1000); - } - }; - - $(".stream").delegate("a.comment_action", "tap click", function(evt){ - evt.preventDefault(); - var link = $(this); - - if(link.hasClass('inactive')) { - var parent = link.closest(".bottom_bar").first(), - container = link.closest('.bottom_bar').find('.add_comment_bottom_link_container').first(); - - $.ajax({ - url: link.attr('href'), - beforeSend: function(){ - link.addClass('loading'); - }, - context: link, - success: function(data){ - var textarea = function(target) { return target.closest(".stream_element").find('textarea.comment_box').first()[0] }; - link.removeClass('loading'); - - if(!link.hasClass("add_comment_bottom_link")){ - link.removeClass('inactive'); - } - - container.hide(); - parent.append(data); - - MBP.autogrow(textarea($(this))); - } - }); - } - }); - - $(".stream").delegate("a.cancel_new_comment", "tap click", function(evt){ - evt.preventDefault(); - var link = $(this), - form = link.closest("form"), - commentActionLink = link.closest(".bottom_bar").find("a.comment_action").first(), - container = link.closest('.bottom_bar').find('.add_comment_bottom_link_container'); - - if(container.length > 0 ){ - container.first().show(); - } - - commentActionLink.addClass("inactive"); - form.remove(); - }); - - $(document).on("submit", ".new_comment", function(evt){ - evt.preventDefault(); - var form = $(this); - - $.post(form.attr('action')+"?format=mobile", form.serialize(), function(data){ - var bottomBar = form.closest('.bottom_bar').first(), - container = bottomBar.find('.add_comment_bottom_link_container'), - commentActionLink = bottomBar.find("a.comment_action").first(), - reactionLink = bottomBar.find(".show_comments").first(), - commentCount = bottomBar.find(".comment_count"); - - if(container.length > 0) { - container.before(data); - form.remove(); - container.show(); - - } else { - var comments = $("<ul class='comments'></ul>"); - container = $("<div class='comments_container not_all_present'></div>"); - - comments.html(data); - container.append(comments); - form.remove(); - container.appendTo(bottomBar); - } - - reactionLink.text(reactionLink.text().replace(/(\d+)/, function(match){ return parseInt(match) + 1; })); - commentCount.text(commentCount.text().replace(/(\d+)/, function(match){ return parseInt(match) + 1; })); - commentActionLink.addClass("inactive"); - bottomBar.find('time.timeago').timeago(); - }, 'html'); - }); - - - $(".service_icon").bind("tap click", function() { - var service = $(this).toggleClass("dim"), - selectedServices = $("#new_status_message .service_icon:not(.dim)"), - provider = service.attr("id"), - hiddenField = $("#new_status_message input[name='services[]'][value='" + provider + "']"), - publisherMaxChars = 40000, - serviceMaxChars; - - - $("#new_status_message .counter").remove(); - - $.each(selectedServices, function() { - serviceMaxChars = parseInt($(this).attr("maxchar")); - if(publisherMaxChars > serviceMaxChars) { - publisherMaxChars = serviceMaxChars; - } - }); - - $('#status_message_text').charCount({allowed: publisherMaxChars, warning: publisherMaxChars/10 }); - - if(hiddenField.length > 0) { hiddenField.remove(); } - else { - $("#new_status_message").append( - $("<input/>", { - name: "services[]", - type: "hidden", - value: provider - }) - ); - } - }); - - $("#submit_new_message").bind("tap click", function(evt){ - evt.preventDefault(); - $("#new_status_message").submit(); - }); -}); +//= require mobile/publisher +//= require mobile/mobile_comments +//= require mobile/mobile_post_actions +//= require mobile/mobile_drawer // @license-end diff --git a/app/assets/javascripts/mobile/mobile_application.js b/app/assets/javascripts/mobile/mobile_application.js new file mode 100644 index 0000000000000000000000000000000000000000..d10e2111d626706c0dc08f0f2f2efdb51ff38647 --- /dev/null +++ b/app/assets/javascripts/mobile/mobile_application.js @@ -0,0 +1,17 @@ +(function(){ + Diaspora.Mobile = { + initialize: function(){ + $(".shield a").click(function(){ + $(this).parents(".stream_element").removeClass("shield-active"); + return false; + }); + + // init autosize plugin + autosize($("textarea")); + } + }; +})(); + +$(document).ready(function(){ + Diaspora.Mobile.initialize(); +}); diff --git a/app/assets/javascripts/mobile/mobile_comments.js b/app/assets/javascripts/mobile/mobile_comments.js new file mode 100644 index 0000000000000000000000000000000000000000..1690b2d9ce26712ea026776509a06d9b6260e480 --- /dev/null +++ b/app/assets/javascripts/mobile/mobile_comments.js @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2010-2011, Diaspora Inc. This file is + * licensed under the Affero General Public License version 3 or later. See + * the COPYRIGHT file. + */ + +(function() { + Diaspora.Mobile.Comments = { + stream: function(){ return $(".stream"); }, + + initialize: function() { + var self = this; + + this.stream().on("tap click", "a.show-comments", function(evt){ + evt.preventDefault(); + self.toggleComments($(this)); + }); + + this.stream().on("tap click", "a.comment-action", function(evt) { + evt.preventDefault(); + self.showCommentBox($(this)); + var bottomBar = $(this).closest(".bottom-bar").first(); + var commentContainer = bottomBar.find(".comment-container").first(); + self.scrollToOffset(commentContainer); + }); + + this.stream().on("submit", ".new_comment", this.submitComment); + }, + + submitComment: function(evt){ + evt.preventDefault(); + var form = $(this); + var commentBox = form.find(".comment_box"); + var commentText = $.trim(commentBox.val()); + if(!commentText){ + commentBox.focus(); + return false; + } + + $.post(form.attr("action") + "?format=mobile", form.serialize(), function(data){ + Diaspora.Mobile.Comments.updateStream(form, data); + }, "html").fail(function(){ + Diaspora.Mobile.Comments.resetCommentBox(this); + }); + + autosize($(".add-comment-switcher:not(.hidden) textarea")); + }, + + toggleComments: function(toggleReactionsLink) { + if(toggleReactionsLink.hasClass("loading")) { return; } + + if(toggleReactionsLink.hasClass("active")) { + this.hideComments(toggleReactionsLink); + toggleReactionsLink.parents(".bottom-bar").find(".add-comment-switcher").addClass("hidden"); + } else { + this.showComments(toggleReactionsLink); + } + }, + + hideComments: function(toggleReactionsLink) { + var bottomBar = toggleReactionsLink.closest(".bottom-bar").first(); + this.bottomBarLazy(bottomBar).deactivate(); + toggleReactionsLink.removeClass("active"); + }, + + showComments: function(toggleReactionsLink) { + var bottomBar = toggleReactionsLink.closest(".bottom-bar").first(), + bottomBarContainer = this.bottomBarLazy(bottomBar), + existingCommentsContainer = bottomBarContainer.getCommentsContainer(), + commentActionLink = bottomBar.find("a.comment-action"); + + bottomBarContainer.activate(); + bottomBarContainer.showLoader(); + + if (existingCommentsContainer.length > 0) { + this.showLoadedComments(toggleReactionsLink, existingCommentsContainer, commentActionLink); + bottomBarContainer.hideLoader(); + } else { + this.showUnloadedComments(toggleReactionsLink, bottomBar, commentActionLink); + } + }, + + showLoadedComments: function(toggleReactionsLink, existingCommentsContainer, commentActionLink) { + this.showCommentBox(commentActionLink); + existingCommentsContainer.find("time.timeago").timeago(); + }, + + showUnloadedComments: function(toggleReactionsLink, bottomBar, commentActionLink) { + toggleReactionsLink.addClass("loading"); + var bottomBarContainer = this.bottomBarLazy(bottomBar); + var self = this; + $.ajax({ + url: toggleReactionsLink.attr("href"), + success: function (data) { + toggleReactionsLink.addClass("active").removeClass("loading"); + $(data).insertAfter(bottomBar.children(".show-comments").first()); + self.showCommentBox(commentActionLink); + bottomBarContainer.getCommentsContainer().find("time.timeago").timeago(); + bottomBarContainer.activate(); + }, + error: function(){ + bottomBarContainer.deactivate(); + } + }).always(function(){ + toggleReactionsLink.removeClass("loading"); + bottomBarContainer.hideLoader(); + }); + }, + + bottomBarLazy: function(bottomBar) { + return { + loader: function(){ + return bottomBar.find(".ajax-loader"); + }, + + getCommentsContainer: function(){ + return bottomBar.find(".comment-container").first(); + }, + + getShowCommentsLink: function(){ + return bottomBar.find("a.show-comments"); + }, + + showLoader: function(){ + this.loader().removeClass("hidden"); + }, + + hideLoader: function(){ + this.loader().addClass("hidden"); + }, + + activate: function(){ + bottomBar.addClass("active").removeClass("inactive"); + this.getShowCommentsLink().addClass("active"); + this.getShowCommentsLink().find("i").removeClass("entypo-chevron-down").addClass("entypo-chevron-up"); + }, + + deactivate: function(){ + bottomBar.removeClass("active").addClass("inactive"); + this.getShowCommentsLink().removeClass("active"); + this.getShowCommentsLink().find("i").addClass("entypo-chevron-down").removeClass("entypo-chevron-up"); + } + }; + }, + + scrollToOffset: function(commentsContainer){ + var commentCount = commentsContainer.find("li.comment").length; + if ( commentCount > 3 ) { + var lastComment = commentsContainer.find("li:nth-child("+(commentCount-3)+")"); + $("html,body").animate({ + scrollTop: lastComment.offset().top + }, 1000); + } + }, + + showCommentBox: function(link){ + var bottomBar = link.closest(".bottom-bar").first(); + var textArea = bottomBar.find("textarea.comment_box").first()[0]; + bottomBar.find(".add-comment-switcher").removeClass("hidden"); + autosize(textArea); + }, + + updateStream: function(form, data) { + var bottomBar = form.closest(".bottom-bar").first(); + this.addNewComments(bottomBar, data); + this.updateCommentCount(bottomBar); + this.increaseReactionCount(bottomBar); + this.handleCommentShowing(form, bottomBar); + bottomBar.find("time.timeago").timeago(); + }, + + addNewComments: function(bottomBar, data) { + if ($(".comment-container", bottomBar).length === 0) { + $(".show-comments", bottomBar).after($("<div/>", {"class": "comment-container"})); + $(".comment-container", bottomBar).append($("<ul/>", {"class": "comments"})); + } + $(".comment-container .comments", bottomBar).append(data); + }, + + // Fix for no comments + updateCommentCount: function(bottomBar) { + var commentCount = bottomBar.find(".comment-count"); + commentCount.text(commentCount.text().replace(/(\d+)/, function (match) { + return parseInt(match, 10) + 1; + })); + }, + + // Fix for no reactions + increaseReactionCount: function(bottomBar) { + var toggleReactionsLink = bottomBar.find(".show-comments").first(); + var count = toggleReactionsLink.text().match(/.*(\d+).*/); + var text = ""; + + // No previous comment + if(!count){ + text = Diaspora.I18n.t("stream.reactions", {count: 1}); + var parent = toggleReactionsLink.parent(); + var postGuid = bottomBar.parents(".stream_element").data("guid"); + + toggleReactionsLink.remove(); + toggleReactionsLink = $("<a/>", {"class": "show-comments", "href": Routes.postComments(postGuid) + ".mobile"}) + .html(text + "<i class='entypo-chevron-up'/>"); + parent.prepend(toggleReactionsLink); + bottomBar.removeClass("inactive").addClass("active"); + } + else { + count = parseInt(count, 10) + 1; + text = Diaspora.I18n.t("stream.reactions", {count: count}); + toggleReactionsLink.html(text + "<i class='entypo-chevron-up'/>"); + } + }, + + handleCommentShowing: function(form, bottomBar) { + var formContainer = form.parent(); + formContainer.find("textarea.form-control").first().val(""); + this.resetCommentBox(formContainer); + var commentActionLink = bottomBar.find("a.comment-action").first(); + commentActionLink.addClass("inactive"); + this.showComments(bottomBar.find(".show-comments").first()); + }, + + resetCommentBox: function(el){ + var commentButton = $(el).find("input.comment-button").first(); + commentButton.attr("value", commentButton.data("reset-with")); + commentButton.removeAttr("disabled"); + commentButton.blur(); + } + }; +})(); + +$(document).ready(function() { + Diaspora.Mobile.Comments.initialize(); +}); diff --git a/app/assets/javascripts/mobile/mobile_drawer.js b/app/assets/javascripts/mobile/mobile_drawer.js new file mode 100644 index 0000000000000000000000000000000000000000..7a96a37d45515c15171d25756f6b6abb588e53cc --- /dev/null +++ b/app/assets/javascripts/mobile/mobile_drawer.js @@ -0,0 +1,24 @@ +(function(){ + Diaspora.Mobile.Drawer = { + initialize: function(){ + $("#all_aspects").bind("tap click", function(evt){ + evt.preventDefault(); + $(this).find("+ li").toggleClass("hide"); + }); + + $("#menu-badge").bind("tap click", function(evt){ + evt.preventDefault(); + $("#app").toggleClass("draw"); + }); + + $("#followed_tags").bind("tap click", function(evt){ + evt.preventDefault(); + $(this).find("+ li").toggleClass("hide"); + }); + } + }; +})(); + +$(function(){ + Diaspora.Mobile.Drawer.initialize(); +}); diff --git a/app/assets/javascripts/mobile/mobile_file_uploader.js b/app/assets/javascripts/mobile/mobile_file_uploader.js index 1084821e94ee2c9b88e3b1f12825c95966d0d909..14f966eb2f1481959c63d57a61b294e1255f1d65 100644 --- a/app/assets/javascripts/mobile/mobile_file_uploader.js +++ b/app/assets/javascripts/mobile/mobile_file_uploader.js @@ -2,7 +2,6 @@ //= require js_image_paths function createUploader(){ - var aspectIds = gon.preloads.aspect_ids; new qq.FileUploaderBasic({ @@ -10,7 +9,7 @@ function createUploader(){ params: {'photo' : {'pending' : 'true', 'aspect_ids' : aspectIds},}, allowedExtensions: ['jpg', 'jpeg', 'png', 'gif', 'tiff'], action: "/photos", - debug: true, + debug: false, button: document.getElementById('file-upload-publisher'), sizeLimit: 4194304, @@ -21,8 +20,8 @@ function createUploader(){ messages: { typeError: Diaspora.I18n.t("photo_uploader.invalid_ext"), - sizeError: Diaspora.I18n.t("photo_uploader.new_photo.size_error"), - emptyError: Diaspora.I18n.t("photo_uploader.new_photo.empty") + sizeError: Diaspora.I18n.t("photo_uploader.size_error"), + emptyError: Diaspora.I18n.t("photo_uploader.empty") }, onSubmit: function(){ @@ -75,10 +74,10 @@ function createUploader(){ }); }, - onAllComplete: function(){ - } - + onAllComplete: function(){} }); } -createUploader(); +window.addEventListener("load", function() { + createUploader(); +}); // @license-end diff --git a/app/assets/javascripts/mobile/mobile_post_actions.js b/app/assets/javascripts/mobile/mobile_post_actions.js new file mode 100644 index 0000000000000000000000000000000000000000..ff83a62f58e2298e8fc4e72ad6105c1aacc11eb9 --- /dev/null +++ b/app/assets/javascripts/mobile/mobile_post_actions.js @@ -0,0 +1,115 @@ +(function(){ + Diaspora.Mobile.PostActions = { + initialize: function() { + $(".like-action", ".stream").bind("tap click", this.onLike); + $(".reshare-action", ".stream").bind("tap click", this.onReshare); + }, + + showLoader: function(link) { + link.addClass("loading"); + }, + + hideLoader: function(link) { + link.removeClass("loading"); + }, + + toggleActive: function(link) { + link.toggleClass("active").toggleClass("inactive"); + }, + + like: function(likeCounter, link){ + var url = link.data("url"); + var onSuccess = function(data){ + Diaspora.Mobile.PostActions.toggleActive(link); + link.data("url", url + "/" + data.id); + if(likeCounter){ + likeCounter.text(parseInt(likeCounter.text(), 10) + 1); + } + }; + + $.ajax({ + url: url, + dataType: "json", + type: "POST", + beforeSend: function() { + Diaspora.Mobile.PostActions.showLoader(link); + }, + success: onSuccess, + complete: function() { + Diaspora.Mobile.PostActions.hideLoader(link); + } + }); + }, + + unlike: function(likeCounter, link){ + var url = link.data("url"); + var onSuccess = function(){ + Diaspora.Mobile.PostActions.toggleActive(link); + link.data("url", url.replace(/\/\d+$/, "")); + + if(likeCounter){ + var newValue = parseInt(likeCounter.text(), 10) - 1; + likeCounter.text(Math.max(newValue, 0)); + } + }; + + $.ajax({ + url: url, + dataType: "json", + type: "DELETE", + beforeSend: function() { + Diaspora.Mobile.PostActions.showLoader(link); + }, + success: onSuccess, + complete: function() { + Diaspora.Mobile.PostActions.hideLoader(link); + } + }); + }, + + onLike: function(evt){ + evt.preventDefault(); + var link = $(evt.target), + likeCounter = $(evt.target).closest(".stream_element").find(".like-count"); + + if(!link.hasClass("loading") && link.hasClass("inactive")) { + Diaspora.Mobile.PostActions.like(likeCounter, link); + } + else if(!link.hasClass("loading") && link.hasClass("active")) { + Diaspora.Mobile.PostActions.unlike(likeCounter, link); + } + }, + + onReshare: function(evt) { + evt.preventDefault(); + + var link = $(this), + href = link.attr("href"), + confirmText = link.attr("title"); + + if(!link.hasClass("loading") && link.hasClass("inactive") && confirm(confirmText)) { + $.ajax({ + url: href + "&provider_display_name=mobile", + dataType: "json", + type: "POST", + beforeSend: function() { + Diaspora.Mobile.PostActions.showLoader(link); + }, + success: function() { + Diaspora.Mobile.PostActions.toggleActive(link); + }, + error: function() { + alert(Diaspora.I18n.t("failed_to_reshare")); + }, + complete: function() { + Diaspora.Mobile.PostActions.hideLoader(link); + } + }); + } + } + }; +})(); + +$(function(){ + Diaspora.Mobile.PostActions.initialize(); +}); diff --git a/app/assets/javascripts/mobile/profile_aspects.js b/app/assets/javascripts/mobile/profile_aspects.js index 2c664f045ef005fb14fe1a93ed44fea17919749a..899a60fe9d54b6d930d1170e59c1993ed490acec 100644 --- a/app/assets/javascripts/mobile/profile_aspects.js +++ b/app/assets/javascripts/mobile/profile_aspects.js @@ -81,4 +81,3 @@ $(document).ready(function(){ $(this).change(profileAspectDropDown_onchange); }); }); - diff --git a/app/assets/javascripts/mobile/publisher.js b/app/assets/javascripts/mobile/publisher.js new file mode 100644 index 0000000000000000000000000000000000000000..6954631cfdb21273b030b566953fb4465da5dd8d --- /dev/null +++ b/app/assets/javascripts/mobile/publisher.js @@ -0,0 +1,49 @@ +$(document).ready(function(){ + // no publisher available + if($("#new_status_message").length === 0) { return; } + + $(".service_icon").bind("tap click", function() { + var service = $(this).toggleClass("dim"), + selectedServices = $("#new_status_message .service_icon:not(.dim)"), + provider = service.attr("id"), + hiddenField = $("#new_status_message input[name='services[]'][value='" + provider + "']"), + publisherMaxChars = 40000, + serviceMaxChars; + + + $("#new_status_message .counter").remove(); + + $.each(selectedServices, function() { + serviceMaxChars = parseInt($(this).attr("maxchar"), 10); + if(publisherMaxChars > serviceMaxChars) { + publisherMaxChars = serviceMaxChars; + } + }); + + if (selectedServices.length > 0) { + var counter = $("<span class='counter'></span>"); + $("#status_message_text").after(counter); + $("#status_message_text").charCount({ + allowed: publisherMaxChars, + warning: publisherMaxChars / 10, + counter: counter + }); + } + + if(hiddenField.length > 0) { hiddenField.remove(); } + else { + $("#new_status_message").append( + $("<input/>", { + name: "services[]", + type: "hidden", + value: provider + }) + ); + } + }); + + $("#submit_new_message").bind("tap click", function(evt){ + evt.preventDefault(); + $("#new_status_message").submit(); + }); +}); diff --git a/app/assets/javascripts/pages/users-getting-started.js b/app/assets/javascripts/pages/users-getting-started.js index 2fed55655a8c6af6c3649b5ba6ba4f672983dd6c..cb82e03a07d9b4278c0b02e61885bcc32ff76f23 100644 --- a/app/assets/javascripts/pages/users-getting-started.js +++ b/app/assets/javascripts/pages/users-getting-started.js @@ -18,7 +18,7 @@ Diaspora.Pages.UsersGettingStarted = function() { /* flash message prompt */ var message = Diaspora.I18n.t("getting_started.hey", {'name': $("#profile_first_name").val()}); - Diaspora.page.flashMessages.render({success: true, notice: message}); + app.flashMessages.success(message); }); $("#profile_first_name").bind("change", function(){ @@ -45,7 +45,7 @@ Diaspora.Pages.UsersGettingStarted = function() { confirmation = confirm(confirmMessage); } - Diaspora.page.flashMessages.render({success: true, notice: message}); + app.flashMessages.success(message); return confirmation; }); @@ -66,14 +66,14 @@ Diaspora.Pages.UsersGettingStarted = function() { startText: "", emptyText: "no_results", selectionAdded: function(elem){tagFollowings.create({"name":$(elem[0]).text().substring(2)})}, - selectionRemoved: function(elem){ + selectionRemoved: function(elem){ tagFollowings.where({"name":$(elem[0]).text().substring(2)})[0].destroy(); elem.remove(); } }); autocompleteInput.bind('keydown', function(evt){ - if(evt.keyCode === 13 || evt.keyCode === 9 || evt.keyCode === 32){ + if(evt.which === Keycodes.ENTER || evt.which === Keycodes.TAB || evt.which === Keycodes.SPACE) { evt.preventDefault(); if( $('li.as-result-item.active').length === 0 ){ $('li.as-result-item').first().click(); diff --git a/app/assets/javascripts/widgets/flash-messages.js b/app/assets/javascripts/widgets/flash-messages.js deleted file mode 100644 index 142efce74d20d0e6046529f5e8d6824b5e9627d9..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/widgets/flash-messages.js +++ /dev/null @@ -1,39 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later - -(function() { - var FlashMessages = function() { - var self = this; - - this.subscribe("widget/ready", function() { - self.animateMessages(); - }); - - this.animateMessages = function() { - self.flashMessages().addClass("expose").delay(8000).fadeTo(200, 0.5); - }; - - this.render = function(result) { - self.flashMessages().removeClass("expose").remove(); - - $("<div/>", { - id: result.success ? "flash_notice" : "flash_error" - }) - .html($("<div/>", { - 'class': "message" - }) - .text(result.notice)) - .prependTo(document.body); - - - self.animateMessages(); - }; - - this.flashMessages = function() { - return $("#flash_notice, #flash_error, #flash_alert"); - }; - }; - - Diaspora.Widgets.FlashMessages = FlashMessages; -})(); -// @license-end - diff --git a/app/assets/javascripts/widgets/infinite-scroll.js b/app/assets/javascripts/widgets/infinite-scroll.js deleted file mode 100644 index d3fa5be01af2102bb163bee6ec6a4f1b28db6e05..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/widgets/infinite-scroll.js +++ /dev/null @@ -1,62 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later - -/* Copyright (c) 2010-2011, Diaspora Inc. This file is -* licensed under the Affero General Public License version 3 or later. See -* the COPYRIGHT file. -*/ - -(function() { - var InfiniteScroll = function() { - var self = this; - this.options = { - bufferPx: 500, - debug: false, - donetext: Diaspora.I18n.t("infinite_scroll.no_more"), - loadingText: "", - loadingImg: ImagePaths.get("ajax-loader.gif"), - navSelector: "#pagination", - nextSelector: ".paginate", - itemSelector: ".stream_element", - pathParse: function(pathStr) { - var newPath = pathStr.replace("?", "?only_posts=true&"), - lastTime = $('#main_stream .stream_element').last().find(".time").attr("integer"); - - if(lastTime === undefined){ - lastTime = $('#main_stream').data('time_for_scroll'); - } - - return newPath.replace(/max_time=\d+/, "max_time=" + lastTime); - } - }; - - this.subscribe("widget/ready", function(evt, opts) { - $.extend(self.options, opts); - if($('#main_stream').length !== 0) { - $('#main_stream').infinitescroll(self.options, function(newElements) { - self.globalPublish("stream/scrolled", newElements); - }); - } else if($('#people_stream').length !== 0) { - $("#people_stream").infinitescroll($.extend(self.options, { - navSelector : ".pagination", - nextSelector : ".next_page", - pathParse : function(pathStr, nextPage) { - return pathStr.replace("page=2", "page=" + nextPage); - } - }), function(newElements) { - self.globalPublish("stream/scrolled", newElements); - }); - } - }); - - this.reInitialize = function() { - $("#main_stream").infinitescroll("destroy"); - self.publish("widget/ready"); - }; - - this.globalSubscribe("stream/reloaded", self.reInitialize, this); - }; - - Diaspora.Widgets.InfiniteScroll = InfiniteScroll; -})(); -// @license-end - diff --git a/app/assets/javascripts/widgets/lightbox.js b/app/assets/javascripts/widgets/lightbox.js deleted file mode 100644 index 461be1d0ee21b34809ea6d28d2472285696332f6..0000000000000000000000000000000000000000 --- a/app/assets/javascripts/widgets/lightbox.js +++ /dev/null @@ -1,193 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later - -/* Copyright (c) 2010-2011, Diaspora Inc. This file is - * licensed under the Affero General Public License version 3 or later. See - * the COPYRIGHT file. - */ - - -jQuery.fn.center = (function() { - var $window = $(window); - return function () { - this.css({ - position: "absolute", - top: ($window.height() - this.height()) / 2 + $window.scrollTop() + "px", - left:($window.width() - this.width()) / 2 + $window.scrollLeft() + "px" - }); - return this; - }; -})(); - -(function() { - var Lightbox = function() { - var self = this; - - self.options = { - imageParent: '.stream_element', - imageSelector: 'img.stream-photo' - }; - - this.subscribe("widget/ready", function() { - $.extend(self, { - lightbox: $("#lightbox"), - navigation: $("#lightbox-navigation"), - imageset: $("#lightbox-imageset"), - backdrop: $("#lightbox-backdrop"), - closelink: $("#lightbox-close-link"), - scrollleft: $("#lightbox-scrollleft"), - scrollright: $("#lightbox-scrollright"), - image: $("#lightbox-image"), - body: $(document.body), - window: $(window) - }); - - //self.post.delegate("a.stream-photo-link", "click", self.lightboxImageClicked); - self.imageset.delegate("img", "click", self.imagesetImageClicked); - - self.window.resize(function() { - self.lightbox.css("max-height", (self.window.height() - 100) + "px"); - }).trigger("resize"); - - self.closelink.click(function(evt){ - evt.preventDefault(); - self.resetLightbox(); - }); - self.lightbox.click(self.resetLightbox); - - self.backdrop.click(function(evt) { - evt.preventDefault(); - self.resetLightbox(); - }); - - self.scrollleft.click(function(evt){ - evt.preventDefault(); - evt.stopPropagation(); - self.navigation.animate({scrollLeft: (self.navigation.scrollLeft() - - (self.window.width() - 150))}, 200, 'swing'); - }); - - self.scrollright.click(function(evt){ - evt.preventDefault(); - evt.stopPropagation(); - self.navigation.animate({scrollLeft: (self.navigation.scrollLeft() - + (self.window.width() - 150))}, 200, 'swing'); - }); - - self.body.keydown(function(evt) { - var imageThumb = self.imageset.find("img.selected"); - - switch(evt.keyCode) { - case 27: - self.resetLightbox(); - break; - case 37: - //left - self.selectImage(self.prevImage(imageThumb)); - break; - case 39: - //right - self.selectImage(self.nextImage(imageThumb)); - break; - } - }); - }); - - this.nextImage = function(thumb){ - var next = thumb.next(); - if (next.length === 0) { - next = self.imageset.find("img").first(); - } - return(next); - }; - - this.prevImage = function(thumb){ - var prev = thumb.prev(); - if (prev.length === 0) { - prev = self.imageset.find("img").last(); - } - return(prev); - }; - - this.lightboxImageClicked = function(evt) { - evt.preventDefault(); - - var selectedImage = $(this).find(self.options.imageSelector), - imageUrl = selectedImage.attr("data-full-photo"), - images = selectedImage.parents(self.options.imageParent).find(self.options.imageSelector), - imageThumb; - - if( $.browser.msie ) { - /* No fancy schmancy lightbox for IE, because it doesn't work in IE */ - window.open(imageUrl); - return; - } - - self.imageset.html(""); - images.each(function(index, image) { - image = $(image); - var thumb = $("<img/>", { - src: image.attr("data-small-photo"), - "data-full-photo": image.attr("data-full-photo") - }); - - if(image.attr("data-full-photo") === imageUrl) { - imageThumb = thumb; - } - - self.imageset.append(thumb); - }); - - self - .selectImage(imageThumb) - .revealLightbox(); - - self.scrollToThumbnail(imageThumb); - }; - - this.imagesetImageClicked = function(evt) { - evt.preventDefault(); - evt.stopPropagation(); - - self.selectImage($(this)); - }; - - this.scrollToThumbnail = function(imageThumb) { - self.navigation.animate({scrollLeft: (self.navigation.scrollLeft() - + imageThumb.offset().left +35 - (self.window.width() / 2))}, 200, 'swing'); - }; - - this.selectImage = function(imageThumb) { - $(".selected", self.imageset).removeClass("selected"); - imageThumb.addClass("selected"); - self.image.attr("src", imageThumb.attr("data-full-photo")); - - self.scrollToThumbnail(imageThumb); - - return self; - }; - - this.revealLightbox = function() { - self.body.addClass("lightboxed"); - self.lightbox - .css("max-height", (self.window.height() - 100) + "px") - .show(); - - return self; - }; - - this.resetLightbox = function() { - self.lightbox.hide(); - self.body.removeClass("lightboxed"); - self.image.attr("src", ImagePaths.get("ajax-loader2.gif")); - self.imageset.html(""); - }; - - this.set = function(opts) { - $.extend(self.options, opts); - }; - }; - - Diaspora.Widgets.Lightbox = Lightbox; -})(); -// @license-end - diff --git a/app/assets/javascripts/widgets/timeago.js b/app/assets/javascripts/widgets/timeago.js index dcb680864e9d37771d150be53da84877670f0409..4d159818f3fba8c7c67d6a10ce45aef40f1b49fb 100644 --- a/app/assets/javascripts/widgets/timeago.js +++ b/app/assets/javascripts/widgets/timeago.js @@ -7,14 +7,21 @@ (function() { Diaspora.Widgets.TimeAgo = function() { this.subscribe("widget/ready", function() { - if(Diaspora.I18n.language !== "en") { + if (Diaspora.I18n.language !== "en") { $.timeago.settings.lang = Diaspora.I18n.language; $.timeago.settings.strings[Diaspora.I18n.language] = {}; - $.each($.timeago.settings.strings["en"], function(index) { - if(index === "numbers") { + $.each($.timeago.settings.strings.en, function(index) { + if (index === "numbers") { $.timeago.settings.strings[Diaspora.I18n.language][index] = []; - } - else { + } else if (index === "minutes" || + index === "hours" || + index === "days" || + index === "months" || + index === "years") { + $.timeago.settings.strings[Diaspora.I18n.language][index] = function(value) { + return Diaspora.I18n.t("timeago." + index, {count: value}); + }; + } else { $.timeago.settings.strings[Diaspora.I18n.language][index] = Diaspora.I18n.t("timeago." + index); } }); diff --git a/app/assets/stylesheets/_application.scss b/app/assets/stylesheets/_application.scss new file mode 100644 index 0000000000000000000000000000000000000000..8bd3810d0a6ab81207b8e27c0541dfd11d21290d --- /dev/null +++ b/app/assets/stylesheets/_application.scss @@ -0,0 +1,114 @@ +@import 'perfect-scrollbar'; + +@import 'color-variables'; +@import 'bootstrap-complete'; +@import 'mixins'; + + +// core +@import 'media-box'; +@import 'entypo'; +@import 'icons'; +@import 'mentions'; +@import 'animations'; +@import 'flash_messages'; +@import 'sprites'; +@import 'hovercard'; +@import 'base'; +@import 'interactions'; +@import 'spinner'; +@import 'timeago'; +@import 'vendor/fileuploader'; +@import 'vendor/autoSuggest'; +@import 'typeahead'; +@import 'colors'; +@import 'card-footer'; + +// font overrides +@import 'typography'; + +// layout +@import 'sidebar'; + +// home +@import 'home'; + +// login +@import 'login'; +@import 'registration'; +@import 'forms'; + +// terms +@import 'terms'; + +// profile and settings pages +@import 'settings'; + +// new SPV +@import 'header'; +@import 'footer'; +@import 'opengraph'; +@import 'single-post-view'; +@import 'poll'; + +// map +@import 'leaflet'; +@import 'map'; + +// conversations +@import 'conversations'; + +// publisher +@import 'publisher'; +@import 'aspects'; +@import 'markdown-editor'; + +// bookmarklet +@import 'bookmarklet'; + +// notifications +@import 'notifications'; + +// help +@import 'help'; + +// getting started +@import 'getting-started'; + +// people +@import 'people'; +@import 'invitations'; +@import 'profile'; + +// stream +@import 'tag'; +@import 'stream'; +@import 'stream_element'; +@import 'comments'; +@import 'diaspora_jsxc'; +@import 'chat'; +@import 'markdown-content'; +@import 'oembed'; +@import 'post-content'; + +// contacts +@import 'contacts'; +@import 'navbar_left'; + +// code +@import 'code'; +@import 'highlightjs/github'; + +// statistics +@import 'statistics'; + +// gallery +@import 'blueimp-gallery'; +@import 'blueimp-gallery/blueimp-gallery-indicator'; +@import 'gallery'; + +// settings +@import 'user_applications'; + +// OpenID Connect (API) +@import 'openid_connect_error_page'; diff --git a/app/assets/stylesheets/_flash_messages.scss b/app/assets/stylesheets/_flash_messages.scss index e4b4e46c47ea586cccd98867df8a9d691bf9197a..379675f81a8771b6a7e274d579745f7c7df75aba 100644 --- a/app/assets/stylesheets/_flash_messages.scss +++ b/app/assets/stylesheets/_flash_messages.scss @@ -1,53 +1,30 @@ - -@import 'new_styles/animations'; - -#flash_notice, -#flash_alert, -#flash_error { - position : fixed; +.flash-body { + left: 0; + position: fixed; + text-align: center; + top: -100px; z-index: 999; - top : -100px; - left : 0; - width : 100%; - - text-align : center; - color: $text-dark-grey; - - &.expose { - @include animation(expose, 10s) - } + width: 100%; + pointer-events: none; + &.expose { @include animation(expose, 10s) } - .message { + .flash-message { + border-radius: 0; box-shadow: 0 1px 4px rgba(0,0,0,0.8); - - display : inline-block; - padding: 10px 12px; - min-width: 400px; - max-width: 800px; - - color : #fff; - background-color : rgba(0,0,0,0.8); - border : 1px solid rgba(255,255,255,0.7); - border-radius: 6px; - + display: inline-block; font-weight: bold; - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-size: 13px; - } -} - -#flash_notice { - .message { - color: $text-dark-grey; - background-color: #F4F899; - border-color: darken(#F4F899, 40%); + max-width: 800px; + min-width: 500px; + padding: 10px 12px; + &.alert-danger { border: 1px solid darken($state-danger-bg, 10%); } + &.alert-success { border: 1px solid darken($state-success-bg, 10%); } + &.alert-warning { border: 1px solid darken($state-warning-bg, 10%); } } -} -#flash_error, -#flash_alert { - .message { - background-color: #CA410B; - border-color: darken(#CA410B, 10%); + @media (max-width: $grid-float-breakpoint-max) { + .flash-message { + max-width: 80%; + min-width: 80%; + } } } diff --git a/app/assets/stylesheets/_mixins.scss b/app/assets/stylesheets/_mixins.scss index 5c37c15565be904d90541347f7bb89c6952d4f7f..2b4c02f907fd6db2d469298a9b07a57ed029d541 100644 --- a/app/assets/stylesheets/_mixins.scss +++ b/app/assets/stylesheets/_mixins.scss @@ -21,6 +21,9 @@ $default-border-radius: 3px; @include linear-gradient(lighten($color,20%), darken($color,15%)); } +@mixin header-gradient($color) { + @include linear-gradient(lighten($color, 2%), darken($color, 2%), 0%, 80%); +} @mixin linear-gradient($from, $to, $start:0%, $end:100%){ background: mix($from,$to); @@ -62,7 +65,7 @@ $default-border-radius: 3px; size : 60px 60px; } - border-radius: 70px 10px 10px 70px; + border-radius: 40px 10px 10px 40px; box-shadow: 0 0 32px rgba(255,255,255,.5); position : absolute; @@ -70,7 +73,7 @@ $default-border-radius: 3px; left : 10%; right : 10%; - height: 60px; + height: 80px; margin-top: -40px; padding: 10px 7px 10px 80px; overflow: hidden; @@ -117,3 +120,21 @@ $default-border-radius: 3px; } } } + +@mixin selectable-list() { + .glyphicon-ok, + .glyphicon-refresh { + display: none; + padding-right: 5px; + } + + &.selected { + .glyphicon-ok { display: inline-block;} + .glyphicon-refresh { display: none;} + } + + &.loading { + .glyphicon-refresh { display: inline-block;} + .glyphicon-ok { display: none;} + } +} diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index 2084f5e3d2998ca2dd2167bf890a7ab2b8acf56f..ea933e6e63d518ffd8dcb20a4bca4dafb4982016 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -1,30 +1,8 @@ -@import 'colors'; +@import 'color-variables'; +@import 'bootstrap-variables'; +@import 'animations'; /** ADMIN STYlES **/ - -body > div.container { - margin-top: 40px; - padding-top: 1em; -} - -#admin_nav { - font-size: 1em; - border-bottom: 2px solid #777; - margin-bottom: 20px; - - ul { - display: inline; - } - - li { - font-size: 0.8em; - display: inline; - margin-right: 0.5em; - - a { color: $blue; } - } -} - /** user search **/ .users { @@ -40,12 +18,56 @@ body > div.container { height: 50px; } - .actions li { - margin-top: .3em; - } + .actions{ width: 150px; } + + .pull-right .label{ display: inline-block; } + } +} + +/** Invites panel **/ +.more_invites{ + #add-invites-section{ + line-height: 34px; + margin-bottom: 15px; } } /** reported posts **/ -@import 'report' +@import 'report'; + +/** pod list **/ + +#pod-list { + .pod-title { + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + } + + th.added, + td.added, + td.actions { white-space: nowrap; } + + tr.deleting { + opacity: .5; + } + + tr.checking .recheck i { + animation-duration: .4s; + animation-name: pulsate; + animation-iteration-count: infinite; + animation-direction: alternate; + } + + td.actions { + text-align: right; + + a { color: inherit; } + } + + pre.details { + margin-top: 1em; + white-space: normal; + } +} diff --git a/app/assets/stylesheets/animations.scss b/app/assets/stylesheets/animations.scss new file mode 100644 index 0000000000000000000000000000000000000000..2ef8bee16542a4b068f0fc0efd316985150e8d00 --- /dev/null +++ b/app/assets/stylesheets/animations.scss @@ -0,0 +1,23 @@ +// flash message animations - header height is about 50px +@keyframes expose { + 0% { top: -100px; } + 12% { top: $navbar-height; } + 88% { top: $navbar-height; } + 100% { top: -100px; } +} + +// spinner animation +@keyframes spinner { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +@keyframes pulsate { + from { + opacity: 1; + } + + to { + opacity: .1; + } +} diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss deleted file mode 100644 index 427c0d549e889b87162d9fda0bc5abd93a558dcb..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/application.scss +++ /dev/null @@ -1,98 +0,0 @@ -@import 'bootstrap-fix'; - -@import 'perfect-scrollbar'; - -@import "colors"; -@import 'sizes'; -@import 'mixins'; - -/* core */ -@import 'media-box'; -@import 'autocomplete'; -@import 'entypo-fonts'; -@import 'entypo'; -@import 'mentions'; -@import 'flash_messages'; -@import 'sprites'; -@import 'hovercard'; -@import 'new_styles/base'; -@import 'new_styles/buttons'; -@import 'new_styles/interactions'; -@import 'new_styles/spinner'; -@import 'lightbox'; -@import 'vendor/fileuploader'; -@import 'vendor/autoSuggest'; - -/* font overrides */ -@import 'new_styles/typography'; - -/* login */ -@import 'new_styles/login'; -@import 'new_styles/registration'; -@import 'new_styles/forms'; - -/* navs */ -@import 'new_styles/navs'; - -/* profile and settings pages */ -@import 'new_styles/settings'; - -/* new SPV */ -@import 'header'; -@import 'footer'; -@import 'bootstrap-headerfix'; -@import 'opengraph'; -@import 'single-post-view'; -@import 'new_styles/poll'; - -/* conversations */ -@import 'conversations'; -@import 'jquery.facebox'; -@import 'facebox'; - -/* publisher */ -@import 'publisher'; -@import 'aspects'; - -/* bookmarklet */ -@import 'bookmarklet'; - -/* notifications */ -@import 'notifications'; - -/* help */ -@import 'help'; - -/* getting started */ -@import 'getting-started'; - -/* people */ -@import 'people'; -@import 'invitations'; -@import 'profile'; - -/* stream */ -@import 'tag'; -@import 'stream-faces'; -@import 'stream'; -@import 'stream_element'; -@import 'comments'; -@import 'diaspora_jsxc'; -@import 'chat'; -@import 'markdown-content'; -@import 'oembed'; -@import 'post-content'; - -/* right bar */ -@import 'sidebar'; - -/* contacts */ -@import 'contacts'; -@import 'leftnavbar'; - -/* code */ -@import 'new_styles/code'; -@import 'highlightjs/github'; - -/* statistics */ -@import 'statistics'; diff --git a/app/assets/stylesheets/aspects.scss b/app/assets/stylesheets/aspects.scss index 3c9b1ac22556a0bdeae6e7d98f2bf502f25a1546..115e2bcfaa7818e14b890bef3bbc4314ee629842 100644 --- a/app/assets/stylesheets/aspects.scss +++ b/app/assets/stylesheets/aspects.scss @@ -1,23 +1,14 @@ .aspect_dropdown { li { + @include selectable-list; + .status_indicator { width: 19px; height: 14px; display: inline-block; } - .icon-ok, .icon-refresh { - padding-right: 5px; - display: none; - } - &.selected { - .icon-ok { display: inline-block;} - .icon-refresh { display: none;} - } - &.loading { - .icon-refresh { display: inline-block;} - .icon-ok { display: none;} - } + a { .text { color: #333333; diff --git a/app/assets/stylesheets/autocomplete.scss b/app/assets/stylesheets/autocomplete.scss deleted file mode 100644 index c232052485a0ab1da1752fc88817a7b570105224..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/autocomplete.scss +++ /dev/null @@ -1,87 +0,0 @@ -.ac_results { - border: 1px solid #999; - background-color: transparent; - overflow: hidden; - z-index: 99999; - min-width: 300px !important; - width: 100%; - - border-radius: 3px; - box-shadow: 0 1px 3px #999; -} - -.ac_results ul { - width: 100%; - list-style-position: outside; - list-style: none; - padding: 0; - margin: 0; -} - -.ac_results li { - margin: 0px; - padding: 2px 5px { - left: 50px; - top: 6px; - } - cursor: default; - display: block; - height: 37px; - position: relative; - // if width will be 100% horizontal scrollbar will apear - // when scroll mode will be used - // width 100% - font: menu; - font-size: 1em; - // it is very important, if line-height not setted or setted - // in relative units scroll will be broken in firefox - //:line-height 16px - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -.ac_loading { - background: white image-url('ajax-loader.gif') right center no-repeat; -} - -.ac_odd { - background-color: #fafafa; - background-color: rgba(250,250,250,0.95); -} - -.ac_even { - background-color: #fff; - background-color: rgba(255,255,255,0.95); -} - -.ac_over { - background-color: #3F8FBA; - color: white; -} - -.ac_results { - .avatar { - height: 35px; - width: 35px; - position: absolute; - left: 5px; - top: 5px; - } - - .search_handle { - font-size: 0.8em; - color: #999; - margin-top: -3px; - } - - .ac_over .search_handle{ - color: #fff; - } - - .ac_over .search_handle, .search_handle { - display: block; - overflow: hidden; - text-overflow: ellipsis; - } -} diff --git a/app/assets/stylesheets/base.scss b/app/assets/stylesheets/base.scss new file mode 100644 index 0000000000000000000000000000000000000000..e9a7762e91fb8c26899be90f79059e51817cb05e --- /dev/null +++ b/app/assets/stylesheets/base.scss @@ -0,0 +1,117 @@ +body { + margin-top: $navbar-height; + padding: none; +} + +.container-fluid { max-width: $screen-lg-min; } + +// These names are generated by a rails controller +// scss-lint:disable SelectorFormat +.page-contacts, +.page-conversations, +.page-notifications, +.page-people.action-show, +.page-people.action-contacts, +.page-photos, +.page-posts, +.page-profiles.action-edit, +.page-services.action-index, +.page-streams, +.page-tags, +.page-user_applications, +.page-users.action-edit, +.page-users.action-update, +.page-users.action-privacy_settings { + background-color: $main-background; +} +// scss-lint:enable SelectorFormat + +// Overflow +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +code, +pre { word-wrap: break-word; } + +.tag { word-break: break-all; } + +.avatar { + border-radius: 4px; + + &.micro { + height: 20px; + width: 20px; + } + + &.small { + height: 35px; + width: 35px; + } + + &.medium { + height: auto; + max-width: 75px; + width: auto; + } +} + +.author-name { + color: inherit; +} + +.back-to-top { + background-color: $border-dark-grey; + border-radius: 4px; + bottom: 20px; + color: $white; + display: block; + font-size: 3.5em; + height: 50px; + line-height: 50px; + opacity: 0; + position: fixed; + right: 54px; + transition: opacity ease 400ms; + width: 50px; + z-index: 49; + + &:hover, + &.visible:hover { + color: $white; + opacity: .85; + text-decoration: none; + } + + &.visible { opacity: .5; } +} + +.noscript { + background-color: rgba($black, .9); + height: 100%; + margin-top: -50px; + position: fixed; + width: 100%; + z-index: 9001; + + h3 { + background-color: $white; + margin: 100px; + padding: 50px; + } +} + +// general purpose classes + +.small-horizontal-spacer { + min-height: 20px; +} + +// badge color +.badge-important { + background-color: $red; +} diff --git a/app/assets/stylesheets/bookmarklet.scss b/app/assets/stylesheets/bookmarklet.scss index 42c2dadbd9ed2973fc573c087aef138b55a585a4..ecdaff4b66721fb947d831bd6fa99516f088989e 100644 --- a/app/assets/stylesheets/bookmarklet.scss +++ b/app/assets/stylesheets/bookmarklet.scss @@ -1,2 +1,2 @@ -#bookmarklet { padding:10px 10px 30px 10px; margin-top: 0; } -body.page-status_messages.action-bookmarklet { margin-top: 0px } \ No newline at end of file +#bookmarklet { padding-bottom: 30px; margin-top: 0; } +body.page-status_messages.action-bookmarklet { margin-top: 0px } diff --git a/app/assets/stylesheets/bootstrap-complete.scss b/app/assets/stylesheets/bootstrap-complete.scss index 7e36e38547c269ebeb078c5e9bc77b155e0cfbdc..df03c6ad06206816b8c18e3b1bd71d72398c37cf 100644 --- a/app/assets/stylesheets/bootstrap-complete.scss +++ b/app/assets/stylesheets/bootstrap-complete.scss @@ -1,9 +1,8 @@ // Calling this file bootstrap would cause an infinite recursion during asset compilation. -@import 'bootstrap'; -@import 'bootstrap-responsive'; +@import "bootstrap-sprockets"; +@import "bootstrap-variables"; //our overwrites of bootstrap variables +@import "bootstrap"; +// Plugins -// according to the docs, this is part of bootstrap 2.3.x -.text-left { text-align: left; } -.text-center { text-align: center; } -.text-right { text-align: right; } +@import "bootstrap3-switch"; diff --git a/app/assets/stylesheets/bootstrap-fix.scss b/app/assets/stylesheets/bootstrap-fix.scss deleted file mode 100644 index 47b6c0c4db794369ed4870b3b16bc4a9a6988abf..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/bootstrap-fix.scss +++ /dev/null @@ -1,24 +0,0 @@ -// A temporary fix for broken classes in bootstrap 2. -// Can probably be removed when migration of bootstrap 3 is done. - -input::placeholder, -textarea::placeholder { - color: #999999; -} -input::input-placeholder, -textarea::input-placeholder { - color: #999999; -} - - -// A temporary fix for mention modal #5329 - -#new_status_message_pane .modal { - position: absolute; - max-height: none; -} - -#new_status_message_pane .modal-body{ - overflow-y: visible; - max-height: none; -} diff --git a/app/assets/stylesheets/bootstrap-headerfix.scss b/app/assets/stylesheets/bootstrap-headerfix.scss deleted file mode 100644 index 53f4919dcd2c3626fbaffa3ff13e758d7840953d..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/bootstrap-headerfix.scss +++ /dev/null @@ -1,52 +0,0 @@ -// A temporary fix for displaying the header in the single post view. -// Should be removed once everything uses Bootstrap. - -header { - .container { - width: 950px; - .header-nav { - span { - a { - font-weight: bold; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - } - } - } - li { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - } - } - #conversations_badge, #notification_badge { - background: none; - } - #notification_badge.active { - border-radius: 0; - } - #global_search { - form { - input { - height: 15px; - color: black; - } - } - } - #notification_dropdown { - h4 { - margin: 0; - } - .right { - a { - font-weight: bold; - } - } - .notification_element { - font-size: 13px; - .timeago { - border: medium none; - cursor: text; - } - } - } -} diff --git a/app/assets/stylesheets/bootstrap-variables.scss b/app/assets/stylesheets/bootstrap-variables.scss new file mode 100644 index 0000000000000000000000000000000000000000..bca512cff55bed3195a174a5af87e2b2f0d34d88 --- /dev/null +++ b/app/assets/stylesheets/bootstrap-variables.scss @@ -0,0 +1,866 @@ +// Override Bootstrap variables here (defaults from bootstrap-sass v3.3.4): + +// +// Variables +// -------------------------------------------------- + + +//== Colors +// +//## Gray and brand colors for use across Bootstrap. + +$gray-base: #000; +// $gray-darker: lighten($gray-base, 13.5%) // #222 +// $gray-dark: lighten($gray-base, 20%) // #333 +$gray: lighten($gray-base, 33.5%); // #555 +// $gray-light: lighten($gray-base, 46.7%) // #777 +// $gray-lighter: lighten($gray-base, 93.5%) // #eee + +$brand-primary: darken(#0097FF,5%) !default; // darker creation-blue +$brand-success: #8EDE3D !default; +// $brand-info: #5bc0de +// $brand-warning: #f0ad4e +// $brand-danger: #d9534f + + +//== Scaffolding +// +//## Settings for some of the most global styles. + +//** Background color for `<body>`. +// $body-bg: #fff +//** Global text color on `<body>`. +// $text-color: $gray-dark + +//** Global textual link color. +$link-color: rgb(42,156,235) !default; +//** Link hover color set via `darken()` function. +// $link-hover-color: darken($link-color, 15%) +//** Link hover decoration. +// $link-hover-decoration: underline + + +//== Typography +// +//## Font, line-height, and color for body text, headings, and more. + +// $font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif +// $font-family-serif: Georgia, "Times New Roman", Times, serif +//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`. +// $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace +// $font-family-base: $font-family-sans-serif + +$font-size-base: 13px !default; +// $font-size-large: ceil(($font-size-base * 1.25)) // ~18px +$font-size-small: 11px !default; + +// $font-size-h1: floor(($font-size-base * 2.6)) // ~36px +// $font-size-h2: floor(($font-size-base * 2.15)) // ~30px +// $font-size-h3: ceil(($font-size-base * 1.7)) // ~24px +// $font-size-h4: ceil(($font-size-base * 1.25)) // ~18px +// $font-size-h5: $font-size-base +// $font-size-h6: ceil(($font-size-base * 0.85)) // ~12px + +//** Unit-less `line-height` for use in components like buttons. +// $line-height-base: 1.428571429 // 20/14 +//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc. +// $line-height-computed: floor(($font-size-base * $line-height-base)) // ~20px + +//** By default, this inherits from the `<body>`. +// $headings-font-family: inherit +// $headings-font-weight: 500 +// $headings-line-height: 1.1 +// $headings-color: inherit + + +//== Iconography +// +//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower. + +//** Load fonts from this directory. + +// [converter] If $bootstrap-sass-asset-helper if used, provide path relative to the assets load path. +// [converter] This is because some asset helpers, such as Sprockets, do not work with file-relative paths. +// $icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") + +//** File name for all font files. +// $icon-font-name: "glyphicons-halflings-regular" +//** Element ID within SVG icon file. +// $icon-font-svg-id: "glyphicons_halflingsregular" + + +//== Components +// +//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start). + +// $padding-base-vertical: 6px +// $padding-base-horizontal: 12px + +// $padding-large-vertical: 10px +// $padding-large-horizontal: 16px + +// $padding-small-vertical: 5px +// $padding-small-horizontal: 10px + +// $padding-xs-vertical: 1px +// $padding-xs-horizontal: 5px + +// $line-height-large: 1.3333333 // extra decimals for Win 8.1 Chrome +// $line-height-small: 1.5 + +// $border-radius-base: 4px +// $border-radius-large: 6px +// $border-radius-small: 3px + +//** Global color for active items (e.g., navs or dropdowns). +// $component-active-color: #fff +//** Global background color for active items (e.g., navs or dropdowns). +// $component-active-bg: $brand-primary + +//** Width of the `border` for generating carets that indicator dropdowns. +// $caret-width-base: 4px +//** Carets increase slightly in size for larger components. +// $caret-width-large: 5px + + +//== Tables +// +//## Customizes the `.table` component with basic values, each used across all table variations. + +//** Padding for `<th>`s and `<td>`s. +// $table-cell-padding: 8px +//** Padding for cells in `.table-condensed`. +// $table-condensed-cell-padding: 5px + +//** Default background color used for all tables. +// $table-bg: transparent +//** Background color used for `.table-striped`. +// $table-bg-accent: #f9f9f9 +//** Background color used for `.table-hover`. +// $table-bg-hover: #f5f5f5 +// $table-bg-active: $table-bg-hover + +//** Border color for table and cell borders. +// $table-border-color: #ddd + + +//== Buttons +// +//## For each of Bootstrap's buttons, define text, background and border color. + +// $btn-font-weight: normal + +// $btn-default-color: #333 +// $btn-default-bg: #fff +// $btn-default-border: #ccc + +// $btn-primary-color: #fff +// $btn-primary-bg: $brand-primary +// $btn-primary-border: darken($btn-primary-bg, 5%) + +$btn-success-color: #333 !default; +// $btn-success-bg: $brand-success +// $btn-success-border: darken($btn-success-bg, 5%) + +// $btn-info-color: #fff +// $btn-info-bg: $brand-info +// $btn-info-border: darken($btn-info-bg, 5%) + +// $btn-warning-color: #fff +// $btn-warning-bg: $brand-warning +// $btn-warning-border: darken($btn-warning-bg, 5%) + +// $btn-danger-color: #fff +// $btn-danger-bg: $brand-danger +// $btn-danger-border: darken($btn-danger-bg, 5%) + +// $btn-link-disabled-color: $gray-light + + +//== Forms +// +//## + +//** `<input>` background color +// $input-bg: #fff +//** `<input disabled>` background color +// $input-bg-disabled: $gray-lighter + +//** Text color for `<input>`s +// $input-color: $gray +//** `<input>` border color +// $input-border: #ccc + +// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4 +//** Default `.form-control` border radius +// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS. +// $input-border-radius: $border-radius-base +//** Large `.form-control` border radius +// $input-border-radius-large: $border-radius-large +//** Small `.form-control` border radius +// $input-border-radius-small: $border-radius-small + +//** Border color for inputs on focus +// $input-border-focus: #66afe9 + +//** Placeholder text color +// $input-color-placeholder: #999 + +//** Default `.form-control` height +// $input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2) +//** Large `.form-control` height +// $input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) +//** Small `.form-control` height +// $input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) + +//** `.form-group` margin +// $form-group-margin-bottom: 15px + +// $legend-color: $gray-dark +// $legend-border-color: #e5e5e5 + +//** Background color for textual input addons +// $input-group-addon-bg: $gray-lighter +//** Border color for textual input addons +// $input-group-addon-border-color: $input-border + +//** Disabled cursor for form controls and buttons. +// $cursor-disabled: not-allowed + + +//== Dropdowns +// +//## Dropdown menu container and contents. + +//** Background for the dropdown menu. +// $dropdown-bg: #fff +//** Dropdown menu `border-color`. +// $dropdown-border: rgba(0,0,0,.15) +//** Dropdown menu `border-color` **for IE8**. +// $dropdown-fallback-border: #ccc +//** Divider color for between dropdown items. +// $dropdown-divider-bg: #e5e5e5 + +//** Dropdown link text color. +// $dropdown-link-color: $gray-dark +//** Hover color for dropdown links. +// $dropdown-link-hover-color: darken($gray-dark, 5%) +//** Hover background for dropdown links. +// $dropdown-link-hover-bg: #f5f5f5 + +//** Active dropdown menu item text color. +// $dropdown-link-active-color: $component-active-color +//** Active dropdown menu item background color. +// $dropdown-link-active-bg: $component-active-bg + +//** Disabled dropdown menu item background color. +// $dropdown-link-disabled-color: $gray-light + +//** Text color for headers within dropdown menus. +// $dropdown-header-color: $gray-light + +//** Deprecated `$dropdown-caret-color` as of v3.1.0 +// $dropdown-caret-color: #000 + + +//-- Z-index master list +// +// Warning: Avoid customizing these values. They're used for a bird's eye view +// of components dependent on the z-axis and are designed to all work together. +// +// Note: These variables are not generated into the Customizer. + +// $zindex-navbar: 1000 +// $zindex-dropdown: 1000 +// $zindex-popover: 1060 +// $zindex-tooltip: 1070 +// $zindex-navbar-fixed: 1030 +// $zindex-modal-background: 1040 +// $zindex-modal: 1050 + + +//== Media queries breakpoints +// +//## Define the breakpoints at which your layout will change, adapting to different screen sizes. + +// Extra small screen / phone +//** Deprecated `$screen-xs` as of v3.0.1 +// $screen-xs: 480px +//** Deprecated `$screen-xs-min` as of v3.2.0 +// $screen-xs-min: $screen-xs +//** Deprecated `$screen-phone` as of v3.0.1 +// $screen-phone: $screen-xs-min + +// Small screen / tablet +//** Deprecated `$screen-sm` as of v3.0.1 +// $screen-sm: 768px +// $screen-sm-min: $screen-sm +//** Deprecated `$screen-tablet` as of v3.0.1 +// $screen-tablet: $screen-sm-min + +// Medium screen / desktop +//** Deprecated `$screen-md` as of v3.0.1 +// $screen-md: 992px +// $screen-md-min: $screen-md +//** Deprecated `$screen-desktop` as of v3.0.1 +// $screen-desktop: $screen-md-min + +// Large screen / wide desktop +//** Deprecated `$screen-lg` as of v3.0.1 +// $screen-lg: 1200px +// $screen-lg-min: $screen-lg +//** Deprecated `$screen-lg-desktop` as of v3.0.1 +// $screen-lg-desktop: $screen-lg-min + +// So media queries don't overlap when required, provide a maximum +// $screen-xs-max: ($screen-sm-min - 1) +// $screen-sm-max: ($screen-md-min - 1) +// $screen-md-max: ($screen-lg-min - 1) + + +//== Grid system +// +//## Define your custom responsive grid. + +//** Number of columns in the grid. +// $grid-columns: 12 +//** Padding between columns. Gets divided in half for the left and right. +// $grid-gutter-width: 30px +// Navbar collapse +//** Point at which the navbar becomes uncollapsed. +$grid-float-breakpoint: 992px !default; // $screen-md-min +//** Point at which the navbar begins collapsing. +// $grid-float-breakpoint-max: ($grid-float-breakpoint - 1) + + +//== Container sizes +// +//## Define the maximum width of `.container` for different screen sizes. + +// Small screen / tablet +// $container-tablet: (720px + $grid-gutter-width) +//** For `$screen-sm-min` and up. +// $container-sm: $container-tablet + +// Medium screen / desktop +// $container-desktop: (940px + $grid-gutter-width) +//** For `$screen-md-min` and up. +// $container-md: $container-desktop + +// Large screen / wide desktop +// $container-large-desktop: (1140px + $grid-gutter-width) +//** For `$screen-lg-min` and up. +// $container-lg: $container-large-desktop + + +//== Navbar +// +//## + +// Basics of a navbar +$navbar-height: 50px; +// $navbar-margin-bottom: $line-height-computed +// $navbar-border-radius: $border-radius-base +// $navbar-padding-horizontal: floor(($grid-gutter-width / 2)) +// $navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2) +$navbar-collapse-max-height: 480px; + +// $navbar-default-color: #777 +// $navbar-default-bg: #f8f8f8 +// $navbar-default-border: darken($navbar-default-bg, 6.5%) + +// Navbar links +// $navbar-default-link-color: #777 +// $navbar-default-link-hover-color: #333 +// $navbar-default-link-hover-bg: transparent +// $navbar-default-link-active-color: #555 +// $navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%) +// $navbar-default-link-disabled-color: #ccc +// $navbar-default-link-disabled-bg: transparent + +// Navbar brand label +// $navbar-default-brand-color: $navbar-default-link-color +// $navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%) +// $navbar-default-brand-hover-bg: transparent + +// Navbar toggle +// $navbar-default-toggle-hover-bg: #ddd +// $navbar-default-toggle-icon-bar-bg: #888 +// $navbar-default-toggle-border-color: #ddd + + +// Inverted navbar +// Reset inverted navbar basics +// $navbar-inverse-color: lighten($gray-light, 15%) +// $navbar-inverse-bg: #222 +// $navbar-inverse-border: darken($navbar-inverse-bg, 10%) + +// Inverted navbar links +// $navbar-inverse-link-color: lighten($gray-light, 15%) +// $navbar-inverse-link-hover-color: #fff +// $navbar-inverse-link-hover-bg: transparent +// $navbar-inverse-link-active-color: $navbar-inverse-link-hover-color +// $navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%) +// $navbar-inverse-link-disabled-color: #444 +// $navbar-inverse-link-disabled-bg: transparent + +// Inverted navbar brand label +// $navbar-inverse-brand-color: $navbar-inverse-link-color +// $navbar-inverse-brand-hover-color: #fff +// $navbar-inverse-brand-hover-bg: transparent + +// Inverted navbar toggle +// $navbar-inverse-toggle-hover-bg: #333 +// $navbar-inverse-toggle-icon-bar-bg: #fff +// $navbar-inverse-toggle-border-color: #333 + + +//== Navs +// +//## + +//=== Shared nav styles +// $nav-link-padding: 10px 15px +// $nav-link-hover-bg: $gray-lighter + +// $nav-disabled-link-color: $gray-light +// $nav-disabled-link-hover-color: $gray-light + +//== Tabs +// $nav-tabs-border-color: #ddd + +// $nav-tabs-link-hover-border-color: $gray-lighter + +// $nav-tabs-active-link-hover-bg: $body-bg +// $nav-tabs-active-link-hover-color: $gray +// $nav-tabs-active-link-hover-border-color: #ddd + +// $nav-tabs-justified-link-border-color: #ddd +// $nav-tabs-justified-active-link-border-color: $body-bg + +//== Pills +// $nav-pills-border-radius: $border-radius-base +// $nav-pills-active-link-hover-bg: $component-active-bg +// $nav-pills-active-link-hover-color: $component-active-color + + +//== Pagination +// +//## + +// $pagination-color: $link-color +// $pagination-bg: #fff +// $pagination-border: #ddd + +// $pagination-hover-color: $link-hover-color +// $pagination-hover-bg: $gray-lighter +// $pagination-hover-border: #ddd + +// $pagination-active-color: #fff +// $pagination-active-bg: $brand-primary +// $pagination-active-border: $brand-primary + +// $pagination-disabled-color: $gray-light +// $pagination-disabled-bg: #fff +// $pagination-disabled-border: #ddd + + +//== Pager +// +//## + +// $pager-bg: $pagination-bg +// $pager-border: $pagination-border +// $pager-border-radius: 15px + +// $pager-hover-bg: $pagination-hover-bg + +// $pager-active-bg: $pagination-active-bg +// $pager-active-color: $pagination-active-color + +// $pager-disabled-color: $pagination-disabled-color + + +//== Jumbotron +// +//## + +// $jumbotron-padding: 30px +// $jumbotron-color: inherit +// $jumbotron-bg: $gray-lighter +// $jumbotron-heading-color: inherit +// $jumbotron-font-size: ceil(($font-size-base * 1.5)) + + +//== Form states and alerts +// +//## Define colors for form feedback states and, by default, alerts. + +// $state-success-text: #3c763d +// $state-success-bg: #dff0d8 +// $state-success-border: darken(adjust-hue($state-success-bg, -10), 5%) + +// $state-info-text: #31708f +// $state-info-bg: #d9edf7 +// $state-info-border: darken(adjust-hue($state-info-bg, -10), 7%) + +// $state-warning-text: #8a6d3b +// $state-warning-bg: #fcf8e3 +// $state-warning-border: darken(adjust-hue($state-warning-bg, -10), 5%) + +// $state-danger-text: #a94442 +// $state-danger-bg: #f2dede +// $state-danger-border: darken(adjust-hue($state-danger-bg, -10), 5%) + + +//== Tooltips +// +//## + +//** Tooltip max width +// $tooltip-max-width: 200px +//** Tooltip text color +// $tooltip-color: #fff +//** Tooltip background color +// $tooltip-bg: #000 +// $tooltip-opacity: .9 + +//** Tooltip arrow width +// $tooltip-arrow-width: 5px +//** Tooltip arrow color +// $tooltip-arrow-color: $tooltip-bg + + +//== Popovers +// +//## + +//** Popover body background color +// $popover-bg: #fff +//** Popover maximum width +// $popover-max-width: 276px +//** Popover border color +// $popover-border-color: rgba(0,0,0,.2) +//** Popover fallback border color +// $popover-fallback-border-color: #ccc + +//** Popover title background color +// $popover-title-bg: darken($popover-bg, 3%) + +//** Popover arrow width +// $popover-arrow-width: 10px +//** Popover arrow color +// $popover-arrow-color: $popover-bg + +//** Popover outer arrow width +// $popover-arrow-outer-width: ($popover-arrow-width + 1) +//** Popover outer arrow color +// $popover-arrow-outer-color: fade_in($popover-border-color, 0.05) +//** Popover outer arrow fallback color +// $popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%) + + +//== Labels +// +//## + +//** Default label background color +// $label-default-bg: $gray-light +//** Primary label background color +// $label-primary-bg: $brand-primary +//** Success label background color +// $label-success-bg: $brand-success +//** Info label background color +// $label-info-bg: $brand-info +//** Warning label background color +// $label-warning-bg: $brand-warning +//** Danger label background color +// $label-danger-bg: $brand-danger + +//** Default label text color +// $label-color: #fff +//** Default text color of a linked label +// $label-link-hover-color: #fff + + +//== Modals +// +//## + +//** Padding applied to the modal body +// $modal-inner-padding: 15px + +//** Padding applied to the modal title +// $modal-title-padding: 15px +//** Modal title line-height +// $modal-title-line-height: $line-height-base + +//** Background color of modal content area +// $modal-content-bg: #fff +//** Modal content border color +// $modal-content-border-color: rgba(0,0,0,.2) +//** Modal content border color **for IE8** +// $modal-content-fallback-border-color: #999 + +//** Modal backdrop background color +// $modal-backdrop-bg: #000 +//** Modal backdrop opacity +// $modal-backdrop-opacity: .5 +//** Modal header border color +// $modal-header-border-color: #e5e5e5 +//** Modal footer border color +// $modal-footer-border-color: $modal-header-border-color + +// $modal-lg: 900px +// $modal-md: 600px +// $modal-sm: 300px + + +//== Alerts +// +//## Define alert colors, border radius, and padding. + +// $alert-padding: 15px +// $alert-border-radius: $border-radius-base +// $alert-link-font-weight: bold + +// $alert-success-bg: $state-success-bg +// $alert-success-text: $state-success-text +// $alert-success-border: $state-success-border + +// $alert-info-bg: $state-info-bg +// $alert-info-text: $state-info-text +// $alert-info-border: $state-info-border + +// $alert-warning-bg: $state-warning-bg +// $alert-warning-text: $state-warning-text +// $alert-warning-border: $state-warning-border + +// $alert-danger-bg: $state-danger-bg +// $alert-danger-text: $state-danger-text +// $alert-danger-border: $state-danger-border + + +//== Progress bars +// +//## + +//** Background color of the whole progress component +// $progress-bg: #f5f5f5 +//** Progress bar text color +// $progress-bar-color: #fff +//** Variable for setting rounded corners on progress bar. +// $progress-border-radius: $border-radius-base + +//** Default progress bar color +// $progress-bar-bg: $brand-primary +//** Success progress bar color +// $progress-bar-success-bg: $brand-success +//** Warning progress bar color +// $progress-bar-warning-bg: $brand-warning +//** Danger progress bar color +// $progress-bar-danger-bg: $brand-danger +//** Info progress bar color +// $progress-bar-info-bg: $brand-info + + +//== List group +// +//## +//** Background color on `.list-group-item` +$list-group-bg: $white; +//** `.list-group-item` border color +$list-group-border: transparent; +//** List group border radius +$list-group-border-radius: 0; + +//** Background color of single list items on hover +$list-group-hover-bg: $blue; +//** Text color of active list items +$list-group-active-color: $white; +//** Background color of active list items +$list-group-active-bg: $gray; +//** Border color of active list elements +// $list-group-active-border: $list-group-active-bg +//** Text color for content within active list items +$list-group-active-text-color: $white; + +//** Text color of disabled list items +// $list-group-disabled-color: $gray-light +//** Background color of disabled list items +// $list-group-disabled-bg: $gray-lighter +//** Text color for content within disabled list items +// $list-group-disabled-text-color: $list-group-disabled-color + +// $list-group-link-color: #555 +$list-group-link-hover-color: $white; +// $list-group-link-heading-color: #333 + + +//== Panels +// +//## + +// $panel-bg: #fff +// $panel-body-padding: 15px +// $panel-heading-padding: 10px 15px +// $panel-footer-padding: $panel-heading-padding +// $panel-border-radius: $border-radius-base + +//** Border color for elements within panels +// $panel-inner-border: #ddd +// $panel-footer-bg: #f5f5f5 + +// $panel-default-text: $gray-dark +// $panel-default-border: #ddd +// $panel-default-heading-bg: #f5f5f5 + +// $panel-primary-text: #fff +// $panel-primary-border: $brand-primary +// $panel-primary-heading-bg: $brand-primary + +// $panel-success-text: $state-success-text +// $panel-success-border: $state-success-border +// $panel-success-heading-bg: $state-success-bg + +// $panel-info-text: $state-info-text +// $panel-info-border: $state-info-border +// $panel-info-heading-bg: $state-info-bg + +// $panel-warning-text: $state-warning-text +// $panel-warning-border: $state-warning-border +// $panel-warning-heading-bg: $state-warning-bg + +// $panel-danger-text: $state-danger-text +// $panel-danger-border: $state-danger-border +// $panel-danger-heading-bg: $state-danger-bg + + +//== Thumbnails +// +//## + +//** Padding around the thumbnail image +// $thumbnail-padding: 4px +//** Thumbnail background color +// $thumbnail-bg: $body-bg +//** Thumbnail border color +// $thumbnail-border: #ddd +//** Thumbnail border radius +// $thumbnail-border-radius: $border-radius-base + +//** Custom text color for thumbnail captions +// $thumbnail-caption-color: $text-color +//** Padding around the thumbnail caption +// $thumbnail-caption-padding: 9px + + +//== Wells +// +//## + +// $well-bg: #f5f5f5 +// $well-border: darken($well-bg, 7%) + + +//== Badges +// +//## + +// $badge-color: #fff +//** Linked badge text color on hover +// $badge-link-hover-color: #fff +// $badge-bg: $gray-light + +//** Badge text color in active nav link +// $badge-active-color: $link-color +//** Badge background color in active nav link +// $badge-active-bg: #fff + +// $badge-font-weight: bold +// $badge-line-height: 1 +// $badge-border-radius: 10px + + +//== Breadcrumbs +// +//## + +// $breadcrumb-padding-vertical: 8px +// $breadcrumb-padding-horizontal: 15px +//** Breadcrumb background color +// $breadcrumb-bg: #f5f5f5 +//** Breadcrumb text color +// $breadcrumb-color: #ccc +//** Text color of current page in the breadcrumb +// $breadcrumb-active-color: $gray-light +//** Textual separator for between breadcrumb elements +// $breadcrumb-separator: "/" + + +//== Carousel +// +//## + +// $carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6) + +// $carousel-control-color: #fff +// $carousel-control-width: 15% +// $carousel-control-opacity: .5 +// $carousel-control-font-size: 20px + +// $carousel-indicator-active-bg: #fff +// $carousel-indicator-border-color: #fff + +// $carousel-caption-color: #fff + + +//== Close +// +//## + +// $close-font-weight: bold +// $close-color: #000 +// $close-text-shadow: 0 1px 0 #fff + + +//== Code +// +//## + +// $code-color: #c7254e +// $code-bg: #f9f2f4 + +// $kbd-color: #fff +// $kbd-bg: #333 + +// $pre-bg: #f5f5f5 +// $pre-color: $gray-dark +// $pre-border-color: #ccc +// $pre-scrollable-max-height: 340px + + +//== Type +// +//## + +//** Horizontal offset for forms and lists. +// $component-offset-horizontal: 180px +//** Text muted color +// $text-muted: $gray-light +//** Abbreviations and acronyms border color +// $abbr-border-color: $gray-light +//** Headings small color +// $headings-small-color: $gray-light +//** Blockquote small color +// $blockquote-small-color: $gray-light +//** Blockquote font size +$blockquote-font-size: $font-size-base !default; +//** Blockquote border color +// $blockquote-border-color: $gray-lighter +//** Page header border color +// $page-header-border-color: $gray-lighter +//** Width of horizontal description list titles +// $dl-horizontal-offset: $component-offset-horizontal +//** Horizontal line color. +// $hr-border: $gray-lighter diff --git a/app/assets/stylesheets/card-footer.scss b/app/assets/stylesheets/card-footer.scss new file mode 100644 index 0000000000000000000000000000000000000000..118c8c92fd9b4f4e1747bd082b625a8dfb1df608 --- /dev/null +++ b/app/assets/stylesheets/card-footer.scss @@ -0,0 +1,29 @@ +.card-footer { + background-color: $background-grey; + border-top: 1px solid $border-medium-grey; + bottom: 0; + font-size: $font-size-small; + left: 0; + line-height: $line-height-computed; + margin-left: 0; + min-height: $line-height-computed + 1; + position: absolute; + width: 100%; + + .footer-container { + padding: 1px 5px; + + a { + color: $text-grey; + font-weight: normal; + margin-right: 4px; + } + } +} + +// gallery-picture specific styles for card-footer +.media { + .gallery-picture img { margin-bottom: $line-height-computed + 2; } + + .card-footer .footer-container { font-size: $font-size-base; } +} diff --git a/app/assets/stylesheets/chat.scss b/app/assets/stylesheets/chat.scss index 3be25903865edb9181a01810148a77dbb227d689..8adb9dd524ddcfde2993dd0c5929f0fde3c4a6f6 100644 --- a/app/assets/stylesheets/chat.scss +++ b/app/assets/stylesheets/chat.scss @@ -5,3 +5,10 @@ body > .container-fluid.chat-roster-shown { body > .container-fluid.chat-roster-hidden { #back-to-top { right: 54px; } } + +// This element is instanciated by JSXC. Does not have to follow naming conventions +// scss-lint:disable IdSelector, SelectorFormat +#jsxc_roster { + top: $navbar-height; +} +// scss-lint:enable IdSelector, SelectorFormat diff --git a/app/assets/stylesheets/new_styles/_code.scss b/app/assets/stylesheets/code.scss similarity index 100% rename from app/assets/stylesheets/new_styles/_code.scss rename to app/assets/stylesheets/code.scss diff --git a/app/assets/stylesheets/color-variables.scss b/app/assets/stylesheets/color-variables.scss new file mode 100644 index 0000000000000000000000000000000000000000..d3862a09d7c0bfa11f7ab45b5231d8360db322a1 --- /dev/null +++ b/app/assets/stylesheets/color-variables.scss @@ -0,0 +1,33 @@ +$white: #fff; +$black: #000; + +$text-grey: #999; +$text-dark-grey: #666; +$text: #333; + +$background-white: $white; +$background-grey: #eee; +$background-blue: #e7f2f7; + +$grey: #2b2b2b; +$medium-gray: #ccc; +$light-grey: #ddd; + +$border-grey: $light-grey; +$border-medium-grey: $medium-gray; +$border-dark-grey: $text-grey; +$border-medium-grey: #ccc; + +$link-grey: #777; +$link-disabled-grey: $text-grey; + +$green: #8ede3d; +$light-green: lighten($green, 20%); +$red: #a80000; +$blue: #3f8fba; + +$main-background: #f0f0f0 !default; +$sidebars-background: $background-white !default; +$left-navbar-drawer-background: darken($sidebars-background, 6%); + +$card-shadow: 0 1px 2px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12) !default; diff --git a/app/assets/stylesheets/color_themes/_color_theme_override.scss b/app/assets/stylesheets/color_themes/_color_theme_override.scss new file mode 100644 index 0000000000000000000000000000000000000000..899885f8e79df3a30599419402ad56d7078e2517 --- /dev/null +++ b/app/assets/stylesheets/color_themes/_color_theme_override.scss @@ -0,0 +1,25 @@ +/* Raw CSS */ +body { + a, + a.tag, + .btn-link, + #main_stream .stream_element > .media a.author-name, + #hovercard h4 a, + .stream_element .from a.self { + color: $link-color; + + &:hover, &:focus { + color: darken($link-color, 10%); + } + } + + #publisher_textarea_wrapper > #button_container > span.markdownIndications > a { + color: fade-out($link-color, 0.4); + } + + .left-navbar .hoverable:hover { background-color: $main-color-essence; } + + .poll_form .progress .bar { background-color: $main-color-dark; } + + .badge { background-color: $brand-primary; } +} diff --git a/app/assets/stylesheets/color_themes/_color_theme_override_origwhite.scss b/app/assets/stylesheets/color_themes/_color_theme_override_origwhite.scss new file mode 100644 index 0000000000000000000000000000000000000000..ff7450ecf3775a9f40b63ace3108675380943ddb --- /dev/null +++ b/app/assets/stylesheets/color_themes/_color_theme_override_origwhite.scss @@ -0,0 +1,26 @@ +body { + #main_stream .stream_element { + border: 0; + border-bottom: 1px solid $border-grey; + margin-bottom: 10px; + } + + .profile_header > div { + border-bottom: 1px solid $border-grey; + } + + .left-navbar .hoverable { border-bottom: 0; } + + .profile-sidebar, + .left-navbar-fixed-background, + &.page-tags .left-navbar-fixed-background, + .left-navbar { + border-right: 1px solid $border-grey; + } + + .right-sidebar-fixed-background, + .right-sidebar-fixed-background, + .rightbar { + border-left: 1px solid $sidebars-background; + } +} diff --git a/app/assets/stylesheets/color_themes/dark_green/_style.scss b/app/assets/stylesheets/color_themes/dark_green/_style.scss new file mode 100644 index 0000000000000000000000000000000000000000..f8fe658e77f32f50ae16a93373f88ed3b7b787aa --- /dev/null +++ b/app/assets/stylesheets/color_themes/dark_green/_style.scss @@ -0,0 +1,18 @@ +/* Main color(s) */ +$brand-primary: #009900; + +/* Shades */ +$main-color-essence: fade-out($brand-primary, 0.8); +$main-color-light: lighten($brand-primary, 10%); +$main-color-dark: darken($brand-primary, 20%); + +/* Bootstrap Variables */ +$btn-primary-bg: $brand-primary; +$link-color: $brand-primary; + +/* Custom Variables */ +$header-background-color: $main-color-dark; +$navbar-inverse-bg: $main-color-dark; +$header-search-color: lighten($header-background-color, 10%); + +@import "color_themes/color_theme_override" diff --git a/app/assets/stylesheets/color_themes/dark_green/desktop.scss b/app/assets/stylesheets/color_themes/dark_green/desktop.scss new file mode 100644 index 0000000000000000000000000000000000000000..fc325a5105b7b8276b25b8ea99b14c82303bd066 --- /dev/null +++ b/app/assets/stylesheets/color_themes/dark_green/desktop.scss @@ -0,0 +1,2 @@ +@import "style"; +@import "application"; diff --git a/app/assets/stylesheets/color_themes/dark_green/mobile.scss b/app/assets/stylesheets/color_themes/dark_green/mobile.scss new file mode 100644 index 0000000000000000000000000000000000000000..e8a5437369c51f41d3fb9d9430b24be99a85924b --- /dev/null +++ b/app/assets/stylesheets/color_themes/dark_green/mobile.scss @@ -0,0 +1,2 @@ +@import "style"; +@import "mobile/mobile"; diff --git a/app/assets/stylesheets/color_themes/egyptian_blue/_style.scss b/app/assets/stylesheets/color_themes/egyptian_blue/_style.scss new file mode 100644 index 0000000000000000000000000000000000000000..1895f02bb5c2ce7496c14121cb83929b17fbe6e4 --- /dev/null +++ b/app/assets/stylesheets/color_themes/egyptian_blue/_style.scss @@ -0,0 +1,18 @@ +/* Main color(s) */ +$brand-primary: #1034A6; + +/* Shades */ +$main-color-essence: fade-out($brand-primary, 0.8); +$main-color-light: lighten($brand-primary, 10%); +$main-color-dark: darken($brand-primary, 15%); + +/* Bootstrap Variables */ +$btn-primary-bg: $brand-primary; +$link-color: $brand-primary; + +/* Custom Variables */ +$header-background-color: $main-color-dark; +$navbar-inverse-bg: $main-color-dark; +$header-search-color: lighten($header-background-color, 15%); + +@import "color_themes/color_theme_override" diff --git a/app/assets/stylesheets/color_themes/egyptian_blue/desktop.scss b/app/assets/stylesheets/color_themes/egyptian_blue/desktop.scss new file mode 100644 index 0000000000000000000000000000000000000000..fc325a5105b7b8276b25b8ea99b14c82303bd066 --- /dev/null +++ b/app/assets/stylesheets/color_themes/egyptian_blue/desktop.scss @@ -0,0 +1,2 @@ +@import "style"; +@import "application"; diff --git a/app/assets/stylesheets/color_themes/egyptian_blue/mobile.scss b/app/assets/stylesheets/color_themes/egyptian_blue/mobile.scss new file mode 100644 index 0000000000000000000000000000000000000000..e8a5437369c51f41d3fb9d9430b24be99a85924b --- /dev/null +++ b/app/assets/stylesheets/color_themes/egyptian_blue/mobile.scss @@ -0,0 +1,2 @@ +@import "style"; +@import "mobile/mobile"; diff --git a/app/assets/stylesheets/color_themes/magenta/_style.scss b/app/assets/stylesheets/color_themes/magenta/_style.scss new file mode 100644 index 0000000000000000000000000000000000000000..0f9b4be1fe952d13dd965c0dffcfd0d4583faff1 --- /dev/null +++ b/app/assets/stylesheets/color_themes/magenta/_style.scss @@ -0,0 +1,18 @@ +/* Main color(s) */ +$brand-primary: #FF00FF; + +/* Shades */ +$main-color-essence: fade-out($brand-primary, 0.8); +$main-color-light: lighten($brand-primary, 10%); +$main-color-dark: darken($brand-primary, 30%); + +/* Bootstrap Variables */ +$btn-primary-bg: darken($brand-primary, 5%); +$link-color: $brand-primary; + +/* Custom Variables */ +$header-background-color: $main-color-dark; +$navbar-inverse-bg: $main-color-dark; +$header-search-color: lighten($header-background-color, 10%); + +@import "color_themes/color_theme_override" diff --git a/app/assets/stylesheets/color_themes/magenta/desktop.scss b/app/assets/stylesheets/color_themes/magenta/desktop.scss new file mode 100644 index 0000000000000000000000000000000000000000..fc325a5105b7b8276b25b8ea99b14c82303bd066 --- /dev/null +++ b/app/assets/stylesheets/color_themes/magenta/desktop.scss @@ -0,0 +1,2 @@ +@import "style"; +@import "application"; diff --git a/app/assets/stylesheets/color_themes/magenta/mobile.scss b/app/assets/stylesheets/color_themes/magenta/mobile.scss new file mode 100644 index 0000000000000000000000000000000000000000..e8a5437369c51f41d3fb9d9430b24be99a85924b --- /dev/null +++ b/app/assets/stylesheets/color_themes/magenta/mobile.scss @@ -0,0 +1,2 @@ +@import "style"; +@import "mobile/mobile"; diff --git a/app/assets/stylesheets/color_themes/original/_style.scss b/app/assets/stylesheets/color_themes/original/_style.scss new file mode 100644 index 0000000000000000000000000000000000000000..89dda9ca2a502ba6f6ee37fdefebfd9a410d849e --- /dev/null +++ b/app/assets/stylesheets/color_themes/original/_style.scss @@ -0,0 +1,8 @@ +/* Main color(s) */ +$main-color: #585858; + +/* Shades */ +$main-color-dark: darken($main-color, 15%); + +/* Variables */ +$header-background-color: $main-color-dark; diff --git a/app/assets/stylesheets/color_themes/original/desktop.scss b/app/assets/stylesheets/color_themes/original/desktop.scss new file mode 100644 index 0000000000000000000000000000000000000000..fc325a5105b7b8276b25b8ea99b14c82303bd066 --- /dev/null +++ b/app/assets/stylesheets/color_themes/original/desktop.scss @@ -0,0 +1,2 @@ +@import "style"; +@import "application"; diff --git a/app/assets/stylesheets/color_themes/original/mobile.scss b/app/assets/stylesheets/color_themes/original/mobile.scss new file mode 100644 index 0000000000000000000000000000000000000000..e8a5437369c51f41d3fb9d9430b24be99a85924b --- /dev/null +++ b/app/assets/stylesheets/color_themes/original/mobile.scss @@ -0,0 +1,2 @@ +@import "style"; +@import "mobile/mobile"; diff --git a/app/assets/stylesheets/color_themes/original_white/_style.scss b/app/assets/stylesheets/color_themes/original_white/_style.scss new file mode 100644 index 0000000000000000000000000000000000000000..7f702bcafe32942c1a4a688926dd87310aa3b0fd --- /dev/null +++ b/app/assets/stylesheets/color_themes/original_white/_style.scss @@ -0,0 +1,14 @@ +// Main color(s) +$main-color: #585858; +$background: #fff; + +// Shades +$main-color-dark: darken($main-color, 15%); + +// Variables +$header-background-color: $main-color-dark; +$main-background: $background; +$sidebars-background: $background; +$card-shadow: none; + +@import 'color_themes/color_theme_override_origwhite'; diff --git a/app/assets/stylesheets/color_themes/original_white/desktop.scss b/app/assets/stylesheets/color_themes/original_white/desktop.scss new file mode 100644 index 0000000000000000000000000000000000000000..7c6bf9507f87fcc3fcb0472a9b638e97cefe4e6d --- /dev/null +++ b/app/assets/stylesheets/color_themes/original_white/desktop.scss @@ -0,0 +1,3 @@ +@import 'color-variables'; +@import 'style'; +@import 'application'; diff --git a/app/assets/stylesheets/color_themes/original_white/mobile.scss b/app/assets/stylesheets/color_themes/original_white/mobile.scss new file mode 100644 index 0000000000000000000000000000000000000000..24ffc11db4857411ca859e696dcaeb7d1047da31 --- /dev/null +++ b/app/assets/stylesheets/color_themes/original_white/mobile.scss @@ -0,0 +1,3 @@ +@import 'color-variables'; +@import 'style'; +@import 'mobile/mobile'; diff --git a/app/assets/stylesheets/colors.scss b/app/assets/stylesheets/colors.scss index a6c4b50df0436ca0477790e9058593c47fb39990..389c64123665de78bef61dd1b555edf84b50aa93 100644 --- a/app/assets/stylesheets/colors.scss +++ b/app/assets/stylesheets/colors.scss @@ -1,28 +1,8 @@ -$highlight-white: #FAFAFA; - -$background-white: #FFFFFF; -$background-grey: #EEEEEE; -$background-blue: #E7F2F7; - -$grey: #2B2B2B; -$light-grey: #DDDDDD; - -$border-grey: #DDDDDD; -$border-dark-grey: #999999; - -$link-blue : rgb(42,156,235); -$link-grey: #777777; -$link-disabled-grey: #999999; - -$text-grey: #999999; -$text-dark-grey: #666666; -$text: #333333; - -$white: white; -$black: black; -$green: #8EDE3D; -$light-green: lighten($green,20%); -$red: #A80000; -$blue: #3F8FBA; -$dark-blue: darken(#0984C8,10%); -$creation-blue: #0097FF; +.gray { + color: $text-grey; + + [class^="entypo-"], + [class*="entypo-"] { + color: $text-grey; + } +} diff --git a/app/assets/stylesheets/comments.scss b/app/assets/stylesheets/comments.scss index d21f77fdee96867023afbbf1288a8b6d37510cfd..0ad5cb838b6d120e08fed50a4a1165c1f9e16866 100644 --- a/app/assets/stylesheets/comments.scss +++ b/app/assets/stylesheets/comments.scss @@ -8,11 +8,11 @@ } .media { margin-top: 10px; } } - .comments > .comment, .comment.new_comment_form_wrapper { + .comments > .comment, + .comment.new-comment-form-wrapper { .avatar { - margin-top: 5px; - height: 30px; - width: 30px; + height: 35px; + width: 35px; } margin: 0; border-top: 1px dotted $border-grey; @@ -20,8 +20,8 @@ .info { margin-top: 5px; - font-size: 11px; - line-height: 11px; + font-size: $font-size-small; + line-height: $font-size-small; } >.highlighted { @@ -30,19 +30,21 @@ } } .submit_button { + margin-top: 10px; input { float: right; } padding-left: 12px; - width: 95%; display: none; } .comment_box { - width: 95%; - height: 30px; + height: 35px; + resize: none; } textarea.comment_box:focus, textarea.comment_box:valid, textarea.comment_box:active { border-color: $border-dark-grey; & + .submit_button { display: block; } + min-height: 35px; + box-shadow: none; } } diff --git a/app/assets/stylesheets/contacts.scss b/app/assets/stylesheets/contacts.scss index 9a356689d4c7b3ddb90030885eb4fae0147cba9c..aaef928f7cac9ea9af6f07a555e5f13348b9344a 100644 --- a/app/assets/stylesheets/contacts.scss +++ b/app/assets/stylesheets/contacts.scss @@ -1,21 +1,34 @@ +.page-contacts { + .sidebar { padding-bottom: 10px; } + + .stream.contacts .header { + border-bottom: 1px solid $border-grey; + min-height: 55px; + form { margin: 0; } + input, + .btn { + margin-bottom: 11px; + margin-top: 11px; + } + } + + .stream.contacts .aspect-controls { + margin-bottom: 7px; + margin-left: 30px; + margin-right: -10px; + margin-top: 7px; + } +} + #contacts_container { #people_stream.contacts { .header { - border-bottom: 1px solid $border-grey; - margin-top: 10px; - min-height: 53px; #change_aspect_name { cursor: pointer; } #aspect_name_form { display: none; - form { margin: 0px; } - input { - margin-bottom: 0px; - margin-top: 10px; - } - .btn { margin-top: 10px; } } #contact_list_search { - margin: 6px 30px 0 0; + margin: 11px 0 0; width: 150px; &:focus { width: 250px; } } @@ -27,7 +40,7 @@ #chat_privilege_toggle > .enabled { color: #000; } - .entypo.contacts-header-icon { + .contacts-header-icon { font-size: 24.5px; line-height: 40px; color: lighten($black,75%); @@ -42,13 +55,13 @@ cursor: pointer; font-size: 20px; line-height: 50px; - margin: 10px; + margin: 0 10px; color: lighten($black,75%); &:hover { color: $black; } } &.in_aspect { - border-left: 3px solid $green; - background-color: lighten($green,35%); + border-left: 3px solid $brand-success; + background-color: lighten($brand-success,35%); } &:not(.in_aspect) { border-left: 3px solid $white; } } @@ -57,7 +70,7 @@ text-align: center; margin-top: 50px; } - .well { margin: 20px 0 10px; } + .well { margin: 10px; } } } diff --git a/app/assets/stylesheets/conversations.scss b/app/assets/stylesheets/conversations.scss index 99b202885e5bad96a935e717c4cf805e776f735f..01540628eeb0ea3af586893f183b253890529f01 100644 --- a/app/assets/stylesheets/conversations.scss +++ b/app/assets/stylesheets/conversations.scss @@ -1,32 +1,67 @@ -#conversations_container { - .stream_container { border-left: none; } +.page-conversations { + .framed-content { padding: 0 10px 10px; } + .sidebar-header .pull-right { margin-top: 12px; } + + .sidebar { + margin-bottom: 50px; + .pagination { margin: 5px; } + } + + .pagination-container > .pagination { + border-radius: 0; + border-top: 1px solid $border-grey; + margin: 0; + padding: 10px; + text-align: center; + width: 100%; + } .stream_element { - border-bottom: 1px solid $border-grey; - &:first-child { border-top: none; } - a.author{ - font-weight: bold; - } + background-color: $white; + padding: 10px; - .avatar{ + .avatar { width: 50px; height: 50px; } + > .media { margin: 0; } + } + + .stream_element.message, + .stream_element.new-message { + border: 1px solid $light-grey; + box-shadow: $card-shadow; + margin-bottom: 20px; + + .avatar { min-width: 50px; } + + .author { + font-weight: bold; + } + p { margin: 0 0 1em 0; &:last-child { margin-bottom: 0; } } - &.new_message { border-bottom: none; } - .timestamp { font-size: 11px; } } - .stream_element.conversation { - padding: 8px; - .media { - margin-bottom: 0px; - margin-left: 0px; + .stream_element.new-message, + .new-conversation { + label { font-weight: bold; } + + textarea { + max-width: 100%; + min-width: 100%; + width: 100%; } + } + + .stream_element.conversation { + border-top: 1px solid $border-grey; + + .timestamp { font-size: $font-size-small; } + .media { margin: 0; } &:hover:not(.selected), &.selected { .subject, @@ -41,21 +76,16 @@ background-color: lighten($blue,5%); cursor: pointer; .participants { - height: 25px; + border-color: rgba($border-grey, 1); + height: 31px; margin-top: 5px; padding-top: 5px; - border-color: rgba($border-grey, 1) } } + &.unread { background-color: darken($background-white, 5%); } &.selected { background-color: $blue; } - .avatar { - width: 50px; - height: 50px; - float: left; - } - .last_author, .last_message { font-size: 12px; line-height: 15px; @@ -65,9 +95,8 @@ } .last_author { color: $text-dark-grey; } - .message_count, .unread_message_count { + .message-count, .unread-message-count { margin-left: 3px; - float: right; font-size: 12px; font-weight: normal; } @@ -77,26 +106,23 @@ background-color: rgba($white, 0.7); border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; - float: left; - font-size: 13px; font-weight: bold; height: 15px; line-height: 15px; - margin-left: -50px; - margin-top: 35px; + margin-top: -15px; + position: absolute; text-align: center; width: 50px; } .participants { - float: left; - clear: both; height: 0; width: 100%; overflow: hidden; border-top: 1px dotted rgba($border-grey, 0); transition: height ease 300ms; .avatar { + float: left; margin: 0 5px 0 0; height: 25px; width: 25px; @@ -106,7 +132,7 @@ .img { line-height: 15px; } .subject { - font-size: $font-size-text; + font-size: $font-size-base; > * { overflow: hidden; white-space: nowrap; @@ -121,109 +147,41 @@ color: $blue; } } -} -#conversation_show { - .conversation_participants { - box-shadow: 0 2px 3px -3px #666; - - background-color: $background-white; - margin-bottom: 5px; - border-bottom: 1px solid $border-grey; - padding: 5px; - line-height: 0px; + .stream_container .conversation-participants { + margin-bottom: 20px; .hide_conversation, .delete_conversation { display: block; - margin-top: 25px; margin-left: 10px; + margin-top: 10px; } .avatar { - height: 30px; - width: 30px; - } - - .avatars { - text-align: right; - margin-top: 9px; - } - - a img { margin-bottom: 4px; } - - .conversation_controls { - margin-bottom: 10px; - - a { margin-right: 10px; } - } - } - - .conversation_participants a:hover { text-decoration: none; } - - .stream .stream_element { - padding: 10px; - } -} - -#left_pane { - border-right: solid 1px $border-grey; - h3 { - padding-bottom: 0; - } - - #left_pane_header { - padding: 10px; - padding-right: 20px; - border-bottom: 1px solid $border-grey; - } - - #conversation_inbox { - a:hover { - text-decoration: none; - } - .pagination { - margin-left: auto; - margin-right: auto; - text-align: center; - - .disabled a { - background: $background-grey; - } + display: inline; + height: 50px; + margin-top: 4px; + width: 50px; } } -} - -@media (max-width: 1354px) { - #left_pane #conversation_inbox .pagination ul > li > a { - padding: 4px 7px; - } -} -#conversation_new { - label { font-weight: bold; } + .conversation-participants a:hover { text-decoration: none; } - .well { + .no-conversations { + color: $gray-light; + font-size: $font-size-h4; font-weight: bold; - margin-top: 25px; + padding: 50px 0; + text-align: center; } } -#no_conversations, -#no_conversation_text { - font-weight: bold; - color: #ccc; - text-align: center; - margin-top: 100px; -} - -#no_conversation_text { - font-size: 20px; -} - -#no_conversation_controls { - text-align: center; - font-size: 12px; +// We need this to override the Bootstrap pagination style only for the conversations view +// scss-lint:disable SelectorDepth +.conversation-inbox .pagination > li > a { + padding: 4px 7px; } +// scss-lint:enable SelectorDepth #new_conversation_pane { ul.as-selections { width: 100% !important; } diff --git a/app/assets/stylesheets/entypo.scss b/app/assets/stylesheets/entypo.scss deleted file mode 100644 index a2d2a3774567db7952867a65e710cb0461d53c74..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/entypo.scss +++ /dev/null @@ -1,322 +0,0 @@ -.entypo { - font-family: 'entypo'; - font-style: normal; - color: black; - - &.red { - color: #A40802; - } - &.white { - color: white; - } - &.gray { - color: #aaa; - } - &.blue { - color: #3f8fba; - } - - &.large { - font-size: 2.5em; - } - - &.middle { - font-size: 1.5em; - } - - &.small { - font-size: 1.2em; - } - - /* main icon map */ - &.add-to-list:before { content: '\e003'; } /* e003 */ - &.add-user:before { content: '\e700'; } /* e700 */ - &.address:before { content: '\e723'; } /* e723 */ - &.adjust:before { content: '\25d1'; } /* 25d1 */ - &.air:before { content: '\e753'; } /* e753 */ - &.airplane:before { content: '\2708'; } /* 2708 */ - &.archive:before { content: '\e738'; } /* e738 */ - &.area-graph:before { content: '\1f53e'; } /* 1f53e */ - &.arrow-combo:before { content: '\e74f'; } /* e74f */ - &.attach:before { content: '\1f4ce'; } /* 1f4ce */ - &.back-in-time:before { content: '\e771'; } /* e771 */ - &.back:before { content: '\1f519'; } /* 1f519 */ - &.bag:before { content: '\1f45c'; } /* 1f45c */ - &.bar-graph:before { content: '\1f4ca '; } /* 1f4ca */ - &.battery:before { content: '\1f50b'; } /* 1f50b */ - &.beamed-note:before { content: '\266b'; } /* 266b */ - &.bell:before { content: '\1f514'; } /* 1f514 */ - &.block:before { content: '\1f6ab'; } /* 1f6ab */ - &.book:before { content: '\1f4d5 '; } /* 1f4d5 */ - &.bookmark:before { content: '\1f516'; } /* 1f516 */ - &.bookmarks:before { content: '\1f4d1'; } /* 1f4d1 */ - &.box:before { content: '\1f4e6'; } /* 1f4e6 */ - &.briefcase:before { content: '\1f4bc'; } /* 1f4bc */ - &.browser:before { content: '\e74e'; } /* e74e */ - &.brush:before { content: '\e79a'; } /* e79a */ - &.bucket:before { content: '\e756'; } /* e756 */ - &.calendar:before { content: '\1f4c5'; } /* 1f4c5 */ - &.camera:before { content: '\1f4f7'; } /* 1f4f7 */ - &.cart:before { content: '\e73d'; } /* e73d */ - &.cc-by:before { content: '\e7a6'; } /* e7a6 */ - &.cc-nc-eu:before { content: '\e7a8'; } /* e7a8 */ - &.cc-nc-jp:before { content: '\e7a9'; } /* e7a9 */ - &.cc-nc:before { content: '\e7a7'; } /* e7a7 */ - &.cc-nd:before { content: '\e7ab'; } /* e7ab */ - &.cc-pd:before { content: '\e7ac'; } /* e7ac */ - &.cc-remix:before { content: '\e7af'; } /* e7af */ - &.cc-sa:before { content: '\e7aa'; } /* e7aa */ - &.cc-share:before { content: '\e7ae'; } /* e7ae */ - &.cc-zero:before { content: '\e7ad'; } /* e7ad */ - &.cc:before { content: '\e7a5'; } /* e7a5 */ - &.ccw:before { content: '\27f2'; } /* 27f2 */ - &.cd:before { content: '\1f4bf'; } /* 1f4bf */ - &.chat:before { content: '\e720'; } /* e720 */ - &.check:before { content: '\2713'; } /* 2713 */ - &.chevron-down:before { content: '\e75c'; } /* e75c */ - &.chevron-left:before { content: '\e75d'; } /* e75d */ - &.chevron-right:before { content: '\e75e'; } /* e75e */ - &.chevron-small-down:before { content: '\e760'; } /* e760 */ - &.chevron-small-left:before { content: '\e761'; } /* e761 */ - &.chevron-small-right:before { content: '\e762'; } /* e762 */ - &.chevron-small-up:before { content: '\e763'; } /* e763 */ - &.chevron-thin-down:before { content: '\e764'; } /* e764 */ - &.chevron-thin-left:before { content: '\e765'; } /* e765 */ - &.chevron-thin-right:before { content: '\e766'; } /* e766 */ - &.chevron-thin-up:before { content: '\e767'; } /* e767 */ - &.chevron-up:before { content: '\e75f'; } /* e75f */ - &.circled-cross:before { content: '\2716'; } /* 2716 */ - &.circled-down:before { content: '\e758'; } /* e758 */ - &.circled-help:before { content: '\e704'; } /* e704 */ - &.circled-info:before { content: '\e705'; } /* e705 */ - &.circled-left:before { content: '\e759'; } /* e759 */ - &.circled-minus:before { content: '\2796'; } /* 2796 */ - &.circled-plus:before { content: '\2795'; } /* 2795 */ - &.circled-right:before { content: '\e75a'; } /* e75a */ - &.circled-up:before { content: '\e75b'; } /* e75b */ - &.clipboard:before { content: '\1f4cb'; } /* 1f4cb */ - &.clock:before { content: '\1f554'; } /* 1f554 */ - &.cloud:before { content: '\2601'; } /* 2601 */ - &.code:before { content: '\e714'; } /* e714 */ - &.cog:before { content: '\2699'; } /* 2699 */ - &.comment:before { content: '\e718'; } /* e718 */ - &.compass:before { content: '\e728'; } /* e728 */ - &.credit-card:before { content: '\1f4b3'; } /* 1f4b3 */ - &.cross-hair:before { content: '\1f3af'; } /* 1f3af */ - &.cross:before { content: '\2715'; } /* 2715 */ - &.cup:before { content: '\2615'; } /* 2615 */ - &.cw:before { content: '\27f3'; } /* 27f3 */ - &.cycle:before { content: '\1f504'; } /* 1f504 */ - &.database:before { content: '\e754'; } /* e754 */ - &.db-logo:before { content: '\f603'; } /* f603 */ - &.db-shape:before { content: '\f600'; } /* f600 */ - &.direction:before { content: '\27a2'; } /* 27a2 */ - &.doc:before { content: '\e730'; } /* e730 */ - &.docs:before { content: '\e736'; } /* e736 */ - &.dot:before { content: '\e78b'; } /* e78b */ - &.down-1:before { content: '\2b07'; } /* 2b07 */ - &.down-bold:before { content: '\e4b0'; } /* e4b0 */ - &.down-thin:before { content: '\2193'; } /* 2193 */ - &.down:before { content: '\261f'; } /* 261f */ - &.download:before { content: '\1f4e5'; } /* 1f4e5 */ - &.drive:before { content: '\e755'; } /* e755 */ - &.droplet:before { content: '\1f4a7'; } /* 1f4a7 */ - &.erase:before { content: '\232b'; } /* 232b */ - &.export:before { content: '\e715'; } /* e715 */ - &.eye:before { content: '\e70a'; } /* e70a */ - &.fb:before { content: '\23ea'; } /* 23ea */ - &.feather:before { content: '\2712'; } /* 2712 */ - &.ff:before { content: '\23e9'; } /* 23e9 */ - &.flag:before { content: '\2691'; } /* 2691 */ - &.flash:before { content: '\26a1'; } /* 26a1 */ - &.flashlight:before { content: '\1f526'; } /* 1f526 */ - &.flow-branch:before { content: '\e791'; } /* e791 */ - &.flow-cascade:before { content: '\e790'; } /* e790 */ - &.flow-line:before { content: '\e793'; } /* e793 */ - &.flow-parallel:before { content: '\e794'; } /* e794 */ - &.flow-tree:before { content: '\e792'; } /* e792 */ - &.folder:before { content: '\1f4c1 '; } /* 1f4c1 */ - &.forward:before { content: '\27a6'; } /* 27a6 */ - &.gauge:before { content: '\e7a2'; } /* e7a2 */ - &.globe:before { content: '\1f30e'; } /* 1f30e */ - &.graduation-cap:before { content: '\1f393 '; } /* 1f393 */ - &.heart-empty:before { content: '\2661'; } /* 2661 */ - &.heart:before { content: '\2665'; } /* 2665 */ - &.help:before { content: '\2753'; } /* 2753 */ - &.home:before { content: '\2302'; } /* 2302 */ - &.hourglass:before { content: '\23f3'; } /* 23f3 */ - &.inbox:before { content: '\e777'; } /* e777 */ - &.infinity:before { content: '\221e'; } /* 221e */ - &.info:before { content: '\2139'; } /* 2139 */ - &.install:before { content: '\e778'; } /* e778 */ - &.key:before { content: '\1f511'; } /* 1f511 */ - &.keyboard:before { content: '\2328'; } /* 2328 */ - &.landscape-doc:before { content: '\e737'; } /* e737 */ - &.language:before { content: '\e752'; } /* e752 */ - &.layout:before { content: '\268f'; } /* 268f */ - &.leaf:before { content: '\1f342 '; } /* 1f342 */ - &.left-1:before { content: '\2b05'; } /* 2b05 */ - &.left-bold:before { content: '\e4ad'; } /* e4ad */ - &.left-thin:before { content: '\2190'; } /* 2190 */ - &.left:before { content: '\261c'; } /* 261c */ - &.level-down:before { content: '\21b3'; } /* 21b3 */ - &.level-up:before { content: '\21b0'; } /* 21b0 */ - &.lifebuoy:before { content: '\e788'; } /* e788 */ - &.light-bulb:before { content: '\1f4a1'; } /* 1f4a1 */ - &.light-down:before { content: '\1f505'; } /* 1f505' */ - &.light-up:before { content: '\1f506'; } /* 1f506 */ - &.line-graph:before { content: '\1f4c8'; } /* 1f4c8 */ - &.link:before { content: '\1f517'; } /* 1f517 */ - &.list:before { content: '\2630'; } /* 2630 */ - &.location:before { content: '\e724'; } /* e724 */ - &.lock-open:before { content: '\1f513'; } /* 1f513 */ - &.lock:before { content: '\1f512'; } /* 1f512 */ - &.login:before { content: '\e740'; } /* e740 */ - &.logout:before { content: '\e741'; } /* e741 */ - &.loop:before { content: '\1f501'; } /* 1f501 */ - &.magnet:before { content: '\e7a1'; } /* e7a1 */ - &.mail:before { content: '\2709'; } /* 2709 */ - &.map:before { content: '\e727'; } /* e727 */ - &.megaphone:before { content: '\1f4e3'; } /* 1f4e3 */ - &.mic:before { content: '\1f3a4'; } /* 1f3a4 */ - &.minus:before { content: '\2d'; } /* 2d */ - &.mobile:before { content: '\1f4f1'; } /* 1f4f1 */ - &.monitor:before { content: '\1f4bb'; } /* 1f4bb */ - &.moon:before { content: '\263d'; } /* 263d */ - &.mouse:before { content: '\e789'; } /* e789 */ - &.music:before { content: '\1f3b5'; } /* 1f3b5 */ - &.mute:before { content: '\1f507'; } /* 1f507 */ - &.network:before { content: '\e776'; } /* e776 */ - &.new:before { content: '\1f4a5'; } /* 1f4a5 */ - &.newspaper:before { content: '\1f4f0'; } /* 1f4f0 */ - &.note:before { content: '\266a'; } /* 266a */ - &.numbered-list:before { content: '\e005'; } /* e005 */ - &.open-book:before { content: '\1f4d6'; } /* 1f4d6 */ - &.palette:before { content: '\1f3a8'; } /* 1f3a8 */ - &.paper-plane:before { content: '\e79b'; } /* e79b */ - &.paus:before { content: '\2389'; } /* 2389 */ - &.pencil:before { content: '\270e'; } /* 270e */ - &.phone:before { content: '\1f4de'; } /* 1f4de */ - &.picture:before { content: '\1f304'; } /* 1f304 */ - &.pie-chart:before { content: '\e751'; } /* e751 */ - &.play:before { content: '\25b6'; } /* 25b6 */ - &.plus:before { content: '\2b'; } /* 2b */ - &.popup:before { content: '\e74c'; } /* e74c */ - &.print:before { content: '\e716'; } /* e716 */ - &.progress-0:before { content: '\e768'; } /* e768 */ - &.progress-1:before { content: '\e769'; } /* e769 */ - &.progress-2:before { content: '\e76a'; } /* e76a */ - &.progress-3:before { content: '\e76b'; } /* e76b */ - &.publish:before { content: '\e74d'; } /* e74d */ - &.quote:before { content: '\275e'; } /* 275e */ - &.record:before { content: '\26ab'; } /* 26ab */ - &.reply-all:before { content: '\e713'; } /* e713 */ - &.reply:before { content: '\e712'; } /* e712 */ - &.resize-full:before { content: '\e744'; } /* e744 */ - &.resize-small:before { content: '\e746'; } /* e746 */ - &.retweet:before { content: '\e717'; } /* e717 */ - &.right-1:before { content: '\27a1'; } /* 27a1 */ - &.right-bold:before { content: '\e4ae'; } /* e4ae */ - &.right-thin:before { content: '\2192'; } /* 2192 */ - &.right:before { content: '\261e'; } /* 261e */ - &.rocket:before { content: '\1f680'; } /* 1f680 */ - &.rss:before { content: '\e73a'; } /* e73a */ - &.save:before { content: '\1f4be'; } /* 1f4be */ - &.search:before { content: '\1f50d'; } /* 1f50d */ - &.share:before { content: '\e73c'; } /* e73c */ - &.shareable:before { content: '\e73e'; } /* e73e */ - &.shuffle:before { content: '\1f500'; } /* 1f500 */ - &.signal:before { content: '\1f4f6'; } /* 1f4f6 */ - &.sound:before { content: '\1f50a'; } /* 1f50a */ - &.squared-cross:before { content: '\274e'; } /* 274e */ - &.squared-minus:before { content: '\229f'; } /* 229f */ - &.squared-plus:before { content: '\229e'; } /* 229e */ - &.star-empty:before { content: '\2606'; } /* 2606 */ - &.star:before { content: '\2605'; } /* 2605 */ - &.stop:before { content: '\25a0'; } /* 25a0 */ - &.suitcase:before { content: '\e78e'; } /* e78e */ - &.sweden:before { content: '\f601'; } /* f601 */ - &.switch:before { content: '\21c6'; } /* 21c6 */ - &.tag:before { content: '\e70c'; } /* e70c */ - &.text-doc-inverted:before { content: '\e731'; } /* e731 */ - &.text-doc:before { content: '\1f4c4'; } /* 1f4c4 */ - &.thermometer:before { content: '\e757'; } /* e757 */ - &.three-dots:before { content: '\e78d'; } /* e78d */ - &.thumbs-down:before { content: '\1f44e'; } /* 1f44e */ - &.thumbs-up:before { content: '\1f44d'; } /* 1f44d */ - &.thunder-cloud:before { content: '\26c8'; } /* 26c8 */ - &.ticket:before { content: '\1f3ab'; } /* 1f3ab */ - &.to-end:before { content: '\23ed'; } /* 23ed */ - &.to-start:before { content: '\23ee'; } /* 23ee */ - &.tools:before { content: '\2692'; } /* 2692 */ - &.traffic-cone:before { content: '\e7a3'; } /* e7a3 */ - &.trash:before { content: '\e729'; } /* e729 */ - &.triangle-down:before { content: '\25be'; } /* 25be */ - &.triangle-left:before { content: '\25c2'; } /* 25c2 */ - &.triangle-right:before { content: '\25b8'; } /* 25b8 */ - &.triangle-up:before { content: '\25b4'; } /* 25b4 */ - &.trophy:before { content: '\1f3c6'; } /* 1f3c6 */ - &.two-dots:before { content: '\e78c'; } /* e78c */ - &.up-1:before { content: '\2b06'; } /* 2b06 */ - &.up-bold:before { content: '\e4af'; } /* e4af */ - &.up-thin:before { content: '\2191'; } /* 2191 */ - &.up:before { content: '\261d'; } /* 261d */ - &.upload-cloud:before { content: '\e711'; } /* e711 */ - &.upload:before { content: '\1f4e4'; } /* 1f4e4 */ - &.user:before { content: '\1f464'; } /* 1f464 */ - &.users:before { content: '\1f465'; } /* 1f465 */ - &.vcard:before { content: '\e722'; } /* e722 */ - &.video:before { content: '\1f3ac'; } /* 1f3ac */ - &.voicemail:before { content: '\2707'; } /* 2707 */ - &.volume:before { content: '\e742'; } /* e742 */ - &.warning:before { content: '\26a0'; } /* 26a0 */ - &.water:before { content: '\1f4a6'; } /* 1f4a6 */ - - /* social extention map */ - &.behance:before { content: '\f34e'; } /* f34e */ - &.c-dribbble:before { content: '\f31c'; } /* f31c */ - &.c-facebook:before { content: '\f30d'; } /* f30d */ - &.c-flickr:before { content: '\f304'; } /* f304 */ - &.c-google+:before { content: '\f310'; } /* f310 */ - &.c-lastfm:before { content: '\f322'; } /* f322 */ - &.c-linkedin:before { content: '\f319'; } /* f319 */ - &.c-pinterest:before { content: '\f313'; } /* f313 */ - &.c-rdio:before { content: '\f325'; } /* f325 */ - &.c-skype:before { content: '\f33a'; } /* f33a */ - &.c-spotify:before { content: '\f328'; } /* f328 */ - &.c-stumbleupon:before { content: '\f31f'; } /* f31f */ - &.c-tumblr:before { content: '\f316'; } /* f316 */ - &.c-twitter:before { content: '\f30a'; } /* f30a */ - &.c-vimeo:before { content: '\f307'; } /* f307 */ - &.dribbble:before { content: '\f31b'; } /* f31b */ - &.dropbox:before { content: '\f330'; } /* f330 */ - &.evernote:before { content: '\f333'; } /* f333 */ - &.facebook:before { content: '\f30c'; } /* f30c */ - &.flattr:before { content: '\f336'; } /* f336 */ - &.flickr:before { content: '\f303'; } /* f303 */ - &.github:before { content: '\f300'; } /* f300 */ - &.google+:before { content: '\f30f'; } /* f30f */ - &.google-circles:before { content: '\f351'; } /* f351 */ - &.instagram:before { content: '\f32d'; } /* f32d */ - &.lastfm:before { content: '\f321'; } /* f321 */ - &.linkedin:before { content: '\f318'; } /* f318 */ - &.mixi:before { content: '\f34b'; } /* f34b */ - &.paypal:before { content: '\f342'; } /* f342 */ - &.picasa:before { content: '\f345'; } /* f345 */ - &.pinterest:before { content: '\f312'; } /* f312 */ - &.qq:before { content: '\f32a'; } /* f32a */ - &.rdio:before { content: '\f324'; } /* f324 */ - &.renren:before { content: '\f33c'; } /* f33c */ - &.s-facebook:before { content: '\f30e'; } /* f30e */ - &.sina-weibo:before { content: '\f33f'; } /* f33f */ - &.skype:before { content: '\f339'; } /* f339 */ - &.smashing:before { content: '\f357'; } /* f357 */ - &.social-c-github:before { content: '\f301'; } /* f301 */ - &.soundcloud:before { content: '\f348'; } /* f348 */ - &.spotify:before { content: '\f327'; } /* f327 */ - &.stumbleupon:before { content: '\f31e'; } /* f31e */ - &.tumblr:before { content: '\f315'; } /* f315 */ - &.twitter:before { content: '\f309'; } /* f309 */ - &.vimeo:before { content: '\f306'; } /* f306 */ - &.vk:before { content: '\f354'; } /* f354 */ -} diff --git a/app/assets/stylesheets/error_pages.scss b/app/assets/stylesheets/error_pages.scss index 59ac55d58e19851b83cafed5b464ef6d177b64a1..a15f9fa0c5919fdda4463a550dc0d68d7e1ed868 100644 --- a/app/assets/stylesheets/error_pages.scss +++ b/app/assets/stylesheets/error_pages.scss @@ -1,48 +1,34 @@ -@import 'colors'; +@import 'color-variables'; @import 'mixins'; html { min-height: 100%; } -#big-number { - font-family: Roboto-BoldCondensed, Helvetica, Arial, sans-serif; - font-size: 250px; - line-height: 1em; - text-align: center; - padding-top: 100px; - text-shadow: 0 2px 0 #fff, 0 -1px 0 #999; - color: #ddd; -} -.transparent { - opacity: 0.8; -} -#content { - font-family: Roboto, Helvetica, Arial, sans-serif; - text-align: center; - text-shadow: 0 1px 0 #fff; - font-size: 1.25em; - line-height: 1.5em; - color: $text-dark-grey; - position: absolute; - left: 0; right: 0; +.error-404 { + background: image-url('peeping-tom.png') no-repeat bottom; + background-attachment: fixed; } -#error_404 { - width: 100%; - height: 100%; +.error-404, +.error-422, +.error-500, +.error-not-public { + background-color: $background-grey; bottom:0px; + color: $text-dark-grey; + font-family: Helvetica, Arial, sans-serif; + height: 100%; margin: 0px; - font-family: Roboto, Helvetica, Arial, sans-serif; text-align: center; text-shadow: 0 1px 0 #fff; - color: #666; - background: image-url("peeping-tom.png") no-repeat bottom; - background-attachment: fixed; + width: 100%; - #big-number { - font-family: Roboto-BoldCondensed, Helvetica, Arial, sans-serif; + .big-number { + color: $text-grey; + font-family: Helvetica, Arial, sans-serif; font-size: 250px; + line-height: 1em; + padding-top: 50px; text-shadow: 0 2px 0 #fff, 0 -1px 0 #999; - color: #ddd; } a { @@ -55,55 +41,7 @@ html { min-height: 100%; } } .transparent { - filter: alpha(opacity=80); - opacity: 0.8; - } -} - -#error_422 { - background-color: #fff; - color: #666; - text-align: center; - font-family: arial, sans-serif; - - div.dialog { - width: 25em; - padding: 0 4em; - margin: 4em auto 0 auto; - border: 1px solid #ccc; - border-right-color: #999; - border-bottom-color: #999; - } - - h1 { - font-size: 100%; - color: #f00; - line-height: 1.5em; - } -} - -#error_500 { - text-align: center; - background-color: rgb(252,252,252); - color: #444; - font-family: 'helvetica neue', 'helvetica', 'arial', sans-serif; - margin: 0; - padding: 1em; - - header { - height: 100px; - background-color: #333; - position:relative; - } - - #diaspora_logo { - position: relative; - margin-top: 50px; - } - - h1 { - font-size: 100%; - color: #444; - line-height: 1.5em; + filter: alpha(opacity = 60); + opacity: .6; } } diff --git a/app/assets/stylesheets/facebox.scss b/app/assets/stylesheets/facebox.scss deleted file mode 100644 index 18b07f2a3281328cb8e8ed2a12918ecc6906f615..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/facebox.scss +++ /dev/null @@ -1,32 +0,0 @@ -.facebox_content { display: none; } - -#facebox { - input[type='text'], input.text { width: 98%; } -} - -#facebox_header { - position: relative; - padding-bottom: 10px; - - .right { - z-index: 3; - right: 1em; - top: 14px; - color: #ccc; - - img { - vertical-align: top; - position: relative; - top: 0px; - } - } - - h3, h4 { - .description { margin-top: 0px; } - } - - .tiny_text { - font-size: 11px; - font-weight: normal; - } -} diff --git a/app/assets/stylesheets/footer.scss b/app/assets/stylesheets/footer.scss index 2fc0168a53d26f3adb5cb219aca85a38a3b60e90..ad1c398a2ab8d8b2f9b127749c9620003ac138ac 100644 --- a/app/assets/stylesheets/footer.scss +++ b/app/assets/stylesheets/footer.scss @@ -1,28 +1,29 @@ -footer { - width: 100%; - left: 0; - bottom: 0; - color: $text-grey; +html { + min-height: 100%; + position: relative; +} - .container { - width: 95%; - margin: 4em auto 0 auto; - padding: 0.5em 0 1em 0; - border-top: 1px solid $border-grey; - } +body { margin-bottom: 150px; } - .logos-powered_by_diaspora { - display: inline-block; - margin-top: 3px; - height: 11px; - width: 145px; +footer.footer { + background-color: $background-grey; + border-top: 1px solid $border-grey; + bottom: 0; + max-height: 130px; + padding-top: 15px; + padding-bottom: 15px; + position: absolute; + width: 100%; + + .powered-by-diaspora { + color: $link-grey; + font-weight: bold; } ul#footer_nav { margin: 0; padding: 0; display: inline-block; - float: right; > li { display: inline; diff --git a/app/assets/stylesheets/forms.scss b/app/assets/stylesheets/forms.scss new file mode 100644 index 0000000000000000000000000000000000000000..98a02a62303055439d2e5445018e51f227a5d487 --- /dev/null +++ b/app/assets/stylesheets/forms.scss @@ -0,0 +1,100 @@ +// We need these to reset Bootstrap styles +// scss-lint:disable QualifyingElement +input, +input[type=email], +input[type=text], +input[type=password], +textarea { + &, + &:active, + &:invalid, + &:invalid:required, + &:focus, + &:active:focus, + &:invalid:focus, + &:invalid:required:focus { + border-color: $border-grey; + box-shadow: none; + color: $text-dark-grey; + } +} +// scss-lint:enable QualifyingElement + +textarea { + resize: vertical; +} + +// Forms described here are only used on the public pages at the moment +.block-form { + margin: 20px auto; + + fieldset { + background-color: $white; + margin-bottom: 1em; + position: relative; // To correctly place the entypo icon + + input { + border-bottom-width: 0; + border-radius: 0; + color: $text-dark-grey; + margin: 0; + } + + .form-control { + font-size: 16px; + height: 40px; + padding: 10px; + padding-left: 40px; + } + + .form-control:first-of-type, + .form-control:first-of-type:focus, + .form-control:first-of-type:invalid, + .form-control:first-of-type:invalid:focus, + .form-control:first-of-type:invalid:required, + .form-control:first-of-type:invalid:required:focus { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + } + + .form-control:last-of-type, + .form-control:last-of-type:focus, + .form-control:last-of-type:invalid, + .form-control:last-of-type:invalid:focus, + .form-control:last-of-type:invalid:required, + .form-control:last-of-type:invalid:required:focus { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + border-bottom-width: 1px; + } + + [class^="entypo-"], + [class*="entypo-"] { + color: $text-grey; + font-size: 20px; + left: 10px; + line-height: 20px; + position: absolute; + text-align: center; + top: 10px; + width: 20px; + } + + [class^="entypo-"]:nth-of-type(2), + [class*="entypo-"]:nth-of-type(2) { + top: 50px; + } + + [class^="entypo-"]:nth-of-type(3), + [class*="entypo-"]:nth-of-type(3) { + top: 90px; + } + + [class^="entypo-"]:nth-of-type(4), + [class*="entypo-"]:nth-of-type(4) { + top: 130px; + } + + ::placeholder { text-transform: uppercase; } + } +} diff --git a/app/assets/stylesheets/gallery.scss b/app/assets/stylesheets/gallery.scss new file mode 100644 index 0000000000000000000000000000000000000000..3cfcb2d2b4538f1be84fba43420a1204fc25365d --- /dev/null +++ b/app/assets/stylesheets/gallery.scss @@ -0,0 +1,61 @@ +$thumbnail-size: 12px; +$thumbnail-margin: 2px; +$thumbnail-active-size: $thumbnail-size + $thumbnail-margin; + +#blueimp-gallery { + .slides { + height: calc(100% - 40px); + padding: 20px 0 0 0; + margin: 0; + } + + [class^="entypo-"], [class*="entypo-"] { + color: $text-grey; + display: block; + width: 40px; + height: 40px; + line-height: 40px; + margin: 0; + padding: 0; + } + + .play-pause { + z-index: 2; + color: $text-grey; + } + + .prev, .next { + border-color: $text-grey; + } + + .prev [class^="entypo-"], .prev [class*="entypo-"] { + padding-right: 6px; + } + + .next [class^="entypo-"], .next [class*="entypo-"] { + padding-left: 6px; + } + + .indicator { + margin: 8px 0; + position: unset; + height: $thumbnail-size + 5px; + li { + border: none; + margin: $thumbnail-margin; + vertical-align: middle; + width: $thumbnail-size; + height: $thumbnail-size; + border-radius: $thumbnail-size / 2; + + &.active, &:hover{ + margin: $thumbnail-margin / 2; + width: $thumbnail-active-size; + height: $thumbnail-active-size; + border-radius: $thumbnail-active-size / 2; + transition: linear 0.2s; + transition-property: height, width, margin; + } + } + } +} diff --git a/app/assets/stylesheets/getting-started.scss b/app/assets/stylesheets/getting-started.scss index 57b4d0a6fdf0658ef81a875a75a748f05cf7d0db..12c4931a1c565223024d04981ebb56db66c87b69 100644 --- a/app/assets/stylesheets/getting-started.scss +++ b/app/assets/stylesheets/getting-started.scss @@ -1,7 +1,11 @@ #hello-there { - .avatar { - width: 50px; - height: 50px; + #profile_photo_upload .avatar { + max-height: 200px; + max-width: 200px; + } + + .well .avatar { + min-width: 50px; } .well .media{ @@ -9,11 +13,7 @@ } .awesome { - text-align: center; - - .btn.creation { - text-shadow: none; - } + margin-top: 15px; } .hero-unit { @@ -25,16 +25,12 @@ margin-top: 80px; } - p, form { - margin-left: 30px; - } - ul.as-selections { width: 100%; - li.as-original { + width: 100%; input { - margin-bottom: 15px; + height: 32px; } } } @@ -52,10 +48,8 @@ #welcome-to-diaspora { background: orange; box-shadow: inset 0 -2px 10px rgba(0,0,0,0.35); - margin-bottom: 20px; - margin-top: -40px; padding-bottom: 30px; - padding-top: 60px; + padding-top: 20px; h1,h3 { color: $white; diff --git a/app/assets/stylesheets/header.scss b/app/assets/stylesheets/header.scss index 7e4757ae8ffe5901a83a9294e5dbc6af441cf7f5..9cb3a533df27bd51baeb67c919b23463705dee6d 100644 --- a/app/assets/stylesheets/header.scss +++ b/app/assets/stylesheets/header.scss @@ -1,429 +1,148 @@ -.timeago { - color: $text-grey; +.navbar.navbar-fixed-top { border-bottom: none; -} - -body > header { - box-shadow: 0 1px 3px rgba(0,0,0,0.9); - background: image-url('header-bg.png') rgb(40,35,35); - z-index: 1001; - padding: 6px 0; - color: #CCC; - height: 26px; - position: fixed; - width: 100%; - min-width: 620px; - top: 0; - left: 0; - border-bottom: 1px solid #000; - - > div > div.container { - height: 26px; - } - - .diaspora_header_logo { - float: left; - margin-top: -6px; - height: 38px; - width: 65px; - } - - .ie-user-menu-active { height: 150px; } - - a.header_root_link { - display: inline-block; - margin-top: 5px; - } + box-shadow: 1px 0 2px $black; + a:focus {outline: 0 none; } - a { - color: #CCC; - color: rgb(147,147,147); - - &:hover, &:focus { - background: none; - color: $highlight-white; + .navbar-brand { + font-weight: bold; + font-size: $font-size-h3; + } + + @media (max-width: $grid-float-breakpoint-max) { + .navbar-header > .nav li { display: inline-block !important; } + .nav-badge { + color: $navbar-inverse-link-color; + padding-left: 12px; + padding-right: 12px; + &:hover { color: $navbar-inverse-link-hover-color; } + &:hover, + &:focus { + background-color: transparent; + } } - &:focus { - outline: thin dotted $border-dark-grey; - text-decoration: none; + #navbar-collapse { + .form-group, .twitter-typeahead { + display: block !important; + margin-bottom: 0; + &, & input { width: 100% } + } } } - - &.landing { - height: 40px; - .right { top: 10px; } - } - - #nav_badges { - display: inline-block; - margin-top: 2px; - float: left; - width: 61px; - - a:hover { text-decoration: none; } - - .badge { - width: 22px; - position: relative; - top: 2px; - display: inline; - margin: 0 2px; - font-weight: bold; - font-size: smaller; - - .badge_count { - border-radius: 2px; - z-index: 3; - position: absolute; - top: -4px; - left: 15px; - padding: 1px 2px; - background-color: $red; - line-height: 12px; - color: #fff; + @media (min-width: $grid-float-breakpoint) { + input[type="search"] { + @include transition(width); + margin-top: 2px; + width: 200px; + &:not(.active) { + background-color: $navbar-inverse-bg; + border-color: $gray-light; + width: 150px; } - - &:hover .badge_count { background-color: lighten($red, 5%); } - - .icons-notifications_grey { height: 16px; } - - &.active .icons-notifications_grey:hover { - background-position: sprite-position($icons-sprites, notifications_grey); + } + #user_menu { + &.open .dropdown-toggle { background-color: darken($navbar-inverse-bg, 7%); } + .dropdown-toggle { + margin: 0 1px; + min-width: 160px; } - - .icons-mail_grey { height: 11px } - - a.badge_link { - display: block; + .dropdown-menu { + background-color: darken($navbar-inverse-bg, 7%); + border-top: none; width: 100%; - height: 16px; - float: left; + & > li > a { + color: $gray-light; + padding-left: 55px; + &:hover { + background-color: $link-color; + color: $gray-lighter; + } + } } } + } - #notification_badge, #conversations_badge { - float: left; - padding: 0px 3px; - } - - #conversations_badge { - padding-top: 3px; - margin-right: 0px; - padding-right: 0px; - } - - #notification_badge.active { - z-index: 10; - background-color: #fff; - border: 1px solid $border-dark-grey; - border-bottom: 0px; - margin-left: 0px; - padding-bottom: 12px; + .navbar-nav:not(.nav-badges) > li > a { font-weight: bold; } + .nav-badges { + li { height: $navbar-height; } + .dropdown-open { + background-color: $dropdown-bg; + & > a { color: $dropdown-link-color; } + .dropdown-menu { display: block; } } - - #notification_dropdown { - background: white; - border: solid $border-dark-grey 1px; - box-shadow: 0 0px 13px rgba(20,20,20,0.5); - left: 300px; - width: 380px; - display: none; - float: left; - color: $grey; - - a { color: $blue; } - a.disabled { - color: $link-disabled-grey; - cursor: default; + .dropdown-menu { + border-top: none; + margin-left: -1px; + padding: 0px; + width: 400px; + .avatar { + width: 35px; + height: 35px; } - .header { + padding: 10px; border-bottom: 1px solid $border-grey; - padding: 5px 10px 5px 5px; - - h4 { - padding-bottom: 0; - margin-bottom: 0; - font-size: 16px; - color: $black; - } - - a { - font-size: 11px; - font-weight: bold; + h4 { margin: 5px 0; } + } + .notifications { + position: relative; + max-height: 350px; + } + .stream_element.media { + padding: 5px; + .tooltip { position: fixed; } + .unread-toggle { + margin-right: 10px; + opacity: 1; } + & > .pull-right > .aspect_membership_dropdown { display: none; } } - - .ajax_loader { + .ajax-loader { border-bottom: 1px solid $border-grey; - text-align: center; - padding: 15px; - } - .notifications{ - overflow: hidden; - position: relative; - max-height: 325px; - - .media.stream_element { - border-bottom: 1px solid $border-grey; - padding: 5px; - min-height: 35px; - line-height: 18px; - margin: 0; - - img.avatar { - width: 35px; - height: 35px; - } - - .pull-right > .aspect_membership_dropdown { display: none; } - .unread-toggle { margin: 10px; } - - .entypo { - cursor: pointer; - color: lighten($black,75%); - font-size: 17px; - line-height: 17px; - } - .tooltip { - position: fixed; - } - - &.unread { - background-color: $background-grey; - color: $black; - .unread-toggle { - .entypo { color: $black; } - } - } - + padding: 10px; + .spinner { + height: 30px; + width: 30px; } } - .view_all { - background-color: $blue; - border-bottom: 1px solid $border-dark-grey; + background-color: $link-color; + border-top: 3px solid $white; text-align: center; a { + color: $white; display: block; - padding: 5px; - color: white; - font-size: 12px; font-weight: bold; + padding: 5px; + &:hover { text-decoration: none; } } } } } - - #global_search { - float: right; - margin-right: 10px; - position: relative; - - form { - position: absolute; - right: 0; - - input { - box-shadow: 0 1px 1px #444; - border-radius: 15px; - @include transition(width); - width: 100px; - background-color: #444; - border: 1px solid #222; - font-size: 13px; - padding: 4px; - margin-top: 1px; - - &:hover { background-color: #555; } - - &.active { - background-color: $highlight-white; - background-color: rgba(160,160,160,0.6); - } - - &:focus { - outline: none; - background-color: white; - width: 200px; - } - - &::input-placeholder { text-shadow: none; } - &::placeholder { text-shadow: none; } - &.ac_loading::-webkit-search-cancel-button { -webkit-appearance: none; } - } - } - } - - ul#user_menu { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - text-shadow: 0 1px 0 #000; - color: rgb(147,147,147); - min-width: 100px; - cursor: pointer; - z-index: 10; - display: inline; - visibility: hidden; - top: -4px; - float: right; - margin: -2px -3px 0px 0px; - padding: 0; - - > li { - display: block; - border-left: 1px solid #333; - border-right: 1px solid #333; - - &:first-child { - visibility: visible; - } - - &:last-child { - border-bottom: 1px solid #333; - } - } - - &.active { - box-shadow: 0 0px 13px rgba(20,20,20,0.5); - background-color: rgb(34,30,30); - visibility: visible; - - > li { - border-color: $border-dark-grey; - } - } - } - - .user-menu-item a { - padding: 4px 8px 4px 40px; - height: 100%; - color: $text-grey; - - &:hover { - background-color: $blue; - color: $highlight-white; - text-decoration: none; - } - } - - .user-menu-trigger { - padding: 10px 25px 10px 40px; - - &:hover { - color: $highlight-white; - .user-name { color: $highlight-white; } - } - } - - .user-name { - - &:hover { - background-color: transparent; - text-decoration: none; - } - - &:focus { outline: none; } - } - - .user-menu-more-indicator { - position: absolute; - right: 5px; - } - - .user-menu-avatar { - height: 25px; - width: 25px; - position: absolute; - left: 8px; - top: 8px; - display: block; + [class^="entypo-"], [class*="entypo-"] { + color: inherit; + font-size: $font-size-h3; + vertical-align: middle; } - - .header-nav { - font-weight: bold; - float: left; - height: 100%; - margin-right: 5px; - margin-top: 2px; - - a { - padding: 0 10px; - width: 100%; - &:hover { text-decoration: none; } - } - - > span { - height: 100%; - display: inline-block; - margin-left: -4px; - border-left: 1px solid #333; - border-right: 1px solid #333; - - &:last-child { - margin-left: -5px; - } + .nav-badge { + margin-bottom: -2px; + .badge { + position: absolute; + right: 10px; + top: 10px; } } - /* When the user is not connected */ - ul#landing_nav { - position: absolute; - top: 4px; - right: 0; - margin: 0; - padding: 0; - - > li { - text-shadow: 0 1px 0 #000; - display: inline; - margin-right: 0.5em; - - a { - color: $blue; - - &.login { - border-radius: 5px; - box-shadow: 0 1px 1px #666; - padding: 5px 8px; - background-color: #000; - border-top: 1px solid #000; - - &:hover { background-color: #222; } - } - } - - &:last-child { margin-right: 0; } + #user_menu { + .avatar { + height: 30px; + width: 30px; } - } -} - - -/* - * Extract here from application.sass because - * needed for the header in the bootstrap part - */ -ul.dropdown { - padding: 0px; - - li { - display: none; - - a { display: block; } - - &:first-child { - display: block; - - a { - height: auto; - display: inline; - } + .user-avatar { + height: $navbar-height; + padding: ($navbar-height - 30px)/2 0; + margin-bottom: -$navbar-padding-vertical; + margin-top: -$navbar-padding-vertical; + margin-right: 10px; } } - - &.active { - z-index: 30; - li { display: block; } - } } diff --git a/app/assets/stylesheets/help.scss b/app/assets/stylesheets/help.scss index 56fde842eb499a6fc84d772598e42213df6adfea..d5a8647704b1ca25d5b4595f89f889d56ab8b0a2 100644 --- a/app/assets/stylesheets/help.scss +++ b/app/assets/stylesheets/help.scss @@ -97,10 +97,10 @@ ul#help_nav { font-size: 50px; line-height: 70px; - i.entypo{ + [class^="entypo-"], [class*="entypo-"] { color: #bfbfbf; - &.chat{ color: #000000; } + &.entypo-chat{ color: #000000; } } } } diff --git a/app/assets/stylesheets/home.scss b/app/assets/stylesheets/home.scss index acb3e91958db0ad30bb1aad77224e9b60e3513a7..b661e4b4f4cd613c2949fa5a6e07a9291fd6b751 100644 --- a/app/assets/stylesheets/home.scss +++ b/app/assets/stylesheets/home.scss @@ -1,84 +1,56 @@ -body { - margin-top: 50px; - background-color: white; - background-image : none; -} - -li { - list-style: none; -} - -footer h3 { - margin-bottom: 25px; - text-align: center; -} - -footer { - margin-bottom: 12px; - padding: 42px; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; - width: auto -} - -#header { - /* Hack to hide the header */ - box-shadow:none; - border:none; - background:none; - - left: 0px; - padding: 15px 0px; -} - -#header img { - margin-left: 15px; -} - -#login-link { - float: right; - margin-right: 15px; -} - -#steps { - text-align: center; -} - -#banner { - border-bottom : 1px solid #ccc; - border-top : 1px solid #eee; - padding : 30px; - margin-top: 20px; - text-align: center; - - box-shadow : 0 9px 15px -10px rgba(0,0,0,0.7); -} - -#links { - margin: 0; - padding: 0; - text-align: center; -} - -#links .section { - margin: 0; - padding: 0; - display: inline-block; - vertical-align: top; - width: 24%; - max-width: 24%; -} - -#change-page { - color: #999; - text-align: center; - font-style: italic; -} - -.helpful { - cursor: help; -} - -.row { - margin-bottom: 60px; +.page-home { + background-color: $main-background; + + h3 { + border-bottom: 1px dashed $border-grey; + font-weight: bold; + margin: 0 0 15px; + padding-bottom: 15px; + } + + .container-fluid.home-user { + padding-bottom: 75px; + padding-top: 75px; + } + + .dandelion-background { + background: image-url('dandelion.jpg'); + background-position: center; + background-repeat: no-repeat; + background-size: cover; + } + + .jumbotron { + background-color: rgba($black, .4); + margin-bottom: 0; + + h1, + h2 { + color: $white; + font-weight: bold; + text-shadow: 0 2px 2px $black; + } + } + + .landing-info-card { + background-color: $white; + border: 1px solid $light-grey; + box-shadow: $card-shadow; + margin-bottom: 25px; + margin-top: 25px; + min-height: 150px; + padding: 15px; + } + + .login-form { + fieldset { background: none; } + + .block-form { + background-color: rgba($white, .25); + border-radius: 5px; + margin: 0; + max-width: 400px; + padding: 1em; + } + } } diff --git a/app/assets/stylesheets/hovercard.scss b/app/assets/stylesheets/hovercard.scss index eb5ae9518d817f061667a73134c31272a5cedfcf..1cf9ae620d0f24f6fc604fdad58cf0dfe7493168 100644 --- a/app/assets/stylesheets/hovercard.scss +++ b/app/assets/stylesheets/hovercard.scss @@ -8,7 +8,6 @@ max-width: 400px; background-color: $background-white; - height: 70px; border: 1px solid $border-dark-grey; font-size: small; @@ -27,11 +26,14 @@ $image_width: 80px; /* including margin */ - & > h4, & > div { + > h4, + > div:not(.card-footer) { margin-left: $image_width; } - & > h4, & > div, .hashtags { + > h4, + > div, + .hashtags { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; @@ -65,32 +67,6 @@ } .btn-group.aspect_membership_dropdown { margin: 0 !important; } - - .hovercard_footer { - position: absolute; - bottom: 0; - left: 0; - background-color: $background-grey; - margin-left: 0; - - width: 100%; - min-height: 19px; - - font-size: 10px; - line-height: 18px; - - border-top: 1px solid #cccccc; - - .footer_container { - padding: 1px 5px; - - a { - color: $text-grey; - margin-right: 4px; - font-weight: normal; - } - } - } } #hovercard_container { diff --git a/app/assets/stylesheets/icons.scss b/app/assets/stylesheets/icons.scss new file mode 100644 index 0000000000000000000000000000000000000000..b4496bbd3a179780a2fcc03a4243dfdde01b6af0 --- /dev/null +++ b/app/assets/stylesheets/icons.scss @@ -0,0 +1,13 @@ +[class^="entypo-"], [class*="entypo-"] { + font-style: normal; + color: black; + + &.red { color: #A40802; } + &.white { color: white; } + &.gray { color: #aaa; } + &.blue { color: #3f8fba; } + + &.small { font-size: 1em; } + &.middle { font-size: 1.5em; } + &.large { font-size: 2.5em; } +} diff --git a/app/assets/stylesheets/interactions.scss b/app/assets/stylesheets/interactions.scss new file mode 100644 index 0000000000000000000000000000000000000000..90c5d00631121bf0b62d2e982a4a44d9dfdef16f --- /dev/null +++ b/app/assets/stylesheets/interactions.scss @@ -0,0 +1,65 @@ +.control-icons { + a { + &:hover { text-decoration: none; } + + [class^="entypo-"], + [class*="entypo-"] { + color: $text-grey; + font-size: $font-size-base; + line-height: $line-height-base; + vertical-align: middle; + } + + [class^="entypo-"]:hover, + [class*="entypo-"]:hover { + color: $text; + } + + &.hide_conversation i { font-size: $line-height-computed * 1.5; } + &.delete_conversation i { font-size: $font-size-base * 1.5; } + &.destroy_participation i { color: $black; } + &.destroy_participation i:hover { color: $text-dark-grey; } + } +} + +.stream_container, +.single-post-interactions { + .control-icons { + float: right; + z-index: 6; + + .block_user, + .comment_report, + .create_participation, + .delete, + .destroy_participation, + .post_report { + display: inline-block; + } + + > a:hover { text-decoration: none; } + } +} + +.stream_element, +.comment, +.photo, +.stream_element:hover .comment { + .control-icons { + @include transition(opacity); + opacity: 0; + } + + &:hover .control-icons { opacity: 1; } +} + +.stream_element, +.comment, +.photo { + .control-icons > a { + @include transition(opacity); + opacity: .8; + } + + .control-icons > a:hover { opacity: 1; } +} diff --git a/app/assets/stylesheets/invitations.scss b/app/assets/stylesheets/invitations.scss index 366b0caf4059e4be47d75c83df643bce2f928ae8..a78bed09f9304570a59aa4834c56efca25889282 100644 --- a/app/assets/stylesheets/invitations.scss +++ b/app/assets/stylesheets/invitations.scss @@ -8,13 +8,12 @@ #invitationsModal { .modal-header, .modal-body { color: $text; - font-size: $font-size-text; + font-size: $font-size-base; text-align: initial; } #paste_link { font-weight: 700; } #invite_code { margin-top: 10px; } #codes_left { color: $text-grey; } - .control-label { width: 120px; } .controls { margin-left: 140px; } #email_invitation { padding-top: 10px; diff --git a/app/assets/stylesheets/leftnavbar.scss b/app/assets/stylesheets/leftnavbar.scss deleted file mode 100644 index 6bee6e8d63824454f729f513c6a869e52a1843e5..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/leftnavbar.scss +++ /dev/null @@ -1,127 +0,0 @@ -#leftNavBar { - a { - color: $link-grey; - font-weight: bold; - text-decoration: none; - } - - ul { - margin: 0px; - padding: 0px; - list-style: none; - } - - .selected { color: $black; } - .selected a { color: $black; } - - .hoverable { - display: block; - margin-right: 6px; - padding: 4px; - &:hover { background-color: $background-blue; } - } - - .selectable { - display: block; - margin-left: 21px; - overflow: hidden; - text-overflow: ellipsis; - } - - #home_user_badge { - border-bottom: 1px dashed $border-grey; - margin-bottom: 10px; - min-height: 50px; - padding-bottom: 10px; - padding-left: 4px; - - .avatar { - float: left; - height: 50px; - width: 50px; - } - - h4 { - margin-left: 60px; - padding-top: 15px; - overflow: hidden; - text-overflow: ellipsis; - - a { color: $black; } - } - } - - #stream_selection { - & > li { - margin-bottom: 5px; - } - } - - #aspects_list, #tags_list { - .hoverable > .action { - visibility: hidden; - margin: 0 3px; - } - .hoverable:hover > .action { - visibility: visible; - } - } - - #aspects_list { - .entypo.check { - float: left; - visibility: hidden; - &.selected { visibility: visible; } - } - .selected + a { - color: #333333; - } - } - - #tags_list { - .delete_tag_following { - font-size: 20px; - line-height: 15px; - } - - #new_tag_following { - margin-left: 20px; - margin-top: 5px; - } - - /* ---- override app/stylesheets/vendor/autoSuggest.css ---- */ - ul.as-selections { padding: 1px 5px 4px 5px; } - .tag_input { - line-height: $font-size-text; - vertical-align: top; - width: 100%; - } - - .as-result { - margin-top: -1px; - margin-left: 1px; - } - - .as-list { - em { - background-color: #aabbcc; - color: black; - padding: 0px; - } - - color: black; - position: static; /* override absolute */ - margin: 0px; - border-radius: 0px 0px 3px 3px; - box-shadow: 0px 1px 1px #666; - } - - .as-result-item.active { - color: black; - text-shadow: none; - background-color: $background-blue; - border-color: $background-blue; - } - /* ---- end override app/stylesheets/vendor/autoSuggest.css ---- */ - } -} diff --git a/app/assets/stylesheets/lightbox.scss b/app/assets/stylesheets/lightbox.scss deleted file mode 100644 index 872126eb0fc51025e933493c229bf4f9f6b52b5b..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/lightbox.scss +++ /dev/null @@ -1,147 +0,0 @@ -#lightbox{ - z-index: 1003; - position: fixed; - top: 0; - right: 0; - display: none; - overflow-y: auto; - width: 100%; - text-align: center; - padding-top: 80px; - padding-bottom: 20px; - - color: $text-dark-grey; - text-shadow: none; - font-size: 12px; - - &.show{ - position: absolute; - display: block; - } - - #lightbox-image{ - box-shadow: 0 10px 20px black; - top: 0; - display: block; - margin-bottom: 120px; - background: white; - } - - #lightbox-content{ - text-align: left; - display: inline-block; - } - - #lightbox-links{ - margin-top: 12px; - - .attribution{ - float: right; - } - - #lightbox-attribution-link{ - color: #999; - font-weight: bold; - &:hover{ - color: #eee; - } - } - } - - #lightbox-close-link, - #lightbox-attribution-link, - #lightbox-short-link{ - display: inline-block; - color: #333; - text-decoration: none; - line-height: 14px; - - &:hover{ - color: #eee; - } - } - - #lightbox-close-link{ - color: $text-dark-grey; - margin-bottom: 12px; - } -} - -#lightbox-backdrop{ - box-shadow:inset 0 0 50px #000000; - - z-index: 1002; - position: fixed; - height: 100%; - width: 100%; - top: 0; - left: 0; - background-color: rgba(0,0,0,0.9); - display: none; -} - -#lightbox-navigation{ - z-index: 1004; - position: fixed; - width: 100%; - left: 0; - bottom: 0; - text-align: center; - background-color: rgba(0,0,0,0.4); - padding: 5px 0; - white-space: nowrap; - overflow: hidden; -} - -#lightbox-scrollleft, #lightbox-scrollright{ - z-index: 1005; - color: #fff; - background-color: #0f0f0f; - display: inline-block; - height: 70px; - width: 30px; - position: fixed; - cursor: pointer; - font-size: 3em; -} - -#lightbox-scrollleft{ - left: 0px; -} - -#lightbox-scrollright{ - right: 0px; -} - -#lightbox-imageset{ - display: inline-block; - vertical-align: bottom; - padding-left: 50px; - padding-right: 50px; - - img{ - transition: opacity 0.2s; - opacity: 0.2; - height: 70px; - width: 70px; - margin-right: 5px; - cursor: pointer; - background-color: white; - - &:last-child{ - margin-right: 0; - } - - &.selected{ - opacity: 1; - } - } -} - -body.lightboxed{ - overflow: hidden; - #lightbox-backdrop{ - display: block; - } -} - diff --git a/app/assets/stylesheets/new_styles/_login.scss b/app/assets/stylesheets/login.scss similarity index 60% rename from app/assets/stylesheets/new_styles/_login.scss rename to app/assets/stylesheets/login.scss index d0da964288095908545755502409bc8c6219e60f..b0336a8e060dee989e014ee4a512ced492e7ae04 100644 --- a/app/assets/stylesheets/new_styles/_login.scss +++ b/app/assets/stylesheets/login.scss @@ -1,16 +1,16 @@ -#login, -#forgot_password, -#reset_password { +.page-sessions.action-new, +.page-passwords.action-new, +.page-passwords.action-edit { padding-top: 25px; .logos-asterisk { - margin: auto; - width: 154px; height: 154px; + margin: auto; margin-bottom: 12px; + width: 154px; } - form.block-form { + .block-form { max-width: 400px; } } diff --git a/app/assets/stylesheets/map.scss b/app/assets/stylesheets/map.scss new file mode 100644 index 0000000000000000000000000000000000000000..c521795bf7bf5b7e09f9d63c3b1c71ed514084f7 --- /dev/null +++ b/app/assets/stylesheets/map.scss @@ -0,0 +1,21 @@ +.mapContainer { + position: relative; + overflow: hidden; +} + +.stream_element .near-from:hover { + cursor: pointer; + text-decoration: underline; +} + +.leaflet-control-zoom { + display: none; +} + +.leaflet-bottom .leaflet-control { + margin-bottom: 0; +} + +.leaflet-right .leaflet-control { + margin-right: 0; +} diff --git a/app/assets/stylesheets/markdown-content.scss b/app/assets/stylesheets/markdown-content.scss index 9caacef448ebff6f17f215099cba425df96a9e02..316907fb162f6f9427700a68b7f47a5d2c953dee 100644 --- a/app/assets/stylesheets/markdown-content.scss +++ b/app/assets/stylesheets/markdown-content.scss @@ -14,4 +14,8 @@ margin-top: 0; } } + + .img-responsive { + display: inline; + } } diff --git a/app/assets/stylesheets/markdown-editor.scss b/app/assets/stylesheets/markdown-editor.scss new file mode 100644 index 0000000000000000000000000000000000000000..cb731118b0c6436563372d8c1b013273f86bfda0 --- /dev/null +++ b/app/assets/stylesheets/markdown-editor.scss @@ -0,0 +1,141 @@ +.md-footer, +.md-header { + background: $sidebars-background; + border: 0; + display: block; + height: 42px; + margin: 0; + padding: 6px 6px 0; + + [class^="entypo-"], + [class*="entypo-"], + .glyphicon { + color: $black; + } +} + +.md-header, +.nav-tabs { + border-bottom: 0; + margin: 0; + z-index: 1; +} + +.md-header.btn-toolbar { + background-color: $background-grey; + overflow: hidden; + + .btn-group { + margin-bottom: 8px; + + [class^="entypo-"], + [class*="entypo-"] { + font-size: 13px; + } + + [data-handler="bootstrap-markdown-cmdUrl"], + [data-handler="bootstrap-markdown-cmdImage"], + [data-handler="bootstrap-markdown-cmdList"], + [data-handler="bootstrap-markdown-cmdListO"], + [data-handler="bootstrap-markdown-cmdCode"], + [data-handler="bootstrap-markdown-cmdQuote"] { + height: 28.5px; + line-height: 1.25; + } + } + + @media(max-width: $screen-xs) { + [data-handler="bootstrap-markdown-cmdList"], + [data-handler="bootstrap-markdown-cmdListO"] { + display: none; + } + + [data-handler="bootstrap-markdown-cmdCode"] { + // !important is needed to override BS' specific rules + // scss-lint:disable ImportantRule + border-bottom-left-radius: $border-radius-small !important; + border-top-left-radius: $border-radius-small !important; + // scss-lint:enable ImportantRule + } + } +} + +.md-cancel { + box-sizing: content-box; + + &, + .entypo-cross { + color: $text-grey; + font-size: 18px; + height: 18px; + line-height: 18px; + width: 18px; + } + + &:hover .entypo-cross { color: $text; } +} + + +.md-preview { + background: $white; + color: $text-color; + // !important is needed to override the CSS rules dynamically added to the element + // scss-lint:disable ImportantRule + height: auto !important; + // scss-lint:enable ImportantRule + min-height: 90px; + overflow: auto; + position: relative; + // !important is needed to override the CSS rules dynamically added to the element + // scss-lint:disable ImportantRule + width: 100% !important; + // scss-lint:enable ImportantRule + z-index: 10; +} + +.md-controls { + float: right; + padding: 3px; + + .md-control { + color: $text-grey; + padding: 3px; + padding-left: 10px; + right: 5px; + } +} + + +.write-preview-tabs { + &, + & .full-height { + height: 36px; + } + + > li { + > a { padding: 7px 15px; } + + &:not(.active) * { color: $brand-primary; } + + &.active * { color: $black; } + } + + a:focus { outline: none; } + + li { + &:not(.active) a:focus, + &:not(.active) a:hover { + background-color: transparent; + border: 1px solid transparent; + } + + &.active:focus { color: $black; } + } + + .diaspora-custom-compose::before { + bottom: -2px; + position: relative; + } +} + +.publisher-textarea-wrapper:not(.active) .md-header { display: none; } diff --git a/app/assets/stylesheets/media-box.scss b/app/assets/stylesheets/media-box.scss index 2c11626d9da9bf98e3cedf0eb28cc1204d1281d3..7f6139ab132dee084e978e41f99ec25113a2a641 100644 --- a/app/assets/stylesheets/media-box.scss +++ b/app/assets/stylesheets/media-box.scss @@ -1,4 +1,6 @@ -.media { margin: 10px; } +.media { + margin: 10px; +} .media, .bd { @@ -10,8 +12,8 @@ .media .img { float: left; margin-right: 10px; + + img { display: block; } } -.media .img img { display: block } .media .imgEt { float: right; margin-left: 10px; } - diff --git a/app/assets/stylesheets/mentions.scss b/app/assets/stylesheets/mentions.scss index 6647170eeeeab35bbf126549b4ba526ca838e44c..71028e629c3b0352d3a0f9093eb8ad00d80fa561 100644 --- a/app/assets/stylesheets/mentions.scss +++ b/app/assets/stylesheets/mentions.scss @@ -20,6 +20,8 @@ box-sizing: border-box; } + .form-control[disabled] { background-color: transparent; } + .mentions-autocomplete-list { background: white; display: none; @@ -69,28 +71,21 @@ bottom: 0px; left: 0px; top: 0px; - padding: 4px 6px; + padding: $padding-base-vertical $padding-base-horizontal; } .mentions { color: white; - font-size: 14px; + font-size: $font-size-base; font-family: Arial, Helvetica, sans-serif; - line-height: normal; overflow: hidden; width: 100%; white-space: pre-wrap; word-wrap: break-word; - > div { - color: white; - white-space: pre-wrap; - width: 100%; - - strong { - background: #d8dfea; - font-weight: normal; - } + > strong { + background: $background-blue; + font-weight: normal; } } } diff --git a/app/assets/stylesheets/mobile/comments.scss b/app/assets/stylesheets/mobile/comments.scss new file mode 100644 index 0000000000000000000000000000000000000000..3b10f6bd3c3f73a3d1b7f715b372cd94ef2aa713 --- /dev/null +++ b/app/assets/stylesheets/mobile/comments.scss @@ -0,0 +1,106 @@ +.bottom-bar { + border-radius: 0 0 5px 5px; + z-index: 3; + display: block; + position: relative; + padding: 8px 10px 10px; + background: $background-grey; + margin-top: 10px; + border-top: 1px solid $border-grey; + min-height: 22px; + overflow: hidden; + + > a, + .show-comments, + .show-comments > [class^="entypo"] { + @include transition(color); + color: $text-grey; + font-weight: bold; + } + + .show-comments { + position: relative; + top: 3px; + + > [class^="entypo"] { margin-left: .5em; } + + &:hover, + &:active, + &:focus { + outline: none; + text-decoration: none; + } + + &.active:not(.bottom_collapse), + &.active:not(.bottom_collapse) > [class^="entypo"] { + color: $text; + } + } + + .post-stats { + top: -5px; + float: right; + position: relative; + display: flex; + margin-bottom: -15px; + + .count { + background-color: $background-grey; + text-align: center; + z-index: 2; + } + + .icon-count-group { + display: flex; + flex-flow: column; + justify-content: center; + margin: 0 7px; + } + + [class^="entypo"] { + color: $text-grey; + font-size: 24px; + height: 28px; + margin: 0; + width: 100%; + } + + [class^="entypo"]:hover, + [class^="entypo"]:active, + [class^="entypo"]:focus { + text-decoration: none; + } + + .entypo-reshare.active { color: $blue; } + + .entypo-heart.active { color: $red; } + } + + .post-action { + height: 28px; + + .disabled { color: $medium-gray; } + } + + .add-comment-switcher { padding-top: 10px; } + + &.inactive .post-stats .count, + &.inactive .comment-container { + display: none; + } +} + +.stream_element .comments { + margin: 0; + padding: 0; + width: 100%; + + .content { padding: 0; } + + .comment { + border-top: 1px solid $border-medium-grey; + padding: 10px 0 0; + + &:first-child { padding-top: 20px; } + } +} diff --git a/app/assets/stylesheets/mobile/conversations.scss b/app/assets/stylesheets/mobile/conversations.scss new file mode 100644 index 0000000000000000000000000000000000000000..ac6495f65fe97c5807d75c4dfd0bc4c246547bbf --- /dev/null +++ b/app/assets/stylesheets/mobile/conversations.scss @@ -0,0 +1,63 @@ +.conversations-title { + margin: 0 0 20px 0; + h3 { display: inline; } +} +.conversation { + .conversation-participants { + padding: 1rem 1.2rem; + + h3 { margin: 0; } + + .delete_conversation { + font-size: 2rem; + + [class^="entypo-"], [class*="entypo-"] { + color: $link-grey; + } + } + + .avatars { + margin: 0 -0.15rem; + .avatar { + margin: 0.15rem; + float: left; + + img { + height: 50px; + width: 50px; + border-radius: 5px; + } + } + } + } + + .stream .stream_element .timeago, + .conversation-participants .last-message-timeago { + display: block; + font-style: italic; + color: $text-grey; + } + + .stream .stream_element { + padding: 0.5rem; + + .ltr { + padding-left: 0px; + } + } +} + +.conversations { + img.avatar { + margin: 10px; + float: left; + } + .no-messages { + text-align: center; + margin-top: 40px; + } +} + +.subject { padding: 0 10px; } + +.message-count, .unread-message-count { margin: 10px 2px; } diff --git a/app/assets/stylesheets/mobile/header.scss b/app/assets/stylesheets/mobile/header.scss index 3c887aa8d7b60d2200c7c1d721f3c61c0b45c920..cc07ce80870fddd16cafb9567f545bbcbb9fb128 100644 --- a/app/assets/stylesheets/mobile/header.scss +++ b/app/assets/stylesheets/mobile/header.scss @@ -1,56 +1,96 @@ /* This file contains the CSS code corresponding to the header and the drawer (including the menu) of the mobile version */ -header { - position: fixed; - height: 45px; - top: 0px; - z-index: 10; - background: image-url('header-bg-long.jpg') rgb(40,35,35); - box-shadow: 0 1px 2px #333; - border-bottom: 1px solid #222; -} +$drawer-width: 400px; +$drawer-width-offset: $drawer-width + 50px; +$mobile-navbar-height: 46px; -#main_nav { +#main-nav.navbar-fixed-top { width: 100%; + height: $mobile-navbar-height !important; + min-height: $mobile-navbar-height !important; + max-height: $mobile-navbar-height !important; + + .login { + color: $white; + font-weight: bold; + padding: 13px; + } - #header_title { - display: inline-block; - width: 30px; - height: 30px; - padding: 7px; + .navbar { + margin: 0; + padding: 0; + border: none; + min-height: $mobile-navbar-height; } - #nav_badges { + .navbar-right { float: right; - margin: 7px 0px; - display: inline-block; + } - .badge { - display: inline; - margin: 0px 4px; - padding: 10px 6px; - font-weight: bold; - font-size: smaller; + .navbar-nav { + margin-bottom: 0; + margin-top: 0; + li { float: left; } + } + + #header-title { + padding: 7px 15px; + margin: 0 0 0 -15px; + height: $mobile-navbar-height; + } + + #nav-badges { + float: right; + margin: 0 -15px; + display: inline-flex; + + li > a, li > button { background-color: transparent; - img { - height: 30px; - width: 30px; + &.badge-link { + font-size: 26px; + padding: 14px 6px; + text-align: center; + width: $mobile-navbar-height; + height: $mobile-navbar-height; + + [class^="entypo-"], [class^="diaspora-custom-"] { + color: $white; + width: 100%; + padding: 0; + margin: 0; + + &.entypo-bell, &.diaspora-custom-compose { + text-align: center; + font-size: 22px; + + &:before { + position: relative; + top: -2px; + } + } + } } } - .badge_count { - border-radius: 2px; + .navbar-toggle { + display: block; + margin: 6px 15px; + } + + .badge { z-index: 3; + top: 6px; + right: 6px; + padding: 2px 6px; position: absolute; - top: 3px; - padding: 1px 3px; background-color: $red; - margin-left: -8px; } - - #conversation_icon { - height: 18px; + } + #header-title{ + img { + height: 30px; + width: 30px; } } } @@ -59,38 +99,34 @@ header { position: fixed; top: 0; bottom: 0; - width: 100%; + width: $drawer-width; + @media (max-width: $drawer-width-offset) { + width: 80%; + } left: 100%; background-color: #444; - box-shadow: -2px 0px 2px 1px #333; + box-shadow: none; header { - position: static; - left: 100%; - right: -80%; - - #global_search { - position: relative; + width: 100%; + position: absolute; + height: $mobile-navbar-height; + background-color: $navbar-inverse-bg; + border-bottom: solid $navbar-inverse-border 1px; + #global-search { form { - position: absolute; - left: 5px; - right: 22%; + padding: 0 15px; + width: 100%; input { - box-shadow: 0 1px 1px #444; - border-radius: 15px; - width: 100%; margin-top: 7px; - background-color: #444; - border: 1px solid #222; + background-color: $navbar-inverse-bg; font-size: 13px; - padding: 4px; color: black; &.active { - background-color: $highlight-white; - background-color: rgba(160,160,160,0.6); + background-color: $white; } &:focus { @@ -106,26 +142,25 @@ header { nav { position: absolute; - top: 45px; - bottom: 0px; + top: $mobile-navbar-height; + bottom: 0; overflow: auto; width: 100%; li { - font-size: 25px; + font-size: 1.8rem; line-height: 25px; - font-weight: bold; color: $light-grey; - border-bottom: solid rgb(53, 53, 53) 2px; + border-bottom: solid $navbar-inverse-border 1px; } li:hover { background-color: $link-grey; } - .no_border { - padding: 0px; - border-bottom: 0px; + .no-border { + padding: 0; + border-bottom: 0; &:hover { background-color: transparent; @@ -158,11 +193,27 @@ header { ul { list-style: none; - margin: 0px; + margin: 0; + padding: 0; } } +#main-nav, #drawer { + transition: all 0.25s ease; + z-index: 10; +} + /* This class is added when the user open the drawer */ -#app.draw > * { - transform: translateX(-80%); +#app.draw { + #main-nav, #drawer { + transform: translateX(-$drawer-width); + } + @media (max-width: $drawer-width-offset) { + #main-nav { + transform: translateX(-80%); + } + #drawer { + transform: translateX(-100%); + } + } } diff --git a/app/assets/stylesheets/mobile/mobile.scss b/app/assets/stylesheets/mobile/mobile.scss index 107dab2769b36f71835aca600856925e5702fc38..87e496e04603a3895e1a1a93b326a308a2a23674 100644 --- a/app/assets/stylesheets/mobile/mobile.scss +++ b/app/assets/stylesheets/mobile/mobile.scss @@ -1,12 +1,22 @@ -@import "bootstrap"; -@import "bootstrap-responsive"; -@import "colors"; +@import 'color-variables'; +@import "bootstrap-complete"; @import "_mixins"; @import "vendor/autoSuggest"; +@import 'animations'; @import "_flash_messages"; +@import 'entypo'; +@import 'icons'; +@import 'spinner'; -@import "header"; +@import "mobile/header"; @import "mobile/tags"; +@import "mobile/conversations"; +@import "mobile/settings"; +@import "mobile/stream_element"; +@import "mobile/comments"; +@import 'mobile/openid_connect_error_page'; + +@import 'typography'; a { color: #2489ce; @@ -19,53 +29,42 @@ code { } body { - background: { - image: image-url("mobile/hatched-light.jpg"); - position: fixed; - /* scale background image down for iOS retina display */ - size: 200px; - } - padding: 0px; + background-color: $main-background; + padding: 0; } -h3 { - margin-top: 0px; +textarea { + resize: vertical; } -.clear { - clear: both; -} +h3 { margin-top: 0; } +.clear { clear: both; } +#main { padding: 56px 10px 0 10px; } -#app > * { - transition: all 0.25s ease; -} +textarea { resize: vertical; } -#main { - padding: 55px 10px 0px 10px; +.avatar { + border-radius: 4px; } -.message { - padding-left: 2px; -} +.badge-important { background-color: $red; } .stream_element, .comments { overflow: auto; position: relative; text-align: left; - padding: 10px 0; min-height: 34px; + padding: 10px 0 0 0; + list-style: none; * { max-width: 100%; } .avatar { - border-radius: 4px; - float: left; - height: 35px; - width: 35px; - margin: { - right: 10px; }; } + margin-top: 0; + max-width: 35px; + } .from { a { @@ -82,59 +81,39 @@ h3 { } } - > .content, - .reshare > .content { - padding: 5px; - } - .info { - margin: { - top: 0; }; } - .photo_attachments { - margin: { - top: 6px; }; } - .timeago { - font: { - weight: normal; }; } - padding: 0 !important; + > .content, .reshare > .content { padding: 6px; } + .info{ margin-top: 0; } + .photo_attachments{ margin-top: 6px; } + .timeago{ font-weight: normal; } } + .shield{ padding: 10px; font-size: larger; - } +} -.shield_wrapper{ +.nsfw-shield{ height: 100%; width: 100%; background-color: LightGrey; - position: absolute; - border-radius: 5px; + border-radius: 0; z-index: 2; } -.new_comment { - padding: 10px; -} - -.stream_element .comments { +.ajax-loader { + border-top: 1px solid $border-medium-grey; + margin-top: 10px; + padding-top: 10px; + text-align: center; width: 100%; - padding: 0; - margin: 0; - top: 3px; - .content { - padding: 0; - } +} - .comment { - padding: { - top: 10px; - bottom: 5px; - } - } +.stream_element:not(.shield-active) .shield{ + display: none; } -.comment { - border: { - top: 1px solid #ccc; }; +.stream_element.shield-active .nsfw-hidden{ + display: none; } .login_error, @@ -148,17 +127,32 @@ h3 { text-shadow: 1px 1px 20px rgb(126, 240, 77); } #login_form { - padding: 0; - /* ensure url bar is banished from view on iOS */ margin-bottom: 40px !important; .login-container { padding: 10px; label, legend { text-transform: uppercase; } + .form-control { margin-bottom: 20px; } + .form-group { margin: 10px 0; } + } +} + +footer { + margin-bottom: 20px; + text-align: center; + + ul { + padding-left: 0; + + li { + list-style: none; + margin-bottom: 5px; + } } } +.settings_container, .stream_element, #login_form { border-radius: 5px; @@ -168,16 +162,39 @@ h3 { margin-bottom: 10px; border: 1px solid #bbb; - border-top: 1px solid $border-grey; - border-bottom: 1px solid #aaa; + border-bottom-color: #aaa; } -.stream_element div.img img.avatar { - margin: 10px; -} +.stream_element { + padding: 0px; -.stream_element .bd { - padding-top: 10px; + div.img img.avatar { + margin: 10px; + } + + .bd { + padding-top: 10px; + } + + .media { + padding: 0; + } + + .photo_attachments { + border-radius: 3px 3px 0 0; + + border: { + bottom: 1px solid #ccc; + } + + img.big-stream-photo { + border-radius: 3px 3px 0 0; + width: 100%; + } + a { + padding: 0; } + margin-top: 0; + } } .photo_attachments { @@ -202,18 +219,23 @@ h3 { .more-link, .no-more-posts { display: block; text-align: center; - padding: 0 10px; - margin: 0 10px; + padding: 0; + margin: 20px 0; border-radius: 5px; + border: 1px solid $text-grey; - background: { - color: rgba(220,220,220,0.8); - } + background: { color: rgba(220,220,220,0.8); } h1, h2 { color: $text-grey; padding: 20px; text-shadow: 0 2px 0 #fff; + margin: 0; + } + + &:hover, &:active{ + text-decoration: none; + border: 1px solid $text-dark-grey; } } .no-more-posts { @@ -256,7 +278,7 @@ h3 { font-size: larger; text-align: center; - img { + img:not(.avatar) { max-width: 100%; } @@ -279,42 +301,38 @@ h3 { } &.photos { - border-bottom: 0px !important; + border-bottom: 0 !important; } } #photo_controls { - margin-bottom: 5px; -} - -.arrow { - color: white !important; - font-size: 26pt; - text: { - shadow: 0 1px 2px #333; - decoration: none; }; - padding: 0; - position: fixed; - bottom: 10%; - z-index: 1; - height: 50px; - width: 50px; -} - -#left.arrow { - left: 5%; + .arrow { + font-size: 10em; + text-decoration: none; + text-shadow: 0 0 3px $white; + position: fixed; + bottom: -0.2em; + z-index: 1; + &.left { + left: -0.2em; + } + &.right { + right: -0.2em; + text-align: right; + } + .entypo-chevron-left, .entypo-chevron-right { margin-right: 0; } + } } -#right.arrow{ - right: 5%; +.header-full-width { + background-color: #fff; + border-bottom: 1px solid #aaa; + margin: -10px; // Counter the #main padding + margin-bottom: 10px; + padding-top: 5px; } #author_info { - margin: -10px; - margin-bottom: 10px; - padding-top: 5px; - background-color: #fff; - border-bottom: 1px solid #aaa; word-wrap: break-word; img { @@ -344,7 +362,7 @@ h3 { } } - .bottom_bar { + .bottom-bar { position: static; } } @@ -358,109 +376,6 @@ h3 { float: right; } -.bottom_bar { - border-radius: 0 0 5px 5px; - z-index: 3; - display: block; - position: relative; - padding: 10px; - padding-top: 8px; - background: $background-grey; - - margin: { - top: 10px; }; - - border: { - top: 1px solid $border-grey; - }; - - min-height: 22px; - - > a, - .show_comments { - @include transition(color); - color: $text-grey; - font-weight: bold; - } - - .show_comments { - position: relative; - top: 3px; - color: #ccc; - } - - a.show_comments { - color: $text-grey; - - &.active:not(.bottom_collapse) { - color: #444; - padding: { - right: 14px; - } - background: { - image: image-url("mobile/arrow_down_small.png"); - position: center right; - repeat: no-repeat; - } - } - } - - .show_comments.bottom_collapse { - position: absolute; - right: 10px; - top: 14px; - padding: 5px 10px; - } - - #bottom_bar_tabs { - display: table; - width: 100%; - text: { - align: center; - } - border: { - bottom: 1px solid #ccc; - } - font: { - size: 28px; - } - color: #ccc; - - .tab { - display: table-cell; - position:relative; - top: -5px; - - border: { - right: 1px solid #ccc; - } - - &:last-child { - border: none; - } - } - } -} - -.floater { - float: right; } - -.stream_element .photo_attachments { - border-radius: 3px 3px 0 0; - - border: { - bottom: 1px solid #ccc; - } - - img.big-stream-photo { - border-radius: 3px 3px 0 0; - width: 100%; - } - a { - padding: 0; } - margin-top: 0; -} - .photo_area { border-radius: 3px; text-align: center; } @@ -470,54 +385,31 @@ h3 { background: { size: 20px; repeat: no-repeat; - position: center; }; - - height: 13px; + position: center; + }; + height: 20px; width: 20px; - padding: 5px; + padding: 0; + margin-left: 15px; - margin: { - left: 5px; }; + &:last-child{ + margin-right: 5px; + } &.loading { background-image: image-url("mobile-spinner.gif"); } } -.reshare_action { - background-image: image-url("mobile/reshare_mobile.png"); - &.active { - background-image: image-url("mobile/reshare_mobile_active.png"); - } -} - -.like_action { - background-image: image-url("mobile/heart_mobile_grey.png"); - &.active { - background-image: image-url("mobile/heart_mobile_red.png"); - } -} - -.comment_action.image_link { - background-image: image-url("mobile/pencil_mobile_grey_active.png"); - &.inactive { - background-image: image-url("mobile/pencil_mobile_grey.png"); - } -} - #new_status_message { - margin: 0px; - - fieldset { - padding: 10px; + margin: 0; - .service_icon { - cursor: pointer; + .service_icon { + cursor: pointer; - &.dim { - opacity: 0.6; - } + &.dim { + opacity: .6; } } @@ -526,14 +418,8 @@ h3 { } textarea { - border-radius: 0; - box-shadow: 0 2px 3px #999; - border: none; - border-bottom: 1px solid $border-dark-grey; - width: 96%; - padding: 2%; - margin: 0px; - font-size: 14px; + min-width: 100%; + max-width: 100%; } } @@ -542,34 +428,12 @@ select { padding: 7px; } -.new_comment { - padding: 10px 0; - padding-top: 20px; -} - .comment.add_comment_bottom_link_container { position: relative; text-align: center; padding: 25px !important; } -.post_stats { - position: absolute; - right: 8px; - top: 31px; - z-index: 2; - - span { - color: $text-dark-grey; - font-weight: bold; - padding: 2px 7px; - margin: 5px 6px; - background: { - color: $background-grey; - } - } -} - .additional_photo_count { opacity: 0.5; @@ -594,10 +458,10 @@ select { .reshare_via { width: 100%; position: absolute; - bottom: -7px; + bottom: -10px; text-align: center; span { - padding: 2px 10px; + padding: 0 10px; font-weight: bold; color: $text-grey; background: { @@ -623,10 +487,13 @@ select { overflow: hidden; } + .notifications { list-style: none; - margin: 0px; + margin: 0; clear: right; + + &, & ul { padding: 0; } } .notifications_for_day { @@ -637,42 +504,6 @@ select { margin-bottom: 5px; } -.message_count { - border-radius: 2px 2px 2px 2px; - float: right; - margin: 10px 10px 1px 5px; - padding: 0 2px 1px; - position: relative; - background-color: #999; - color: #eee; - font-size: 10px; - line-height: 12px; - -} - -.conversation_participants img.avatar{ - height:35px; - width:35px; - margin: 5px 0 5px 2px; -} - -.conversations img.avatar{ - margin: 10px; - float: left; -} - -.unread_message_count { - border-radius: 2px 2px 2px 2px; - float: right; - margin: 10px 2px 1px 5px; - padding: 0 2px 1px; - position: relative; - background-color: #B11; - color: #EEE; - font-size: 10px; - line-height: 12px; -} - .last_author { position: relative; margin: 10px 10px 2px; @@ -689,11 +520,6 @@ select { color: #3F8FBA; } -form#new_conversation.new_message input.button.creation{ - float: right; - margin: 0 5px 5px; -} - h3.ltr { font-size: 18px; line-height: 27px; @@ -712,10 +538,6 @@ h3.ltr { word-wrap: break-word; } -textarea#message_text { - margin: 10px 0 10px; -} - form#new_conversation.new_conversation { background-color: #FFFFFF; border-bottom: 1px solid $border-dark-grey; @@ -727,89 +549,13 @@ form#new_conversation.new_conversation { font-weight: normal; line-height: 20px; } - .span-10 { - margin: 5px; - } -} - -.span-2 { - margin: 5px 5px; - text-transform: uppercase; -} - -.span-10 { - width: 100%; } textarea#conversation_text { - border: 0.2s; - border-radius: 0 0 0 0; font-size: larger; - left: 0; - margin: 10px 0; - width: 218px; - padding: 0; -} - -.bottom_submit_section { - display: block; - position: relative; - text-align: right; - padding-bottom: 5px; -} - -.button.creation { - display: inline-block; - padding: 4px 12px; - margin-bottom: 0; - font-size: 14px; - line-height: 20px; - color: #333333; - text-align: center; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - vertical-align: middle; - cursor: pointer; - background-color: #f5f5f5; - background-image: gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); - background-repeat: repeat-x; - border: 1px solid #cccccc; - border-color: #e6e6e6 #e6e6e6 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-bottom-color: #b3b3b3; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.button.creation:hover, -.button.creation:focus, -.button.creation:active { - color: #333333; - background-color: #e6e6e6; -} - -.button.creation:active { - background-color: #cccccc \9; -} - -.button.creation:first-child { - margin-left: 0; -} - -.button.creation:hover, -.button.creation:focus { - color: #333333; - text-decoration: none; - background-position: 0 -15px; - transition: background-position 0.1s linear; -} - -.button.creation:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; + width: 100%; + min-width: 100%; + max-width: 100%; } .registrations_error, @@ -839,6 +585,8 @@ form#new_user.new_user input.btn { } } +.media { padding: 12px 0 } + .conversation_error { color: #DF0101; text-shadow: 1px 1px 5px #666; @@ -850,7 +598,8 @@ form#new_user.new_user input.btn { } #conversation_inbox, .notifications { - .pagination { + div.pagination { + width: 100%; margin-left: auto; margin-right: auto; text-align: center; @@ -865,10 +614,6 @@ form#new_user.new_user input.btn { } } -input#user_password, #user_username, #user_password_confirmation, #user_email { - height: 30px; -} - #flash_notice, #flash_alert, #flash_error { @@ -886,25 +631,11 @@ input#user_password, #user_username, #user_password_confirmation, #user_email { padding: 1px } -.session_mobile { - margin-top: -55px; -} - h1.session { font-size: 40px; font-weight: 200; } -.landing { - padding: 20px; - margin: -10px -20px 10px -20px; - background-color:#4b4b4b; - box-shadow: 0 3px 40px rgba(0,0,0,0.8); - z-index: 10; - position: relative; - text-align: center; -} - form p.checkbox_select { position: relative; label { @@ -923,16 +654,14 @@ form p.checkbox_select { margin-top: 5px; min-height: 100px; position: relative; + margin-bottom: 15px; + text-align: center; + padding: 0; img { border-radius: 5px; box-shadow: 0 1px 2px #666; - position: absolute; - left: 0; - height: 100px; - width: 100px; - &.avatar { @include transition(opacity, 0.5s); &.loading { @@ -940,18 +669,15 @@ form p.checkbox_select { } } } - padding-left: 120px; } -#settings_nav { - font-size: 1em; - - ul { - margin: 0 0 0 15px; - } - - li { +#birth-date { + text-align: center; + select{ + width: 32%; display: inline; + &:first-of-type{ float: left; } + &:last-of-type{ float: right; } } } @@ -959,9 +685,11 @@ form#update_profile_form { select { padding: 3px; } + + .submit_block { margin-bottom: 20px; } } -select#user_language, #user_auto_follow_back_aspect_id, #aspect_ids_ { +select#user_language, select#user_color_theme, #user_auto_follow_back_aspect_id, #aspect_ids_ { padding: 3px; } @@ -972,10 +700,6 @@ select#user_language, #user_auto_follow_back_aspect_id, #aspect_ids_ { color: inherit; background-color: $background-grey; border-radius: 10px; - .img .avatar { - width: 50px; - height: 50px; - } } .search-mobile { @@ -1005,10 +729,7 @@ select#aspect_ids_ { float: left; padding: 3px 12px; cursor: pointer; - - &:hover img { - opacity: 0.4; - } + .entypo-camera { margin-right: 0; } } #publisher_textarea_wrapper { @@ -1137,16 +858,8 @@ select#aspect_ids_ { } } -.remove_post { - position: absolute; - top: 2px; - right: 5px; - opacity: 0.5; -} - -.remove_comment { - opacity: 0.5; -} +.remove_post { opacity: 0.5; } +.remove_comment { opacity: 0.5; } .center { text-align: center; @@ -1171,6 +884,11 @@ select#aspect_ids_ { margin: 0 10px 0 0; padding: 3px; + &, &:focus, &:active{ + box-shadow: none; + border-color: #CCCCCC; + } + &.has_connection { background-color: $light-green; } @@ -1181,4 +899,14 @@ select#aspect_ids_ { word-wrap: break-word; } +#email_prefs { + .checkbox{ + margin: 15px 0; + } +} +.small-horizontal-spacer { margin: 15px 0; } + +.form-control, .form-control:active, .form-control:focus { box-shadow: none; } +.form-control:active, .form-control:focus { border-color: #999999; } + .tag_following_action { margin: 5px 0 10px 0; } diff --git a/app/assets/stylesheets/mobile/openid_connect_error_page.scss b/app/assets/stylesheets/mobile/openid_connect_error_page.scss new file mode 100644 index 0000000000000000000000000000000000000000..c87efeb4e58d05d6f58642ac942e0984bfb54f31 --- /dev/null +++ b/app/assets/stylesheets/mobile/openid_connect_error_page.scss @@ -0,0 +1,9 @@ +.landing { margin: -56px -20px 10px; } + +.api-error { + background-color: $light-grey; + box-shadow: $card-shadow; + margin-top: 20px; + + h4 { text-align: center; } +} diff --git a/app/assets/stylesheets/mobile/settings.scss b/app/assets/stylesheets/mobile/settings.scss new file mode 100644 index 0000000000000000000000000000000000000000..76bbbffb2a8e3d47cb054937462e52aa47da8072 --- /dev/null +++ b/app/assets/stylesheets/mobile/settings.scss @@ -0,0 +1,47 @@ +#settings_nav { + border-bottom: 1px solid $border-grey; + margin-bottom: 1rem; + padding-bottom: 1rem; + + ul { + padding: 0px; + margin: 0px; + } + + li { + display: inline; + font-size: 1.7rem; + padding: 0px 0.3rem; + + &:first-child { padding-left: 0px; } + &:last-child { padding-right: 0px; } + } +} + +.services_page { + h3 { + margin: 1rem 0px; + } + + .services_explanation { + border-top: 1px solid $border-grey; + margin-top: 1rem; + padding: 1rem 0; + } +} + +.applications-page .applications-explanation { + margin-bottom: 15px; +} + +.application-img { + margin: auto; + max-width: 150px; + text-align: center; + + .entypo-browser { + font-size: 137px; + height: 160px; + margin-top: -45px; + } +} diff --git a/app/assets/stylesheets/mobile/stream_element.scss b/app/assets/stylesheets/mobile/stream_element.scss new file mode 100644 index 0000000000000000000000000000000000000000..13734c6a9e7447e91f263e9f72447fa7581abab7 --- /dev/null +++ b/app/assets/stylesheets/mobile/stream_element.scss @@ -0,0 +1,16 @@ +.stream_element { + .location { + color: $text-grey; + font-size: $font-size-small; + white-space: normal; + } + + .poll { + border-top: 1px solid $border-grey; + margin-top: 20px; + padding-top: 10px; + .poll-head .question { + font-weight: bold; + } + } +} diff --git a/app/assets/stylesheets/navbar_left.scss b/app/assets/stylesheets/navbar_left.scss new file mode 100644 index 0000000000000000000000000000000000000000..5a7a585bfb0193fc1a06826f8ab58e406ff3d18b --- /dev/null +++ b/app/assets/stylesheets/navbar_left.scss @@ -0,0 +1,200 @@ +.left-navbar { + padding: 0; + padding-bottom: 10px; + + a { + text-decoration: none; + outline: 0; + } + + ul { + margin: 0; + padding: 0; + list-style: none; + } + + .hoverable { + color: $link-grey; + display: block; + padding: 10px 20px; + font-weight: bold; + + a { + color: $link-grey; + } + + &:hover, &:hover a, &:hover [class^="entypo"] { + background-color: $blue; + border-color: $blue; + color: $white; + } + } + + .all-aspects .hoverable.selected, + .followed-tags-sidebar .hoverable.selected, + .selected > .hoverable { + color: $white; + background: $gray; + border-color: $gray; + } + + .all-aspects ul, + .followed-tags-sidebar ul { + background: $left-navbar-drawer-background; + li { padding: 0; } + .entypo-check { visibility: hidden; } + .entypo-check.selected { visibility: visible; } + .selectable { + display: block; + overflow: hidden; + text-overflow: ellipsis; + padding: 10px 20px 10px 40px; + } + .hoverable > .action { + position: relative; + bottom: 30px; + right: 20px; + visibility: hidden; + } + .hoverable:hover > .action { visibility: visible; } + } + + #tags_list { + #new_tag_following { + padding: 10px 20px 10px 30px; + } + + /* ---- override app/stylesheets/vendor/autoSuggest.css ---- */ + .as-original{ width: 100%; } + .tag_input { + line-height: $font-size-base; + vertical-align: top; + width: 100%; + } + + .as-result { + margin-top: -1px; + margin-left: 1px; + } + + .as-list { + em { + background-color: #aabbcc; + color: black; + padding: 0px; + } + + color: black; + position: static; /* override absolute */ + margin: 0px; + border-radius: 0px 0px 3px 3px; + box-shadow: 0px 1px 1px #666; + } + + .as-result-item.active { + color: black; + text-shadow: none; + background-color: $background-blue; + border-color: $background-blue; + } + /* ---- end override app/stylesheets/vendor/autoSuggest.css ---- */ + } +} + +.info-bar { + margin-top: 20px; + padding: 10px 20px 0; + + .excellence-box, + .info-links { + border-top: 1px solid $border-grey; + padding: 5px; + } + + .excellence-box { + margin-top: 10px; + + .content { + font-size: $font-size-base; + } + } + + .section { + margin-top: 10px; + + &:last-child { + margin-bottom: 10px; + } + + &:not(.collapsed) .entypo-triangle-right, + &.collapsed .entypo-triangle-down, + &.collapsed .content { + display: none; + } + + &.collapsed .title h5 { + font-weight: normal; + } + } + + .title { + cursor: pointer; + padding-bottom: 5px; + + h5 { + color: $text-dark-grey; + font-size: $font-size-base; + font-weight: bold; + margin: 0; + } + } + + .content { + color: $text-grey; + font-size: $font-size-small; + line-height: 18px; + padding: 10px 0; + + p, + ul { + margin: 0; + } + + ul { + list-style: none; + margin-bottom: 5px; + padding-left: 0; + } + + .btn-link { + font-size: $font-size-small; + padding-left: 0; + } + + > [name="invite_code"] { + box-sizing: border-box; + font-size: $font-size-small; + height: 30px; + width: 100%; + } + } + + .right-service-icons { + padding: 10px { + bottom: 0; + } + text-align: center; + + .social-media-logos-facebook-24x24, + .social-media-logos-twitter-24x24, + .social-media-logos-tumblr-24x24, + .social-media-logos-wordpress-24x24 { + height: 24px; + width: 24px; + } + + a { + display: inline-block; + } + } +} diff --git a/app/assets/stylesheets/new_styles/_animations.scss b/app/assets/stylesheets/new_styles/_animations.scss deleted file mode 100644 index 93ca29ad3d1b845eaeab16ddcafc53f8ff9ca98e..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_animations.scss +++ /dev/null @@ -1,7 +0,0 @@ -/* flash message animations - header height is about 40px */ -@keyframes expose { - 0% { top : -100px; } - 15% { top : 34px; } - 85% { top : 34px; } - 100% { top : -100px; } -} diff --git a/app/assets/stylesheets/new_styles/_base.scss b/app/assets/stylesheets/new_styles/_base.scss deleted file mode 100644 index 318b99484460b7df4463fdc3c5b9f69067b9b4e6..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_base.scss +++ /dev/null @@ -1,102 +0,0 @@ -html, -body { - /* hack to ensure fixed elements at height: 100%; are in relation to the window */ - max-height : 100%; -} - -body { - margin-top: 40px; - padding : none; - font-size: $font-size-text; - - &.lock { - overflow: hidden; - } -} - -blockquote p { - font-size: $font-size-text; - line-height: $line-height; -} - -/* Overflow */ -h1, h2, h3, h4, h5, h6, -p, -blockquote, -code, -pre { word-wrap: break-word; } -a.tag { word-break: break-all; } - -/* new link color */ -a { color : $link-blue } - -.avatar { - border-radius: 4px; - - &.micro { - height: 20px; - width: 20px; - } - - &.small { - height: 35px; - width: 35px; - } - - &.medium { - height: auto; - width: auto; - max-width: 75px; - } -} - -.author-name { - color: inherit; -} - -/* bootstrap label fixes for Roboto */ -.label { - padding : 2px 5px; - padding-bottom : 3px; - - span { - display : inline-block; - position : relative; - top : 1px; - font-family : Roboto-Bold; - } -} - -#back-to-top { - display: block; - color: white; - position: fixed; - z-index: 49; - right: 20px; - bottom: 20px; - opacity: 0; - font-size: 2.9em; - padding: 0 12px 0 12px; - border-radius: 10px; - background-color: #aaa; - &:hover { opacity: 0.85 !important; } - &.visible { opacity: 0.5; } - line-height: 1.5; -} - -/* general purpose classes */ - -.small-horizontal-spacer { - min-height: 20px; -} - -.big-horizontal-spacer { - height: 50px; -} - -/* responsive */ -@media (max-width: 767px) { - body { - padding : 0; - } -} diff --git a/app/assets/stylesheets/new_styles/_buttons.scss b/app/assets/stylesheets/new_styles/_buttons.scss deleted file mode 100644 index 732f98af36806ad219ba9cc47b1d679edcac1f49..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_buttons.scss +++ /dev/null @@ -1,31 +0,0 @@ -.btn.creation { - $button-border-color: #aaa; - @include button-gradient($creation-blue); - color: #fff; - border: 1px solid darken($button-border-color,20%); - text-shadow: none; - &:hover { - background: $creation-blue; - border: 1px solid darken($button-border-color,35%); - } -} -.btn-group.open > .btn.creation { - background: $creation-blue; -} - -.btn.green { - $button-border-color: #aaa; - @include button-gradient($green); - color: $grey; - border: 1px solid darken($button-border-color,20%); - - &:hover { - background: $green; - border: 1px solid darken($button-border-color,35%); - } -} -.btn-group.open > .btn.green { - background: $green; -} - -.btn.delete { color: desaturate($red,10%); } diff --git a/app/assets/stylesheets/new_styles/_forms.scss b/app/assets/stylesheets/new_styles/_forms.scss deleted file mode 100644 index 7e4203b84d56c441468de5f045d6949efa5fe360..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_forms.scss +++ /dev/null @@ -1,105 +0,0 @@ -input, -input[type=email], -input[type=text], -input[type=password], -textarea { /* Bootstrap reset */ - &, - &:active, - &:invalid, - &:invalid:required, - &:focus, - &:active:focus, - &:invalid:focus, - &:invalid:required:focus { - border-color: $border-grey; - box-shadow: none; - color : $text-dark-grey; - } -} - -/* autocomplete colors */ -input:-webkit-autofill{ - background-color: #fff !important; - background-image: none !important; -} - -/* Forms described here are only used on the public pages at the moment */ -form.block-form { - margin: 20px auto; - - label { - color : $text-dark-grey; - position: absolute; - top: -9999px; - left: -9999px; - } - - fieldset { - margin-bottom: 1em; - background-color: #fff; - position: relative; /* To correctly place the entypo icon */ - - input { - color : $text-dark-grey; - margin: 0px; - border-bottom-width: 0px; - border-radius: 0px; - } - - .form-control { - font-size: 16px; - height: 40px; - padding: 10px; - padding-left: 40px; - } - - .form-control:first-of-type { - &, - &:focus, - &:invalid, - &:invalid:focus, - &:invalid:required, - &:invalid:required:focus { - border-top-left-radius: 5px; - border-top-right-radius: 5px; - } - } - - .form-control:last-of-type { - &, - &:focus, - &:invalid, - &:invalid:focus, - &:invalid:required, - &:invalid:required:focus { - border-bottom-left-radius: 5px; - border-bottom-right-radius: 5px; - border-bottom-width: 1px; - } - } - - .entypo { - position: absolute; - top: 10px; - left: 10px; - width: 20px; - text-align: center; - color: $text-grey; - font-size: 20px; - } - - .entypo:nth-of-type(2) { - top: 50px; - } - - .entypo:nth-of-type(3) { - top: 90px; - } - - .entypo:nth-of-type(4) { - top: 130px; - } - - ::placeholder { text-transform: uppercase; } - } -} diff --git a/app/assets/stylesheets/new_styles/_interactions.scss b/app/assets/stylesheets/new_styles/_interactions.scss deleted file mode 100644 index 96c147eaf9ede6f069da27f19efe3bdbf8859f8f..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_interactions.scss +++ /dev/null @@ -1,60 +0,0 @@ -.control-icons { - a { - margin-right: 5px; - &:hover { text-decoration: none; } - - i.entypo { - color: $text-grey; - font-size: $font-size-text; - line-height: $line-height; - vertical-align: middle; - &:hover { color: $text; } - &.cross { font-size: $line-height; } - } - - &.hide_conversation i { - font-size: $line-height*1.5; - } - - &.delete_conversation i { - font-size: $font-size-text*1.5; - } - - &.destroy_participation i { - color: $black; - &:hover { color: $text-dark-grey; } - } - } -} - -.stream_container, #single-post-interactions { - .control-icons { - z-index: 6; - float: right; - - .block_user, - .comment_report, - .create_participation, - .delete, - .destroy_participation, - .post_report { - display: inline-block; - } - - & > a:hover { - text-decoration: none; - } - } - - .stream_element, .comment, .photo, .stream_element:hover .comment { - .control-icons > a { - @include transition(opacity); - opacity: 0; - } - - &:hover .control-icons { - & > a { opacity: 0.8; } - & > a:hover { opacity: 1; } - } - } -} diff --git a/app/assets/stylesheets/new_styles/_navs.scss b/app/assets/stylesheets/new_styles/_navs.scss deleted file mode 100644 index d93871c929c3c41e8a826fb3281e2a77e2be59da..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_navs.scss +++ /dev/null @@ -1,15 +0,0 @@ -.nav.nav-tabs{ - li > a { - color: $text-dark-grey; - .entypo, .mentionIcon { - color: $text-dark-grey; - margin-right: 5px; - } - .mentionIcon { font-weight: 700; } - } - li.active > a { - background-color: $background-grey; - color: $black; - .entypo, .mentionIcon { color: $black; } - } -} diff --git a/app/assets/stylesheets/new_styles/_poll.scss b/app/assets/stylesheets/new_styles/_poll.scss deleted file mode 100644 index c7eba90cef0c2553150a781ee272ac30539ce6c0..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_poll.scss +++ /dev/null @@ -1,39 +0,0 @@ -.poll_form { - border-top: 1px solid $border-grey; - border-bottom: 1px solid $border-grey; - margin: 10px 0px 10px 0px; - padding: 10px 0px 5px 0px; - - .poll_content { - margin-top: 5px; - } - .toggle_result_wrapper { - display: inline-block; - margin-top: 10px; - } - form { - margin-bottom: 0px; - } - - .progress { - background-image: none; - box-shadow: 0 0 0; - margin-bottom: 5px; - height: 10px !important; - - .bar { - background-image: none; - background-color: $border-dark-grey; - color: $text-dark-grey; - text-align: left; - } - } - .submit[disabled] { - cursor: default; - color: $text-grey; - - &:hover, &:active { - background-image: none; - } - } -} diff --git a/app/assets/stylesheets/new_styles/_registration.scss b/app/assets/stylesheets/new_styles/_registration.scss deleted file mode 100644 index 7d006d1871ff0738173e79b1934a4f4c41f21401..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_registration.scss +++ /dev/null @@ -1,52 +0,0 @@ -#registration { - .ball { - height: 633px; - max-width: 100%; - background: image-url("branding/ball.png") no-repeat; - background-size: contain; - } - - .v-center { - display: table; - height: 633px; - - .content { - display: table-cell; - vertical-align: middle; - - #pod-name { - text-align: center; - margin: 12px; - font-size : 35px; - } - } - } - - form { - max-width: 400px; - - .captcha_img { - position: absolute; - left: 10px; - width: 120px; - top: 169px; - } - - #user_captcha { - font-size: 16px; - height: 40px; - padding: 10px 10px 10px 130px; - line-height: $line-height; - box-sizing: border-box; - width: 100%; - border-bottom: 1px solid $border-grey; - border-bottom-left-radius: 5px; - border-bottom-right-radius: 5px; - } - - #terms > a { - color: inherit; - text-decoration: underline; - } - } -} diff --git a/app/assets/stylesheets/new_styles/_settings.scss b/app/assets/stylesheets/new_styles/_settings.scss deleted file mode 100644 index 88e181e88b9e4ce150fe2138defbddab75dfe3b2..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_settings.scss +++ /dev/null @@ -1,22 +0,0 @@ -/* Specific styles for the settings pages (profile, user account, privacy, services) */ -#inner_account_delete { - width: 700px; -} - -.as-selections #tags { - border: none; - box-shadow: none; -} - -.enclosed-checkbox label { - margin-bottom: 0; -} - -#profile_photo_upload .avatar { - height: auto; - width: auto; - max-width: 200px; - margin-bottom: 10px; -} - -.settings_visibilty { margin-left: 10px; } diff --git a/app/assets/stylesheets/new_styles/_spinner.scss b/app/assets/stylesheets/new_styles/_spinner.scss deleted file mode 100644 index 49086f97ecdb016ade8707b79c7ee5d9d61b827e..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_spinner.scss +++ /dev/null @@ -1,38 +0,0 @@ -@keyframes fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - -@keyframes spin { - 0% { -webkit-transform: rotate(0deg); } - 100% { -webkit-transform: rotate(360deg); } -} - -#paginate, #infscr-loading { - margin-top: 10px; - padding: 8px 0; - text-align: center; - width: 100%; - display: block; - clear: both; -} - -.loaded { - animation: fade-in 0.16s linear; -} - -.loader { - mask-image: image-url('static-loader.png'); - animation: spin 1s infinite ease-in-out, fade-in 0.2s ease-in; - - background-image : image-url("static-loader.png"); - - display: inline-block; - width : 14px; - height: 14px; - - &.hidden{ - display : none; - } -} - diff --git a/app/assets/stylesheets/new_styles/_typography.scss b/app/assets/stylesheets/new_styles/_typography.scss deleted file mode 100644 index d56f074f04d424f8e39c6bbd45c9e658a2d9c6d3..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/new_styles/_typography.scss +++ /dev/null @@ -1,23 +0,0 @@ -/* Roboto */ -@font-face { - font-family : Roboto; - src : image-url('fonts/Roboto-Regular.ttf'); - weight : normal; -} - -@font-face { - font-family : Roboto-Bold; - src : image-url('fonts/Roboto-Bold.ttf'); - weight : normal; -} - -@font-face { - font-family : Roboto-Light; - src : image-url('fonts/Roboto-Light.ttf'); - weight : normal; -} - -body, p, h1, h2, h3, h4, h5, h6, textarea, input { - font-family : "Helvetica Neue", Helvetica, sans-serif; - font-weight : normal; -} diff --git a/app/assets/stylesheets/notifications.scss b/app/assets/stylesheets/notifications.scss index d784105c79ff621a57a12bb7e95bc46f544bde74..f4349d1e124a2bc76a557b36cbdaec6a9f3daaa2 100644 --- a/app/assets/stylesheets/notifications.scss +++ b/app/assets/stylesheets/notifications.scss @@ -1,37 +1,25 @@ #notifications_container { - .nav.nav-tabs{ - li > a { - .badge.badge-default { display: none; } - } - } - .stream { .header { border-bottom: 1px solid $border-grey; - .btn-toolbar, h4 { - margin-bottom: 10px; - line-height: 40px; - } margin-bottom: 10px; } - .year_container { margin-top: 40px; } + .btn-toolbar { margin: 11px 0; } + + .framed-content { padding-bottom: 10px; } + .year { background-color: $white; color: $text-grey; font-size: 40px; line-height: 40px; - margin-bottom: -20px; + margin-bottom: 20px; + margin-top: 40px; text-align: center; } - .year_container + .day_group { - border-top: 1px solid $border-grey; - padding-top: 60px; - } - .day_group + .day_group { - border-top: 1px dashed $border-grey; margin-top: 10px; padding-top: 10px; } @@ -55,47 +43,60 @@ overflow: visible; } - .stream_element.media { - padding: 10px; - margin: 0px; - font-size: 13px; - line-height: 18px; - border-bottom: 1px solid $border-grey; - &:last-child { border: none !important; } + .pagination { text-align: center; } - &.unread { - background-color: $background-grey; - .unread-toggle { - opacity: 1 !important; - .entypo { color: $black; } - } - } + .no-notifications { + margin: 0 10px; + text-align: center; + } + } - &:hover { - .unread-toggle { opacity: 1 !important; } - } + .list-group .list-group-item { + [class^="entypo-"], [class*="entypo-"], .mentionIcon { margin-right: 5px; } + .mentionIcon { font-weight: bold; } - .avatar { - width: 35px; - height: 35px; - } + &.active { + [class^="entypo-"], [class*="entypo-"], .mentionIcon { color: $component-active-color; } + } + } +} + +#notifications_container .stream, header .nav-badges .notifications { + .stream_element.media { + padding: 10px; + margin: 0px; + line-height: 18px; + border-bottom: 1px solid $border-grey; + &:last-child { border: none !important; } + &.unread { + background-color: $background-grey; .unread-toggle { - padding: 9px 5px; - .entypo { - cursor: pointer; - color: lighten($black,75%); - font-size: 17px; - line-height: 17px; - } - opacity: 0; + opacity: 1 !important; + .entypo-eye { color: $black; } } + } - .btn-group.aspect_membership_dropdown { margin: 5px 0; } + &:hover { + .unread-toggle { opacity: 1 !important; } } - .pagination { text-align: center; } + .avatar { + width: 35px; + height: 35px; + } + + .unread-toggle { + padding: 9px 5px; + .entypo-eye { + cursor: pointer; + color: lighten($black,75%); + font-size: 17px; + line-height: 17px; + } + opacity: 0; + } - .no_notifications { text-align: center; } + .btn-group.aspect_membership_dropdown { margin: 5px 0; } } } diff --git a/app/assets/stylesheets/openid_connect_error_page.scss b/app/assets/stylesheets/openid_connect_error_page.scss new file mode 100644 index 0000000000000000000000000000000000000000..15e659fc3f55e0264a99612cfee75f26ddebaaf8 --- /dev/null +++ b/app/assets/stylesheets/openid_connect_error_page.scss @@ -0,0 +1,7 @@ +.api-error { + background-color: $light-grey; + box-shadow: $card-shadow; + margin-top: 20px; + + h4 { text-align: center; } +} diff --git a/app/assets/stylesheets/people.scss b/app/assets/stylesheets/people.scss index c217dcca4b434478dce6d0c6d0722bb28e310280..66dcb70826a7ec6183483732896c8da65b3ad348 100644 --- a/app/assets/stylesheets/people.scss +++ b/app/assets/stylesheets/people.scss @@ -3,6 +3,7 @@ .term { font-weight: 700; } small { margin-left: 15px; } } + #invitations-button { padding-left: 0; } } #people_stream { .media, .media-body { @@ -11,7 +12,7 @@ .stream_element.media { border-bottom: 1px solid $border-grey; padding: 10px; - margin: 0px; + margin: 0; font-size: 13px; line-height: 16px; min-height: 50px; @@ -24,6 +25,23 @@ line-height: 50px; margin-right: 10px; } - .info { font-size: 11px; } + .info { font-size: $font-size-small; } + } +} +#blocked_people { + .blocked_person { + border-bottom: 1px solid $border-grey; + font-size: 13px; + line-height: 16px; + margin: 0; + min-height: 50px; + padding: 10px 0; + &:last-of-type { border-bottom: 0; } + .avatar { + width: 50px; + height: 50px; + } + .info { font-size: $font-size-small; } + .btn-danger { margin-top: 9px; } } } diff --git a/app/assets/stylesheets/poll.scss b/app/assets/stylesheets/poll.scss new file mode 100644 index 0000000000000000000000000000000000000000..e5d80527048e444119e71c720a7b02441a60f238 --- /dev/null +++ b/app/assets/stylesheets/poll.scss @@ -0,0 +1,60 @@ +.poll_form { + border-bottom: 1px solid $border-grey; + border-top: 1px solid $border-grey; + margin: 10px 0; + padding: 10px 0 5px; + + .toggle-result-wrapper { + display: inline-block; + margin-top: 10px; + } + + form { + margin-bottom: 0; + } + + .progress { + background-image: none; + box-shadow: 0 0 0; + height: 10px; + margin-bottom: 5px; + + .bar { + background: $border-dark-grey none; + color: $text-dark-grey; + height: 100%; + text-align: left; + } + } + + .submit[disabled] { + color: $text-grey; + cursor: default; + + &:hover, + &:active { + background-image: none; + } + } +} + +.poll-content { + margin-top: 5px; + + [type=radio], + label { + font-weight: normal; + margin-bottom: 5px; + vertical-align: middle; + } + + [type=radio], + form .poll-result, + form .progress { + display: none; // Hide the result by default when the vote is possible + } + + form [type=radio] { + display: inline; + } +} diff --git a/app/assets/stylesheets/poltergeist_disable_transition.scss b/app/assets/stylesheets/poltergeist_disable_transition.scss new file mode 100644 index 0000000000000000000000000000000000000000..61a5c8efad3220ab1001e824b06cd1cb918f9911 --- /dev/null +++ b/app/assets/stylesheets/poltergeist_disable_transition.scss @@ -0,0 +1,9 @@ +// Overrides used for poltergeist tests +// scss-lint:disable all +* { + -moz-transition: none !important; + -o-transition: none !important; + -webkit-transition: none !important; + transition: none !important; +} +// scss-lint:enable all diff --git a/app/assets/stylesheets/post-content.scss b/app/assets/stylesheets/post-content.scss index 3300d25f541b616e687f014578e0b5063c427d40..c58f567e1bfb97b9dc93fc618365f1b80aa5b707 100644 --- a/app/assets/stylesheets/post-content.scss +++ b/app/assets/stylesheets/post-content.scss @@ -1,4 +1,6 @@ +.message-content, .post-content { + img { max-width: 100%; } .photo_attachments { margin-top: 7px; padding-bottom: 10px; diff --git a/app/assets/stylesheets/profile.scss b/app/assets/stylesheets/profile.scss index 7c868ff55b9267ad3260c0d18bddefdb8e9a8b7d..727c99fee276fbe73f6d6bd4014923e42f793f65 100644 --- a/app/assets/stylesheets/profile.scss +++ b/app/assets/stylesheets/profile.scss @@ -1,15 +1,15 @@ #profile_container { .profile_header { - margin-bottom: 20px; - border-left: 1px solid #dddddd; + margin-bottom: 15px; + background-color: $white; padding-left: 10px; + padding-right: 10px; padding-top: 20px; - margin-left: -10px; margin-top: -20px; + box-shadow: $card-shadow; #edit_profile, #unblock_user_button, .aspect_dropdown { - margin-top: 5px; - margin-right: 10px; + margin-top: 15px; } #author_info { @@ -32,18 +32,18 @@ color: $text-grey; &:before { content: '\26aa'; } } - &.entypo.check { color: darken($green,20%); } + &.entypo-check { color: darken($brand-success,20%); } } .description { margin-bottom: 20px; .tag { background-color: transparent; - font-size: $font-size-text; + font-size: $font-size-base; } - .tag:not(.entypo) { + .tag { font-weight: 700; } - .entypo.tag { + .entypo-tag { margin: 0 5px; font-weight: normal; &:hover {text-decoration: none;} @@ -51,9 +51,8 @@ } } - #profile_horizontal_bar { + #profile-horizontal-bar { border-top: 1px dashed $border-grey; - border-bottom: 1px solid $border-grey; min-height: 50px; margin-top: 10px; #profile_buttons { @@ -62,7 +61,7 @@ text-decoration: none; cursor: pointer; margin-right: 25px; - .entypo.profile-header-icon, .profile-header-icon { + .profile-header-icon { font-size: 24.5px; line-height: 30px; color: lighten($black,75%); @@ -75,13 +74,14 @@ ul#profile_nav { list-style: none; margin: 0; + padding: 0; > li { display: inline-block; &.active { - border-bottom: 3px solid $creation-blue; + border-bottom: 3px solid $brand-primary; a { color: $black; - .entypo { color: $black; } + [class^="entypo-"], [class*="entypo-"] { color: $black; } } } a { @@ -89,13 +89,13 @@ font-size: 16px; line-height: 46px; color: lighten($black,50%); - .entypo { + [class^="entypo-"], [class*="entypo-"] { color: lighten($black,50%); margin-right: 2px; } &:hover { color: $black; - .entypo { color: $black; } + [class^="entypo-"], [class*="entypo-"] { color: $black; } text-decoration: none; } } @@ -105,16 +105,19 @@ } #profile { - padding: 10px 20px; + padding: 20px; + margin-bottom: 35px; + #profile_photo { margin-top: 10px; padding-bottom: 10px; - border-bottom: 1px dashed $border-grey; text-align: center; } ul#profile_information { + border-top: 1px dashed $border-grey; margin: 0; + padding: 0; list-style: none; overflow-x: hidden; word-wrap: break-word; @@ -127,4 +130,32 @@ } .stream_container > .pagination { text-align: center; } + + #people_stream { + background-color: $white; + box-shadow: $card-shadow; + } +} + +#email-form{ + padding: 0; + .form-group{ + margin-left: 0; + margin-right: 0; + } +} + +#birth-date{ + text-align: center; + select{ + width: 32%; + display: inline; + &:first-of-type{ float: left; } + &:last-of-type{ float: right; } + } +} + +#update_profile_form { + .profile-visibility-hint { margin-left: 10px; } + .visibility-hint-icon { cursor: default; } } diff --git a/app/assets/stylesheets/publisher.scss b/app/assets/stylesheets/publisher.scss index 8df3350b3d3b78bee24a04e94b210ba4392be20b..2504f8d345c189ee41a7f7e64e95452d34591a01 100644 --- a/app/assets/stylesheets/publisher.scss +++ b/app/assets/stylesheets/publisher.scss @@ -1,10 +1,12 @@ -#publisher { +.publisher { z-index: 1; color: $text-grey; + margin: 0; + margin-bottom: 20px; &.closed { #button_container, - #location_container, + .location-container, #hide_publisher, #photodropzone_container, .counter, @@ -12,40 +14,64 @@ display: none !important; } + .mentions-box { + margin-top: 0; + } + #publisher_textarea_wrapper { border: 1px solid $border-grey !important; } } - .mentions-autocomplete-list ul { width: 100% !important; } + .container-fluid{ padding: 0; } + + .twitter-typeahead { + width: calc(100% + 2px); + + .tt-menu { width: 100%; } + } form { margin: 0; #fileInfo { display: none !important; } - #hide_publisher { - margin-top: 10px; - } #publisher_spinner { + margin: 20px; text-align: center; } .options_and_submit { - #publisher_service_icons { - margin-right: 10px; - .btn-link { - padding-left: 5px; - padding-right: 5px; - text-decoration: none; + padding: 10px 0; + + #publisher-service-icons { + text-decoration: none; + + .entypo-cog, .service_icon { + color: $text-grey; + font-size: 16px; + line-height: 16px; } - .btn-link.question_mark { margin-left: 5px; } - .btn-link.question_mark .entypo { color: $text-grey; } - .btn-link.question_mark:hover .entypo { color: $black; } + .service_icon { padding: 6px 5px; } + .btn.btn-link.question_mark:hover .entypo-cog { color: $black; } .dim { opacity: 0.3; } - .social_media_logos-wordpress-16x16 { + .social-media-logos-wordpress-16x16 { display: inline-block; height: 16px; width: 16px; } } + + @media(max-width: $screen-xs) { + .btn-toolbar { + width: 100%; + display: flex; + .btn, .aspect_dropdown{ flex-grow: 1; } + .aspect_dropdown .btn { width: 100%; } + } + .btn-group:first-child { margin: 0; } + .dropdown-menu.pull-right { + left: 0; + right: auto; + } + } } #publisher_textarea_wrapper { @@ -56,11 +82,11 @@ input[type='text']#status_message_text { border: none; box-shadow: none; - margin: none; + margin: 0; } textarea { - border: none; + border: 0 solid $light-grey; margin: 0; box-shadow: none; resize: none; @@ -68,11 +94,10 @@ } &.active textarea { - min-height: 70px; + min-height: 90px; } - .help-block { - font-size: 13px; + .markdownIndications { line-height: 30px; padding-left: 10px; margin-bottom: 0; @@ -80,20 +105,15 @@ a { color: lighten($blue,20%); } } - .mentions-input-box .mentions { - line-height: $line-height !important; - } - - &.with_attachments .row-fluid#photodropzone_container { + &.with_attachments #photodropzone_container { border-top: 1px dashed $border-grey; } - .row-fluid#poll_creator_container { - display: none; + #poll_creator_container { border-top: 1px dashed $border-grey; padding:4px 6px 4px 6px; box-sizing: border-box; - .remove-answer.entypo.cross { + .remove-answer.entypo-cross { display: none; color: lighten($black,75%); &.active { display: block; } @@ -104,15 +124,7 @@ } } - &.with_location .row-fluid#location_container { - height: 30px; - border-top: 1px dashed $border-grey; - input[type='text'] { - margin-bottom: 0; - color: $text-grey; - } - } - &.active .row-fluid#button_container { + &.active #button_container { border-top: 1px solid $border-grey; } @@ -143,7 +155,7 @@ color: black; font-size: 50px; line-height: 50px; - font-style: bold; + font-weight: bold; position: absolute; z-index: 2; opacity: 0.85; @@ -173,67 +185,103 @@ #upload_error { color: white; - font-style: bold; + font-weight: bold; border-top: 1px solid white; background-color: $red; text-align: center; } - #publisher-images { - margin-right: 5px; - #file-upload, - #locator, - #poll_creator, - #hide_location { - text-decoration: none !important; - font-size: 16px; - padding: 4px 5px; - i { - color: $text-grey; - } - &:hover{ - i { color: black; } - } - input[type='file'] { - cursor: pointer; - &::-webkit-file-upload-button { - cursor: pointer; - } - } - } - #hide_location { - display: none; - } - } - &.with_location #publisher-images { - #hide_location { display: inline-block; } - #locator { display: none; } - } - - .counter { - height: 30px; - line-height: 30px; - position: absolute; - right: 100px; - bottom: -31px; - font-size: 13px; - } - &.with_location .counter { - bottom: -62px; - } - .warning { - color: orange; - } - .exceeded { - color: red; - } } } .aspect_dropdown { .radio { - min-height: 0px; - padding-left: 0px; + min-height: 0; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; } } } + +.publisher-textarea-wrapper { + &:not(.with-location) .location-container, + &.markdown-preview .location-container, + &:not(.with-poll) .poll-creator-container, + &.markdown-preview .poll-creator-container, + &.markdown-preview .photodropzone-container, + &.markdown-preview .publisher-buttonbar { + display: none; + } + + &.with-location .loader { + height: 20px; + width: 20px; + } + + &.with-location .location-container { + border-top: 1px dashed $border-grey; + height: 30px; + margin-bottom: 0; + + [type='text'] { + border: 0; + color: $text-grey; + height: 20px; + margin-bottom: 0; + padding: 0; + } + } + + .counter { + line-height: 30px; + margin-right: 10px; + } + + &:not(.with-location) .publisher-buttonbar { + .hide-location { display: none; } + .locator { display: inline-block; } + } + + &.with-location .publisher-buttonbar { + .hide-location { display: inline-block; } + .locator { display: none; } + } + + &.submitting .mentions-box { display: none; } + + .twitter-typeahead { + left: -1px; + // Override inline rule of Typeahead + // scss-lint:disable ImportantRule + position: absolute !important; + // scss-lint:enable ImportantRule + } + + .mentions-box { + // Leave space for markdown editor header + margin-top: 42px; + } +} + +.publisher-buttonbar { + float: right; + margin-right: 5px; + + .btn.btn-link { + font-size: 16px; + line-height: $line-height-computed; + padding: 4px 2px; + text-decoration: none; + i { color: $text-grey; } + + [type='file'], + [type='file']::-webkit-file-upload-button { + cursor: pointer; + } + } + + .btn.btn-link:hover { + i { color: $black; } + } +} diff --git a/app/assets/stylesheets/registration.scss b/app/assets/stylesheets/registration.scss new file mode 100644 index 0000000000000000000000000000000000000000..53c65674dce01b865f35adad143edd15763bc3c1 --- /dev/null +++ b/app/assets/stylesheets/registration.scss @@ -0,0 +1,53 @@ +.page-registrations.action-new, +.page-registrations.action-create { + .ball { + background: image-url('branding/ball.png') no-repeat; + background-size: contain; + height: 633px; + max-width: 100%; + } + + .v-center { + display: table; + height: 633px; + } + + .content { + display: table-cell; + vertical-align: middle; + + h2 { + font-size: 35px; + margin: 12px; + text-align: center; + } + } + + form { + max-width: 400px; + } + + .captcha-img { + left: 10px; + position: absolute; + top: 169px; + width: 120px; + } + + .captcha-input { + border-bottom: 1px solid $border-grey; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + box-sizing: border-box; + font-size: 16px; + height: 40px; + line-height: $line-height-base; + padding: 10px 10px 10px 130px; + width: 100%; + } + + .terms > a { + color: inherit; + text-decoration: underline; + } +} diff --git a/app/assets/stylesheets/report.scss b/app/assets/stylesheets/report.scss index d964b55cd4918dbd26ab016804b0fc76728938ec..4282ad6371eb0a53c5c95bae860ec161b3d86c16 100644 --- a/app/assets/stylesheets/report.scss +++ b/app/assets/stylesheets/report.scss @@ -1,21 +1,8 @@ #reports { - padding-top: 2em; - .content { - float: left; - span { - display: block; - } - span.text { - padding-bottom: 1em; - } + .reason { + padding-bottom: 20px; } - .options { - float: right; - } - .clear { - clear: both; - border-bottom: 1px solid #808080; - padding-bottom: 1em; - margin-bottom: 1em; + form input { + margin-right: 5px; } } diff --git a/app/assets/stylesheets/rtl.scss b/app/assets/stylesheets/rtl.scss index b46cf4d8b97a0b73a10e3e32f7fa64def345d118..15a56487275564609498cc1f35e64356d4cec13b 100644 --- a/app/assets/stylesheets/rtl.scss +++ b/app/assets/stylesheets/rtl.scss @@ -1,151 +1,18 @@ -@import "colors"; - body { direction: rtl; text-align: right; } -#user_menu { - left: 0; - right: auto; -} - -.diaspora_header_logo { - float: right; - margin-left: 1em; - margin-right: 0; -} - -#global_search { - float: right; -} - -#notification_badge, #conversations_badge { - margin: 0 10px 0 -5px; -} - -#nav_badges { - left: auto; - right: 460px; - margin-right: -20px; -} - - -#notification_dropdown { - left: auto; - right: 507px; -} - -#view_all_notifications { - float: left; - margin-right: 0; - margin-left: 3px; -} - -#notification_badge, #conversations_badge { - margin: 0 10px 0 -5px; -} - -#notification_badge a, #conversations_badge a { - right: 0; -} - -.append-2 { - padding-left: 80px; - padding-right: 0px; - float: right; -} - -footer ul#footer_nav { - float: left; -} - .right { left: 0; right: auto; } -.rightBar .right { - margin-right: 70px; -} - -.stream .avatar { - float: right; -} - .stream_element .content { padding-right: 60px; padding-left: 0; } -#publisher_textarea_wrapper textarea { - left: auto; -} - -#publisher_textarea_wrapper #file-upload, #publisher_textarea_wrapper #hide_publisher, #facebox .close { - right: auto; - left: 0; - margin-left: 3px; -} - -#publisher .options_and_submit .public_toggle { - text-align: left; -} - -#publisher #click_to_share img { - right: 0; - left: auto; -} - -#publisher #click_to_share span { - margin-right: 12px; - margin-left: 0; -} - -#publisher_textarea_wrapper #photodropzone { - right: 5px; - left: auto; -} - -#publisher_textarea_wrapper #photodropzone li .circle { - left: -7px; - right: auto; -} - -#publisher_textarea_wrapper #photodropzone li .x { - left: -1px; - right: auto; -} - -#webSocketContainer { - left: auto !important; - right: -100px; -} - -header ul#user_menu { - padding: 5px 30px 5px 5px; - right: auto; - margin: -2px 0 0 -5px; -} - -header ul#user_menu .avatar { - left: auto; - right: 2px; -} - -header ul#user_menu a { - padding-left: 15px; -} - -header ul#user_menu .right { - right: auto; - left: 5px; -} - -#sort_by { - float: left; -} - .stream_element .right { left: 12px; right: auto; @@ -179,64 +46,21 @@ form p.checkbox_select label { left: auto; } -.prepend-5 { - float: right; - padding-right: 200px; - padding-left: 0; -} - #update_profile_form h4 textarea[placeholder] { right: -9999px; left: auto; } -.prepend-8 { - padding-right: 320px; - padding-left: 0; -} - -.span-2 { - float: right; - text-align: right; - margin-left: 0; - margin-right: 10px; -} - -#facebox_header h3, #facebox_header h4 { - text-align: right; -} - -textarea.comment_box { - left: auto; - right: -9999px; -} - label { right: 0.48em; left: auto; } -ul#settings_nav { - right: 198px; - left: auto; -} - ul, ol { margin: 0 0 1.5em 1.5em; padding-right: 3.333em; } -ul#settings_nav > li { - margin-left: 1em; - margin-right: 0; -} - -.column, .span-1, .span-2, .span-3, .span-4, .span-5, .span-6, .span-7, .span-8, .span-9, .span-10, .span-11, .span-12, .span-13, .span-14, .span-15, .span-16, .span-17, .span-18, .span-19, .span-20, .span-21, .span-22, .span-23, .span-24 { - float: right; - margin-left: 10px; - margin-right: 0; -} - .last { margin-left: 0; } @@ -256,36 +80,7 @@ ul.comments li form p, ul.show_comments li form p, div.likes li form p, div.disl left: 20px; } -.aspect_list .name { - right: 1em; - left: auto; -} - -.aspect_list ul > li .right { - left: 1em; - right: auto; -} - -.share_with .add_aspect .right { - right: auto; - left: 1em; -} - -.share_with .done .right { - right: auto; - left: 1em; -} - -.share_with .add_aspect p { - padding-right: 1em; - padding-left: 0; -} - -#facebox { - text-align: right; -} - -.stream_element.conversation .message_count { +.stream_element.conversation .message-count { right: auto; left: 10px; } @@ -295,30 +90,6 @@ ul.comments li form p, ul.show_comments li form p, div.likes li form p, div.disl left: 10px; } -ul.left_nav .item_count, ul.left_nav .edit { - float: left; -} - -.conversation_participants .right, .stream .new_message .right { - right: auto; - left: 0; -} - -.prepend-9 { - padding-left: 0; - padding-right: 361px; -} - -.stream_container { - border-left: 0; - border-right: 1px solid $border-grey; -} - -.stream .new_message .right input[type=reset] { - float: left; - margin-right: 10px; -} - div.content span.rtl { display: block; } diff --git a/app/assets/stylesheets/settings.scss b/app/assets/stylesheets/settings.scss new file mode 100644 index 0000000000000000000000000000000000000000..11cb5b13f5b3072954906c03aa304c2fa9175db0 --- /dev/null +++ b/app/assets/stylesheets/settings.scss @@ -0,0 +1,38 @@ +// Specific styles for the settings pages (profile, user account, privacy, services) + +// These names are generated by a rails controller +// scss-lint:disable SelectorFormat +.page-profiles.action-edit, +.page-services.action-index, +.page-user_applications, +.page-users.action-edit, +.page-users.action-update, +.page-users.action-privacy_settings { + .framed-content { + padding-left: 10px; + padding-right: 10px; + } +} +// scss-lint:enable SelectorFormat + +.enclosed-checkbox label { + margin-bottom: 0; +} + +.profile-photo-upload { + text-align: center; + + .avatar { + height: auto; + margin-bottom: 20px; + max-width: 200px; + width: auto; + } +} + +.settings-visibility { margin-left: 10px; } + +.page-profiles.action-edit textarea { + max-width: 100%; + min-width: 100%; +} diff --git a/app/assets/stylesheets/sidebar.scss b/app/assets/stylesheets/sidebar.scss index 28d012cebf2f5c3f711c4dd0894b4bfb02f47f97..1df833b427409f54eb9e42c586fc69f53395f6c7 100644 --- a/app/assets/stylesheets/sidebar.scss +++ b/app/assets/stylesheets/sidebar.scss @@ -1,61 +1,20 @@ -.rightBar { - padding-top: 20px; - - .section { - margin-bottom: 20px; - - > .title { - border-bottom: 1px solid $border-grey; - padding-bottom: 2px; - - &.no_icon { padding-left: 8px; } - - h5 { - color: $text-dark-grey; - font-weight: bold; - font-size: 13px; - margin: 0; - &.title-header { margin-left: 5px; } - } - } - - .content { - color: $text-grey; - font-size: 11px; - line-height: 18px; - padding: 5px; - - p, ul { margin: 0; } - - ul { - margin-bottom: 5px; - padding-left: 0; - li { list-style: none; } - } - - & > #invite_code { - box-sizing: border-box; - font-size: 11px; - height: 30px; - width: 100%; - } - - & > #right_service_icons { - text-align: center; - padding: 10px { - bottom: 0; - }; - .social_media_logos-facebook-24x24, - .social_media_logos-twitter-24x24, - .social_media_logos-tumblr-24x24, - .social_media_logos-wordpress-24x24 { - height: 24px; - width: 24px; - } - a { - display: inline-block; - } - } +.sidebar, +.framed-content { + background-color: $white; + border: 1px solid $light-grey; + border-top: 0; + box-shadow: $card-shadow; + + .header, + .sidebar-header { + padding-left: 10px; + padding-right: 10px; + + h3 { + line-height: 40px; + margin: 7px 0; } } + + .list-group { margin-bottom: 0; } } diff --git a/app/assets/stylesheets/single-post-view.scss b/app/assets/stylesheets/single-post-view.scss index d39f20d42dd5b2b3e2602e960a4341f00fb7696b..e0cb2894e21c94c620bc770219ebec2cbd33b43a 100644 --- a/app/assets/stylesheets/single-post-view.scss +++ b/app/assets/stylesheets/single-post-view.scss @@ -3,11 +3,9 @@ } #single-post-content { - border-right: solid 1px #cccccc; - padding-right: 12px; - #head { - padding-bottom: 10px; + .head { border-bottom: 1px solid $border-grey; + padding: 10px 0; #post-info { .author{ color: $grey; } .info { @@ -17,26 +15,34 @@ .post_scope { margin-right: 5px; } .status-message-location { padding-top: 2px; - line-height: $font-size-text; + line-height: $font-size-base; } } .bd { padding-left: 10px; } } - .row-fluid.reshare { + .near-from { + color: $text-grey; + font-size: 12px; + margin: 10px 15px 0; + } + .mapContainer { + margin: 10px 15px 0; + } + .reshare.row { border-top: 1px solid lighten($border-grey,5%); padding-top: 10px; margin-top: 10px; } #reshare-info { line-height: 15px; - i.retweet { + i.entypo-reshare { color: $text-dark-grey; font-size: 28px; line-height: 30px; - margin-left: 8px; - margin-right: 8px; + margin-left: 7px; + margin-right: 7px; } .post-context { font-size: 12px; @@ -60,24 +66,23 @@ .img { margin-right: 10px; } } #single-post-actions { - padding-right: 5px; i { font-size: 28px; line-height: 30px; } - i.comment:hover { + i.entypo-comment:hover { color: #424242; } .post_report i.gray:hover { color: $red; } - i.heart.gray:hover { + i.entypo-heart.gray:hover { color: $red; } - i.heart.red:hover { + i.entypo-heart.red:hover { color: #f55f5a; } - i.retweet:hover { + i.entypo-reshare:hover { color: #3f8fba; } time { @@ -93,49 +98,27 @@ } } - #body { - margin-left: 20px; - padding-top: 20px; - width: auto; - - #real-post-content div.reshare { - border-left: 2px solid #DDD; - padding-left: 10px; - } + .body { + padding: 20px 15px; .nsfw-off { display: none; } .nsfw-shield { display: none; } - .oembed { width: 95%; } - .photo_attachments { - img.big_stream_photo { max-width: 90%; } - } } } #single-post-interactions { - border-left: 1px solid #cccccc; - position: relative; - left: -1px; - margin-left: 0; - padding-left: 15px; - - .comment.media .img { - margin-left: 5px; - } - .no_comments { + > .framed-content { padding-top: 10px; - padding-bottom: 10px; - background-color: $background-grey; - text-align: center; - border-radius: 4px; - margin-bottom: 30px; } + .no-comments { text-align: center; } + a { color: $blue; } .count { + float: left; i { display: inline-block; text-align: center; @@ -152,5 +135,16 @@ #reshares, #likes, #comments-meta { margin-left: 7px; margin-bottom: 8px; + img{ display: inline; } + } + + .comments > .comment, + .comment.new-comment-form-wrapper { + padding: 10px; + } + + .count, + .interaction-avatars { + line-height: 25px; } } diff --git a/app/assets/stylesheets/sizes.scss b/app/assets/stylesheets/sizes.scss deleted file mode 100644 index 3679382d4a3bc77c1ffd149e9b829b8e2d540c53..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/sizes.scss +++ /dev/null @@ -1,2 +0,0 @@ -$font-size-text: 13px; -$line-height: 20px; diff --git a/app/assets/stylesheets/spinner.scss b/app/assets/stylesheets/spinner.scss new file mode 100644 index 0000000000000000000000000000000000000000..9302fc4340b8e4113b769e46ccb5ea30dabe2bab --- /dev/null +++ b/app/assets/stylesheets/spinner.scss @@ -0,0 +1,28 @@ +#paginate, #infscr-loading { + margin-top: 10px; + padding: 8px 0; + text-align: center; + width: 100%; + display: block; + clear: both; +} + +.loader { + display: inline-block; + width : 32px; + height: 32px; +} + +.spinner { + width: 100%; + height: 100%; + margin: auto; + border-radius: 50%; + border-width: 3px; + border-style: solid; + border-color: $border-dark-grey transparent $border-dark-grey $border-dark-grey; + animation-duration: 1s; + animation-iteration-count: infinite; + animation-name: spinner; + animation-timing-function: linear; +} diff --git a/app/assets/stylesheets/sprites.scss b/app/assets/stylesheets/sprites.scss index e78a5c3d9b127473195f011c1431980290c64fe0..981e20cc36dd9c5210d695c6d6d8bc586f8f4561 100644 --- a/app/assets/stylesheets/sprites.scss +++ b/app/assets/stylesheets/sprites.scss @@ -1,7 +1,5 @@ /* ===== sprites ===== */ -@import 'icons/*.png'; @import 'branding/logos/*.png'; -@import 'social_media_logos/*.png'; -@include all-icons-sprites; +@import 'social-media-logos/*.png'; @include all-logos-sprites; -@include all-social_media_logos-sprites; +@include all-social-media-logos-sprites; diff --git a/app/assets/stylesheets/statistics.scss b/app/assets/stylesheets/statistics.scss index 983fbd1b77fa74e304a50f21593dc6f2802b307e..891b34005ae5d1c7aeefa6fea15b9500be5161b7 100644 --- a/app/assets/stylesheets/statistics.scss +++ b/app/assets/stylesheets/statistics.scss @@ -4,11 +4,11 @@ h3{ margin: 0px; padding: 10px; - background-color: $green; + background-color: $brand-success; } - .span-3 { - width: 30%; + .statistic { + width: 100%; height: 150px; text-align: center; border: 1px solid $border-grey; @@ -25,4 +25,4 @@ background-color: $background-grey; } } -} \ No newline at end of file +} diff --git a/app/assets/stylesheets/stream-faces.scss b/app/assets/stylesheets/stream-faces.scss deleted file mode 100644 index b05f19f43c6895ce9b7f4ae91d4ba9eb604b4b42..0000000000000000000000000000000000000000 --- a/app/assets/stylesheets/stream-faces.scss +++ /dev/null @@ -1,7 +0,0 @@ -#selected_aspect_contacts .avatar { - height: 32px; - width: 32px; - margin-bottom: 2px; -} - -.stream-faces a:hover { text-decoration: none; } diff --git a/app/assets/stylesheets/stream.scss b/app/assets/stylesheets/stream.scss index 55545d529e3af5116b0ea5420778b913875c4be6..56bc4d5a64af33c4f25e41bb2cdc09a9124bcce6 100644 --- a/app/assets/stylesheets/stream.scss +++ b/app/assets/stylesheets/stream.scss @@ -1,11 +1,26 @@ .stream_container { - border-left: 1px solid $border-grey; - padding-left: 10px; - padding-top: 20px; - margin-left: -10px; - margin-top: -20px; - #publisher { - margin-bottom: 15px; - } - .well#ignore-info { text-align: center; } + .stream-title { + margin: 12px 0; + } +} + +.main-stream-publisher { + margin-top: 20px; + padding: 0; + + .avatar { + height: 50px; + width: 50px; + } + + .publisher { + margin-left: 65px; + } +} + +@media(max-width: $screen-xs-max) { + + .main-stream-publisher .publisher { + margin-left: 0; + } } diff --git a/app/assets/stylesheets/stream_element.scss b/app/assets/stylesheets/stream_element.scss index 0258500e181e947be51cff45c71792496d09ad6a..26899f05ffd80babf74a8480000a016c18bc7816 100644 --- a/app/assets/stylesheets/stream_element.scss +++ b/app/assets/stylesheets/stream_element.scss @@ -1,5 +1,5 @@ -#main_stream .stream_element, -#main_stream > div > .photo { +.stream_element, +.photo { & > .media { margin: 0px; } @@ -9,41 +9,72 @@ } } -#main_stream > div > .photo { - & > .media { +.photo { + > .media { overflow: visible; - > .bd { - position: relative; - overflow: inherit; - > .control-icons { - border-radius: 4px; - padding-left: 5px; - position: absolute; - right: 6px; - text-align: center; - top: 1px; - } + position: relative; + + .control-icons { + background: $white; + border-radius: 4px; + padding-left: 4px; + position: absolute; + right: 4px; + text-align: center; + top: 1px; } - &:hover > .bd > .control-icons { background: #fff; } } + .thumbnail { - height: 200px; + background: $white; + border-radius: 0; + box-shadow: $card-shadow; + height: 240px; + margin: 0 0 15px; padding: 10px; - margin: 0 5px 10px; + + // Vertically align the image text-align: center; - line-height: 200px; - border: 1px solid $border-grey; - background: #fefefe; - box-shadow: 3px 3px 2px #eee; - img { - &.big_photo { max-height: 200px; } + white-space: nowrap; + + &:hover, + &:focus, + &:active { + border-color: $light-grey; + text-decoration: none; + } + + &::before { + content: ''; + display: inline-block; + height: 100%; + vertical-align: middle; + } + + .big-photo { + display: inline; + margin-left: -4px; + max-height: 200px; + vertical-align: middle; } } } #main_stream .stream_element { - border-bottom: 1px solid $border-grey; + margin-bottom: 20px; + border: 1px solid $light-grey; + box-shadow: $card-shadow; + + &.highlighted { + border-left: 3px solid $brand-primary; + padding-left: 8px; + } +} + +.stream_element { + background-color: $white; padding: 10px; + & > .media { &.shield-active .nsfw-hidden { display: none; } &:not(.shield-active) .nsfw-shield { display: none; } @@ -62,31 +93,9 @@ a.author-name { color: $blue; } .feedback { margin-top: 5px; - font-size: 11px; - line-height: 11px; + font-size: $font-size-small; + line-height: $font-size-small; } - .likes { - margin-top: 10px; - font-size: 12px; - line-height: 16px; - .bd { display: inline-block; } - .entypo.heart { - display: inline-block; - font-size: 16px; - vertical-align: top; - margin-top: -2px; - margin-right: 5px; - } - } - .stream_photo { - float: left; - margin-top: 6px; - } - .status-message-location .near-from { - font-size: 11px; - color: $text-grey; - } - .grey { color: $text-grey; } .post-content p:last-of-type { margin-bottom: 0; } .nsfw-shield { color: $text-grey; @@ -97,6 +106,16 @@ } } + .permalink { + @include transition(opacity); + opacity: 0; + } + + &:hover .permalink { + opacity: .8; + &:hover { opacity: 1; } + } + div.reshare { border-left: 2px solid $border-grey; margin-top: 3px; @@ -135,13 +154,40 @@ } } - &.highlighted { - padding-left: 8px; - border-left: 3px solid $creation-blue; + .likes, + .reshares { + font-size: 12px; + line-height: 16px; + margin-top: 10px; + + .author-name, + .bd { + display: inline-block; + } + + .author-name { margin-right: 3px; } + + .entypo-heart, + .entypo-reshare { + display: inline-block; + font-size: 16px; + line-height: $line-height-computed; + margin-right: 5px; + vertical-align: top; + } + } + + .status-message-location { + color: $text-grey; + font-size: $font-size-small; + } + + .leaflet-control-zoom { + display: block; } - &.post_preview { - background-color: lighten($creation-blue,45%); - border: 1px solid $creation-blue; + .no-posts-info { + margin-bottom: 10px; + margin-top: 10px; } } diff --git a/app/assets/stylesheets/tag.scss b/app/assets/stylesheets/tag.scss index aa49a815d4597d60ebf25ebdf93bffd536a898f0..a167fafe89094daea924d4b6c04a1fb28ddf1347 100644 --- a/app/assets/stylesheets/tag.scss +++ b/app/assets/stylesheets/tag.scss @@ -22,27 +22,30 @@ h1.tag { &:hover { border-bottom: 1px solid $border-dark-grey; } } } +.page-tags { + #tags_show { + .sidebar { + h3 { + font-size: 13px; + line-height: 1.1; + } -#tags_show { - .span3 { - h4 { margin: 25px 0 15px; } - .side_stream #people_stream { - .name { display: block; } - .name, .diaspora_handle, .tags { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + .side_stream #people_stream { + .name { display: block; } + .name, .diaspora_handle { + word-break: break-all; + } } } - } - .span7 { - .tag-following-action { - max-width: 100%; - input[type="submit"] { - overflow: hidden; - text-overflow: ellipsis; + .col-md-9 { + .tag-following-action { max-width: 100%; - } + input[type="submit"] { + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + } + } } } } diff --git a/app/assets/stylesheets/terms.scss b/app/assets/stylesheets/terms.scss new file mode 100644 index 0000000000000000000000000000000000000000..94eec299c25f46651ec4c779eacce3e3ca5301d3 --- /dev/null +++ b/app/assets/stylesheets/terms.scss @@ -0,0 +1,3 @@ +#terms { + .nav-tabs { margin-top: 40px; } +} diff --git a/app/assets/stylesheets/timeago.scss b/app/assets/stylesheets/timeago.scss new file mode 100644 index 0000000000000000000000000000000000000000..cbc0e917b204674ccf6bc535f6b64f3c66fc9eb5 --- /dev/null +++ b/app/assets/stylesheets/timeago.scss @@ -0,0 +1,3 @@ +.timeago { + color: $text-grey; +} diff --git a/app/assets/stylesheets/typeahead.scss b/app/assets/stylesheets/typeahead.scss new file mode 100644 index 0000000000000000000000000000000000000000..7f427c0972a63c19efe9bd0ceb4d52b105665deb --- /dev/null +++ b/app/assets/stylesheets/typeahead.scss @@ -0,0 +1,34 @@ +.tt-menu { + background-color: $navbar-inverse-bg; + box-shadow: 0 5px 10px rgba(0,0,0,.2); +} + +.navbar.navbar-fixed-top .tt-menu { + margin-top: ($navbar-height - $input-height-small) / 2; + width: 300px; +} + +.tt-suggestion { + border-top: 1px solid $gray-dark; + color: $white; + cursor: pointer; + line-height: 20px; + &.tt-cursor { + background-color: $brand-primary; + border-top: 1px solid $brand-primary; + } + + &.search-suggestion-person { + padding: 8px; + .avatar { + height: 40px; + margin-right: 8px; + width: 40px; + } + .diaspora-id { font-size: $font-size-small; } + } + &.search-suggestion-hashtag { + padding: 8px 20px; + .name { line-height: 25px; } + } +} diff --git a/app/assets/stylesheets/typography.scss b/app/assets/stylesheets/typography.scss new file mode 100644 index 0000000000000000000000000000000000000000..0aa346ae1b0f58462a051361f0bf209f8ec9b4a8 --- /dev/null +++ b/app/assets/stylesheets/typography.scss @@ -0,0 +1,23 @@ +// diaspora custom icons font +@font-face { + font-family: 'diaspora-custom'; + src: image-url('fonts/diaspora-custom.ttf'); + font-weight: normal; + font-style: normal; + +} + +[class^="diaspora-custom-"]:before, +[class*=" diaspora-custom-"]:before { + font-family: 'diaspora-custom'; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-style: normal; + font-variant: normal; + font-weight: normal; + text-transform: none; +} + +.diaspora-custom-compose:before { + content: 'a'; +} diff --git a/app/assets/stylesheets/user_applications.scss b/app/assets/stylesheets/user_applications.scss new file mode 100644 index 0000000000000000000000000000000000000000..87a0005ce7dab47db2900e1fa48ff748003dc225 --- /dev/null +++ b/app/assets/stylesheets/user_applications.scss @@ -0,0 +1,35 @@ +.application-img { + float: left; + margin: 9px 0; + max-height: 60px; + text-align: center; + width: 60px; + + [class^="entypo-"] { + font-size: 60px; + height: 60px; + margin: 0; + padding: 0; + width: 100%; + + &::before { + position: relative; + top: -15px; + } + } +} + +.application-authorizations { + display: inline-block; + float: right; + padding: 0 0 15px 15px; + width: calc(100% - 60px); +} + +.application-tos-policy > b { + &:first-child { margin-right: 5px; } + &:nth-child(2) { margin-left: 5px; } +} + +.user-consent { margin-top: 20px; } +.approval-button { display: inline; } diff --git a/app/assets/stylesheets/vendor/autoSuggest.css b/app/assets/stylesheets/vendor/autoSuggest.css index 760365e3c503f966c28edfb747325ec84cdf16f4..df97073d939b8655f757a5040cfc0ce9ecf6f5e9 100644 --- a/app/assets/stylesheets/vendor/autoSuggest.css +++ b/app/assets/stylesheets/vendor/autoSuggest.css @@ -1,212 +1,185 @@ /* AutoSuggest CSS - Version 1.2 */ ul.as-selections { - list-style-type: none; - border: 1px solid #ccc; - margin: 0; - overflow: auto; - background-color: #fff; - border-radius: 3px; - /* 1% padding (all sides) + 98% width = 100% */ - padding: 1%; - width: 98%; -} - -ul.as-selections.loading { - background: asset_path("ajax-loader.gif") right center no-repeat; + list-style-type: none; + margin: 0; + overflow: auto; + background-color: #fff; + border-radius: 3px; + width: 100%; + padding: 0; } ul.as-selections li { - float: left; - margin: 1px 4px 1px 0; - cursor: pointer; + float: left; + margin: 1px 4px 1px 0; + cursor: pointer; } ul.as-selections li.as-selection-item { - color: #2b3840; - font-size: 13px; - text-shadow: 0 1px 1px #fff; - background-color: #ddeefe; - background-image: gradient(linear, 0% 0%, 0% 100%, from(#ddeefe), to(#bfe0f1)); - border: 1px solid #acc3ec; - padding: 0; + color: #2b3840; + font-size: 13px; + text-shadow: 0 1px 1px #fff; + background-color: #ddeefe; + background-image: gradient(linear, 0% 0%, 0% 100%, from(#ddeefe), to(#bfe0f1)); + border: 1px solid #acc3ec; + padding: 0; padding-top: 6px; padding-bottom: 6px; padding-left: 6px; - border-radius: 5px; - box-shadow: 0 1px 1px #e4edf2; + border-radius: 5px; + box-shadow: 0 1px 1px #e4edf2; line-height: 10px; - margin-top: -1px; margin-bottom: 10px; } ul.as-selections li.as-selection-item:last-child { - margin-left: 30px; + margin-left: 30px; } ul.as-selections li.as-selection-item a.as-close { - float: right; - margin: 0px 3px 0 0px; - padding: 0 3px; - cursor: pointer; - color: #5491be; - font-family: "Helvetica", helvetica, arial, sans-serif; - font-size: 14px; - font-weight: bold; - text-shadow: 0 1px 1px #fff; - transition: color .1s ease-in; + float: right; + margin: 0px 3px 0 0px; + padding: 0 3px; + cursor: pointer; + color: #5491be; + font-family: "Helvetica", helvetica, arial, sans-serif; + font-size: 14px; + font-weight: bold; + text-shadow: 0 1px 1px #fff; + transition: color .1s ease-in; } ul.as-selections li.as-selection-item.blur { - color: #666666; - background-color: #f4f4f4; - background-image: gradient(linear, 0% 0%, 0% 100%, from(#f4f4f4), to(#d5d5d5)); - border-color: #bbb; - border-top-color: #ccc; - box-shadow: 0 1px 1px #e9e9e9; + color: #666666; + background-color: #f4f4f4; + background-image: gradient(linear, 0% 0%, 0% 100%, from(#f4f4f4), to(#d5d5d5)); + border-color: #bbb; + border-top-color: #ccc; + box-shadow: 0 1px 1px #e9e9e9; } ul.as-selections li.as-selection-item.blur a.as-close { - color: #999; + color: #999; } ul.as-selections li:hover.as-selection-item { - color: #2b3840; - background-color: #bbd4f1; - background-image: gradient(linear, 0% 0%, 0% 100%, from(#bbd4f1), to(#a3c2e5)); - border-color: #6da0e0; - border-top-color: #8bb7ed; + color: #2b3840; + background-color: #bbd4f1; + background-image: gradient(linear, 0% 0%, 0% 100%, from(#bbd4f1), to(#a3c2e5)); + border-color: #6da0e0; + border-top-color: #8bb7ed; } ul.as-selections li:hover.as-selection-item a.as-close { - color: #4d70b0; + color: #4d70b0; } ul.as-selections li.as-selection-item.selected { - border-color: #1f30e4; + border-color: #1f30e4; } ul.as-selections li.as-selection-item a:hover.as-close { - color: #1b3c65; + color: #1b3c65; } ul.as-selections li.as-selection-item a:active.as-close { - color: #4d70b0; + color: #4d70b0; } ul.as-selections li.as-original { - margin-left: 0; + width: 100%; + margin: 0; list-style: none; + padding: 0; } ul.as-selections li.as-original input { - border: none; - outline: none; - font-size: 13px; - width: auto; - padding: 0; - margin: 0; - height: 20px; - line-height: 20px; - width: 300px; -} - -ul.as-selections li.as-original.as-original{ - width: auto; + outline: none; + font-size: 13px; + margin: 0; + line-height: 20px; + width: 100%; } ul.as-list { - position: absolute; - list-style-type: none; + position: absolute; + list-style-type: none; list-style: none; - margin: 2px 0 0 0; - padding: 0; - font-size: 13px; - color: #000; - background-color: #fff; - background-color: rgba(255,255,255,0.95); - z-index: 2; - box-shadow: 0 2px 12px #222; - border-radius: 5px; + margin: 2px 0 0 0; + padding: 0; + font-size: 13px; + color: #000; + background-color: #fff; + background-color: rgba(255,255,255,0.95); + z-index: 2; + box-shadow: 0 2px 12px #222; + border-radius: 5px; } li.as-result-item, li.as-message { - margin: 0 0 0 0; - padding: 5px; - background-color: transparent; - border: 1px solid #fff; - border-bottom: 1px solid #ddd; - cursor: pointer; - border-radius: 3px; + margin: 0 0 0 0; + padding: 5px; + background-color: transparent; + border: 1px solid #fff; + border-bottom: 1px solid #ddd; + cursor: pointer; + border-radius: 3px; } li:first-child.as-result-item { - margin: 0; + margin: 0; } li.as-message { - margin: 0; - cursor: default; + margin: 0; + cursor: default; } li.as-result-item.active { - background-color: #3668d9; - background-image: gradient(linear, 0% 0%, 0% 64%, from(rgb(110, 129, 245)), to(rgb(62, 82, 242))); - border-color: #3342e8; - color: #fff; - text-shadow: 0 1px 2px #122042; + background-color: #3668d9; + background-image: gradient(linear, 0% 0%, 0% 64%, from(rgb(110, 129, 245)), to(rgb(62, 82, 242))); + border-color: #3342e8; + color: #fff; + text-shadow: 0 1px 2px #122042; } li.as-result-item em { - font-style: normal; - background: #444; - padding: 0 2px; - color: #fff; + font-style: normal; + background: #444; + padding: 0 2px; + color: #fff; } li.as-result-item.active em { - background: #253f7a; - color: #fff; -} - -/* Webkit Hacks */ -@media screen and (-webkit-min-device-pixel-ratio:0) { - ul.as-selections li.as-selection-item { - padding-top: 6px; - padding-bottom: 6px; - } - ul.as-selections li.as-selection-item a.as-close { - margin-top: -1px; - } - ul.as-selections li.as-original input { - height: 20px; - } + background: #253f7a; + color: #fff; } /* Opera Hacks */ @media all and (-webkit-min-device-pixel-ratio:10000), not all and (-webkit-min-device-pixel-ratio:0) { - ul.as-list { - border: 1px solid #ccc; - } - ul.as-selections li.as-selection-item a.as-close { - margin-left: 4px; - margin-top: 0; - } + ul.as-list { + border: 1px solid #ccc; + } + ul.as-selections li.as-selection-item a.as-close { + margin-left: 4px; + margin-top: 0; + } } /* IE Hacks */ ul.as-list { - border: 1px solid #ccc\9; + border: 1px solid #ccc\9; } ul.as-selections li.as-selection-item a.as-close { - margin-left: 4px\9; - margin-top: 0\9; + margin-left: 4px\9; + margin-top: 0\9; } /* Firefox 3.0 Hacks */ ul.as-list, x:-moz-any-link, x:default { - border: 1px solid #ccc; + border: 1px solid #ccc; } BODY:first-of-type ul.as-list, x:-moz-any-link, x:default { /* Target FF 3.5+ */ - border: none; + border: none; } diff --git a/app/assets/templates/activity-streams-photo_tpl.jst.hbs b/app/assets/templates/activity-streams-photo_tpl.jst.hbs deleted file mode 100644 index 6908cb400b7cd153503276b62dec1c2b9e1ef0f1..0000000000000000000000000000000000000000 --- a/app/assets/templates/activity-streams-photo_tpl.jst.hbs +++ /dev/null @@ -1,3 +0,0 @@ -<a href="{{object_url}}" class="stream-photo-link"> - <img src="{{image_url}}" data-small-photo="{{image_url}}" data-full-photo="{{image_url}}" class="stream-photo" /> -</a> diff --git a/app/assets/templates/aspect_create_modal_tpl.jst.hbs b/app/assets/templates/aspect_create_modal_tpl.jst.hbs index bcb32655383e0ad6c00826b769fa5a1f3082e0bb..00cd08d22a367df1141f8a7bc297e9bf21f4808e 100644 --- a/app/assets/templates/aspect_create_modal_tpl.jst.hbs +++ b/app/assets/templates/aspect_create_modal_tpl.jst.hbs @@ -1,40 +1,51 @@ -<div class="modal hide fade" id="newAspectModal" tabindex="-1" role="dialog" aria-labelledby="newAspectModalLabel" aria-hidden="true"> +<div class="modal fade" id="newAspectModal" tabindex="-1" role="dialog" aria-labelledby="newAspectModalLabel" + aria-hidden="true" xmlns="http://www.w3.org/1999/html"> - <div class="modal-header"> - <button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button> - <h3 id="newAspectModalLabel">{{ t "aspects.create.add_a_new_aspect" }}</h3> - </div> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button class="close" type="button" data-dismiss="modal" aria-hidden="true">×</button> + <h3 class="modal-title" id="newAspectModalLabel">{{ t "aspects.create.add_a_new_aspect" }}</h3> + </div> - <div class="modal-body"> - <form> - <fieldset> - {{#if addPersonId}} - <input id="aspect_person_id" type="hidden" value="{{ personId }}"> - {{/if}} + <div class="modal-body"> + <form> + <fieldset> + {{#if personId}} + <input id="aspect_person_id" type="hidden" value="{{ personId }}"> + {{/if}} - <div class="control-group"> - <label for="aspect_name">{{ t "aspects.name" }}</label> - <input id="aspect_name" class="input-block-level" maxlength=20 type="text"> - </div> + <form class="form-horizontal"> + <div class="form-group"> + <label class="col-sm-2 control-label" for="aspect_name">{{ t "aspects.name" }}</label> + <div class="col-sm-10"> + <input id="aspect_name" class="input-block-level form-control" maxlength=20 type="text"/> + </div> + </div> - <div class="control-group"> - <label for="aspect_contacts_visible" class="checkbox inline"> - <input id="aspect_contacts_visible" type="checkbox"> - {{ t "aspects.make_aspect_list_visible" }} - </label> - </div> + <div class="form-group"> + <div class="col-sm-offset-2 col-sm-10"> + <div class="checkbox"> + <label for="aspect_contacts_visible" class="checkbox inline"> + <input id="aspect_contacts_visible" type="checkbox"> {{ t "aspects.make_aspect_list_visible" }} + </label> + </div> + </div> + </div> + </form> - </fieldset> - </form> - </div> + </fieldset> + </form> + </div> - <div class="modal-footer"> - <div class="btn" data-dismiss="modal" aria-hidden="true"> - {{ t "cancel" }} - </div> - <div class="btn creation"> - {{ t "create" }} + <div class="modal-footer"> + <div class="btn btn-default" data-dismiss="modal" aria-hidden="true"> + {{ t "cancel" }} + </div> + <div class="btn btn-primary"> + {{ t "create" }} + </div> + </div> </div> </div> - </div> diff --git a/app/assets/templates/aspect_membership_dropdown_tpl.jst.hbs b/app/assets/templates/aspect_membership_dropdown_tpl.jst.hbs new file mode 100644 index 0000000000000000000000000000000000000000..d77f8ed4983eba240baeef5e7d0863a262460d1c --- /dev/null +++ b/app/assets/templates/aspect_membership_dropdown_tpl.jst.hbs @@ -0,0 +1,52 @@ +<button class="btn dropdown-toggle {{extraButtonClass}}" data-toggle="dropdown" tabindex="0"> + <span class="text"> + {{#if allAspectsAreSelected }} + {{ t "aspect_dropdown.all_aspects" }} + {{else if onlyOneAspectIsSelected}} + {{ firstMembershipName }} + {{else if noAspectIsSelected}} + {{ t "aspect_dropdown.add_to_aspect"}} + {{else}} + {{ t "aspect_dropdown.toggle" count=aspectMembershipsLength }} + {{/if}} + </span> + <span class="caret" /> +</button> + +<ul class="dropdown-menu aspect_membership pull-right" unselectable="on"> +{{#each aspects}} + <li + {{#if membership}} + class="aspect_selector selected" + {{else}} + class="aspect_selector" + {{/if}} + + data-aspect_id="{{id}}" + {{#if membership}} + data-membership_id="{{membership.id}}" + {{/if}} + > + <a> + <span class="status_indicator"> + <i class="glyphicon glyphicon-ok" /> + <i class="glyphicon glyphicon-refresh" /> + </span> + <span class="text"> + {{name}} + </span> + </a> + </li> +{{/each}} +{{#if dropdownMayCreateNewAspect}} + <li class="divider" /> + <li class="newItem add_aspect"> + <a data-target="#newAspectModal" data-toggle="modal" href="#"> + {{ t "aspects.create.add_a_new_aspect" }} + </a> + </li> +{{/if}} +</ul> +{{#if dropdownMayCreateNewAspect}} + <div class="newAspectContainer"/> +{{/if}} diff --git a/app/assets/templates/aspect_tpl.jst.hbs b/app/assets/templates/aspect_tpl.jst.hbs index 840ee584e777cbc496402a58f807a846116daa3b..f441ad540068f7ad158d2aeeaaed3e8b3bafd4b2 100644 --- a/app/assets/templates/aspect_tpl.jst.hbs +++ b/app/assets/templates/aspect_tpl.jst.hbs @@ -1,9 +1,11 @@ +<a href="/aspects/query" class="selectable aspect-item" data-guid="{{id}}"> + {{#if selected}} + <i class="entypo-check selected"></i> + {{else}} + <div class="entypo-check"></div> + {{/if}} + {{name}} +</a> <a href="/contacts?a_id={{id}}" class="action modify_aspect pull-right"> - <i class="entypo pencil"></i> + <i class="entypo-pencil"></i> </a> -{{#if selected}} - <i class="entypo check selected"></i> -{{else}} - <div class="entypo check"></div> -{{/if}} -<a href="/aspects/query" class="selectable" data-guid="{{id}}"> {{name}} </a> diff --git a/app/assets/templates/aspects-list_tpl.jst.hbs b/app/assets/templates/aspects-list_tpl.jst.hbs index 9883ad5b3ac177622b005fdcce2395628521bfbb..63c34834de343dd0090060f88ed725f859f22b39 100644 --- a/app/assets/templates/aspects-list_tpl.jst.hbs +++ b/app/assets/templates/aspects-list_tpl.jst.hbs @@ -7,5 +7,5 @@ <a href="#" class="selectable new_aspect" data-toggle="modal" data-target="#newAspectModal"> {{ t "aspect_navigation.add_an_aspect" }} </a> - <div id="newAspectContainer"></div> </li> +<div id="newAspectContainer"></div> diff --git a/app/assets/templates/comment-stream_tpl.jst.hbs b/app/assets/templates/comment-stream_tpl.jst.hbs index 1ba92fe988217475f73ad9a39616233e3574dfa0..0b6678a108ffab9cceba7a680621503e7162f060 100644 --- a/app/assets/templates/comment-stream_tpl.jst.hbs +++ b/app/assets/templates/comment-stream_tpl.jst.hbs @@ -1,17 +1,15 @@ -{{#unless all_comments_loaded}} - <div class="show_comments comment {{#unless showExpandCommentsLink}} hidden {{/unless}}"> - <div class="media"> - <a href="/posts/{{id}}#comments" class="toggle_post_comments"> - {{t "stream.more_comments" count=moreCommentsCount}} - </a> - </div> +<div class="show_comments comment {{#unless showExpandCommentsLink}} hidden {{/unless}}"> + <div class="media"> + <a href="/posts/{{id}}#comments" class="toggle_post_comments"> + {{t "stream.more_comments" count=moreCommentsCount}} + </a> </div> -{{/unless}} +</div> <div class="comments"> </div> {{#if loggedIn}} - <div class="comment media new_comment_form_wrapper {{#unless commentsCount}} hidden {{/unless}}"> + <div class="comment media new-comment-form-wrapper {{#unless commentsCount}} hidden {{/unless}}"> {{#with current_user}} <a href="/people/{{guid}}" class="img"> {{{personImage this}}} @@ -20,9 +18,9 @@ <div class="bd"> <form accept-charset="UTF-8" action="/posts/{{id}}/comments" class="new_comment" id="new_comment_on_{{id}}" method="post"> - <textarea class="comment_box" id="comment_text_on_{{id}}" name="text" rows="2" required placeholder="{{t "stream.comment"}}" /> + <textarea class="comment_box form-control" id="comment_text_on_{{id}}" name="text" rows="1" required placeholder="{{t "stream.comment"}}" /> <div class="submit_button"> - <input class="btn creation" id="comment_submit_{{id}}" name="commit" type="submit" value="{{t "stream.comment"}}" /> + <input class="btn btn-primary" id="comment_submit_{{id}}" name="commit" type="submit" value="{{t "stream.comment"}}" /> </div> </form> </div> diff --git a/app/assets/templates/comment_tpl.jst.hbs b/app/assets/templates/comment_tpl.jst.hbs index 9a96c8916026a98850db0ea329ac1b05f63d7de3..2f8a9ae1463b8b565d256b7a4092ca7482ee2005 100644 --- a/app/assets/templates/comment_tpl.jst.hbs +++ b/app/assets/templates/comment_tpl.jst.hbs @@ -10,11 +10,11 @@ {{#if loggedIn}} {{#if canRemove}} <a href="#" class="delete comment_delete" title="{{t "delete"}}"> - <i class="entypo trash"></i> + <i class="entypo-trash"></i> <a/> {{else}} - <a href="#" data-type="comment" class="comment_report" title="{{t "report.name"}}"> - <i class="entypo warning"></i> + <a href="#" data-type="Comment" class="comment_report" title="{{t "report.name"}}"> + <i class="entypo-warning"></i> </a> {{/if}} {{/if}} diff --git a/app/assets/templates/contact_tpl.jst.hbs b/app/assets/templates/contact_tpl.jst.hbs index a89542f4ef1e04857cdb674edaf51b8bfa72359c..beddbdc3ba2f22a1398dd1c304adf0be1e7427b2 100644 --- a/app/assets/templates/contact_tpl.jst.hbs +++ b/app/assets/templates/contact_tpl.jst.hbs @@ -1,4 +1,4 @@ -<div class="stream_element media contact {{in_aspect}}" id={{person_id}}> +<div class="clearfix stream_element media contact {{in_aspect}}" id={{person_id}}> <div class="pull-right"> {{{aspectMembershipIndicator this in_aspect}}} </div> diff --git a/app/assets/templates/feedback_tpl.jst.hbs b/app/assets/templates/feedback_tpl.jst.hbs index e41c1459c3446a576b77b05e059eafa78f61e08f..724a37638e5efe917dc731c721f452161b634abe 100644 --- a/app/assets/templates/feedback_tpl.jst.hbs +++ b/app/assets/templates/feedback_tpl.jst.hbs @@ -1,4 +1,4 @@ -<span class="post_scope grey"> +<span class="post_scope gray"> {{#if public}} {{t "stream.public"}} {{else}} @@ -14,22 +14,28 @@ </span> -<a href="#" class="like" rel='nofollow'> - {{#if userLike}} - {{t "stream.unlike"}} - {{else}} - {{t "stream.like"}} - {{/if}} -</a> -· - -{{#if userCanReshare}} - <a href="#" class="reshare" rel='nofollow'> - {{t "stream.reshare"}} +{{#if preview}} + <span>{{t "stream.like"}}</span> +{{else}} + <a href="#" class="like" rel='nofollow'> + {{#if userLike}} + {{t "stream.unlike"}} + {{else}} + {{t "stream.like"}} + {{/if}} </a> +{{/if}} +· +{{#if preview}} + <span>{{t "stream.reshare"}}</span> + · +{{else if userCanReshare}} + <a href="#" class="reshare" rel='nofollow'>{{t "stream.reshare"}}</a> · {{/if}} -<a href="#" class="focus_comment_textarea" rel="nofollow"> - {{t "stream.comment"}} -</a> +{{#if preview}} + <span>{{t "stream.comment"}}</span> +{{else}} + <a href="#" class="focus_comment_textarea" rel="nofollow">{{t "stream.comment"}}</a> +{{/if}} diff --git a/app/assets/templates/flash_messages_tpl.jst.hbs b/app/assets/templates/flash_messages_tpl.jst.hbs new file mode 100644 index 0000000000000000000000000000000000000000..1a8fe6fa0b241b3c748472793a89430190d7d67c --- /dev/null +++ b/app/assets/templates/flash_messages_tpl.jst.hbs @@ -0,0 +1,5 @@ +<div class="flash-body expose"> + <div class="flash-message alert {{ alertLevel }}" role="alert"> + {{ message }} + </div> +</div> diff --git a/app/assets/templates/header_tpl.jst.hbs b/app/assets/templates/header_tpl.jst.hbs index 40493d0fa682c326ac74d22220f6b11ce451ca00..a895d99c92e32de79ba2777751cb75fed529306c 100644 --- a/app/assets/templates/header_tpl.jst.hbs +++ b/app/assets/templates/header_tpl.jst.hbs @@ -1,111 +1,124 @@ -<div class="container" style="position:relative;"> - - <a href="/stream" data-stream-title="{{t "my_stream"}}"> - <div alt="logo" class="diaspora_header_logo logos-header-logo"> - </div> - </a> +<nav class="navbar navbar-inverse navbar-fixed-top"> + <div class="container-fluid"> + <div class="row"> + <div class="col-md-12"> + <div class="navbar-header"> + <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#navbar-collapse"> + <span class="sr-only">{{t "header.toggle_navigation"}}</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a href="/stream" class="navbar-brand" data-stream-title="{{t "my_stream"}}"> + {{ podname }} + </a> + <ul class="nav nav-badges visible-sm"> + <li> + <a href="/notifications" title="{{t "header.notifications"}}" class="notifications-link nav-badge"> + <i class="entypo-bell"></i> + <span class="badge badge-important {{#unless current_user.notifications_count}} hidden {{/unless}}"> + {{current_user.notifications_count}} + </span> + </a> + </li> + <li> + <a href="/conversations" title="{{t "header.conversations"}}" class="conversations-link nav-badge"> + <i class="entypo-mail"></i> + <span class="badge badge-important {{#unless current_user.unread_messages_count}} hidden {{/unless}}"> + {{current_user.unread_messages_count}} + </span> + </a> + </li> + </ul> + </div> - <span class="header-nav"> - <span> - <a href="/stream"> - {{t "my_stream"}} - </a> - </span> + <div class="collapse navbar-collapse" id="navbar-collapse"> + <ul class="nav navbar-nav navbar-left"> + <li><a href="/stream">{{t "my_stream"}}</a></li> + <li><a href="/activity">{{t "my_activity"}}</a></li> + <li class="visible-xs"><a href="/notifications">{{t "header.notifications"}}</a></li> + <li class="visible-xs"><a href="/conversations">{{t "header.conversations"}}</a></li> + <li class="visible-sm visible-xs"><a href="/mobile/toggle">{{t "header.toggle_mobile"}}</a></li> + </ul> - <span> - <a href="/activity"> - {{t "my_activity"}} - </a> - </span> - </span> + <ul class="nav navbar-nav navbar-left nav-badges hidden-sm hidden-xs"> + <li class="dropdown" id="notification-dropdown"> + <a id="notifications-link" href="/notifications" title="{{t "header.notifications"}}" class="notifications-link nav-badge hidden-sm hidden-xs" role="button" data-toggle="dropdown" aria-expanded="false" data-target="#"> + <i class="entypo-bell"></i> + <span class="badge badge-important {{#unless current_user.notifications_count}} hidden {{/unless}}"> + {{current_user.notifications_count}} + </span> + </a> - <div id="nav_badges"> - <div class="badge badge-inverse" id="notification_badge"> - <div class="icons-notifications_grey" > - <a id="notifications-badge" href="/notifications" title="{{t "header.notifications"}}" class="badge_link" > - <div class="badge_count {{#unless current_user.notifications_count}} hidden {{/unless}}"> - {{current_user.notifications_count}} - </div> - </a> - </div> - </div> + <ul class="dropdown-menu" role="menu"> + <div class="header"> + <div class="pull-right"> + <a href="#" id="mark_all_read_link" class="btn btn-default btn-sm {{#unless current_user.notifications_count}}disabled{{/unless}}"> + {{t "header.mark_all_as_read"}} + </a> + </div> + <h4> + {{t "header.recent_notifications"}} + </h4> + </div> + <div class="notifications"> + <div class="ajax-loader"> + <div class="spinner"></div> + </div> + </div> + <div class="view_all"> + <a href="/notifications" id="view_all_notifications"> + {{t "header.view_all"}} + </a> + </div> + </ul> - <div class="badge badge-inverse" id="conversations_badge"> - <div class="icons-mail_grey" > - <a href="/conversations" title="{{t "header.conversations"}}" class="badge_link" > - <div class="badge_count {{#unless current_user.unread_messages_count}} hidden {{/unless}}"> - {{current_user.unread_messages_count}} - </div> - </a> - </div> - </div> + </li> + <li> + <a id="conversations-link" href="/conversations" title="{{t "header.conversations"}}" class="conversations-link nav-badge hidden-sm hidden-xs"> + <i class="entypo-mail"></i> + <span class="badge badge-important {{#unless current_user.unread_messages_count}} hidden {{/unless}}"> + {{current_user.unread_messages_count}} + </span> + </a> + </li> + </ul> - <div id="notification_dropdown"> - <div class="header"> - <div class="pull-right"> - <a href="#" id="mark_all_read_link" class="{{#unless current_user.notifications_count}}disabled{{/unless}}"> - {{t "header.mark_all_as_read"}} - </a> - </div> + <ul class="nav navbar-nav navbar-right"> + <li class="dropdown" id="user_menu"> + <a href="{{urlTo "person" current_user.guid}}" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"> + <span class="user-avatar pull-left"> + {{{personImage current_user "small"}}} + </span> + <span class="user-name">{{current_user.name}}</span> + <span class="caret"></span> + </a> - <h4> - {{t "header.recent_notifications"}} - </h4> - </div> + <ul class="dropdown-menu" role="menu"> + <li><a href="/people/{{current_user.guid}}">{{t "header.profile"}}</a></li> + <li><a href="/contacts">{{t "header.contacts"}}</a></li> + <li><a href="/user/edit">{{t "header.settings"}}</a></li> + <li><a href="/help">{{t "header.help"}}</a></li> + {{#if current_user.admin}} + <li><a href="/admins/dashboard">{{t "header.admin"}}</a></li> + {{else if current_user.moderator}} + <li><a href="/report">{{t "header.moderator"}}</a></li> + {{/if}} + <li><a href="/users/sign_out" data-method="delete">{{t "header.log_out"}}</a></li> + </ul> + </li> + </ul> - <div class="notifications"> - <div class="ajax_loader"> - <img alt="Ajax-loader" src="{{imageUrl "ajax-loader.gif"}}"> - </div> - </div> - <div class="view_all"> - <a href="/notifications" id="view_all_notifications"> - {{t "header.view_all"}} - </a> + <form id="header-search-form" accept-charset="UTF-8" action="/search" class="navbar-form navbar-right" role="search" method="get"> + <div class="form-group"> + <input id="q" name="q" placeholder="{{t "header.search"}}" results="5" type="search" autocomplete="off" class="form-control input-sm"> + </div> + <input name="utf8" type="hidden" value="✓"> + </form> </div> </div> - </div> - - <ul class="dropdown" id="user_menu"> - <li class="user-menu-trigger"> - <div class="user-menu-more-indicator"> - â–¼ - </div> - {{{personImage current_user 'small' 'avatar user-menu-avatar'}}} - <a class="user-name" href="#">{{current_user.name}}</a> - </li> - <li class="user-menu-item"><a href="/people/{{current_user.guid}}">{{t "header.profile"}}</a></li> - <li class="user-menu-item"><a href="/contacts">{{t "header.contacts"}}</a></li> - <li class="user-menu-item"><a href="/user/edit">{{t "header.settings"}}</a></li> - <li class="user-menu-item"><a href="/help">{{t "header.help"}}</a></li> - {{#if current_user.admin}} - <li class="user-menu-item"><a href="/admins/user_search">{{t "header.admin"}}</a></li> - {{else if current_user.moderator}} - <li class="user-menu-item"><a href="/report">{{t "header.moderator"}}</a></li> - {{/if}} - <li class="user-menu-item"><a href="/users/sign_out" data-method="delete">{{t "header.log_out"}}</a></li> - </ul> - - - <div id="global_search"> - <form id="header-search-form" accept-charset="UTF-8" action="/search" class="search_form" method="get"> - <input name="utf8" type="hidden" value="✓"> - <input id="q" name="q" placeholder="{{t "header.search"}}" results="5" type="search" autocomplete="off" class="ac_input"> - </form> - </div> - - <div id="lightbox"> - <div id="lightbox-content"> - <a href="#" id="lightbox-close-link">[x] {{t "header.close"}}</a> - <img id="lightbox-image"> - <div id="lightbox-navigation"> - <div id="lightbox-scrollleft">«</div> - <div id="lightbox-imageset"></div> - <div id="lightbox-scrollright">»</div> </div> </div> </div> - <div id="lightbox-backdrop"></div> - -</div> +</nav> diff --git a/app/assets/templates/help_tpl.jst.hbs b/app/assets/templates/help_tpl.jst.hbs index 45bb0ed7e9e95aa0a58f7712468aa7aa4ca710d6..9a1579b7e0a0912d33aac8e61d5528c3a8399bfb 100644 --- a/app/assets/templates/help_tpl.jst.hbs +++ b/app/assets/templates/help_tpl.jst.hbs @@ -4,8 +4,8 @@ <h2 class="help_header">{{ title_header }}</h2> </div> - <div class="row-fluid"> - <div class="span3"> + <div class="row"> + <div class="col-md-3"> <div id='faq_nav'> <ul> <li> @@ -78,7 +78,7 @@ </div> </div> - <div class="span9 last" id=faq> + <div class="col-md-9 last" id=faq> </div> </div> </div> diff --git a/app/assets/templates/hovercard_tpl.jst.hbs b/app/assets/templates/hovercard_tpl.jst.hbs index 32908a08055f87ccf4cd5be82b83c035fe1e046e..c95ef3e9484367d1b65872a216ea5a3b95d9018e 100644 --- a/app/assets/templates/hovercard_tpl.jst.hbs +++ b/app/assets/templates/hovercard_tpl.jst.hbs @@ -7,8 +7,8 @@ </h4> <div class="handle"></div> <div id="hovercard_dropdown_container"></div> - <div class="hovercard_footer"> - <div class="footer_container"> + <div class="card-footer"> + <div class="footer-container"> <div class="hashtags"></div> </div> </div> diff --git a/app/assets/templates/likes-info_tpl.jst.hbs b/app/assets/templates/likes-info_tpl.jst.hbs index 71206eb5039be971f6006e28a2eef92d91d073b3..ff5346657aa35874ec9a4c491ea3479e4cd213b6 100644 --- a/app/assets/templates/likes-info_tpl.jst.hbs +++ b/app/assets/templates/likes-info_tpl.jst.hbs @@ -1,11 +1,11 @@ {{#if likesCount}} <div class="comment"> <div class="media"> - <i class="entypo heart"></i> + <i class="entypo-heart"></i> <div class="bd"> - {{#unless likes_fetched}} - <a href="#" class="expand_likes grey"> + {{#unless displayAvatars}} + <a href="#" class="expand-likes gray"> {{t "stream.likes" count=likesCount}} </a> diff --git a/app/assets/templates/no_posts_info_tpl.jst.hbs b/app/assets/templates/no_posts_info_tpl.jst.hbs new file mode 100644 index 0000000000000000000000000000000000000000..b617b72f10582e555a0399e47f0c80b1e7d96929 --- /dev/null +++ b/app/assets/templates/no_posts_info_tpl.jst.hbs @@ -0,0 +1,5 @@ +<div class="stream_element"> + <div class="no-posts-info text-center"> + <strong>{{ t "stream.no_posts_yet" }}</strong> + </div> +</div> diff --git a/app/assets/templates/photo-viewer_tpl.jst.hbs b/app/assets/templates/photo-viewer_tpl.jst.hbs deleted file mode 100644 index da353f40a17f0cd5d9931ca48a76bddc567c347b..0000000000000000000000000000000000000000 --- a/app/assets/templates/photo-viewer_tpl.jst.hbs +++ /dev/null @@ -1,7 +0,0 @@ -<div class="photo-set"> - {{#each photos}} - <div class="img-bounding-box"> - <img src="{{sizes.large}}"/> - </div> - {{/each}} -</div> \ No newline at end of file diff --git a/app/assets/templates/photo_tpl.jst.hbs b/app/assets/templates/photo_tpl.jst.hbs index 4f8e8b1bff1b18a97dd8757618c9374a20b5ddbf..683aa3de2ddaf4a3ce99950545fa58b8dbcab1ce 100644 --- a/app/assets/templates/photo_tpl.jst.hbs +++ b/app/assets/templates/photo_tpl.jst.hbs @@ -1,29 +1,37 @@ -<div class="media span4"> - <div class="bd"> - {{#if loggedIn}} - <div class="control-icons"> - {{#if authorIsCurrentUser}} - <a href="#" rel="nofollow" class="delete remove_post" title="{{t "delete"}}"> - <i class="entypo trash"></i> - </a> - {{else}} - <a href="#" rel="nofollow" data-type="post" class="post_report" title="{{t "report.name"}}"> - <i class="entypo warning"></i> - </a> - <a href="#" rel="nofollow" class="block_user" title="{{t "ignore"}}"> - <i class="entypo block"></i> - </a> - <a href="#" rel="nofollow" class="delete hide_post" title="{{t "stream.hide"}}"> - <i class="entypo cross"></i> - </a> - {{/if}} - </div> - {{/if}} - - <div class="thumbnail"> - <a href="#" class="photo-link"> - <img src="{{sizes.large}}" class="photo big_photo" data-small-photo="{{sizes.small}}" data-full-photo="{{sizes.large}}" rel="lightbox"> - </a> +<div class="media"> + {{#if loggedIn}} + <div class="control-icons"> + {{#if authorIsCurrentUser}} + <a href="#" rel="nofollow" class="delete remove_post" title="{{t "delete"}}"> + <i class="entypo-trash"></i> + </a> + {{else}} + <a href="#" rel="nofollow" data-type="Post" class="post_report" title="{{t "report.name"}}"> + <i class="entypo-warning"></i> + </a> + <a href="#" rel="nofollow" class="block_user" title="{{t "ignore"}}"> + <i class="entypo-block"></i> + </a> + <a href="#" rel="nofollow" class="delete hide_post" title="{{t "stream.hide"}}"> + <i class="entypo-cross"></i> + </a> + {{/if}} </div> + {{/if}} + + <a href="{{sizes.large}}" class="thumbnail img-thumbnail photo-link gallery-picture"> + <img src="{{sizes.large}}" class="photo big-photo"> + </a> + <div class="card-footer"> + <div class="footer-container"> + {{#if status_message}} + <a href="{{urlTo "post" status_message.id}}"> + <time class="timeago" data-original-title="{{{localTime created_at}}}" datetime="{{created_at}}" /> + </a> + {{else}} + <time class="timeago" data-original-title="{{{localTime created_at}}}" datetime="{{created_at}}" /> + {{/if}} + </div> + </div> </div> diff --git a/app/assets/templates/pod_table_entry_tpl.jst.hbs b/app/assets/templates/pod_table_entry_tpl.jst.hbs new file mode 100644 index 0000000000000000000000000000000000000000..e43ee6c6f454ffdfe6bab3e71f6344f61c0858cc --- /dev/null +++ b/app/assets/templates/pod_table_entry_tpl.jst.hbs @@ -0,0 +1,41 @@ + +<td class="ssl-status""> + {{#if ssl}} + <i title="{{t 'admin.pods.ssl_enabled'}}" class="entypo-check"> + {{else}} + <i title="{{t 'admin.pods.ssl_disabled'}}" class="entypo-block"> + {{/if}} + </i> +</td> +<td class="pod-title" title="{{host}}">{{host}}</td> +<td class="added"> + <small><time datetime="{{created_at}}" title="{{localTime created_at}}" /></small> +</td> +<td> + {{#if has_no_errors}} + <i title="{{status_text}}" class="glyphicon glyphicon-ok"></i> + {{else}} + {{status_text}} + {{/if}} + {{#unless is_unchecked}} + <br><small>{{t 'admin.pods.last_check'}} <time datetime="{{checked_at}}" title="{{localTime checked_at}}" /></small> + {{/unless}} + {{#if offline}} + | <small>{{t 'admin.pods.offline_since'}} <time datetime="{{offline_since}}" title="{{localTime offline_since}}" /></small> + {{/if}} + {{#if is_unchecked}}<br><small class="text-muted">{{t 'admin.pods.no_info'}}</small>{{/if}} + <pre class="details" style="display: none;"> + {{#unless is_unchecked}} + {{t 'admin.pods.server_software'}} {{#if software}}{{software}}{{else}}{{t 'admin.pods.unknown'}}{{/if}} + <br>{{t 'admin.pods.response_time'}} {{response_time_fmt}} + {{#if has_errors}}<br>{{error}}{{/if}} + {{/unless}} + </pre> +</td> +<td class="actions"> + {{#unless is_unchecked}} + <a class="more" href="#"><i title="{{t 'admin.pods.more_info'}}" class="entypo-circled-help"></i></a> + {{/unless}} + <a class="recheck" href="{{urlTo 'adminPodRecheck' id}}"><i title="{{t 'admin.pods.check'}}" class="entypo-cycle"></i></a> + <a href="{{pod_url}}" target="_blank"><i title="{{t 'admin.pods.follow_link'}}" class="entypo-forward"></i></a> +</td> diff --git a/app/assets/templates/pod_table_tpl.jst.hbs b/app/assets/templates/pod_table_tpl.jst.hbs new file mode 100644 index 0000000000000000000000000000000000000000..a37fea525adff5abc8534bd0de2b5e0ab263c474 --- /dev/null +++ b/app/assets/templates/pod_table_tpl.jst.hbs @@ -0,0 +1,14 @@ + +<table class="table"> + <thead> + <tr> + <th><i title="{{t 'admin.pods.ssl'}}" class="glyphicon glyphicon-lock"></i></th> + <th>{{t 'admin.pods.pod'}}</th> + <th class="added">{{t 'admin.pods.added'}}</th> + <th>{{t 'admin.pods.status'}}</th> + <th><i title="{{t 'admin.pods.actions'}}" class="entypo-tools pull-right"></i></th> + </tr> + </thead> + <tbody> + </tbody> +</table> diff --git a/app/assets/templates/poll_creator_tpl.jst.hbs b/app/assets/templates/poll_creator_tpl.jst.hbs index ea5ce6207f458599e739fdd76cc02ab439315790..b95231a1405d0d7c3f1af183d22557cd43000690 100644 --- a/app/assets/templates/poll_creator_tpl.jst.hbs +++ b/app/assets/templates/poll_creator_tpl.jst.hbs @@ -1,21 +1,21 @@ -<div class="poll-question control-group"> - <input class="input-block-level" placeholder="{{t 'publisher.question' }}" type="text" name="poll_question"> +<div class="poll-question form-group"> + <input class="input-block-level form-control" placeholder="{{t 'publisher.question' }}" type="text" name="poll_question"> </div> -<div class="poll-answers"> - <div class="poll-answer row-fluid"> - <div class="span11"> - <input type="text" class="input-block-level" name="poll_answers[]" placeholder="{{t 'publisher.option' }}"> +<div class="poll-answers form-group clearfix row"> + <div class="poll-answer form-group clearfix"> + <div class="col-md-11"> + <input type="text" class="input-block-level form-control" name="poll_answers[]" placeholder="{{t 'publisher.option' }}"> </div> - <div class="span1"> - <i class="remove-answer entypo cross"></i> + <div class="col-md-1"> + <i class="remove-answer entypo-cross"></i> </div> </div> - <div class="poll-answer row-fluid"> - <div class="span11"> - <input type="text" class="input-block-level" name="poll_answers[]" placeholder="{{t 'publisher.option' }}"> + <div class="poll-answer form-group clearfix"> + <div class="col-md-11"> + <input type="text" class="input-block-level form-control" name="poll_answers[]" placeholder="{{t 'publisher.option' }}"> </div> - <div class="span1"> - <i class="remove-answer entypo cross"></i> + <div class="col-md-1"> + <i class="remove-answer entypo-cross"></i> </div> </div> </div> diff --git a/app/assets/templates/poll_tpl.jst.hbs b/app/assets/templates/poll_tpl.jst.hbs index 4b73b1a86668dc55357658f1e9e78e320e60760c..a1a9be576fb0115dd2b47663de203f6679645109 100644 --- a/app/assets/templates/poll_tpl.jst.hbs +++ b/app/assets/templates/poll_tpl.jst.hbs @@ -1,41 +1,39 @@ {{#if poll}} <div class="poll_form"> - <div class="row-fluid poll_head"> + <div class="poll_head"> <strong>{{poll.question}}</strong> <div class="poll_statistic pull-right"> {{t "poll.count" count=poll.participation_count}} </div> </div> - <div class="row-fluid poll_content"> + <div class="poll-content"> {{#if show_form}} <form action="/posts/{{poll.post_id}}/poll_participations" method="POST"> - {{#poll.poll_answers}} - <label class="radio result-row"> - <input type="radio" name="vote" value="{{id}}"/> - {{answer}} - <span class="percentage pull-right" style="display: none;"></span> - <div class="poll_progress_bar_wrapper progress" style="display: none"> - <div class="poll_progress_bar bar" data-answerid="{{id}}"> - </div> - </div> - </label> - {{/poll.poll_answers}} - <div class="toggle_result_wrapper"> - <a class="toggle_result" href="#">{{t "poll.show_result"}}</a> + {{/if}} + {{#poll.poll_answers}} + <div class="result-row"> + <input type="radio" name="vote" value="{{id}}"/> + <label>{{answer}}</label> + <div class="poll-result pull-right"> + <span class="percentage"></span> + ({{t "poll.answer_count" count=vote_count}}) </div> - <input type="submit" class="button submit pull-rigth btn" style="float:right;" value="{{t "poll.vote"}}"/> - </form> - {{else}} - {{#poll.poll_answers}} - <div class="result-row"> - {{answer}} - <span class="percentage pull-right"></span> - <div class="poll_progress_bar_wrapper progress"> - <div class="poll_progress_bar bar" data-answerid="{{id}}"> - </div> - </div> + <div class="poll_progress_bar_wrapper progress"> + <div class="poll_progress_bar bar" data-answerid="{{id}}" style="height: 100%"></div> </div> - {{/poll.poll_answers}} + </div> + {{/poll.poll_answers}} + {{#if show_form}} + <div class="toggle-result-wrapper"> + {{#if preview}} + <span>{{t "poll.show_result"}}</span> + {{else}} + <a class="toggle_result" href="#">{{t "poll.show_result"}}</a> + {{/if}} + </div> + <input type="submit" class="submit pull-right btn btn-default" value="{{t "poll.vote"}}"/> + <div class="clearfix"></div> + </form> {{/if}} {{#if is_reshare }} @@ -43,7 +41,6 @@ {{{t "poll.go_to_original_post" original_post_link=original_post_link}}} </div> {{/if}} - </div> </div> {{/if}} diff --git a/app/assets/templates/profile_header_tpl.jst.hbs b/app/assets/templates/profile_header_tpl.jst.hbs index c1d9487b100cbb793b92579c7fc7a538a62dc9fd..4885810e5d4be838e2499ec6ad0598abfd5ff707 100644 --- a/app/assets/templates/profile_header_tpl.jst.hbs +++ b/app/assets/templates/profile_header_tpl.jst.hbs @@ -1,63 +1,66 @@ -{{#if loggedIn}} - <div class="pull-right"> - {{#if is_own_profile}} - {{!-- can't block myself, so don't check it here --}} - <a href="{{urlTo 'editProfile'}}" id="edit_profile" class="btn btn-primary creation">{{t 'people.edit_my_profile'}}</a> - {{else}} {{#if is_blocked}} - <a href="#" id="unblock_user_button" class="btn btn-danger">{{t 'people.stop_ignoring'}}</a> - {{else}} - <div class="placeholder aspect_membership_dropdown"></div> - {{/if}}{{/if}} - </div> -{{/if}} - -<div id="author_info"> - <h2> - <span id="name">{{name}}</span> - <span id="diaspora_handle">{{diaspora_id}}</span> - {{#if show_profile_btns}} - {{{sharingMessage this}}} - {{/if}} - </h2> +<div id="author_info" class="row"> + <div class="col-sm-10"> + <h2> + <span id="name">{{name}}</span> + <span id="diaspora_handle">{{diaspora_id}}</span> + {{#if show_profile_btns}} + {{{sharingMessage this}}} + {{/if}} + </h2> - {{#if has_tags}} - <div class="description"> - <i class="entypo tag"></i> - {{fmtTags profile.tags}} - </div> - {{else}} - {{#if is_own_profile}} + {{#if has_tags}} <div class="description"> - <i>{{t 'profile.you_have_no_tags'}}</i> - <span class="add_tags"> - <a href="{{urlTo 'editProfile'}}">{{t 'profile.add_some'}}</a> - </span> + <i class="entypo-tag"></i> + {{fmtTags profile.tags}} + </div> + {{else}} + {{#if is_own_profile}} + <div class="description"> + <i>{{t 'profile.you_have_no_tags'}}</i> + <span class="add_tags"> + <a href="{{urlTo 'editProfile'}}">{{t 'profile.add_some'}}</a> + </span> + </div> + {{/if}} + {{/if}} + </div> + <div class="clearfix col-sm-2"> + {{#if loggedIn}} + <div class="pull-right"> + {{#if is_own_profile}} + {{!-- can't block myself, so don't check it here --}} + <a href="{{urlTo 'editProfile'}}" id="edit_profile" class="btn btn-primary">{{t 'people.edit_my_profile'}}</a> + {{else}} {{#if is_blocked}} + <a href="#" id="unblock_user_button" class="btn btn-danger">{{t 'people.stop_ignoring'}}</a> + {{else}} + <div class="placeholder aspect_membership_dropdown"></div> + {{/if}}{{/if}} </div> {{/if}} - {{/if}} + </div> </div> -<div id="profile_horizontal_bar"> +<div id="profile-horizontal-bar"> {{#if show_profile_btns}} <div id="profile_buttons" class="pull-right"> {{#if is_receiving}} {{!-- create status message with mention --}} <span class="profile_button"> - <span id="mention_button" class="profile-header-icon" title="{{t 'people.mention'}}" data-placement="bottom" data-toggle="modal" data-target="#mentionModal">@</span> + <span id="mention_button" class="profile-header-icon" title="{{t 'people.mention'}}" data-placement="bottom" data-toggle="modal">@</span> </span> {{/if}} {{#if is_mutual}} {{!-- create private conversation with person --}} <span class="profile_button"> - <i id="message_button" class="entypo profile-header-icon mail" title="{{t 'people.message'}}" data-placement="bottom" data-toggle="modal" data-target="#conversationModal"></i> + <i id="message_button" class="entypo-mail profile-header-icon" title="{{t 'people.message'}}" data-placement="bottom" data-toggle="modal"></i> </span> {{/if}} {{#unless is_blocked}} {{!-- ignore the person --}} <a href="#" class="profile_button" rel="nofollow"> - <i id="block_user_button" class="entypo profile-header-icon block block_user" title="{{t 'ignore'}}" data-placement="bottom"></i> + <i id="block_user_button" class="entypo-block profile-header-icon block_user" title="{{t 'ignore'}}" data-placement="bottom"></i> </a> {{/unless}} </div> @@ -66,16 +69,16 @@ <ul id="profile_nav"> <li {{#isCurrentProfilePage guid diaspora_id}} class="active" {{/isCurrentProfilePage}}> <a href="{{urlTo 'person' guid}}" id="posts_link"> - <i class="entypo docs"></i> + <i class="entypo-docs"></i> {{t 'profile.posts'}} </a> </li> {{#if show_photos}} <li {{#isCurrentPage 'personPhotos' guid}} class="active" {{/isCurrentPage}}> <a href="{{urlTo 'personPhotos' guid}}" id="photos_link"> - <i class="entypo picture"></i> + <i class="entypo-picture"></i> {{t 'profile.photos'}} - <div class="badge badge-default">{{photos.count}}</div> + <div class="badge badge-default">{{photos}}</div> </a> </li> {{/if}} @@ -83,15 +86,15 @@ <li {{#isCurrentPage 'personContacts' guid}} class="active" {{/isCurrentPage}}> {{#if is_own_profile}} <a href="{{urlTo 'contacts'}}" id="contacts_link"> - <i class="entypo users"></i> + <i class="entypo-users"></i> {{t 'profile.contacts'}} - <div class="badge badge-default">{{contacts.count}}</div> + <div class="badge badge-default">{{contacts}}</div> </a> {{else}} <a href="{{urlTo 'personContacts' guid}}" id="contacts_link"> - <i class="entypo users"></i> + <i class="entypo-users"></i> {{t 'profile.contacts'}} - <div class="badge badge-default">{{contacts.count}}</div> + <div class="badge badge-default">{{contacts}}</div> </a> {{/if}} </li> diff --git a/app/assets/templates/profile_sidebar_tpl.jst.hbs b/app/assets/templates/profile_sidebar_tpl.jst.hbs index 69cc76d835d96aea89b839a45b8e8f7c17098566..f7345c899f2dc3975858922aeee1120a3423f250 100644 --- a/app/assets/templates/profile_sidebar_tpl.jst.hbs +++ b/app/assets/templates/profile_sidebar_tpl.jst.hbs @@ -11,7 +11,7 @@ {{#if bio}} <li> <h4>{{t 'profile.bio'}}</h4> - <div class="{{txtDirClass bio}}">{{fmtText bio}}</div> + <div class="{{txtDirClass bio}} markdown-content">{{fmtText bio}}</div> </li> {{/if}} {{#if location}} diff --git a/app/assets/templates/reshare_tpl.jst.hbs b/app/assets/templates/reshare_tpl.jst.hbs index b1334fa0ad42755c8611d3e8c79f790f40042996..048b789f1d811f00580ad8c26eb61a638695f0ce 100644 --- a/app/assets/templates/reshare_tpl.jst.hbs +++ b/app/assets/templates/reshare_tpl.jst.hbs @@ -12,16 +12,11 @@ {{name}} {{/linkToAuthor}} - <span class="details grey"> + <span class="details gray"> - <a href="/posts/{{id}}"> - <time class="timeago" datetime="{{created_at}}"/> + <time class="timeago" data-original-title="{{{localTime created_at}}}" datetime="{{created_at}}" /> </a> - - {{#if interactions.reshares_count}} - - - {{t "stream.reshares" count=interactions.reshares_count}} - {{/if}} </span> </div> {{/with}} diff --git a/app/assets/templates/reshares-info_tpl.jst.hbs b/app/assets/templates/reshares-info_tpl.jst.hbs new file mode 100644 index 0000000000000000000000000000000000000000..fadfcb73421fa0cb5f1537e2fe546fdd11fe46c5 --- /dev/null +++ b/app/assets/templates/reshares-info_tpl.jst.hbs @@ -0,0 +1,23 @@ +{{#if resharesCount}} + <div class="comment"> + <div class="media"> + <i class="entypo-reshare"></i> + + <div class="bd"> + {{#unless displayAvatars}} + <a href="#" class="expand-reshares gray"> + {{t "stream.reshares" count=resharesCount}} + </a> + + {{else}} + + {{#each reshares}} + {{#linkToAuthor author}} + {{{personImage this 'small' 'micro'}}} + {{/linkToAuthor}} + {{/each}} + {{/unless}} + </div> + </div> + </div> +{{/if}} diff --git a/app/assets/templates/search_suggestion_tpl.jst.hbs b/app/assets/templates/search_suggestion_tpl.jst.hbs new file mode 100644 index 0000000000000000000000000000000000000000..a2c734cab5dd3304d0fdfbaaf717ce029af4451a --- /dev/null +++ b/app/assets/templates/search_suggestion_tpl.jst.hbs @@ -0,0 +1,13 @@ +{{#if person}} + <div class="search-suggestion-person"> + {{#if avatar}} + <img src="{{ avatar }}" class="avatar pull-left"> + {{/if}} + <div class="name">{{ name }}</div> + <div class="diaspora-id">{{ handle }}</div> + </div> +{{else}}{{#if hashtag}} + <div class="search-suggestion-hashtag"> + <div class="name">{{ name }}</div> + </div> +{{/if}}{{/if}} diff --git a/app/assets/templates/single-post-viewer/single-post-actions_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-actions_tpl.jst.hbs index a183acba3b2bea08b1f680690db2c28e896aa2e9..9173a1bbacb0b695617bde29c448d05bdd5307f7 100644 --- a/app/assets/templates/single-post-viewer/single-post-actions_tpl.jst.hbs +++ b/app/assets/templates/single-post-viewer/single-post-actions_tpl.jst.hbs @@ -1,25 +1,25 @@ <div class='pull-right'> {{#if loggedIn}} - <a href="#" class="like" title="{{#if userLike}} {{t "viewer.unlike"}} {{else}} {{t "viewer.like"}} {{/if}}"> + <a href="#" class="like" title="{{#if userLike}} {{t "stream.unlike"}} {{else}} {{t "stream.like"}} {{/if}}"> {{#if userLike}} - <i class="entypo heart red large"></i> + <i class="entypo-heart red large"></i> {{else}} - <i class="entypo heart gray large"></i> + <i class="entypo-heart gray large"></i> {{/if}} </a> - - <a href="#" class="focus-comment" title="{{t "viewer.comment"}}"> - <i class="entypo comment gray large"></i> + + <a href="#" class="focus-comment" title="{{t "stream.comment"}}"> + <i class="entypo-comment gray large"></i> </a> - + {{#if userCanReshare}} - <a href="#" class="reshare" title="{{t "viewer.reshare"}}"> - <i class="entypo retweet gray large"></i> + <a href="#" class="reshare" title="{{t "stream.reshare"}}"> + <i class="entypo-reshare gray large"></i> </a> {{else}} {{#if userReshare}} <a href="#" class="reshare-viewonly" title="{{t "viewer.reshared"}}"> - <i class="entypo retweet blue large"></i> + <i class="entypo-reshare blue large"></i> </a> {{/if}} {{/if}} diff --git a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs index 4bffd46ff15102230b63dbca9aa96d50a72857dd..75d051777b0360f3033b133e19f9cd642a17cfc9 100644 --- a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs +++ b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs @@ -1,100 +1,111 @@ -<div id='head' class='row-fluid'> - <div class='row-fluid'> - <div id='post-info' class='span8'> - <div class="img pull-left"> - {{#if root}} - {{#linkToAuthor root.author}} - {{{personImage this 'medium'}}} - {{/linkToAuthor}} - {{else}} - {{#linkToAuthor author}} - {{{personImage this 'medium'}}} - {{/linkToAuthor}} - {{/if}} - </div> - - <div class="bd"> - <span class='author'> +<div id="head" class="head clearfix"> + <div class="col-md-12"> + <div class="row"> + <div id="post-info" class="col-md-8"> + <div class="img pull-left"> {{#if root}} {{#linkToAuthor root.author}} - {{name}} + {{{personImage this "medium"}}} {{/linkToAuthor}} {{else}} {{#linkToAuthor author}} - {{name}} + {{{personImage this "medium"}}} {{/linkToAuthor}} {{/if}} - </span> + </div> - <div class='info'> - {{#if public}} - <span class='post_scope' title="{{t "stream.public"}}"> - <i class="entypo globe small"></i> - </span> - {{else}} - <span class='post_scope' title="{{t "stream.limited"}}"> - <i class="entypo lock small"></i> - </span> - {{/if}} - <span class="post-time"> + <div class="bd"> + <span class="author"> {{#if root}} - <a href="/posts/{{root.id}}"> - <time datetime="{{root.created_at}}" title="{{localTime root.created_at}}" /> - </a> + {{#linkToAuthor root.author}} + {{name}} + {{/linkToAuthor}} {{else}} - <a href="/posts/{{id}}"> - <time datetime="{{created_at}}" title="{{localTime created_at}}" /> - </a> + {{#linkToAuthor author}} + {{name}} + {{/linkToAuthor}} {{/if}} </span> - {{#if root}} - {{#if root.provider_display_name}} - {{t "stream.via" provider=root.provider_display_name}} + + <div class="info"> + {{#if public}} + <span class="post_scope" title="{{t "stream.public"}}"> + <i class="entypo-globe small"></i> + </span> + {{else}} + <span class="post_scope" title="{{t "stream.limited"}}"> + <i class="entypo-lock small"></i> + </span> {{/if}} - {{else}} - {{#if provider_display_name}} - {{t "stream.via" provider=provider_display_name}} + <span class="post-time"> + {{#if root}} + <a href="/posts/{{root.id}}"> + <time datetime="{{root.created_at}}" title="{{localTime root.created_at}}" /> + </a> + {{else}} + <a href="/posts/{{id}}"> + <time datetime="{{created_at}}" title="{{localTime created_at}}" /> + </a> + {{/if}} + </span> + {{#if root}} + {{#if root.provider_display_name}} + {{t "stream.via" provider=root.provider_display_name}} + {{/if}} + {{else}} + {{#if provider_display_name}} + {{t "stream.via" provider=provider_display_name}} + {{/if}} {{/if}} - {{/if}} - <div class='status-message-location' /> + </div> + {{#unless root}} + <div id="single-post-moderation" /> + {{/unless}} </div> - {{#unless root}} - <div id='single-post-moderation' /> - {{/unless}} </div> + {{#unless root}} + <div id="single-post-actions" class="col-md-4" /> + {{/unless}} </div> - {{#unless root}} - <div id='single-post-actions' class='span4' /> - {{/unless}} - </div> - {{#if root}} - <div class='row-fluid reshare'> - <div class='span8' id='reshare-info'> - <i class='entypo retweet small pull-left'></i> - <div class="img pull-left"> - {{#linkToAuthor author}} - {{{personImage this 'small'}}} - {{/linkToAuthor}} - </div> - <span class="author"> - {{#linkToAuthor author}} - {{name}} - {{/linkToAuthor}} - </span> - <div class="post-context"> - <span class="post-time"> - <a href="/posts/{{id}}"> - <time datetime="{{created_at}}" title="{{localTime created_at}}" /> - </a> + {{#if location.lat}} + <div class="row"> + <div class='near-from'> + {{t "publisher.near_from" location=location.address}} + </div> + <div class="mapContainer small-map"></div> + </div> + {{/if}} + {{#if root}} + <div class="row reshare"> + <div class="col-md-8" id="reshare-info"> + <i class="entypo-reshare small pull-left"></i> + <div class="img pull-left"> + {{#linkToAuthor author}} + {{{personImage this "small"}}} + {{/linkToAuthor}} + </div> + <span class="author"> + {{#linkToAuthor author}} + {{name}} + {{/linkToAuthor}} </span> - <span id='single-post-moderation' /> + <div class="post-context"> + <span class="post-time"> + <a href="/posts/{{id}}"> + <time datetime="{{created_at}}" title="{{localTime created_at}}" /> + </a> + </span> + <span id="single-post-moderation" /> + </div> </div> + <div id="single-post-actions" class="col-md-4" /> </div> - <div id='single-post-actions' class='span4' /> - </div> - {{/if}} + {{/if}} + </div> </div> -<div id='body' class='row-fluid'> - <div id='real-post-content' class='post-content span12'> +<div class="row"> + <div id="body" class="body clearfix"> + <div id="real-post-content" class="post-content col-md-12"> + </div> </div> </div> diff --git a/app/assets/templates/single-post-viewer/single-post-interactions_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-interactions_tpl.jst.hbs index 2488ea0de6cc9f371316f2b20689d1a44fc0da24..a8acd4b38399ccafb4b8a09a028a5ed26363c54a 100644 --- a/app/assets/templates/single-post-viewer/single-post-interactions_tpl.jst.hbs +++ b/app/assets/templates/single-post-viewer/single-post-interactions_tpl.jst.hbs @@ -1,10 +1,10 @@ {{#if resharesCount}} - <div id='reshares'> + <div id="reshares" class="clearfix"> <span class="count"> - <i class='entypo retweet middle gray'></i> + <i class="entypo-reshare middle gray"></i> <span>{{resharesCount}}</span> </span> - <span> + <span class="interaction-avatars"> {{#each reshares}} {{#linkToAuthor author}} {{{personImage this 'small' 'micro'}}} @@ -14,12 +14,12 @@ </div> {{/if}} {{#if likesCount}} - <div id='likes'> + <div id="likes" class="clearfix"> <span class="count"> - <i class='entypo heart middle gray'></i> + <i class="entypo-heart middle gray"></i> <span>{{likesCount}}</span> </span> - <span> + <span class="interaction-avatars"> {{#each likes}} {{#linkToAuthor author}} {{{personImage this 'small' 'micro'}}} @@ -29,14 +29,14 @@ </div> {{/if}} {{#if commentsCount}} - <div id='comments-meta'> - <span class='count'> - <i class='entypo comment middle gray'></i> + <div id="comments-meta" class="clearfix"> + <span class="count"> + <i class="entypo-comment middle gray"></i> <span>{{commentsCount}}</span> </span> </div> {{else}} - <div class='no_comments'> + <div class="no-comments"> <h4>{{t "comments.no_comments" }}</h4> </div> {{/if}} diff --git a/app/assets/templates/single-post-viewer/single-post-moderation_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-moderation_tpl.jst.hbs index fa96417b2df7171b9c42e6b3a7c02b28d3d15068..d81f6a14b61a33607e046c1ad26585bbc394e742 100644 --- a/app/assets/templates/single-post-viewer/single-post-moderation_tpl.jst.hbs +++ b/app/assets/templates/single-post-viewer/single-post-moderation_tpl.jst.hbs @@ -2,26 +2,26 @@ {{#if loggedIn}} {{#if authorIsCurrentUser}} <a href="#" class="remove_post" title="{{t "delete"}}"> - <i class="entypo trash"></i> + <i class="entypo-trash"></i> </a> {{else}} - <a href="#" data-type="post" class="post_report" title="{{t "report.name"}}"> - <i class="entypo warning"></i> + <a href="#" data-type="Post" class="post_report" title="{{t "report.name"}}"> + <i class="entypo-warning"></i> </a> <a href="#" data-type="post" class="block_user" title="{{t "ignore"}}"> - <i class="entypo block"></i> + <i class="entypo-block"></i> </a> {{#if participation}} <a href="#" data-type="nofollow" class="destroy_participation" title="{{t "stream.disable_post_notifications"}}"> - <i class="entypo bell"></i> + <i class="entypo-bell"></i> </a> {{else}} <a href="#" data-type="nofollow" class="create_participation" title="{{t "stream.enable_post_notifications"}}"> - <i class="entypo bell"></i> + <i class="entypo-bell"></i> </a> {{/if}} <a href="#" data-type="post" class="hide_post" title="{{t "stream.hide"}}"> - <i class="entypo cross"></i> + <i class="entypo-cross"></i> </a> {{/if}} {{/if}} diff --git a/app/assets/templates/single-post-viewer_tpl.jst.hbs b/app/assets/templates/single-post-viewer_tpl.jst.hbs index 322d96367f69487fbbcf887245b346356459c475..3060591956c442595e0ecb9541c2bc8b3ea74914 100644 --- a/app/assets/templates/single-post-viewer_tpl.jst.hbs +++ b/app/assets/templates/single-post-viewer_tpl.jst.hbs @@ -1,8 +1,8 @@ -<div id='single-post-container' class='container-fluid'> - <div class='row-fluid'> - <div id='single-post-content' class='span6'> +<div id="single-post-container"> + <div class='row'> + <div id='single-post-content' class='col-md-6 single-post-content'> </div> - <div id='single-post-interactions' class='span6'> + <div id='single-post-interactions' class='col-md-6 single-post-interactions'> </div> </div> </div> diff --git a/app/assets/templates/status-message-location_tpl.jst.hbs b/app/assets/templates/status-message-location_tpl.jst.hbs index c6c7ea7ecf86eb2050cf12a97ae3f40dc6be78f8..1cb8bda65288bf5af43bf474c22ca2f7cc5965b0 100644 --- a/app/assets/templates/status-message-location_tpl.jst.hbs +++ b/app/assets/templates/status-message-location_tpl.jst.hbs @@ -1,5 +1,8 @@ -{{#if location}} +{{#if location.address}} <div class='near-from'> - {{ t "publisher.near_from" location=location}} + {{t "publisher.near_from" location=location.address}} + </div> + <div> + <div class="mapContainer empty"></div> </div> {{/if}} diff --git a/app/assets/templates/status-message_tpl.jst.hbs b/app/assets/templates/status-message_tpl.jst.hbs index 31a0982773616fd71894e9e3ed51fc721e095b39..14ee8889aa7c91b5bfbe6751887a63e1ccea980b 100644 --- a/app/assets/templates/status-message_tpl.jst.hbs +++ b/app/assets/templates/status-message_tpl.jst.hbs @@ -24,15 +24,15 @@ {{#if largePhoto}} <div class="photo_attachments nsfw-hidden"> - <a href="#" class="stream-photo-link"> - {{#with largePhoto}} - <img src="{{sizes.large}}" class="stream-photo big_stream_photo" data-small-photo="{{sizes.small}}" data-full-photo="{{sizes.large}}" rel="lightbox"> - {{/with}} - </a> + {{#with largePhoto}} + <a href="{{sizes.large}}" class="stream-photo-link gallery-picture"> + <img src="{{sizes.large}}" class="stream-photo big_stream_photo"> + </a> + {{/with}} {{#each smallPhotos}} - <a href="#" class="stream-photo-link"> - <img src="{{sizes.small}}" class="stream-photo thumb_small" data-small-photo="{{sizes.small}}" data-full-photo="{{sizes.large}}" rel="lightbox"> + <a href="{{sizes.large}}" class="stream-photo-link gallery-picture"> + <img src="{{sizes.small}}" class="stream-photo thumb_small"> </a> {{/each}} </div> diff --git a/app/assets/templates/stream-element_tpl.jst.hbs b/app/assets/templates/stream-element_tpl.jst.hbs index 3cd2e02c7b6b87e69399b88bc184ade1007b8612..2520c1e677147b6b7539b939d1023757f6d485bd 100644 --- a/app/assets/templates/stream-element_tpl.jst.hbs +++ b/app/assets/templates/stream-element_tpl.jst.hbs @@ -8,30 +8,32 @@ <div class="bd"> {{#if loggedIn}} <div class="control-icons"> - {{#if authorIsCurrentUser}} - <a href="#" rel="nofollow" class="delete remove_post" title="{{t "delete"}}"> - <i class="entypo trash"></i> - </a> - {{else}} - <a href="#" rel="nofollow" data-type="post" class="post_report" title="{{t "report.name"}}"> - <i class="entypo warning"></i> - </a> - <a href="#" rel="nofollow" class="block_user" title="{{t "ignore"}}"> - <i class="entypo block"></i> - </a> - {{#if participation}} - <a href="#" rel="nofollow" class="destroy_participation" title="{{t "stream.disable_post_notifications"}}"> - <i class="entypo bell"></i> + {{#unless preview}} + {{#if authorIsCurrentUser}} + <a href="#" rel="nofollow" class="delete remove_post" title="{{t "delete"}}"> + <i class="entypo-trash"></i> </a> {{else}} - <a href="#" rel="nofollow" class="create_participation" title="{{t "stream.enable_post_notifications"}}"> - <i class="entypo bell"></i> + <a href="#" rel="nofollow" data-type="Post" class="post_report" title="{{t "report.name"}}"> + <i class="entypo-warning"></i> + </a> + <a href="#" rel="nofollow" class="block_user" title="{{t "ignore"}}"> + <i class="entypo-block"></i> + </a> + {{#if participation}} + <a href="#" rel="nofollow" class="destroy_participation" title="{{t "stream.disable_post_notifications"}}"> + <i class="entypo-bell"></i> + </a> + {{else}} + <a href="#" rel="nofollow" class="create_participation" title="{{t "stream.enable_post_notifications"}}"> + <i class="entypo-bell"></i> + </a> + {{/if}} + <a href="#" rel="nofollow" class="delete hide_post" title="{{t "stream.hide"}}"> + <i class="entypo-cross"></i> </a> {{/if}} - <a href="#" rel="nofollow" class="delete hide_post" title="{{t "stream.hide"}}"> - <i class="entypo cross"></i> - </a> - {{/if}} + {{/unless}} </div> {{/if}} @@ -40,15 +42,18 @@ {{name}} {{/linkToAuthor}} - <span class="details grey"> + <span class="details gray"> - - <a href="/posts/{{id}}"> + {{#if preview}} <time class="timeago" data-original-title="{{{localTime created_at}}}" datetime="{{created_at}}" /> - </a> + {{else}} + <a href="/posts/{{id}}"> + <time class="timeago" data-original-title="{{{localTime created_at}}}" datetime="{{created_at}}" /> + </a> - {{#if interactions.reshares_count}} - - - {{t "stream.reshares" count=interactions.reshares_count}} + <a href="/posts/{{id}}" class="permalink" title="{{t "stream.permalink"}}"> + <i class="entypo-link"></i> + </a> {{/if}} </span> </div> @@ -58,6 +63,7 @@ <div class="feedback nsfw-hidden"> </div> <div class="likes nsfw-hidden"> </div> + <div class="reshares nsfw-hidden"> </div> <div class="comments nsfw-hidden"> </div> </div> </div> diff --git a/app/assets/templates/stream-faces_tpl.jst.hbs b/app/assets/templates/stream-faces_tpl.jst.hbs deleted file mode 100644 index 2e9898905ca1c1776d789132d91c7086439cda88..0000000000000000000000000000000000000000 --- a/app/assets/templates/stream-faces_tpl.jst.hbs +++ /dev/null @@ -1,5 +0,0 @@ -{{#people}} - {{#linkToAuthor this}} - {{{personImage this "small"}}} - {{/linkToAuthor}} -{{/people}} diff --git a/app/assets/templates/tag_following_action_tpl.jst.hbs b/app/assets/templates/tag_following_action_tpl.jst.hbs index 2d31000f41bc29d301e0f53672fae1ef0f4ad2f6..e3c35496b461553b186784033f2d817595150366 100644 --- a/app/assets/templates/tag_following_action_tpl.jst.hbs +++ b/app/assets/templates/tag_following_action_tpl.jst.hbs @@ -1,8 +1,8 @@ <div class="pull-right tag-following-action"> <form accept-charset="UTF-8" action="/tag_followings" method="post"> - <input type="submit" class="btn + <input type="submit" class="btn {{#if tag_is_followed }} - green followed + btn-success followed {{else}} btn-default {{/if}} diff --git a/app/assets/templates/tag_following_list_tpl.jst.hbs b/app/assets/templates/tag_following_list_tpl.jst.hbs index d4ba359fba017e3e947d12f04bc3b4321f4696ad..3d8edbcf43f5a5071945c9c28e236a267a999188 100644 --- a/app/assets/templates/tag_following_list_tpl.jst.hbs +++ b/app/assets/templates/tag_following_list_tpl.jst.hbs @@ -1,5 +1,5 @@ <li> <form id="new_tag_following" accept-charset="UTF-8" action="/tag_followings" method="post"> - <input class="tag_input" type="text" name="name" placeholder="{{t "stream.followed_tag.add_a_tag"}}" /> + <input class="tag_input form-control" type="text" name="name" placeholder="{{t "stream.followed_tag.add_a_tag"}}" /> </form> </li> diff --git a/app/assets/templates/tag_following_tpl.jst.hbs b/app/assets/templates/tag_following_tpl.jst.hbs index 61b564c9d178f24a8d08829c0728c8e495ee11b2..5733c7273c940a9bb3fc7cb4df5331485329434b 100644 --- a/app/assets/templates/tag_following_tpl.jst.hbs +++ b/app/assets/templates/tag_following_tpl.jst.hbs @@ -1,4 +1,6 @@ -<a href="#" id="unfollow_{{name}}" rel="nofollow" class="action delete_tag_following pull-right" title="{{t "delete"}}">×</a> <a href="/tags/{{name}}" class="selectable"> #{{ name }} </a> +<a href="#" id="unfollow_{{name}}" rel="nofollow" class="action delete-tag-following pull-right" title="{{t "delete"}}"> + <i class="entypo-cross"></i> +</a> diff --git a/app/controllers/admin/pods_controller.rb b/app/controllers/admin/pods_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..1b4d2bf2f0c513688f16c5bfa72f55171f4e92fc --- /dev/null +++ b/app/controllers/admin/pods_controller.rb @@ -0,0 +1,32 @@ + +module Admin + class PodsController < AdminController + respond_to :html, :json + + def index + pods_json = PodPresenter.as_collection(Pod.all) + + respond_with do |format| + format.html do + gon.preloads[:pods] = pods_json + gon.unchecked_count = Pod.unchecked.count + gon.version_failed_count = Pod.version_failed.count + gon.error_count = Pod.check_failed.count + + render "admins/pods" + end + format.json { render json: pods_json } + end + end + + def recheck + pod = Pod.find(params[:pod_id]) + pod.test_connection! + + respond_with do |format| + format.html { redirect_to admin_pods_path } + format.json { render json: PodPresenter.new(pod).as_json } + end + end + end +end diff --git a/app/controllers/admins_controller.rb b/app/controllers/admins_controller.rb index f4b345ec7b31f5bb10ca1ca47e494256373b7ef4..dc04103912e8c146a11ab9d9bc64315d21fcae10 100644 --- a/app/controllers/admins_controller.rb +++ b/app/controllers/admins_controller.rb @@ -1,4 +1,9 @@ class AdminsController < Admin::AdminController + include ApplicationHelper + + def dashboard + gon.push(pod_version: pod_version) + end def user_search if params[:admins_controller_user_search] diff --git a/app/controllers/api/openid_connect/authorizations_controller.rb b/app/controllers/api/openid_connect/authorizations_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..7103ad95ef17746ff051e2c5a96c5a588b91a1b2 --- /dev/null +++ b/app/controllers/api/openid_connect/authorizations_controller.rb @@ -0,0 +1,255 @@ +module Api + module OpenidConnect + class AuthorizationsController < ApplicationController + rescue_from Rack::OAuth2::Server::Authorize::BadRequest do |e| + logger.info e.backtrace[0, 10].join("\n") + error, _description = e.message.split(" :: ") + handle_params_error(error, "The request was malformed: please double check the client id and redirect uri.") + end + + rescue_from OpenSSL::SSL::SSLError do |e| + logger.info e.backtrace[0, 10].join("\n") + handle_params_error("bad_request", e.message) + end + + rescue_from JSON::JWS::VerificationFailed do |e| + logger.info e.backtrace[0, 10].join("\n") + handle_params_error("bad_request", e.message) + end + + before_action :auth_user_unless_prompt_none! + + def new + auth = Api::OpenidConnect::Authorization.find_by_client_id_user_and_scopes(params[:client_id], + current_user, params[:scope]) + reset_auth(auth) + if logged_in_before?(params[:max_age]) + reauthenticate(params) + elsif params[:prompt] + prompt = params[:prompt].split(" ") + handle_prompt(prompt, auth) + else + handle_authorization_form(auth) + end + end + + def create + restore_request_parameters + process_authorization_consent(params[:approve]) + end + + def destroy + authorization = Api::OpenidConnect::Authorization.find_by(id: params[:id]) + if authorization + authorization.destroy + else + flash[:error] = I18n.t("api.openid_connect.authorizations.destroy.fail", id: params[:id]) + end + redirect_to api_openid_connect_user_applications_url + end + + private + + def reset_auth(auth) + return unless auth + auth.o_auth_access_tokens.destroy_all + auth.code_used = false + auth.save + end + + def handle_prompt(prompt, auth) + if prompt.include? "select_account" + handle_params_error("account_selection_required", + "There is no support for choosing among multiple accounts") + elsif prompt.include? "consent" + request_authorization_consent_form + else + handle_authorization_form(auth) + end + end + + def handle_authorization_form(auth) + if auth + process_authorization_consent("true") + else + request_authorization_consent_form + end + end + + def request_authorization_consent_form + add_claims_to_scopes + endpoint = Api::OpenidConnect::AuthorizationPoint::EndpointStartPoint.new(current_user) + handle_start_point_response(endpoint) + end + + def add_claims_to_scopes + return unless params[:claims] + claims_json = JSON.parse(params[:claims]) + return unless claims_json + claims_array = claims_json["userinfo"].try(:keys) + return unless claims_array + req = build_rack_request + claims = claims_array.unshift(req[:scope]).join(" ") + req.update_param("scope", claims) + end + + def logged_in_before?(seconds) + if seconds.nil? + false + else + (Time.now - current_user.current_sign_in_at) > seconds.to_i + end + end + + def handle_start_point_response(endpoint) + _status, header, response = endpoint.call(request.env) + if response.redirect? + redirect_to header["Location"] + else + save_params_and_render_consent_form(endpoint) + end + end + + def save_params_and_render_consent_form(endpoint) + @o_auth_application = endpoint.o_auth_application + @response_type = endpoint.response_type + @redirect_uri = endpoint.redirect_uri + @scopes = endpoint.scopes + save_request_parameters + @app = UserApplicationPresenter.new @o_auth_application, @scopes + render :new + end + + def save_request_parameters + session[:client_id] = @o_auth_application.client_id + session[:response_type] = @response_type + session[:redirect_uri] = @redirect_uri + session[:scopes] = scopes_as_space_seperated_values + session[:nonce] = params[:nonce] + end + + def scopes_as_space_seperated_values + @scopes.join(" ") + end + + def process_authorization_consent(approved_string) + endpoint = Api::OpenidConnect::AuthorizationPoint::EndpointConfirmationPoint.new( + current_user, to_boolean(approved_string)) + handle_confirmation_endpoint_response(endpoint) + end + + def handle_confirmation_endpoint_response(endpoint) + _status, header, _response = endpoint.call(request.env) + delete_authorization_session_variables + redirect_to header["Location"] + end + + def delete_authorization_session_variables + session.delete(:client_id) + session.delete(:response_type) + session.delete(:redirect_uri) + session.delete(:scopes) + session.delete(:nonce) + end + + def to_boolean(str) + str.downcase == "true" + end + + def restore_request_parameters + req = build_rack_request + req.update_param("client_id", session[:client_id]) + req.update_param("redirect_uri", session[:redirect_uri]) + req.update_param("response_type", response_type_as_space_seperated_values) + req.update_param("scope", session[:scopes]) + req.update_param("nonce", session[:nonce]) + end + + def build_rack_request + Rack::Request.new(request.env) + end + + def response_type_as_space_seperated_values + [*session[:response_type]].join(" ") + end + + def handle_params_error(error, error_description) + if params[:client_id] && params[:redirect_uri] + handle_params_error_when_client_id_and_redirect_uri_exists(error, error_description) + else + render_error I18n.t("api.openid_connect.error_page.could_not_authorize"), error_description + end + end + + def handle_params_error_when_client_id_and_redirect_uri_exists(error, error_description) + app = Api::OpenidConnect::OAuthApplication.find_by(client_id: params[:client_id]) + if app && app.redirect_uris.include?(params[:redirect_uri]) + redirect_prompt_error_display(error, error_description) + else + render_error I18n.t("api.openid_connect.error_page.could_not_authorize"), + "Invalid client id or redirect uri" + end + end + + def redirect_prompt_error_display(error, error_description) + redirect_params_hash = {error: error, error_description: error_description, state: params[:state]} + redirect_fragment = redirect_params_hash.compact.map {|key, value| key.to_s + "=" + value }.join("&") + redirect_to params[:redirect_uri] + "?" + redirect_fragment + end + + def auth_user_unless_prompt_none! + prompt = params[:prompt] + if prompt && prompt.include?("none") + handle_prompt_none + elsif prompt && prompt.include?("login") + new_params = params.except("controller", "action").merge(prompt: prompt.remove("login")) + reauthenticate(new_params) + else + authenticate_user! + end + end + + def handle_prompt_none + if params[:prompt] == "none" + if user_signed_in? + handle_prompt_with_signed_in_user + else + handle_params_error("login_required", "User must already be logged in when `prompt` is `none`") + end + else + handle_params_error("invalid_request", "The 'none' value cannot be used with any other prompt value") + end + end + + def handle_prompt_with_signed_in_user + client_id = params[:client_id] + if client_id + auth = Api::OpenidConnect::Authorization.find_by_client_id_user_and_scopes(client_id, + current_user, params[:scope]) + if auth + process_authorization_consent("true") + else + handle_params_error("interaction_required", "User must already be authorized when `prompt` is `none`") + end + else + handle_params_error("bad_request", "Client ID is missing from request") + end + end + + def reauthenticate(params) + sign_out current_user + redirect_to new_api_openid_connect_authorization_path(params) + end + + def render_error(error_description, detailed_error=nil) + @error_description = error_description + @detailed_error = detailed_error + if request.format == :mobile + render "api/openid_connect/error/error.mobile", layout: "application.mobile" + else + render "api/openid_connect/error/error", layout: "with_header_with_footer" + end + end + end + end +end diff --git a/app/controllers/api/openid_connect/clients_controller.rb b/app/controllers/api/openid_connect/clients_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..0a6f7ba942c82355fbf0140827f5fa3cdacb1e80 --- /dev/null +++ b/app/controllers/api/openid_connect/clients_controller.rb @@ -0,0 +1,52 @@ +module Api + module OpenidConnect + class ClientsController < ApplicationController + rescue_from OpenIDConnect::HttpError do |e| + http_error_page_as_json(e) + end + + rescue_from OpenIDConnect::ValidationFailed, + ActiveRecord::RecordInvalid, Api::OpenidConnect::Error::InvalidSectorIdentifierUri do |e| + validation_fail_as_json(e) + end + + rescue_from Api::OpenidConnect::Error::InvalidRedirectUri do |e| + validation_fail_redirect_uri(e) + end + + rescue_from OpenSSL::SSL::SSLError do |e| + validation_fail_as_json(e) + end + + # Inspired by https://github.com/nov/openid_connect_sample/blob/master/app/controllers/connect/clients_controller.rb#L24 + def create + registrar = OpenIDConnect::Client::Registrar.new(request.url, params) + client = Api::OpenidConnect::OAuthApplication.register! registrar + render json: client.as_json(root: false) + end + + def find + client = Api::OpenidConnect::OAuthApplication.find_by(client_name: params[:client_name]) + if client + render json: {client_id: client.client_id} + else + render json: {error: "Client with name #{params[:client_name]} does not exist"} + end + end + + private + + def http_error_page_as_json(e) + render json: {error: :invalid_request, error_description: e.message}, status: 400 + end + + def validation_fail_as_json(e) + render json: {error: :invalid_client_metadata, error_description: e.message}, status: 400 + end + + def validation_fail_redirect_uri(e) + render json: {error: :invalid_redirect_uri, error_description: e.message}, status: 400 + end + end + end +end diff --git a/app/controllers/api/openid_connect/discovery_controller.rb b/app/controllers/api/openid_connect/discovery_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..19c9001b41ed8d1914a5484b424f9eeb7c182e16 --- /dev/null +++ b/app/controllers/api/openid_connect/discovery_controller.rb @@ -0,0 +1,61 @@ +# Copyright (c) 2011 nov matake +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# See https://github.com/nov/openid_connect_sample/blob/master/app/controllers/discovery_controller.rb + +module Api + module OpenidConnect + class DiscoveryController < ApplicationController + def webfinger + jrd = { + links: [{ + rel: OpenIDConnect::Discovery::Provider::Issuer::REL_VALUE, + href: root_url + }] + } + jrd[:subject] = params[:resource] if params[:resource].present? + render json: jrd, content_type: "application/jrd+json" + end + + def configuration + render json: OpenIDConnect::Discovery::Provider::Config::Response.new( + issuer: root_url, + registration_endpoint: api_openid_connect_clients_url, + authorization_endpoint: new_api_openid_connect_authorization_url, + token_endpoint: api_openid_connect_access_tokens_url, + userinfo_endpoint: api_openid_connect_user_info_url, + jwks_uri: api_openid_connect_url, + scopes_supported: Api::OpenidConnect::Authorization::SCOPES, + response_types_supported: Api::OpenidConnect::OAuthApplication.available_response_types, + request_object_signing_alg_values_supported: %i(none), + request_parameter_supported: true, + request_uri_parameter_supported: true, + subject_types_supported: %w(public pairwise), + id_token_signing_alg_values_supported: %i(RS256), + token_endpoint_auth_methods_supported: %w(client_secret_basic client_secret_post private_key_jwt), + claims_parameter_supported: true, + claims_supported: %w(sub name nickname profile picture), + userinfo_signing_alg_values_supported: %w(none) + ) + end + end + end +end diff --git a/app/controllers/api/openid_connect/id_tokens_controller.rb b/app/controllers/api/openid_connect/id_tokens_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..26eb17bdebd261044e59133de3df9bc341627b35 --- /dev/null +++ b/app/controllers/api/openid_connect/id_tokens_controller.rb @@ -0,0 +1,36 @@ +# Copyright (c) 2011 nov matake +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +module Api + module OpenidConnect + class IdTokensController < ApplicationController + def jwks + render json: JSON::JWK::Set.new(build_jwk).as_json + end + + private + + def build_jwk + JSON::JWK.new(Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY, use: :sig, kid: :default) + end + end + end +end diff --git a/app/controllers/api/openid_connect/token_endpoint_controller.rb b/app/controllers/api/openid_connect/token_endpoint_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..36b0ed31ce84e85f5fdc2dffd95b987fabf9d2a8 --- /dev/null +++ b/app/controllers/api/openid_connect/token_endpoint_controller.rb @@ -0,0 +1,60 @@ +module Api + module OpenidConnect + class TokenEndpointController < ApplicationController + def create + req = Rack::Request.new(request.env) + if req["client_assertion_type"] == "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" + handle_jwt_bearer(req) + end + self.status, response.headers, self.response_body = Api::OpenidConnect::TokenEndpoint.new.call(request.env) + nil + end + + private + + def handle_jwt_bearer(req) + jwt_string = req["client_assertion"] + jwt = JSON::JWT.decode jwt_string, :skip_verification + o_auth_app = Api::OpenidConnect::OAuthApplication.find_by(client_id: jwt["iss"]) + raise Rack::OAuth2::Server::Authorize::BadRequest(:invalid_request) unless o_auth_app + public_key = fetch_public_key(o_auth_app, jwt) + JSON::JWT.decode(jwt_string, JSON::JWK.new(public_key).to_key) + req.update_param("client_id", o_auth_app.client_id) + req.update_param("client_secret", o_auth_app.client_secret) + end + + def fetch_public_key(o_auth_app, jwt) + public_key = fetch_public_key_from_json(o_auth_app.jwks, jwt) + if public_key.empty? && o_auth_app.jwks_uri + response = Faraday.get(o_auth_app.jwks_uri) + public_key = fetch_public_key_from_json(response.body, jwt) + end + raise Rack::OAuth2::Server::Authorize::BadRequest(:unauthorized_client) if public_key.empty? + public_key + end + + def fetch_public_key_from_json(string, jwt) + json = JSON.parse(string) + keys = json["keys"] + public_key = get_key_from_kid(keys, jwt.header["kid"]) + public_key + end + + def get_key_from_kid(keys, kid) + keys.each do |key| + return key if key.has_value?(kid) + end + end + + rescue_from Rack::OAuth2::Server::Authorize::BadRequest, + JSON::JWT::InvalidFormat, JSON::JWK::UnknownAlgorithm do |e| + logger.info e.backtrace[0, 10].join("\n") + render json: {error: :invalid_request, error_description: e.message, status: 400} + end + rescue_from JSON::JWT::VerificationFailed do |e| + logger.info e.backtrace[0, 10].join("\n") + render json: {error: :invalid_grant, error_description: e.message, status: 400} + end + end + end +end diff --git a/app/controllers/api/openid_connect/user_applications_controller.rb b/app/controllers/api/openid_connect/user_applications_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..f25603a52c0e8851ad324445abf072a2eb1cd562 --- /dev/null +++ b/app/controllers/api/openid_connect/user_applications_controller.rb @@ -0,0 +1,11 @@ +module Api + module OpenidConnect + class UserApplicationsController < ApplicationController + before_action :authenticate_user! + + def index + @user_apps = UserApplicationsPresenter.new current_user + end + end + end +end diff --git a/app/controllers/api/openid_connect/user_info_controller.rb b/app/controllers/api/openid_connect/user_info_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..666c2a48eea8f566076f50d4a6351c04a521695a --- /dev/null +++ b/app/controllers/api/openid_connect/user_info_controller.rb @@ -0,0 +1,26 @@ +module Api + module OpenidConnect + class UserInfoController < ApplicationController + include Api::OpenidConnect::ProtectedResourceEndpoint + + before_action do + require_access_token %w(openid) + end + + def show + serializer = UserInfoSerializer.new(current_user) + auth = current_token.authorization + serializer.serialization_options = {authorization: auth} + attributes_without_essential = + serializer.attributes.with_indifferent_access.select {|scope| auth.scopes.include? scope } + attributes = attributes_without_essential.merge( + sub: serializer.sub) + render json: attributes.to_json + end + + def current_user + current_token ? current_token.authorization.user : nil + end + end + end +end diff --git a/app/controllers/api/v0/base_controller.rb b/app/controllers/api/v0/base_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..39d331215e1bed3cf3e43224235dc3e532adc994 --- /dev/null +++ b/app/controllers/api/v0/base_controller.rb @@ -0,0 +1,13 @@ +module Api + module V0 + class BaseController < ApplicationController + include Api::OpenidConnect::ProtectedResourceEndpoint + + protected + + def current_user + current_token ? current_token.authorization.user : nil + end + end + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ccdd2e75c1b425fdb50d0d54f84c3db5e37ae4bd..ebd5b03436db70fc1cd2664628a08f2d8a0a98ed 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -13,6 +13,7 @@ class ApplicationController < ActionController::Base before_action :set_grammatical_gender before_action :mobile_switch before_action :gon_set_current_user + before_action :gon_set_appconfig before_action :gon_set_preloads inflection_method grammatical_gender: :gender @@ -146,6 +147,14 @@ class ApplicationController < ActionController::Base end end + def gon_set_appconfig + gon.push(appConfig: { + chat: {enabled: AppConfig.chat.enabled?}, + settings: {podname: AppConfig.settings.pod_name}, + map: {mapbox: AppConfig.map.mapbox} + }) + end + def gon_set_current_user return unless user_signed_in? a_ids = session[:a_ids] || [] diff --git a/app/controllers/aspect_memberships_controller.rb b/app/controllers/aspect_memberships_controller.rb index 46236d13970f535ba76aba798ea9f29ff066f787..e31b90a78c7c5854a0e70b90e4f256341eba6c08 100644 --- a/app/controllers/aspect_memberships_controller.rb +++ b/app/controllers/aspect_memberships_controller.rb @@ -62,7 +62,7 @@ class AspectMembershipsController < ApplicationController format.all { redirect_to :back } end else - flash.now[:error] = I18n.t("contacts.create.failure") + flash.now[:error] = I18n.t("aspects.add_to_aspect.failure") render nothing: true, status: 409 end end diff --git a/app/controllers/aspects_controller.rb b/app/controllers/aspects_controller.rb index 5c6f5de7941cca5b339f3e332678faacf89222a0..ce21bd95d4776da3ed38ea8303d2a2f6b0518ace 100644 --- a/app/controllers/aspects_controller.rb +++ b/app/controllers/aspects_controller.rb @@ -14,10 +14,13 @@ class AspectsController < ApplicationController aspecting_person_id = params[:person_id] if @aspect.save + result = {id: @aspect.id, name: @aspect.name} if aspecting_person_id.present? - connect_person_to_aspect(aspecting_person_id) + aspect_membership = connect_person_to_aspect(aspecting_person_id) + result[:aspect_membership] = AspectMembershipPresenter.new(aspect_membership).base_hash if aspect_membership end - render json: {id: @aspect.id, name: @aspect.name} + + render json: result else render nothing: true, status: 422 end @@ -96,9 +99,10 @@ class AspectsController < ApplicationController def connect_person_to_aspect(aspecting_person_id) @person = Person.find(aspecting_person_id) if @contact = current_user.contact_for(@person) - @contact.aspects << @aspect + @contact.aspect_memberships.create(aspect: @aspect) else @contact = current_user.share_with(@person, @aspect) + @contact.aspect_memberships.first end end diff --git a/app/controllers/blocks_controller.rb b/app/controllers/blocks_controller.rb index bcea0e561b83451b125510cbc362e0cf4e0b7667..dd5cb4ae996df278b0e8ddb699295082bc29fc4a 100644 --- a/app/controllers/blocks_controller.rb +++ b/app/controllers/blocks_controller.rb @@ -35,9 +35,7 @@ class BlocksController < ApplicationController private def disconnect_if_contact(person) - if contact = current_user.contact_for(person) - current_user.disconnect(contact, :force => true) - end + current_user.contact_for(person).try {|contact| current_user.disconnect(contact) } end def block_params diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index b8bdb3a4c44d2b10202125428272a15deef8f1cb..9abc7503b04a3102268d34a3988354da130b3bb4 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -12,17 +12,16 @@ class CommentsController < ApplicationController end def create - @comment = CommentService.new(post_id: params[:post_id], text: params[:text], user: current_user).create_comment - if @comment - respond_create_success + comment = comment_service.create(params[:post_id], params[:text]) + if comment + respond_create_success(comment) else render nothing: true, status: 404 end end def destroy - service = CommentService.new(comment_id: params[:id], user: current_user) - if service.destroy_comment + if comment_service.destroy(params[:id]) respond_destroy_success else respond_destroy_error @@ -36,22 +35,24 @@ class CommentsController < ApplicationController end def index - service = CommentService.new(post_id: params[:post_id], user: current_user) - @post = service.post - @comments = service.comments + comments = comment_service.find_for_post(params[:post_id]) respond_with do |format| - format.json { render json: CommentPresenter.as_collection(@comments), status: 200 } - format.mobile { render layout: false } + format.json { render json: CommentPresenter.as_collection(comments), status: 200 } + format.mobile { render layout: false, locals: {comments: comments} } end end private - def respond_create_success + def comment_service + @comment_service ||= CommentService.new(current_user) + end + + def respond_create_success(comment) respond_to do |format| - format.json { render json: CommentPresenter.new(@comment), status: 201 } + format.json { render json: CommentPresenter.new(comment), status: 201 } format.html { render nothing: true, status: 201 } - format.mobile { render partial: "comment", locals: {post: @comment.post, comment: @comment} } + format.mobile { render partial: "comment", locals: {comment: comment} } end end diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb index 1b8c91d2bb1757b466f048f16f39cb7caf056065..a0be1dcec673b2d8b4e8d3e5b20014d408261c9f 100644 --- a/app/controllers/contacts_controller.rb +++ b/app/controllers/contacts_controller.rb @@ -14,11 +14,14 @@ class ContactsController < ApplicationController # Used by the mobile site format.mobile { set_up_contacts_mobile } - # Used to populate mentions in the publisher + # Used for mentions in the publisher and pagination on the contacts page format.json { - aspect_ids = params[:aspect_ids] || current_user.aspects.map(&:id) - @people = Person.all_from_aspects(aspect_ids, current_user).for_json - render :json => @people.to_json + @people = if params[:q].present? + Person.search(params[:q], current_user, only_contacts: true).limit(15) + else + set_up_contacts_json + end + render json: @people } end end @@ -31,30 +34,54 @@ class ContactsController < ApplicationController private def set_up_contacts + if params[:a_id].present? + @aspect = current_user.aspects.find(params[:a_id]) + gon.preloads[:aspect] = AspectPresenter.new(@aspect).as_json + end + @contacts_size = current_user.contacts.size + end + + def set_up_contacts_json type = params[:set].presence - type ||= "by_aspect" if params[:a_id].present? + if params[:a_id].present? + type ||= "by_aspect" + @aspect = current_user.aspects.find(params[:a_id]) + end type ||= "receiving" - - @contacts = contacts_by_type(type) - @contacts_size = @contacts.length - gon.preloads[:contacts] = @contacts.map{ |c| ContactPresenter.new(c, current_user).full_hash_with_person } + contacts_by_type(type).paginate(page: params[:page], per_page: 25) + .map {|c| ContactPresenter.new(c, current_user).full_hash_with_person } end def contacts_by_type(type) - case type + order = ["profiles.first_name ASC", "profiles.last_name ASC", "profiles.diaspora_handle ASC"] + contacts = case type when "all" + order.unshift "receiving DESC" current_user.contacts when "only_sharing" current_user.contacts.only_sharing when "receiving" current_user.contacts.receiving when "by_aspect" - @aspect = current_user.aspects.find(params[:a_id]) - gon.preloads[:aspect] = AspectPresenter.new(@aspect).as_json - current_user.contacts + order.unshift "contact_id IS NOT NULL DESC" + contacts_by_aspect(@aspect.id) else raise ArgumentError, "unknown type #{type}" end + contacts.includes(person: :profile) + .order(order) + end + + def contacts_by_aspect(aspect_id) + contacts = current_user.contacts.arel_table + aspect_memberships = AspectMembership.arel_table + current_user.contacts.joins( + contacts.outer_join(aspect_memberships).on( + aspect_memberships[:aspect_id].eq(aspect_id).and( + aspect_memberships[:contact_id].eq(contacts[:id]) + ) + ).join_sources + ) end def set_up_contacts_mobile diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index f1266f3ade42091b23e900379f6b08e19a9566de..11dccbd0a0cbdf16f167516a336e025aacbb98fa 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -45,7 +45,7 @@ class ConversationsController < ApplicationController @response = {} if person_ids.present? && @conversation.save - Postzord::Dispatcher.build(current_user, @conversation).post + Diaspora::Federation::Dispatcher.defer_dispatch(current_user, @conversation) @response[:success] = true @response[:message] = I18n.t('conversations.create.sent') @response[:conversation_id] = @conversation.id @@ -104,7 +104,7 @@ class ConversationsController < ApplicationController private def contacts_data - current_user.contacts.sharing.joins(person: :profile) + current_user.contacts.mutual.joins(person: :profile) .pluck(*%w(contacts.id profiles.first_name profiles.last_name people.diaspora_handle)) .map {|contact_id, *name_attrs| {value: contact_id, name: ERB::Util.h(Person.name_from_attrs(*name_attrs)) } diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index 3d65e1f0dc5f07bc4bbd10536be29e4137a6960c..4799488ae52ad6d8dbe123e22a8e0789445fc21c 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -1,5 +1,2 @@ class HelpController < ApplicationController - def faq - gon.chatEnabled = AppConfig.chat.enabled? - end end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index ee0b7102e9a5e8a9cc3aa78c11ca7c1c67bc767e..3c4a6b5ee0ecb44a95b70aa82417cf8342bc258c 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -19,12 +19,17 @@ class HomeController < ApplicationController partial_dir.join("_show.html.erb").exist? || partial_dir.join("_show.haml").exist? render :show + elsif User.count > 1 && Role.where(name: "admin").any? + render :default else - render :default, - layout: "application" + redirect_to podmin_path end end + def podmin + render :podmin + end + def toggle_mobile session[:mobile_view] = session[:mobile_view].nil? ? true : !session[:mobile_view] diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index 6acf3602dcb3c075f6326441367bab37fc9cd1bd..66653e83e1b619216f02acfa917be8febbf4a3d0 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -3,8 +3,8 @@ # the COPYRIGHT file. class InvitationsController < ApplicationController - - before_action :authenticate_user!, :only => [:new, :create] + before_action :authenticate_user! + before_action :check_invitations_available!, only: :create def new @invite_code = current_user.invitation_code @@ -14,79 +14,50 @@ class InvitationsController < ApplicationController respond_to do |format| format.html do - render 'invitations/new', layout: false + render "invitations/new", layout: false end end end - # this is for legacy invites. We try to look the person who sent them the - # invite, and use their new invite code - # owe will be removing this eventually - # @depreciated - def edit - user = User.find_by_invitation_token(params[:invitation_token]) - invitation_code = user.ugly_accept_invitation_code - redirect_to invite_code_path(invitation_code) - end - - def email - @invitation_code = - if params[:invitation_token] - # this is for legacy invites. - user = User.find_by_invitation_token(params[:invitation_token]) - - user.ugly_accept_invitation_code if user - else - params[:invitation_code] - end - @inviter = user || InvitationCode.where(id: params[:invitation_code]).first.try(:user) - if @invitation_code.present? - render 'notifier/invite', :layout => false - else - flash[:error] = t('invitations.check_token.not_found') - - redirect_to root_url - end - end - def create - emails = inviter_params[:emails].split(',').map(&:strip).uniq + emails = inviter_params[:emails].split(",").map(&:strip).uniq - valid_emails, invalid_emails = emails.partition { |email| valid_email?(email) } + valid_emails, invalid_emails = emails.partition {|email| valid_email?(email) } session[:valid_email_invites] = valid_emails session[:invalid_email_invites] = invalid_emails unless valid_emails.empty? - Workers::Mail::InviteEmail.perform_async(valid_emails.join(','), - current_user.id, - inviter_params) + Workers::Mail::InviteEmail.perform_async(valid_emails.join(","), current_user.id, inviter_params) end if emails.empty? - flash[:error] = t('invitations.create.empty') + flash[:error] = t("invitations.create.empty") elsif invalid_emails.empty? - flash[:notice] = t('invitations.create.sent', :emails => valid_emails.join(', ')) + flash[:notice] = t("invitations.create.sent", emails: valid_emails.join(", ")) elsif valid_emails.empty? - flash[:error] = t('invitations.create.rejected') + invalid_emails.join(', ') + flash[:error] = t("invitations.create.rejected", emails: invalid_emails.join(", ")) else - flash[:error] = t('invitations.create.sent', :emails => valid_emails.join(', ')) - flash[:error] << '. ' - flash[:error] << t('invitations.create.rejected') + invalid_emails.join(', ') + flash[:error] = t("invitations.create.sent", emails: valid_emails.join(", ")) + ". " + + t("invitations.create.rejected", emails: invalid_emails.join(", ")) end redirect_to :back end - def check_if_invites_open - unless AppConfig.settings.invitations.open? - flash[:error] = I18n.t 'invitations.create.no_more' + private - redirect_to :back - end + def check_invitations_available! + return true if AppConfig.settings.enable_registrations? || current_user.invitation_code.can_be_used? + + flash[:error] = if AppConfig.settings.invitations.open? + t("invitations.create.no_more") + else + t("invitations.create.closed") + end + redirect_to :back end - private def valid_email?(email) User.email_regexp.match(email).present? end @@ -94,9 +65,9 @@ class InvitationsController < ApplicationController def html_safe_string_from_session_array(key) return "" unless session[key].present? return "" unless session[key].respond_to?(:join) - value = session[key].join(', ').html_safe + value = session[key].join(", ").html_safe session[key] = nil - return value + value end def inviter_params diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index e0b32f671fb5812588b66756155602a8e165f381..c5387799b4e26897b3e0f914f4bd7c30c7579648 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -15,9 +15,17 @@ class MessagesController < ApplicationController message = current_user.build_message(conversation, opts) if message.save - logger.info "event=create type=comment user=#{current_user.diaspora_handle} status=success " \ + logger.info "event=create type=message user=#{current_user.diaspora_handle} status=success " \ "message=#{message.id} chars=#{params[:message][:text].length}" - Postzord::Dispatcher.build(current_user, message).post + Diaspora::Federation::Dispatcher.defer_dispatch(current_user, message) + + # TODO: can be removed when messages are not relayed anymore + conversation_owner = conversation.author.owner + if conversation_owner && conversation_owner != current_user + remote_subs = conversation.participants.remote.ids + opts = {subscriber_ids: remote_subs} + Diaspora::Federation::Dispatcher.defer_dispatch(conversation_owner, message, opts) unless remote_subs.empty? + end else flash[:error] = I18n.t('conversations.new_conversation.fail') end diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 2d7a5f4ef00f06bfad18b0357ce370909006986f..7ddb9b8d6b0665483bdcb73e36c4988d66868861 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -38,9 +38,6 @@ class NotificationsController < ApplicationController pager.replace(result) end - @notifications.each do |note| - note.note_html = render_to_string( :partial => 'notification', :locals => { :note => note } ) - end @group_days = @notifications.group_by{|note| note.created_at.strftime('%Y-%m-%d')} @unread_notification_count = current_user.unread_notifications.count @@ -54,9 +51,17 @@ class NotificationsController < ApplicationController respond_to do |format| format.html format.xml { render :xml => @notifications.to_xml } - format.json { render :json => @notifications.to_json } + format.json { + render json: @notifications, each_serializer: NotificationSerializer + } end + end + def default_serializer_options + { + context: self, + root: false + } end def read_all diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 154f4337674b9c004f1ff6597b4e1dde597131cd..019516e89e7e090f71951402198d7b3d19b3e5a8 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -3,12 +3,14 @@ # the COPYRIGHT file. class PeopleController < ApplicationController + include GonHelper + before_action :authenticate_user!, except: %i(show stream hovercard) before_action :find_person, only: %i(show stream hovercard) + before_action :authenticate_if_remote_profile!, only: %i(show stream) - respond_to :html, :except => [:tag_index] + respond_to :html respond_to :json, :only => [:index, :show] - respond_to :js, :only => [:tag_index] rescue_from ActiveRecord::RecordNotFound do render :file => Rails.root.join('public', '404').to_s, @@ -61,44 +63,32 @@ class PeopleController < ApplicationController self.formats = self.formats + [:html] @answer_html = render_to_string :partial => 'people/person', :locals => @hashes.first end - render :json => { :search_count => @people.count, :search_html => @answer_html }.to_json - end - - - def tag_index - profiles = Profile.tagged_with(params[:name]).where(:searchable => true).select('profiles.id, profiles.person_id') - @people = Person.where(:id => profiles.map{|p| p.person_id}).paginate(:page => params[:page], :per_page => 15) - respond_with @people + render json: {search_html: @answer_html, contacts: gon.preloads[:contacts]}.to_json end # renders the persons user profile page def show mark_corresponding_notifications_read if user_signed_in? - - @person_json = PersonPresenter.new(@person, current_user).full_hash_with_profile + @presenter = PersonPresenter.new(@person, current_user) respond_to do |format| format.all do if user_signed_in? @contact = current_user.contact_for(@person) end - gon.preloads[:person] = @person_json - gon.preloads[:photos] = { - count: Photo.visible(current_user, @person).count(:all) - } - gon.preloads[:contacts] = { - count: Contact.contact_contacts_for(current_user, @person).count(:all), - } - respond_with @person, layout: "with_header" + gon.preloads[:person] = @presenter.as_json + gon.preloads[:photos_count] = Photo.visible(current_user, @person).count(:all) + gon.preloads[:contacts_count] = Contact.contact_contacts_for(current_user, @person).count(:all) + respond_with @presenter, layout: "with_header" end format.mobile do @post_type = :all person_stream - respond_with @person + respond_with @presenter end - format.json { render json: @person_json } + format.json { render json: @presenter.as_json } end end @@ -120,7 +110,7 @@ class PeopleController < ApplicationController end format.json do - render :json => HovercardPresenter.new(@person) + render json: PersonPresenter.new(@person, current_user).hovercard end end end @@ -144,13 +134,9 @@ class PeopleController < ApplicationController if @person @contact = current_user.contact_for(@person) @contacts_of_contact = Contact.contact_contacts_for(current_user, @person) - gon.preloads[:person] = PersonPresenter.new(@person, current_user).full_hash_with_profile - gon.preloads[:photos] = { - count: Photo.visible(current_user, @person).count(:all) - } - gon.preloads[:contacts] = { - count: @contacts_of_contact.count(:all), - } + gon.preloads[:person] = PersonPresenter.new(@person, current_user).as_json + gon.preloads[:photos_count] = Photo.visible(current_user, @person).count(:all) + gon.preloads[:contacts_count] = @contacts_of_contact.count(:all) @contacts_of_contact = @contacts_of_contact.paginate(page: params[:page], per_page: (params[:limit] || 15)) @hashes = hashes_for_people @contacts_of_contact, @aspects respond_with @person, layout: "with_header" @@ -162,21 +148,6 @@ class PeopleController < ApplicationController end end - # shows the dropdown list of aspects the current user has set for the given person. - # renders "thats you" in case the current user views himself - def aspect_membership_dropdown - @person = Person.find_by_guid(params[:person_id]) - - # you are not a contact of yourself... - return render :text => I18n.t('people.person.thats_you') if @person == current_user.person - - @contact = current_user.contact_for(@person) || Contact.new - @aspect = :profile if params[:create] # let aspect dropdown create new aspects - size = params[:size] || "small" - - render :partial => 'aspect_membership_dropdown', :locals => {:contact => @contact, :person => @person, :hang => 'left', :size => size} - end - private def find_person @@ -192,23 +163,19 @@ class PeopleController < ApplicationController }) end - # view this profile on the home pod, if you don't want to sign in... - authenticate_user! if remote_profile_with_no_user_session? raise ActiveRecord::RecordNotFound if @person.nil? raise Diaspora::AccountClosed if @person.closed_account? end def hashes_for_people(people, aspects) - ids = people.map{|p| p.id} - contacts = {} - Contact.unscoped.where(:user_id => current_user.id, :person_id => ids).each do |contact| - contacts[contact.person_id] = contact - end - - people.map{|p| - {:person => p, - :contact => contacts[p.id], - :aspects => aspects} + people.map {|person| + { + person: person, + contact: current_user.contact_for(person) || Contact.new(person: person), + aspects: aspects + }.tap {|hash| + gon_load_contact(hash[:contact]) + } } end @@ -217,11 +184,12 @@ class PeopleController < ApplicationController end def diaspora_id?(query) - !query.try(:match, /^(\w)*@([a-zA-Z0-9]|[-]|[.]|[:])*$/).nil? + !(query.nil? || query.lstrip.empty?) && Validation::Rule::DiasporaId.new.valid_value?(query) end - def remote_profile_with_no_user_session? - @person.try(:remote?) && !user_signed_in? + # view this profile on the home pod, if you don't want to sign in... + def authenticate_if_remote_profile! + authenticate_user! if @person.try(:remote?) end def mark_corresponding_notifications_read diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index a0c6a5b76b66b59df53884043bce14ed9286ba7a..33b15e5717fe1476b1d142a67e2670dcd10069da 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -20,19 +20,16 @@ class PhotosController < ApplicationController @post_type = :photos @person = Person.find_by_guid(params[:person_id]) authenticate_user! if @person.try(:remote?) && !user_signed_in? + @presenter = PersonPresenter.new(@person, current_user) if @person @contact = current_user.contact_for(@person) if user_signed_in? @posts = Photo.visible(current_user, @person, :all, max_time) respond_to do |format| format.all do - gon.preloads[:person] = PersonPresenter.new(@person, current_user).full_hash_with_profile - gon.preloads[:photos] = { - count: Photo.visible(current_user, @person).count(:all) - } - gon.preloads[:contacts] = { - count: Contact.contact_contacts_for(current_user, @person).count(:all), - } + gon.preloads[:person] = @presenter.as_json + gon.preloads[:photos_count] = Photo.visible(current_user, @person).count(:all) + gon.preloads[:contacts_count] = Contact.contact_contacts_for(current_user, @person).count(:all) render "people/show", layout: "with_header" end format.mobile { render "people/show" } @@ -109,34 +106,6 @@ class PhotosController < ApplicationController end end - def edit - if @photo = current_user.photos.where(:id => params[:id]).first - respond_with @photo - else - redirect_to person_photos_path(current_user.person) - end - end - - def update - photo = current_user.photos.where(:id => params[:id]).first - if photo - if current_user.update_post( photo, photo_params ) - flash.now[:notice] = I18n.t 'photos.update.notice' - respond_to do |format| - format.js{ render :json => photo, :status => 200 } - end - else - flash.now[:error] = I18n.t 'photos.update.error' - respond_to do |format| - format.html{ redirect_to [:edit, photo] } - format.js{ render :status => 403 } - end - end - else - redirect_to person_photos_path(current_user.person) - end - end - private def photo_params @@ -178,10 +147,12 @@ class PhotosController < ApplicationController @photo = current_user.build_post(:photo, params[:photo]) if @photo.save - aspects = current_user.aspects_from_ids(params[:photo][:aspect_ids]) unless @photo.pending - current_user.add_to_streams(@photo, aspects) + unless @photo.public? + aspects = current_user.aspects_from_ids(params[:photo][:aspect_ids]) + current_user.add_to_streams(@photo, aspects) + end current_user.dispatch_post(@photo, :to => params[:photo][:aspect_ids]) end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 1779d0b4ad78beca3b8857149f91bf38b132aa8c..be2c2dcc90a9a15af2021a22bf1d112f1b104a61 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -3,21 +3,13 @@ # the COPYRIGHT file. class PostsController < ApplicationController - include PostsHelper - before_action :authenticate_user!, only: :destroy before_action :set_format_if_malformed_from_status_net, only: :show respond_to :html, :mobile, :json, :xml rescue_from Diaspora::NonPublic do - if user_signed_in? - respond_to do |format| - format.all { render template: "errors/not_public", status: 404, layout: "application" } - end - else - authenticate_user! - end + authenticate_user! end rescue_from Diaspora::NotMine do @@ -25,38 +17,37 @@ class PostsController < ApplicationController end def show - post_service = PostService.new(id: params[:id], user: current_user) - post_service.mark_user_notifications - @post = post_service.post + post = post_service.find!(params[:id]) + post_service.mark_user_notifications(post.id) + presenter = PostPresenter.new(post, current_user) respond_to do |format| - format.html { gon.post = post_service.present_json } - format.xml { render xml: @post.to_diaspora_xml } - format.json { render json: post_service.present_json } + format.html do + gon.post = presenter + render locals: {post: presenter} + end + format.mobile { render locals: {post: post} } + format.xml { render xml: DiasporaFederation::Salmon::XmlPayload.pack(Diaspora::Federation::Entities.post(post)) } + format.json { render json: presenter } end end - def iframe - render text: post_iframe_url(params[:id]), layout: false - end - def oembed post_id = OEmbedPresenter.id_from_url(params.delete(:url)) - post_service = PostService.new(id: post_id, user: current_user, - oembed: params.slice(:format, :maxheight, :minheight)) - render json: post_service.present_oembed + post = post_service.find!(post_id) + oembed = params.slice(:format, :maxheight, :minheight) + render json: OEmbedPresenter.new(post, oembed) + rescue + render nothing: true, status: 404 end def interactions - post_service = PostService.new(id: params[:id], user: current_user) - respond_with post_service.present_interactions_json + post = post_service.find!(params[:id]) + respond_with PostInteractionPresenter.new(post, current_user) end def destroy - post_service = PostService.new(id: params[:id], user: current_user) - post_service.retract_post - @post = post_service.post + post_service.destroy(params[:id]) respond_to do |format| - format.js { render "destroy", layout: false, format: :js } format.json { render nothing: true, status: 204 } format.any { redirect_to stream_path } end @@ -64,6 +55,10 @@ class PostsController < ApplicationController private + def post_service + @post_service ||= PostService.new(current_user) + end + def set_format_if_malformed_from_status_net request.format = :html if request.format == "application/html+xml" end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 2c2bdf2c2f935e2a7723084dbe58d0dbcc2bd1b4..409dcaee00131d54e3584048d602e581e5ab9c23 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -40,6 +40,7 @@ class ProfilesController < ApplicationController #checkbox tags wtf @profile_attrs[:searchable] ||= false @profile_attrs[:nsfw] ||= false + @profile_attrs[:public_details] ||= false if params[:photo_id] @profile_attrs[:photo] = Photo.where(:author_id => current_user.person_id, :id => params[:photo_id]).first @@ -79,6 +80,8 @@ class ProfilesController < ApplicationController end def profile_params - params.require(:profile).permit(:first_name, :last_name, :gender, :bio, :location, :searchable, :tag_string, :nsfw, :date => [:year, :month, :day]) || {} + params.require(:profile).permit(:first_name, :last_name, :gender, :bio, + :location, :searchable, :tag_string, :nsfw, + :public_details, date: %i(year month day)) || {} end end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 8b816e3902651854c4c3792cba8ca0366c7f4466..561c52ea0945064f7b5d1a5d25959656ba92f8a7 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -3,16 +3,16 @@ # the COPYRIGHT file. class RegistrationsController < Devise::RegistrationsController - before_action :check_registrations_open_or_valid_invite!, :check_valid_invite! + before_action :check_registrations_open_or_valid_invite! - layout ->(c) { request.format == :mobile ? "application" : "with_header" }, :only => [:new] + layout -> { request.format == :mobile ? "application" : "with_header" } def create @user = User.build(user_params) - @user.process_invite_acceptence(invite) if invite.present? if @user.sign_up - flash[:notice] = I18n.t 'registrations.create.success' + flash[:notice] = t("registrations.create.success") + @user.process_invite_acceptence(invite) if invite.present? @user.seed_aspects @user.send_welcome_message sign_in_and_redirect(:user, @user) @@ -22,40 +22,30 @@ class RegistrationsController < Devise::RegistrationsController flash.now[:error] = @user.errors.full_messages.join(" - ") logger.info "event=registration status=failure errors='#{@user.errors.full_messages.join(', ')}'" - render action: "new", layout: request.format == :mobile ? "application" : "with_header" + render action: "new" end end - def new - super - end - private - def check_valid_invite! - return true if AppConfig.settings.enable_registrations? #this sucks - return true if invite && invite.can_be_used? - flash[:error] = t('registrations.invalid_invite') - redirect_to new_user_session_path - end - def check_registrations_open_or_valid_invite! - return true if invite.present? - unless AppConfig.settings.enable_registrations? - flash[:error] = t('registrations.closed') - redirect_to new_user_session_path - end + return true if AppConfig.settings.enable_registrations? || invite.try(:can_be_used?) + + flash[:error] = params[:invite] ? t("registrations.invalid_invite") : t("registrations.closed") + redirect_to new_user_session_path end def invite - if params[:invite].present? - @invite ||= InvitationCode.find_by_token(params[:invite][:token]) - end + @invite ||= InvitationCode.find_by_token(params[:invite][:token]) if params[:invite].present? end helper_method :invite def user_params - params.require(:user).permit(:username, :email, :getting_started, :password, :password_confirmation, :language, :disable_mail, :invitation_service, :invitation_identifier, :show_community_spotlight_in_stream, :auto_follow_back, :auto_follow_back_aspect_id, :remember_me, :captcha, :captcha_key) + params.require(:user).permit( + :username, :email, :getting_started, :password, :password_confirmation, :language, :disable_mail, + :show_community_spotlight_in_stream, :auto_follow_back, :auto_follow_back_aspect_id, + :remember_me, :captcha, :captcha_key + ) end end diff --git a/app/controllers/reshares_controller.rb b/app/controllers/reshares_controller.rb index 1e49a5aa005294980e1bbccc0b39ed59c4c3a681..22915891a895c711e37c1614e29971160a6c2846 100644 --- a/app/controllers/reshares_controller.rb +++ b/app/controllers/reshares_controller.rb @@ -11,8 +11,7 @@ class ResharesController < ApplicationController end if @reshare.save - current_user.add_to_streams(@reshare, current_user.aspects) - current_user.dispatch_post(@reshare, :url => post_url(@reshare), :additional_subscribers => @reshare.root_author) + current_user.dispatch_post(@reshare) render :json => ExtremePostPresenter.new(@reshare, current_user), :status => 201 else render :nothing => true, :status => 422 diff --git a/app/controllers/social_relay_controller.rb b/app/controllers/social_relay_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..28cf5065ac59ca076e355028c662144aa6416324 --- /dev/null +++ b/app/controllers/social_relay_controller.rb @@ -0,0 +1,7 @@ +class SocialRelayController < ApplicationController + respond_to :json + + def well_known + render json: SocialRelayPresenter.new + end +end diff --git a/app/controllers/status_messages_controller.rb b/app/controllers/status_messages_controller.rb index a7a4ebea0f2dba8ec0f5c247f342604bb0d6d7a6..87db1237f00367e58b3736e9c6f84378a9cfe047 100644 --- a/app/controllers/status_messages_controller.rb +++ b/app/controllers/status_messages_controller.rb @@ -47,12 +47,17 @@ class StatusMessagesController < ApplicationController end def create - @status_message = StatusMessageCreationService.new(params, current_user).status_message - handle_mention_feedback + normalized_params = params.merge( + services: normalize_services, + aspect_ids: normalize_aspect_ids, + public: normalize_public_flag + ) + status_message = StatusMessageCreationService.new(current_user).create(normalized_params) + handle_mention_feedback(status_message) respond_to do |format| format.html { redirect_to :back } format.mobile { redirect_to stream_path } - format.json { render json: PostPresenter.new(@status_message, current_user), status: 201 } + format.json { render json: PostPresenter.new(status_message, current_user), status: 201 } end rescue StandardError => error handle_create_error(error) @@ -73,9 +78,9 @@ class StatusMessagesController < ApplicationController end end - def handle_mention_feedback + def handle_mention_feedback(status_message) return unless comes_from_others_profile_page? - flash[:notice] = successful_mention_message + flash[:notice] = t("status_messages.create.success", names: status_message.mentioned_people_names) end def comes_from_others_profile_page? @@ -87,11 +92,24 @@ class StatusMessagesController < ApplicationController end def own_profile_page? - request.env["HTTP_REFERER"].include?("/people/" + params[:status_message][:author][:guid].to_s) + request.env["HTTP_REFERER"].include?("/people/" + current_user.guid) end - def successful_mention_message - t("status_messages.create.success", names: @status_message.mentioned_people_names) + def normalize_services + [*params[:services]].compact + end + + def normalize_aspect_ids + aspect_ids = [*params[:aspect_ids]] + if aspect_ids.first == "all_aspects" + current_user.aspect_ids + else + aspect_ids + end + end + + def normalize_public_flag + [*params[:aspect_ids]].first == "public" end def remove_getting_started diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index e8d25dd731a2c70a49e19021c9136f07dbbce99b..a18e934b6b1876bd0981370b586d9570276dd4e1 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -37,9 +37,15 @@ class TagsController < ApplicationController if user_signed_in? gon.preloads[:tagFollowings] = tags end - @stream = Stream::Tag.new(current_user, params[:name], :max_time => max_time, :page => params[:page]) + stream = Stream::Tag.new(current_user, params[:name], max_time: max_time, page: params[:page]) + @stream = TagStreamPresenter.new(stream) respond_with do |format| - format.json { render :json => @stream.stream_posts.map { |p| LastThreeCommentsDecorator.new(PostPresenter.new(p, current_user)) }} + format.json do + posts = stream.stream_posts.map do |p| + LastThreeCommentsDecorator.new(PostPresenter.new(p, current_user)) + end + render json: posts + end end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index eaa03b62b5de19539b0b365ce21796851c356a37..b7242c11881e82bb251a01b2d664b98865d8a7d6 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -3,11 +3,10 @@ # the COPYRIGHT file. class UsersController < ApplicationController - before_action :authenticate_user!, :except => [:new, :create, :public, :user_photo] + before_action :authenticate_user!, except: %i(new create public user_photo) respond_to :html def edit - @aspect = :user_edit @user = current_user set_email_preferences end @@ -18,83 +17,48 @@ class UsersController < ApplicationController def update password_changed = false + user_data = user_params @user = current_user - if u = user_params - - # change email notifications - if u[:email_preferences] - @user.update_user_preferences(u[:email_preferences]) - flash[:notice] = I18n.t 'users.update.email_notifications_changed' + if user_data # change password - elsif params[:change_password] - if @user.update_with_password(u) - password_changed = true - flash[:notice] = I18n.t 'users.update.password_changed' - else - flash[:error] = I18n.t 'users.update.password_not_changed' - end - elsif u[:show_community_spotlight_in_stream] || u[:getting_started] - if @user.update_attributes(u) - flash[:notice] = I18n.t 'users.update.settings_updated' - else - flash[:notice] = I18n.t 'users.update.settings_not_updated' - end - elsif u[:strip_exif] - if @user.update_attributes(u) - flash[:notice] = I18n.t 'users.update.settings_updated' - else - flash[:notice] = I18n.t 'users.update.settings_not_updated' - end - elsif u[:language] - if @user.update_attributes(u) - I18n.locale = @user.language - flash[:notice] = I18n.t 'users.update.language_changed' - else - flash[:error] = I18n.t 'users.update.language_not_changed' - end - elsif u[:email] - @user.unconfirmed_email = u[:email] - if @user.save - @user.send_confirm_email - if @user.unconfirmed_email - flash[:notice] = I18n.t 'users.update.unconfirmed_email_changed' - end - else - flash[:error] = I18n.t 'users.update.unconfirmed_email_not_changed' - end - elsif u[:auto_follow_back] - if @user.update_attributes(u) - flash[:notice] = I18n.t 'users.update.follow_settings_changed' - else - flash[:error] = I18n.t 'users.update.follow_settings_not_changed' - end + if params[:change_password] + password_changed = change_password(user_data) + else + update_user(user_data) end end - set_email_preferences - respond_to do |format| - format.js { render :nothing => true, :status => 204 } - format.all do - if password_changed - redirect_to new_user_session_path - else - render :edit - end - end + if password_changed + redirect_to new_user_session_path + else + set_email_preferences + render :edit + end + end + + def update_privacy_settings + privacy_params = params.fetch(:user).permit(:strip_exif) + + if current_user.update_attributes(strip_exif: privacy_params[:strip_exif]) + flash[:notice] = t("users.update.settings_updated") + else + flash[:error] = t("users.update.settings_not_updated") end + + redirect_to :back end def destroy if params[:user] && params[:user][:current_password] && current_user.valid_password?(params[:user][:current_password]) current_user.close_account! sign_out current_user - redirect_to(stream_path, :notice => I18n.t('users.destroy.success')) + redirect_to(new_user_session_path(format: request[:format]), notice: I18n.t("users.destroy.success")) else if params[:user].present? && params[:user][:current_password].present? - flash[:error] = t 'users.destroy.wrong_password' + flash[:error] = t "users.destroy.wrong_password" else - flash[:error] = t 'users.destroy.no_password' + flash[:error] = t "users.destroy.no_password" end redirect_to :back end @@ -105,16 +69,16 @@ class UsersController < ApplicationController respond_to do |format| format.atom do @posts = Post.where(author_id: @user.person_id, public: true) - .order('created_at DESC') - .limit(25) - .map {|post| post.is_a?(Reshare) ? post.absolute_root : post } - .compact + .order("created_at DESC") + .limit(25) + .map {|post| post.is_a?(Reshare) ? post.absolute_root : post } + .compact end format.any { redirect_to person_path(@user.person) } end else - redirect_to stream_path, :error => I18n.t('users.public.does_not_exist', :username => params[:username]) + redirect_to stream_path, error: I18n.t("users.public.does_not_exist", username: params[:username]) end end @@ -122,6 +86,7 @@ class UsersController < ApplicationController @user = current_user @person = @user.person @profile = @user.profile + gon.preloads[:inviter] = PersonPresenter.new(current_user.invited_by.try(:person), current_user).as_json render "users/getting_started" end @@ -135,7 +100,7 @@ class UsersController < ApplicationController def export_profile current_user.queue_export - flash[:notice] = I18n.t('users.edit.export_in_progress') + flash[:notice] = I18n.t("users.edit.export_in_progress") redirect_to edit_user_path end @@ -145,7 +110,7 @@ class UsersController < ApplicationController def export_photos current_user.queue_export_photos - flash[:notice] = I18n.t('users.edit.export_photos_in_progress') + flash[:notice] = I18n.t("users.edit.export_photos_in_progress") redirect_to edit_user_path end @@ -165,15 +130,16 @@ class UsersController < ApplicationController def confirm_email if current_user.confirm_email(params[:token]) - flash[:notice] = I18n.t('users.confirm_email.email_confirmed', :email => current_user.email) + flash[:notice] = I18n.t("users.confirm_email.email_confirmed", email: current_user.email) elsif current_user.unconfirmed_email.present? - flash[:error] = I18n.t('users.confirm_email.email_not_confirmed') + flash[:error] = I18n.t("users.confirm_email.email_not_confirmed") end redirect_to edit_user_path end private + # rubocop:disable Metrics/MethodLength def user_params params.fetch(:user).permit( :email, @@ -181,27 +147,87 @@ class UsersController < ApplicationController :password, :password_confirmation, :language, + :color_theme, :disable_mail, - :invitation_service, - :invitation_identifier, :show_community_spotlight_in_stream, - :strip_exif, :auto_follow_back, :auto_follow_back_aspect_id, - :remember_me, :getting_started, - email_preferences: [ - :someone_reported, - :also_commented, - :mentioned, - :comment_on_post, - :private_message, - :started_sharing, - :liked, - :reshared - ] + email_preferences: %i( + someone_reported + also_commented + mentioned + comment_on_post + private_message + started_sharing + liked + reshared + ) ) end + # rubocop:enable Metrics/MethodLength + + def update_user(user_data) + if user_data[:email_preferences] + change_email_preferences(user_data) + elsif user_data[:language] + change_language(user_data) + elsif user_data[:email] + change_email(user_data) + elsif user_data[:auto_follow_back] + change_settings(user_data, "users.update.follow_settings_changed", "users.update.follow_settings_not_changed") + elsif user_data[:color_theme] + change_settings(user_data, "users.update.color_theme_changed", "users.update.color_theme_not_changed") + else + change_settings(user_data) + end + end + + def change_password(user_data) + if @user.update_with_password(user_data) + flash[:notice] = t("users.update.password_changed") + true + else + flash.now[:error] = t("users.update.password_not_changed") + false + end + end + + # change email notifications + def change_email_preferences(user_data) + @user.update_user_preferences(user_data[:email_preferences]) + flash.now[:notice] = t("users.update.email_notifications_changed") + end + + def change_language(user_data) + if @user.update_attributes(user_data) + I18n.locale = @user.language + flash.now[:notice] = t("users.update.language_changed") + else + flash.now[:error] = t("users.update.language_not_changed") + end + end + + def change_email(user_data) + @user.unconfirmed_email = user_data[:email] + if @user.save + @user.send_confirm_email + if @user.unconfirmed_email + flash.now[:notice] = t("users.update.unconfirmed_email_changed") + end + else + @user.reload # match user object with the database + flash.now[:error] = t("users.update.unconfirmed_email_not_changed") + end + end + + def change_settings(user_data, successful="users.update.settings_updated", error="users.update.settings_not_updated") + if @user.update_attributes(user_data) + flash.now[:notice] = t(successful) + else + flash.now[:error] = t(error) + end + end def set_email_preferences @email_prefs = Hash.new(true) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e0952ff4ce3da3e403672899f577ad3838d4c211..b488aa4c61d585e9d56859a382f71e129f408f34 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -25,8 +25,10 @@ module ApplicationHelper timeago_tag(time, options.merge(:class => 'timeago', :title => time.iso8601, :force => true)) if time end - def bookmarklet_url( height = 400, width = 620) - "javascript:(function(){f='#{AppConfig.pod_uri.to_s}bookmarklet?url='+encodeURIComponent(window.location.href)+'&title='+encodeURIComponent(document.title)+'¬es='+encodeURIComponent(''+(window.getSelection?window.getSelection():document.getSelection?document.getSelection():document.selection.createRange().text))+'&v=1&';a=function(){if(!window.open(f+'noui=1&jump=doclose','diasporav1','location=yes,links=no,scrollbars=yes,toolbar=no,width=#{width},height=#{height}'))location.href=f+'jump=yes'};if(/Firefox/.test(navigator.userAgent)){setTimeout(a,0)}else{a()}})()" + def bookmarklet_code(height=400, width=620) + "javascript:" + + BookmarkletRenderer.body + + "bookmarklet('#{bookmarklet_url}', #{width}, #{height});" end def contacts_link @@ -50,11 +52,11 @@ module ApplicationHelper def jquery_include_tag buf = [] if AppConfig.privacy.jquery_cdn? - version = Jquery::Rails::JQUERY_VERSION + version = Jquery::Rails::JQUERY_2_VERSION buf << [ javascript_include_tag("//code.jquery.com/jquery-#{version}.min.js") ] - buf << [ javascript_tag("!window.jQuery && document.write(unescape('#{j javascript_include_tag("jquery")}'));") ] + buf << [javascript_tag("!window.jQuery && document.write(unescape('#{j javascript_include_tag('jquery2')}'));")] else - buf << [ javascript_include_tag('jquery') ] + buf << [javascript_include_tag("jquery2")] end buf << [ javascript_include_tag('jquery_ujs') ] buf << [ javascript_tag("jQuery.ajaxSetup({'cache': false});") ] diff --git a/app/helpers/aspect_global_helper.rb b/app/helpers/aspect_global_helper.rb index d51fa05282f341c6c4a8f0b483b4b5d6b7f3ff8e..421215b7d2cf66e0dbcdbd6d74e806b3171d9cfe 100644 --- a/app/helpers/aspect_global_helper.rb +++ b/app/helpers/aspect_global_helper.rb @@ -3,51 +3,6 @@ # the COPYRIGHT file. module AspectGlobalHelper - def aspect_membership_dropdown(contact, person, hang, aspect=nil, size="small") - aspect_membership_ids = {} - - selected_aspects = all_aspects.select{|aspect| contact.in_aspect?(aspect)} - selected_aspects.each do |a| - record = a.aspect_memberships.find { |am| am.contact_id == contact.id } - aspect_membership_ids[a.id] = record.id - end - - button_class = selected_aspects.size>0 ? "green" : "btn-default" - button_class << case size - when "small" - " btn-small" - when "normal" - "" - when "large" - " btn-large" - else - raise ArgumentError, "unknown size #{size}" - end - - render "aspect_memberships/aspect_membership_dropdown", - :selected_aspects => selected_aspects, - :aspect_membership_ids => aspect_membership_ids, - :person => person, - :hang => hang, - :dropdown_class => "aspect_membership", - :button_class => button_class - end - - def aspect_dropdown_list_item(aspect, am_id=nil) - klass = am_id.present? ? "selected" : "" - - str = <<LISTITEM -<li data-aspect_id="#{aspect.id}" data-membership_id="#{am_id}" class="#{klass} aspect_selector" tabindex="0"> - #{aspect.name} -</li> -LISTITEM - str.html_safe - end - - def dropdown_may_create_new_aspect - @aspect == :profile || @aspect == :tag || @aspect == :notification || params[:action] == "getting_started" - end - def aspect_options_for_select(aspects) options = {} aspects.each do |aspect| diff --git a/app/helpers/contacts_helper.rb b/app/helpers/contacts_helper.rb index 6409d2571224cb11c1021629ba0d35d53d66fe55..3f25d326b3fe03d2faa30e6ba45b81f7d39870d0 100644 --- a/app/helpers/contacts_helper.rb +++ b/app/helpers/contacts_helper.rb @@ -1,16 +1,12 @@ module ContactsHelper - def contact_aspect_dropdown(contact) - render :partial => 'people/relationship_action', - :locals => { :person => contact.person, - :contact => contact, - :current_user => current_user } - end - def start_a_conversation_link(aspect, contacts_size) conv_opts = { class: "conversation_button contacts_button"} content_tag :span, conv_opts do - content_tag(:i, nil, :class => 'entypo mail contacts-header-icon', :title => t('contacts.index.start_a_conversation'), 'data-toggle' => 'modal', 'data-target' => '#conversationModal') + content_tag :i, + nil, + class: "entypo-mail contacts-header-icon", + title: t("contacts.index.start_a_conversation") end end end diff --git a/app/helpers/error_messages_helper.rb b/app/helpers/error_messages_helper.rb index 46480b1d37eb5e2a264acad746fd2909489c5632..73b1cab9d6ee433fe8f6cd5e6cffefe8ae139779 100644 --- a/app/helpers/error_messages_helper.rb +++ b/app/helpers/error_messages_helper.rb @@ -9,7 +9,7 @@ module ErrorMessagesHelper options[:message] ||= I18n.t('error_messages.helper.correct_the_following_errors_and_try_again') messages = objects.compact.map { |o| o.errors.full_messages }.flatten unless messages.empty? - content_tag(:div, class: "text-error") do + content_tag(:div, class: "text-danger") do list_items = messages.map { |msg| content_tag(:li, msg) } content_tag(:h2, options[:header_message]) + content_tag(:p, options[:message]) + content_tag(:ul, list_items.join.html_safe) end diff --git a/app/helpers/getting_started_helper.rb b/app/helpers/getting_started_helper.rb index 1be8d1419f9e908b1b8f2962bf6f82af10fad222..fcb8fbc696dbea3a7c6d7263358601657d2a1e14 100644 --- a/app/helpers/getting_started_helper.rb +++ b/app/helpers/getting_started_helper.rb @@ -7,16 +7,4 @@ module GettingStartedHelper def has_completed_getting_started? current_user.getting_started == false end - - def tag_link(tag_name) - if tag_followed?(tag_name) - link_to "##{tag_name}", tag_followings_path(tag_name), :method => :delete, :class => "featured_tag followed" - else - link_to "##{tag_name}", tag_tag_followings_path(tag_name), :method => :post, :class => "featured_tag" - end - end - - def tag_followed?(tag_name) - tags.detect{|t| t.name == tag_name} - end end diff --git a/app/helpers/gon_helper.rb b/app/helpers/gon_helper.rb new file mode 100644 index 0000000000000000000000000000000000000000..f4bb9689d0873adee09e8e3044215b4bf7e7c985 --- /dev/null +++ b/app/helpers/gon_helper.rb @@ -0,0 +1,8 @@ +module GonHelper + def gon_load_contact(contact) + Gon.preloads[:contacts] ||= [] + if Gon.preloads[:contacts].none? {|stored_contact| stored_contact[:person][:id] == contact.person_id } + Gon.preloads[:contacts] << ContactPresenter.new(contact, current_user).full_hash_with_person + end + end +end diff --git a/app/helpers/interim_stream_hackiness_helper.rb b/app/helpers/interim_stream_hackiness_helper.rb index 9ed9ad7a907b5988cf06bf1def7eaa8f985b0c40..4219d29fe48109cdce48790a3f82355a107e94f8 100644 --- a/app/helpers/interim_stream_hackiness_helper.rb +++ b/app/helpers/interim_stream_hackiness_helper.rb @@ -39,27 +39,19 @@ module InterimStreamHackinessHelper end end + def publisher_method(method) + @stream.try(:publisher).try(method) == true + end + def publisher_open - if defined?(@stream) - @stream.publisher.open? - else - false - end + publisher_method(:open) end def publisher_public - if defined?(@stream) - @stream.publisher.public? - else - false - end + publisher_method(:public) end def publisher_explain - if defined?(@stream) - @stream.publisher.public? - else - false - end + publisher_method(:explain) end end diff --git a/app/helpers/invitation_codes_helper.rb b/app/helpers/invitation_codes_helper.rb index a0f614f42b5067ef617c27761169240c358b6685..991cb826c5058ed32c1b3e9cd3c903c0e7b60f59 100644 --- a/app/helpers/invitation_codes_helper.rb +++ b/app/helpers/invitation_codes_helper.rb @@ -6,14 +6,14 @@ module InvitationCodesHelper end def invite_link(invite_code) - text_field_tag :invite_code, invite_code_url(invite_code), :readonly => true + text_field_tag :invite_code, invite_code_url(invite_code), class: "form-control", readonly: true end def invited_by_message inviter = current_user.invited_by if inviter.present? - contact = current_user.contact_for(inviter.person) || Contact.new - render :partial => 'people/add_contact', :locals => {:inviter => inviter.person, :contact => contact} + @person = inviter.person + render partial: "people/add_contact" end end end diff --git a/app/helpers/language_helper.rb b/app/helpers/language_helper.rb index 13ef1b5c16d00ce5c2a4181f942599e6a028bcba..1b890ad34921b742de0e75e72786d8b53a724042 100644 --- a/app/helpers/language_helper.rb +++ b/app/helpers/language_helper.rb @@ -1,4 +1,6 @@ module LanguageHelper + include ApplicationHelper + def available_language_options options = [] AVAILABLE_LANGUAGES.each do |locale, language| diff --git a/app/helpers/layout_helper.rb b/app/helpers/layout_helper.rb index 6468326775f1c847d493a8f0412bc9d889c3b3bd..548ef208238b22a5700f52221e678dbabe05a370 100644 --- a/app/helpers/layout_helper.rb +++ b/app/helpers/layout_helper.rb @@ -46,8 +46,8 @@ module LayoutHelper end end - def include_base_css_framework - stylesheet_link_tag('bootstrap-complete') + def include_color_theme(view="desktop") + stylesheet_link_tag "#{current_color_theme}/#{view}", media: "all" end def old_browser_js_support @@ -67,8 +67,9 @@ module LayoutHelper def flash_messages flash.map do |name, msg| - content_tag(:div, :id => "flash_#{name}") do - content_tag(:div, msg, :class => 'message') + klass = flash_class name + content_tag(:div, msg, class: "flash-body expose") do + content_tag(:div, msg, class: "flash-message message alert alert-#{klass}", role: "alert") end end.join(' ').html_safe end diff --git a/app/helpers/meta_data_helper.rb b/app/helpers/meta_data_helper.rb new file mode 100644 index 0000000000000000000000000000000000000000..6b3dcfc7f6cfcfe84d32f907ef379300729a283a --- /dev/null +++ b/app/helpers/meta_data_helper.rb @@ -0,0 +1,53 @@ +module MetaDataHelper + include ActionView::Helpers::AssetUrlHelper + include ActionView::Helpers::TagHelper + + def og_prefix + 'og: http://ogp.me/ns# article: http://ogp.me/ns/article# profile: http://ogp.me/ns/profile#' + end + + def site_url + AppConfig.environment.url + end + + def default_image_url + asset_url "assets/branding/logos/asterisk.png" + end + + def default_author_name + AppConfig.settings.pod_name + end + + def default_description + AppConfig.settings.default_metas.description + end + + def default_title + AppConfig.settings.default_metas.title + end + + def general_metas + { + description: {name: "description", content: default_description}, + og_description: {property: "description", content: default_description}, + og_site_name: {property: "og:site_name", content: default_title}, + og_url: {property: "og:url", content: site_url}, + og_image: {property: "og:image", content: default_image_url}, + og_type: {property: "og:type", content: "website"} + } + end + + def metas_tags(attributes_list={}, with_general_metas=true) + attributes_list = general_metas.merge(attributes_list) if with_general_metas + attributes_list.map {|_, attributes| meta_tag attributes }.join("\n").html_safe + end + + # recursively calls itself if attribute[:content] is an array + # (metas such as og:image or og:tag can be present multiple times with different values) + def meta_tag(attributes) + return "" if attributes.empty? + return tag(:meta, attributes) unless attributes[:content].respond_to?(:to_ary) + items = attributes.delete(:content) + items.map {|item| meta_tag(attributes.merge(content: item)) }.join("\n") + end +end diff --git a/app/helpers/mobile_helper.rb b/app/helpers/mobile_helper.rb index 470038b4a881d2ac76c6a1d95e888485c437b5ca..23cc959fbbbfe3a44d6eb01c4920e20a89e227f5 100644 --- a/app/helpers/mobile_helper.rb +++ b/app/helpers/mobile_helper.rb @@ -1,41 +1,55 @@ module MobileHelper - def aspect_select_options(aspects, selected) - selected_id = selected == :all ? "" : selected.id - '<option value="" >All</option>\n'.html_safe + options_from_collection_for_select(aspects, "id", "name", selected_id) - end - def mobile_reshare_icon(post) if (post.public? || reshare?(post)) && (user_signed_in? && post.author != current_user.person) absolute_root = reshare?(post) ? post.absolute_root : post if absolute_root && absolute_root.author != current_user.person - reshare = Reshare.where(:author_id => current_user.person_id, - :root_guid => absolute_root.guid).first + reshare = Reshare.where(author_id: current_user.person_id, + root_guid: absolute_root.guid).first klass = reshare.present? ? "active" : "inactive" - link_to '', reshares_path(:root_guid => absolute_root.guid), :title => t('reshares.reshare.reshare_confirmation', :author => absolute_root.author_name), :class => "image_link reshare_action #{klass}" + link_to "", reshares_path(root_guid: absolute_root.guid), + title: t("reshares.reshare.reshare_confirmation", author: absolute_root.author_name), + class: "entypo-reshare reshare-action #{klass}" + else + content_tag :div, nil, class: "entypo-reshare reshare-action disabled" end + else + content_tag :div, nil, class: "entypo-reshare reshare-action disabled" end end def mobile_like_icon(post) if current_user && current_user.liked?(post) - link_to '', post_like_path(post.id, current_user.like_for(post).id), :class => "image_link like_action active" + link_to "", + "#", + data: {url: post_like_path(post.id, current_user.like_for(post).id)}, + class: "entypo-heart like-action active" else - link_to '', post_likes_path(post.id), :class => "image_link like_action inactive" + link_to "", + "#", + data: {url: post_likes_path(post.id)}, + class: "entypo-heart like-action inactive" end end def mobile_comment_icon(post) - link_to '', new_post_comment_path(post), :class => "image_link comment_action inactive" + link_to "", new_post_comment_path(post), class: "entypo-comment comment-action inactive" end - def reactions_link(post) + def reactions_link(post, klass="") reactions_count = post.comments_count + post.likes_count + if klass == "active" + entypo_class = "entypo-chevron-up" + else + entypo_class = "entypo-chevron-down" + end if reactions_count > 0 - link_to "#{t('reactions', :count => reactions_count)}", post_comments_path(post, :format => "mobile"), :class => 'show_comments' + link_to "#{t('reactions', count: reactions_count)}<i class='#{entypo_class}'></i>".html_safe, + post_comments_path(post, format: "mobile"), + class: "show-comments #{klass}" else - html = "<span class='show_comments'>" - html << "#{t('reactions', :count => reactions_count)}" + html = "<span class='show-comments'>" + html << "#{t('reactions', count: reactions_count)}" html << "</span>" end end diff --git a/app/helpers/open_graph_helper.rb b/app/helpers/open_graph_helper.rb index b68dc3a960290ee7a9abfb79f2a4fe3615bc22bb..b337616458c0caffc62c2066b23b958fe4602e08 100644 --- a/app/helpers/open_graph_helper.rb +++ b/app/helpers/open_graph_helper.rb @@ -1,79 +1,4 @@ module OpenGraphHelper - def og_title(title) - meta_tag_with_property('og:title', title) - end - - def og_type(post) - meta_tag_with_property('og:type', 'article') - end - - def og_url(url) - meta_tag_with_property('og:url', url) - end - - def og_image(post=nil) - tags = [] - tags = post.photos.map{|x| meta_tag_with_property('og:image', x.url(:thumb_large))} if post - tags << meta_tag_with_property('og:image', default_image_url) if tags.empty? - tags.join(' ') - end - - def og_description(description) - meta_tag_with_property('og:description', description) - end - - def og_type(type='website') - meta_tag_with_property('og:type', type) - end - - def og_namespace - AppConfig.services.facebook.open_graph_namespace - end - - def og_site_name - meta_tag_with_property('og:site_name', AppConfig.settings.pod_name) - end - - def og_common_tags - [og_site_name] - end - - def og_general_tags - [ - *og_common_tags, - og_type, - og_title('diaspora* social network'), - og_image, - og_url(AppConfig.environment.url), - og_description('diaspora* is the online social world where you are in control.') - ].join("\n").html_safe - end - - def og_page_post_tags(post) - tags = og_common_tags - - if post.message - tags.concat [ - *tags, - og_type("#{og_namespace}:frame"), - og_title(post_page_title(post, :length => 140)), - og_url(post_url(post)), - og_image(post), - og_description(post.message.plain_text_without_markdown truncate: 1000) - ] - end - - tags.join("\n").html_safe - end - - def og_prefix - "og: http://ogp.me/ns# #{og_namespace}: https://diasporafoundation.org/ns/joindiaspora#" - end - - def meta_tag_with_property(name, content) - tag(:meta, :property => name, :content => content) - end - def og_html(cache) "<a href=\"#{cache.url}\" target=\"_blank\">" + " <div>" + @@ -91,14 +16,4 @@ module OpenGraphHelper def oembed_image_tag(cache, prefix) image_tag(cache.data["#{prefix}url"], cache.options_hash(prefix)) end - private - - # This method compensates for hosting assets off of s3 - def default_image_url - if image_path("branding/logos/asterisk.png").include?("http") - image_path("branding/logos/asterisk.png") - else - "#{root_url.chop}#{image_path('branding/logos/asterisk.png')}" - end - end end diff --git a/app/helpers/people_helper.rb b/app/helpers/people_helper.rb index a7df8d8f9300feb7cbcf7aa5f91260a2e33540cb..18461351e5ea94c4e4c520d63dfe9f146a2cfb83 100644 --- a/app/helpers/people_helper.rb +++ b/app/helpers/people_helper.rb @@ -28,12 +28,15 @@ module PeopleHelper opts[:class] << " self" if defined?(user_signed_in?) && user_signed_in? && current_user.person == person opts[:class] << " hovercardable" if defined?(user_signed_in?) && user_signed_in? && current_user.person != person remote_or_hovercard_link = Rails.application.routes.url_helpers.person_path(person).html_safe - "<a data-hovercard='#{remote_or_hovercard_link}' href='#{remote_or_hovercard_link}' class='#{opts[:class]}' #{ ("target=" + opts[:target]) if opts[:target]}>#{h(person.name)}</a>".html_safe + "<a data-hovercard='#{remote_or_hovercard_link}' href='#{remote_or_hovercard_link}' class='#{opts[:class]}'>"\ + "#{html_escape_once(opts[:display_name] || person.name)}</a>"\ + .html_safe end def person_image_tag(person, size = :thumb_small) return "" if person.nil? || person.profile.nil? - image_tag(person.profile.image_url(size), :alt => person.name, :class => 'avatar', :title => person.name, 'data-person_id' => person.id) + image_tag(person.profile.image_url(size), alt: person.name, class: "avatar img-responsive center-block", + title: person.name, "data-person_id" => person.id) end def person_image_link(person, opts={}) @@ -57,7 +60,7 @@ module PeopleHelper absolute = opts.delete(:absolute) if person.local? - username = person.diaspora_handle.split('@')[0] + username = person.username unless username.include?('.') opts.merge!(:username => username) if absolute diff --git a/app/helpers/publisher_helper.rb b/app/helpers/publisher_helper.rb index 8886947250f5c733f2ece53590537d13f7360930..1e7e326a90517eef5b8740faa4c5ee12c5c4c99b 100644 --- a/app/helpers/publisher_helper.rb +++ b/app/helpers/publisher_helper.rb @@ -12,16 +12,19 @@ module PublisherHelper end def service_button(service) + provider_title = I18n.t( + "services.index.share_to", + provider: service.provider.titleize) content_tag :div, - :class => "btn btn-link service_icon dim", - :title => "#{service.provider.titleize} (#{service.nickname})", - :id => "#{service.provider}", - :maxchar => "#{service.class::MAX_CHARACTERS}", - :data => {:toggle=>'tooltip', :placement=>'bottom'} do - if service.provider == 'wordpress' - content_tag(:span, '', :class => "social_media_logos-wordpress-16x16") + class: "btn btn-link service_icon dim", + title: "#{provider_title} (#{service.nickname})", + id: "#{service.provider}", + maxchar: "#{service.class::MAX_CHARACTERS}", + data: {toggle: "tooltip", placement: "bottom"} do + if service.provider == "wordpress" + content_tag(:span, "", class: "social-media-logos-wordpress-16x16") else - content_tag(:i, '', :class => "entypo small #{ service.provider }") + content_tag(:i, "", class: "entypo-social-#{ service.provider } small") end end end diff --git a/app/helpers/report_helper.rb b/app/helpers/report_helper.rb index 2170e3665823f4adfe6073eb8d44215218a0eda0..9eb0178436df98755af1488980d62020b2044f15 100644 --- a/app/helpers/report_helper.rb +++ b/app/helpers/report_helper.rb @@ -3,15 +3,17 @@ # the COPYRIGHT file. module ReportHelper - def report_content(id, type) - if type == 'post' && !(post = Post.find_by_id(id)).nil? - raw t('report.post_label', title: link_to(post_page_title(post), post_path(id))) - elsif type == 'comment' && !(comment = Comment.find_by_id(id)).nil? - # comment_message is not html_safe. To prevent - # cross-site-scripting we have to escape html - raw t('report.comment_label', data: link_to(h(comment_message(comment)), post_path(comment.post.id, anchor: comment.guid))) + def report_content(report) + case (item = report.item) + when Post + raw t("report.post_label", title: link_to(post_page_title(item), post_path(item.id))) + when Comment + raw t("report.comment_label", data: link_to( + h(comment_message(item)), + post_path(item.post.id, anchor: item.author.guid) + )) else - raw t('report.not_found') + raw t("report.not_found") end end end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index f76d793a126615c0ae75fa8bf9f21f17070e8ba4..65a9bdaf452996972a09ddb2555802909d9b1f71 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -1,6 +1,6 @@ module SessionsHelper def prefilled_username - uri = Addressable::URI.parse(session['user_return_to']) + uri = Addressable::URI.parse(session["user_return_to"]) if uri && uri.query_values uri.query_values["username"] else @@ -9,10 +9,14 @@ module SessionsHelper end def display_registration_link? - AppConfig.settings.enable_registrations? && devise_mapping.registerable? && controller_name != 'registrations' + AppConfig.settings.enable_registrations? && devise_mapping.registerable? && controller_name != "registrations" end def display_password_reset_link? - devise_mapping.recoverable? && controller_name != 'passwords' + devise_mapping.recoverable? && controller_name != "passwords" + end + + def flash_class(name) + {notice: "success", alert: "danger", error: "danger"}[name.to_sym] end end diff --git a/app/helpers/user_applications_helper.rb b/app/helpers/user_applications_helper.rb new file mode 100644 index 0000000000000000000000000000000000000000..190c43580eb1ea2270cdf3f094cde6b8974574b0 --- /dev/null +++ b/app/helpers/user_applications_helper.rb @@ -0,0 +1,9 @@ +module UserApplicationsHelper + def user_application_name(app) + if app.name? + "#{html_escape app.name} (#{link_to(app.url, app.url)})" + else + link_to(app.url, app.url) + end + end +end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 0b81a4a3d4dffe72fa33406e2c0eee00de70b466..d79b6b0595891c0c50f6747bbbaef102bee74bed 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -6,4 +6,39 @@ module UsersHelper def owner_image_link person_image_link(current_user.person, :size => :thumb_small) end + + # Returns the path of the current color theme so that it + # can be loaded in app/views/layouts/application.html.haml + # and app/views/layouts/application.mobile.haml. If the user + # is not signed in or has not specified a color theme, the + # default (original) color theme is loaded. + # + # @example if user is not signed in + # current_color_theme #=> "color_themes/original" + # @example if user Alice has not selected a color theme + # current_color_theme #=> "color_themes/original" + # @example if user Alice has selected a "magenta" theme + # current_color_theme #=> "color_themes/magenta" + def current_color_theme + if user_signed_in? + color_theme = current_user.color_theme + end + color_theme ||= AppConfig.settings.default_color_theme + "color_themes/#{color_theme}" + end + + # Returns an array of the color themes available, as + # specified from AVAILABLE_COLOR_THEMES in + # config/initializers/color_themes.rb. + # + # @example if AVAILABLE_COLOR_THEMES = {"original"=>"Original dark", "dark_green" => "Dark green"} + # available_color_themes + # #=> [["Original dark", "original"], ["Dark green", "dark_green"]] + def available_color_themes + opts = [] + AVAILABLE_COLOR_THEMES.map do |theme_code, theme_name| + opts << [theme_name, theme_code] + end + opts + end end diff --git a/app/mailers/notification_mailers/private_message.rb b/app/mailers/notification_mailers/private_message.rb index 6698ba64721addd0501e31579ab90d1e39627bac..ed40e70dd7efb2ad7a4c852f2d9ba93c5fcc7168 100644 --- a/app/mailers/notification_mailers/private_message.rb +++ b/app/mailers/notification_mailers/private_message.rb @@ -8,8 +8,7 @@ module NotificationMailers @participants = @conversation.participants @headers[:from] = "\"#{@message.author_name} (diaspora*)\" <#{AppConfig.mail.sender_address}>" - @headers[:subject] = @conversation.subject.strip - @headers[:subject] = "Re: #{@headers[:subject]}" if @conversation.messages.size > 1 + @headers[:subject] = I18n.t("notifier.private_message.subject") end end end diff --git a/app/mailers/report_mailer.rb b/app/mailers/report_mailer.rb index 35aafcf3e1e9267400a51f35cd812cb2cabdabe7..dbb3c2f125bcf96ef511cd84a7fdbf269049af5a 100644 --- a/app/mailers/report_mailer.rb +++ b/app/mailers/report_mailer.rb @@ -1,15 +1,17 @@ class ReportMailer < ActionMailer::Base default from: AppConfig.mail.sender_address - def self.new_report(type, id) - Role.moderators.map {|role| super(type, id, role) } + def self.new_report(report_id) + report = Report.find_by_id(report_id) + Role.moderators.map {|role| super(report.item_type, report.item_id, report.text, role) } end - def new_report(type, id, role) + def new_report(type, id, reason, role) resource = { - url: report_index_url, - type: I18n.t("notifier.report_email.type." + type), - id: id + url: report_index_url, + type: I18n.t("notifier.report_email.type.#{type.downcase}"), + id: id, + reason: reason } person = Person.find(role.person_id) return unless person.local? diff --git a/app/models/account_deletion.rb b/app/models/account_deletion.rb index a8918d58766df9c6e4c49ac7d12a8607e8271ebd..bab962dca2c2b2ae8aee05e9dcd35367d68d3b49 100644 --- a/app/models/account_deletion.rb +++ b/app/models/account_deletion.rb @@ -10,10 +10,6 @@ class AccountDeletion < ActiveRecord::Base belongs_to :person after_commit :queue_delete_account, :on => :create - xml_name :account_deletion - xml_attr :diaspora_handle - - def person=(person) self[:diaspora_handle] = person.diaspora_handle self[:person_id] = person.id @@ -29,18 +25,14 @@ class AccountDeletion < ActiveRecord::Base end def perform! - self.dispatch if person.local? - AccountDeleter.new(self.diaspora_handle).perform! + Diaspora::Federation::Dispatcher.build(person.owner, self).dispatch if person.local? + AccountDeleter.new(diaspora_handle).perform! end - def subscribers(user) + def subscribers person.owner.contact_people.remote | Person.who_have_reshared_a_users_posts(person.owner).remote end - def dispatch - Postzord::Dispatcher.build(person.owner, self).post - end - def public? true end diff --git a/app/models/api/openid_connect/authorization.rb b/app/models/api/openid_connect/authorization.rb new file mode 100644 index 0000000000000000000000000000000000000000..41c6c0e6fc3f7ba481acb8e582a9d9f0b375deb2 --- /dev/null +++ b/app/models/api/openid_connect/authorization.rb @@ -0,0 +1,90 @@ +# Inspired by https://github.com/nov/openid_connect_sample/blob/master/app/models/authorization.rb + +module Api + module OpenidConnect + class Authorization < ActiveRecord::Base + belongs_to :user + belongs_to :o_auth_application + + validates :user, presence: true, uniqueness: {scope: :o_auth_application} + validates :o_auth_application, presence: true + validate :validate_scope_names + serialize :scopes, JSON + + has_many :o_auth_access_tokens, dependent: :destroy + + before_validation :setup, on: :create + + scope :with_redirect_uri, ->(given_uri) { where redirect_uri: given_uri } + + SCOPES = %w(openid sub aud name nickname profile picture read write) + + def setup + self.refresh_token = SecureRandom.hex(32) + end + + def validate_scope_names + return unless scopes + scopes.each do |scope| + errors.add(:scope, "is not a valid scope name") unless SCOPES.include? scope + end + end + + # Inspired by https://github.com/nov/openid_connect_sample/blob/master/app/models/access_token.rb#L26 + def accessible?(required_scopes=nil) + Array(required_scopes).all? { |required_scope| + scopes.include? required_scope + } + end + + def create_code + SecureRandom.hex(32).tap do |code| + update!(code: code) + update!(code_used: false) + end + end + + def create_access_token + o_auth_access_tokens.create!.bearer_token + end + + def create_id_token + IdToken.new(self, nonce) + end + + def self.find_by_client_id_user_and_scopes(client_id, user, scopes) + app = Api::OpenidConnect::OAuthApplication.where(client_id: client_id) + authorizations = where(o_auth_application: app, user: user).all + authorizations.each do |authorization| + if authorization.scopes.uniq.sort == Array(scopes).uniq.sort + return authorization + end + end + nil + end + + def self.find_by_client_id_and_user(client_id, user) + app = Api::OpenidConnect::OAuthApplication.where(client_id: client_id) + find_by(o_auth_application: app, user: user) + end + + def self.find_by_refresh_token(client_id, refresh_token) + app = Api::OpenidConnect::OAuthApplication.where(client_id: client_id) + find_by(o_auth_application: app, refresh_token: refresh_token) + end + + def self.use_code(code) + return unless code + auth = find_by(code: code) + return unless auth + if auth.code_used + auth.destroy + nil + else + auth.update!(code_used: true) + auth + end + end + end + end +end diff --git a/app/models/api/openid_connect/o_auth_access_token.rb b/app/models/api/openid_connect/o_auth_access_token.rb new file mode 100644 index 0000000000000000000000000000000000000000..053bc86df027d51e49a65d127500913c961df813 --- /dev/null +++ b/app/models/api/openid_connect/o_auth_access_token.rb @@ -0,0 +1,49 @@ +# Copyright (c) 2011 nov matake +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# See https://github.com/nov/openid_connect_sample/blob/master/app/models/access_token.rb + +module Api + module OpenidConnect + class OAuthAccessToken < ActiveRecord::Base + belongs_to :authorization + + before_validation :setup, on: :create + + validates :token, presence: true, uniqueness: true + validates :authorization, presence: true + + scope :valid, ->(time) { where("expires_at >= ?", time) } + + def setup + self.token = SecureRandom.hex(32) + self.expires_at = 24.hours.from_now + end + + def bearer_token + @bearer_token ||= Rack::OAuth2::AccessToken::Bearer.new( + access_token: token, + expires_in: (expires_at - Time.zone.now.utc).to_i + ) + end + end + end +end diff --git a/app/models/api/openid_connect/o_auth_application.rb b/app/models/api/openid_connect/o_auth_application.rb new file mode 100644 index 0000000000000000000000000000000000000000..ccceadfeaab1c09f1894bac15ffa1eb5a970d16a --- /dev/null +++ b/app/models/api/openid_connect/o_auth_application.rb @@ -0,0 +1,119 @@ +# Copyright (c) 2011 nov matake +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# See https://github.com/nov/openid_connect_sample/blob/master/app/models/client.rb + +require "digest" + +module Api + module OpenidConnect + class OAuthApplication < ActiveRecord::Base + has_many :authorizations, dependent: :destroy + has_many :user, through: :authorizations + + validates :client_id, presence: true, uniqueness: true + validates :client_secret, presence: true + validates :client_name, uniqueness: {scope: :redirect_uris} + + %i(redirect_uris response_types grant_types contacts jwks).each do |serializable| + serialize serializable, JSON + end + + before_validation :setup, on: :create + before_validation do + redirect_uris.sort! + end + + def setup + self.client_id = SecureRandom.hex(16) + self.client_secret = SecureRandom.hex(32) + end + + def image_uri + logo_uri ? Diaspora::Camo.image_url(logo_uri) : nil + end + + class << self + def available_response_types + ["id_token", "id_token token", "code"] + end + + def register!(registrar) + registrar.validate! + build_client_application(registrar) + end + + private + + def build_client_application(registrar) + attributes = registrar_attributes(registrar) + check_sector_identifier_uri(attributes) + check_redirect_uris(attributes) + create! attributes + end + + def check_sector_identifier_uri(attributes) + sector_identifier_uri = attributes[:sector_identifier_uri] + return unless sector_identifier_uri + response = Faraday.get(sector_identifier_uri) + sector_identifier_uri_json = JSON.parse(response.body) + redirect_uris = attributes[:redirect_uris] + sector_identifier_uri_includes_redirect_uris = (redirect_uris - sector_identifier_uri_json).empty? + return if sector_identifier_uri_includes_redirect_uris + raise Api::OpenidConnect::Error::InvalidSectorIdentifierUri.new + end + + def check_redirect_uris(attributes) + redirect_uris = attributes[:redirect_uris] + uri_array = redirect_uris.map {|uri| URI(uri) } + any_uri_contains_fragment = uri_array.any? {|uri| !uri.fragment.nil? } + return unless any_uri_contains_fragment + raise Api::OpenidConnect::Error::InvalidRedirectUri.new + end + + def supported_metadata + %i(client_name response_types grant_types application_type + contacts logo_uri client_uri policy_uri tos_uri redirect_uris + sector_identifier_uri subject_type token_endpoint_auth_method jwks jwks_uri) + end + + def registrar_attributes(registrar) + supported_metadata.each_with_object({}) do |key, attr| + value = registrar.public_send(key) + next unless value + case key + when :subject_type + attr[:ppid] = (value == "pairwise") + when :jwks_uri + response = Faraday.get(value) + attr[:jwks] = response.body + attr[:jwks_uri] = value + when :jwks + attr[:jwks] = value.to_json + else + attr[key] = value + end + end + end + end + end + end +end diff --git a/app/models/api/openid_connect/pairwise_pseudonymous_identifier.rb b/app/models/api/openid_connect/pairwise_pseudonymous_identifier.rb new file mode 100644 index 0000000000000000000000000000000000000000..7aeccc9fa53d1a2125b2674b856861ad4bf6bf6d --- /dev/null +++ b/app/models/api/openid_connect/pairwise_pseudonymous_identifier.rb @@ -0,0 +1,45 @@ +# Copyright (c) 2011 nov matake +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# See https://github.com/nov/openid_connect_sample/blob/master/app/models/pairwise_pseudonymous_identifier.rb + +module Api + module OpenidConnect + class PairwisePseudonymousIdentifier < ActiveRecord::Base + self.table_name = "ppid" + + belongs_to :o_auth_application + belongs_to :user + + validates :user, presence: true + validates :identifier, presence: true, uniqueness: {scope: :user} + validates :guid, presence: true, uniqueness: true + + before_validation :setup, on: :create + + private + + def setup + self.guid = SecureRandom.hex(16) + end + end + end +end diff --git a/app/models/aspect_visibility.rb b/app/models/aspect_visibility.rb index a5593b8340f9c759ae17ac7b61d5afc3d9b3a770..88e645727122a5a296bc1251c52d474450c7054b 100644 --- a/app/models/aspect_visibility.rb +++ b/app/models/aspect_visibility.rb @@ -10,4 +10,5 @@ class AspectVisibility < ActiveRecord::Base belongs_to :shareable, :polymorphic => true validates :shareable, :presence => true + validates :aspect, uniqueness: {scope: %i(shareable_id shareable_type)} end diff --git a/app/models/comment.rb b/app/models/comment.rb index 547349f8e2e0d6c9f5ec9899ef48d92657129b68..1fac00c8dd80ea1b1b4dcbe49fff729a43f69aec 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -5,8 +5,8 @@ class Comment < ActiveRecord::Base include Diaspora::Federated::Base - - include Diaspora::Guid + include Diaspora::Fields::Guid + include Diaspora::Fields::Author include Diaspora::Relayable include Diaspora::Taggable @@ -16,12 +16,9 @@ class Comment < ActiveRecord::Base extract_tags_from :text before_create :build_tags - xml_attr :text - xml_attr :diaspora_handle - belongs_to :commentable, :touch => true, :polymorphic => true alias_attribute :post, :commentable - belongs_to :author, :class_name => 'Person' + alias_attribute :parent, :commentable delegate :name, to: :author, prefix: true delegate :comment_email_subject, to: :parent @@ -30,6 +27,10 @@ class Comment < ActiveRecord::Base validates :text, :presence => true, :length => {:maximum => 65535} validates :parent, :presence => true #should be in relayable (pending on fixing Message) + has_many :reports, as: :item + + has_one :signature, class_name: "CommentSignature", dependent: :delete + scope :including_author, -> { includes(:author => :profile) } scope :for_a_stream, -> { including_author.merge(order('created_at ASC')) } @@ -37,46 +38,14 @@ class Comment < ActiveRecord::Base self.text.strip! unless self.text.nil? end - after_save do - self.post.touch - end - after_commit :on => :create do self.parent.update_comments_counter end after_destroy do self.parent.update_comments_counter - end - - def diaspora_handle - self.author.diaspora_handle - end - - def diaspora_handle= nh - self.author = Person.find_or_fetch_by_identifier(nh) - end - - def notification_type(user, person) - if self.post.author == user.person - return Notifications::CommentOnPost - elsif user.participations.where(:target_id => self.post).exists? && self.author_id != user.person.id - return Notifications::AlsoCommented - else - return false - end - end - - def parent_class - Post - end - - def parent - self.post - end - - def parent= parent - self.post = parent + participation = author.participations.where(target_id: post.id).first + participation.unparticipate! if participation.present? end def message @@ -87,14 +56,13 @@ class Comment < ActiveRecord::Base self[:text] = text.to_s.strip #to_s if for nil, for whatever reason end - class Generator < Federated::Generator + class Generator < Diaspora::Federated::Generator def self.federated_class Comment end def initialize(person, target, text) @text = text - @dispatcher_opts = {additional_subscribers: target.comments_authors.where.not(id: person.id)} super(person, target) end diff --git a/app/models/comment_signature.rb b/app/models/comment_signature.rb new file mode 100644 index 0000000000000000000000000000000000000000..357bcb3b89c81c1a3dd8aa506c5e5e06bb539f42 --- /dev/null +++ b/app/models/comment_signature.rb @@ -0,0 +1,7 @@ +class CommentSignature < ActiveRecord::Base + include Diaspora::Signature + + self.primary_key = :comment_id + belongs_to :comment + validates :comment, presence: true +end diff --git a/app/models/contact.rb b/app/models/contact.rb index 861ec07715db141dcab922adea3a951067a9485b..c7970a2f95d8ba8ce0e20871ece323c1156d7ecc 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -3,65 +3,49 @@ # the COPYRIGHT file. class Contact < ActiveRecord::Base + include Diaspora::Federated::Base + belongs_to :user + validates :user, presence: true belongs_to :person - validates :person, :presence => true + validates :person, presence: true + + validates :person_id, uniqueness: {scope: :user_id} delegate :name, :diaspora_handle, :guid, :first_name, to: :person, prefix: true - has_many :aspect_memberships, :dependent => :destroy - has_many :aspects, :through => :aspect_memberships - - has_many :share_visibilities, :source => :shareable, :source_type => 'Post' - has_many :posts, :through => :share_visibilities, :source => :shareable, :source_type => 'Post' + has_many :aspect_memberships, dependent: :destroy + has_many :aspects, through: :aspect_memberships validate :not_contact_for_self, :not_blocked_user, :not_contact_with_closed_account - validates_presence_of :user - validates_uniqueness_of :person_id, :scope => :user_id - before_destroy :destroy_notifications - scope :all_contacts_of_person, ->(x) { where(:person_id => x.id) } + scope :all_contacts_of_person, ->(x) { where(person_id: x.id) } - # contact.sharing is true when contact.person is sharing with contact.user - scope :sharing, -> { where(:sharing => true) } + # contact.sharing is true when contact.person is sharing with contact.user + scope :sharing, -> { where(sharing: true) } # contact.receiving is true when contact.user is sharing with contact.person - scope :receiving, -> { where(:receiving => true) } + scope :receiving, -> { where(receiving: true) } - scope :for_a_stream, -> { - includes(:aspects, :person => :profile). - order('profiles.last_name ASC') - } + scope :mutual, -> { sharing.receiving } - scope :only_sharing, -> { sharing.where(:receiving => false) } + scope :for_a_stream, -> { includes(:aspects, person: :profile).order("profiles.last_name ASC") } - def destroy_notifications - Notification.where(:target_type => "Person", - :target_id => person_id, - :recipient_id => user_id, - :type => "Notifications::StartedSharing").destroy_all - end + scope :only_sharing, -> { sharing.where(receiving: false) } - def dispatch_request - request = self.generate_request - Postzord::Dispatcher.build(self.user, request).post - request - end - - def generate_request - Request.diaspora_initialize(:from => self.user.person, - :to => self.person, - :into => aspects.first) - end - - def receive_shareable(shareable) - ShareVisibility.create!(:shareable_id => shareable.id, :shareable_type => shareable.class.base_class.to_s, :contact_id => self.id) + def destroy_notifications + Notification.where( + target_type: "Person", + target_id: person_id, + recipient_id: user_id, + type: "Notifications::StartedSharing" + ).destroy_all end def contacts @@ -76,10 +60,10 @@ class Contact < ActiveRecord::Base end def mutual? - self.sharing && self.receiving + sharing && receiving end - def in_aspect? aspect + def in_aspect?(aspect) if aspect_memberships.loaded? aspect_memberships.detect{ |am| am.aspect_id == aspect.id } elsif aspects.loaded? @@ -100,26 +84,44 @@ class Contact < ActiveRecord::Base end end + # Follows back if user setting is set so + def receive(_recipient_user_ids) + user.share_with(person, user.auto_follow_back_aspect) if user.auto_follow_back && !receiving + end + + # object for local recipients + def object_to_receive + Contact.create_or_update_sharing_contact(person.owner, user.person) + end + + # @return [Array<Person>] The recipient of the contact + def subscribers + [person] + end + + # creates or updates a contact with active sharing flag. Returns nil if already sharing. + def self.create_or_update_sharing_contact(recipient, sender) + contact = recipient.contacts.find_or_initialize_by(person_id: sender.id) + + return if contact.sharing + + contact.update(sharing: true) + contact + end + private + def not_contact_with_closed_account - if person_id && person.closed_account? - errors[:base] << 'Cannot be in contact with a closed account' - end + errors.add(:base, "Cannot be in contact with a closed account") if person_id && person.closed_account? end def not_contact_for_self - if person_id && person.owner == user - errors[:base] << 'Cannot create self-contact' - end + errors.add(:base, "Cannot create self-contact") if person_id && person.owner == user end def not_blocked_user - if user && user.blocks.where(:person_id => person_id).exists? - errors[:base] << 'Cannot connect to an ignored user' - false - else - true + if receiving && user && user.blocks.where(person_id: person_id).exists? + errors.add(:base, "Cannot connect to an ignored user") end end end - diff --git a/app/models/conversation.rb b/app/models/conversation.rb index afd4d798c0283467e1d7cc2e7c016ef8d610f381..4802d247e0538fe43e86ef1d32d44763ccc9e28f 100644 --- a/app/models/conversation.rb +++ b/app/models/conversation.rb @@ -1,18 +1,11 @@ class Conversation < ActiveRecord::Base include Diaspora::Federated::Base - include Diaspora::Guid + include Diaspora::Fields::Guid + include Diaspora::Fields::Author - xml_attr :subject - xml_attr :created_at - xml_attr :messages, :as => [Message] - xml_reader :diaspora_handle - xml_reader :participant_handles - - has_many :conversation_visibilities, :dependent => :destroy - has_many :participants, :class_name => 'Person', :through => :conversation_visibilities, :source => :person - has_many :messages, -> { order('created_at ASC') } - - belongs_to :author, :class_name => 'Person' + has_many :conversation_visibilities, dependent: :destroy + has_many :participants, class_name: "Person", through: :conversation_visibilities, source: :person + has_many :messages, -> { order("created_at ASC") }, inverse_of: :conversation validate :max_participants validate :local_recipients @@ -38,14 +31,6 @@ class Conversation < ActiveRecord::Base self.participants - [self.author] end - def diaspora_handle - self.author.diaspora_handle - end - - def diaspora_handle= nh - self.author = Person.find_or_fetch_by_identifier(nh) - end - def first_unread_message(user) if visibility = self.conversation_visibilities.where(:person_id => user.person.id).where('unread > 0').first self.messages.to_a[-visibility.unread] @@ -59,15 +44,12 @@ class Conversation < ActiveRecord::Base end end - def public? - false - end - def participant_handles - self.participants.map{|p| p.diaspora_handle}.join(";") + participants.map(&:diaspora_handle).join(";") end - def participant_handles= handles - handles.split(';').each do |handle| + + def participant_handles=(handles) + handles.split(";").each do |handle| participants << Person.find_or_fetch_by_identifier(handle) end end @@ -86,21 +68,7 @@ class Conversation < ActiveRecord::Base self[:subject].blank? ? I18n.t("conversations.new.subject_default") : self[:subject] end - def subscribers(user) - self.recipients - end - - def receive(user, person) - cnv = Conversation.create_with(self.attributes).find_or_create_by!(guid: guid) - - self.participants.each do |participant| - ConversationVisibility.find_or_create_by(conversation_id: cnv.id, person_id: participant.id) - end - - self.messages.each do |msg| - msg.conversation_id = cnv.id - received_msg = msg.receive(user, person) - Notification.notify(user, received_msg, person) if msg.respond_to?(:notification_type) - end + def subscribers + recipients end end diff --git a/app/models/invitation.rb b/app/models/invitation.rb deleted file mode 100644 index 40e5037c9fa4584fd918bde483dd6eb8df97c33e..0000000000000000000000000000000000000000 --- a/app/models/invitation.rb +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -#TODO: kill me -class Invitation < ActiveRecord::Base - - belongs_to :sender, :class_name => 'User' - belongs_to :recipient, :class_name => 'User' - belongs_to :aspect - - before_validation :set_email_as_default_service - - # before_create :share_with_exsisting_user, :if => :recipient_id? - validates :identifier, :presence => true - validates :service, :presence => true - validate :valid_identifier? - validate :recipient_not_on_pod? - validates_presence_of :sender, :aspect, :unless => :admin? - validate :ensure_not_inviting_self, :on => :create, :unless => :admin? - validate :sender_owns_aspect?, :unless => :admin? - validates_uniqueness_of :sender_id, :scope => [:identifier, :service], :unless => :admin? - - - # @note options hash is passed through to [Invitation.new] - # @see [Invitation.new] - # - # @param [Array<String>] emails - # @option opts [User] :sender - # @option opts [Aspect] :aspect - # @option opts [String] :service - # @return [Array<Invitation>] An array of [Invitation] models - # the valid optsnes are saved, and the invalid ones are not. - def self.batch_invite(emails, opts) - - users_on_pod = User.where(:email => emails, :invitation_token => nil) - - #share with anyone whose email you entered who is on the pod - users_on_pod.each{|u| opts[:sender].share_with(u.person, opts[:aspect])} - - emails.map! do |e| - user = users_on_pod.find{|u| u.email == e} - Invitation.create(opts.merge(:identifier => e, :recipient => user)) - end - emails - end - - - # Downcases the incoming service identifier and assigns it - # - # @param ident [String] Service identifier - # @see super - def identifier=(ident) - ident.downcase! if ident - super - end - - # Determine if we want to skip emailing the recipient. - # - # @return [Boolean] - # @return [void] - def skip_email? - !email_like_identifer - end - - # Find or create user, and send that resultant User an - # invitation. - # - # @return [Invitation] self - def send! - if email_like_identifer - EmailInviter.new(self.identifier, sender).send! - else - puts "broken facebook invitation_token" - end - self - end - - - # converts a personal invitation to an admin invite - # used in account deletion - # @return [Invitation] self - def convert_to_admin! - self.admin = true - self.sender = nil - self.aspect = nil - self.save - self - end - # @return [Invitation] self - def resend - self.send! - end - - # @return [String] - def recipient_identifier - case self.service - when 'email' - self.identifier - when'facebook' - I18n.t('invitations.a_facebook_user') - end - end - - # @return [String] - def email_like_identifer - case self.service - when 'email' - self.identifier - when 'facebook' - false - end - end - - # @note before_save - def set_email_as_default_service - self.service ||= 'email' - end - - # @note Validation - def ensure_not_inviting_self - if self.identifier == self.sender.email - errors[:base] << 'You can not invite yourself.' - end - end - - # @note Validation - def sender_owns_aspect? - if self.sender_id != self.aspect.user_id - errors[:base] << 'You do not own that aspect.' - end - end - - - def recipient_not_on_pod? - return true if self.recipient.nil? - if self.recipient.username? - errors[:recipient] << "The user '#{self.identifier}' (#{self.recipient.diaspora_handle}) is already on this pod, so we sent them a share request" - end - end - - # @note Validation - def valid_identifier? - return false unless self.identifier - if self.service == 'email' - unless self.identifier.match(Devise.email_regexp) - errors[:base] << 'invalid email' - end - end - end -end diff --git a/app/models/invitation_code.rb b/app/models/invitation_code.rb index 35fa80d490fc24bcf60d193c51b834f81e96f545..7b732359dd19a1fcd2e3480640491760db1122a5 100644 --- a/app/models/invitation_code.rb +++ b/app/models/invitation_code.rb @@ -6,13 +6,13 @@ class InvitationCode < ActiveRecord::Base before_create :generate_token, :set_default_invite_count delegate :name, to: :user, prefix: true - + def to_param - token + token end def can_be_used? - self.count > 0 + count > 0 && AppConfig.settings.invitations.open? end def add_invites! diff --git a/app/models/like.rb b/app/models/like.rb index 530fa2aa50643fdfba54d27529e720f8f44cff35..78eb9c3daeb46be373cd63fbce91fcb1d3dc9820 100644 --- a/app/models/like.rb +++ b/app/models/like.rb @@ -2,8 +2,19 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -class Like < Federated::Relayable - class Generator < Federated::Generator +class Like < ActiveRecord::Base + include Diaspora::Federated::Base + include Diaspora::Fields::Guid + include Diaspora::Fields::Author + include Diaspora::Fields::Target + + include Diaspora::Relayable + + has_one :signature, class_name: "LikeSignature", dependent: :delete + + alias_attribute :parent, :target + + class Generator < Diaspora::Federated::Generator def self.federated_class Like end @@ -19,10 +30,10 @@ class Like < Federated::Relayable after_destroy do self.parent.update_likes_counter + participation = author.participations.where(target_id: target.id).first + participation.unparticipate! if participation.present? end - xml_attr :positive - # NOTE API V1 to be extracted acts_as_api api_accessible :backbone do |t| @@ -31,10 +42,4 @@ class Like < Federated::Relayable t.add :author t.add :created_at end - - def notification_type(user, person) - #TODO(dan) need to have a notification for likes on comments, until then, return nil - return nil if self.target_type == "Comment" - Notifications::Liked if self.target.author == user.person && user.person != person - end end diff --git a/app/models/like_signature.rb b/app/models/like_signature.rb new file mode 100644 index 0000000000000000000000000000000000000000..6978704a9ea16f58594e53c8bd841d22a56ab255 --- /dev/null +++ b/app/models/like_signature.rb @@ -0,0 +1,7 @@ +class LikeSignature < ActiveRecord::Base + include Diaspora::Signature + + self.primary_key = :like_id + belongs_to :like + validates :like, presence: true +end diff --git a/app/models/location.rb b/app/models/location.rb index a1fb3057229213ef91e37153e83cd2723349cdab..0620104adba6a860965c272643713e7cbc1f99f5 100644 --- a/app/models/location.rb +++ b/app/models/location.rb @@ -5,9 +5,6 @@ class Location < ActiveRecord::Base attr_accessor :coordinates include Diaspora::Federated::Base - xml_attr :address - xml_attr :lat - xml_attr :lng belongs_to :status_message diff --git a/app/models/mention.rb b/app/models/mention.rb index caab2a8b214f9c65391a1f991a12be47cb13037d..9ddfd8dade6093ed57d05920586f1eef6a23a811 100644 --- a/app/models/mention.rb +++ b/app/models/mention.rb @@ -5,21 +5,12 @@ class Mention < ActiveRecord::Base belongs_to :post belongs_to :person - validates :post, :presence => true - validates :person, :presence => true + validates :post, presence: true + validates :person, presence: true after_destroy :delete_notification - def notify_recipient - logger.info "event=mention_sent id=#{id} to=#{person.diaspora_handle} from=#{post.author.diaspora_handle}" - Notification.notify(person.owner, self, post.author) unless person.remote? - end - - def notification_type(*args) - Notifications::Mentioned - end - def delete_notification - Notification.where(:target_type => self.class.name, :target_id => self.id).destroy_all + Notification.where(target_type: self.class.name, target_id: id).destroy_all end end diff --git a/app/models/message.rb b/app/models/message.rb index 91ef0405792c08cdba60a3410d5996cf696d1308..82c5512624e435a150e501e717ce4c9fb47bffab 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -1,63 +1,21 @@ -class NotVisibleError < RuntimeError; end class Message < ActiveRecord::Base include Diaspora::Federated::Base - include Diaspora::Guid - include Diaspora::Relayable + include Diaspora::Fields::Guid + include Diaspora::Fields::Author - xml_attr :text - xml_attr :created_at - xml_reader :diaspora_handle - xml_reader :conversation_guid - - belongs_to :author, :class_name => 'Person' - belongs_to :conversation, :touch => true + belongs_to :conversation, touch: true delegate :name, to: :author, prefix: true - validates :text, :presence => true - validate :participant_of_parent_conversation - - after_create do # don't use 'after_commit' here since there is a call to 'save!' - # inside, which would cause an infinite recursion - #sign comment as commenter - self.author_signature = self.sign_with_key(self.author.owner.encryption_key) if self.author.owner + # TODO: can be removed when messages are not relayed anymore + alias_attribute :parent, :conversation - if self.author.owns?(self.parent) - #sign comment as post owner - self.parent_author_signature = self.sign_with_key(self.parent.author.owner.encryption_key) if self.parent.author.owner - end - self.save! - self - end - - def diaspora_handle - self.author.diaspora_handle - end - - def diaspora_handle= nh - self.author = Person.find_or_fetch_by_identifier(nh) - end - - def conversation_guid - self.conversation.guid - end - - def conversation_guid= guid - if cnv = Conversation.find_by_guid(guid) - self.conversation_id = cnv.id - end - end - - def parent_class - Conversation - end - - def parent - self.conversation - end + validates :conversation, presence: true + validates :text, presence: true + validate :participant_of_parent_conversation - def parent= parent - self.conversation = parent + def conversation_guid=(guid) + self.conversation_id = Conversation.where(guid: guid).ids.first end def increase_unread(user) @@ -67,17 +25,23 @@ class Message < ActiveRecord::Base end end - def notification_type(user, person) - Notifications::PrivateMessage unless user.person == person - end - def message @message ||= Diaspora::MessageRenderer.new text end + # @return [Array<Person>] + def subscribers + if author.local? + conversation.participants + else # for relaying, TODO: can be removed when messages are not relayed anymore + conversation.participants.remote + end + end + private + def participant_of_parent_conversation - if self.parent && !self.parent.participants.include?(self.author) + if conversation && !conversation.participants.include?(author) errors[:base] << "Author is not participating in the conversation" else true diff --git a/app/models/notification.rb b/app/models/notification.rb index 91d697a47971a11509d9983af3e1c17d9b9b31ae..aaa56d53d827d7e281f5526f00bd4ce76027d765 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -3,41 +3,17 @@ # the COPYRIGHT file. # class Notification < ActiveRecord::Base - belongs_to :recipient, :class_name => 'User' - has_many :notification_actors, :dependent => :destroy - has_many :actors, :class_name => 'Person', :through => :notification_actors, :source => :person - belongs_to :target, :polymorphic => true - - attr_accessor :note_html + belongs_to :recipient, class_name: "User" + has_many :notification_actors, dependent: :destroy + has_many :actors, class_name: "Person", through: :notification_actors, source: :person + belongs_to :target, polymorphic: true def self.for(recipient, opts={}) - self.where(opts.merge!(:recipient_id => recipient.id)).order('updated_at desc') - end - - def self.notify(recipient, target, actor) - return nil unless target.respond_to?(:notification_type) && recipient.person != actor - - note_type = target.notification_type(recipient, actor) - return nil unless note_type - - return_note = if [Comment, Like, Reshare].any? { |klass| target.is_a?(klass) } - s_target = target.is_a?(Reshare) ? target.root : target.parent - note_type.concatenate_or_create(recipient, s_target, - actor, note_type) - else - note_type.make_notification(recipient, target, - actor, note_type) - end - return_note.email_the_user(target, actor) if return_note - return_note - end - - def as_json(opts={}) - super(opts.merge(:methods => :note_html)) + where(opts.merge!(recipient_id: recipient.id)).order("updated_at DESC") end def email_the_user(target, actor) - self.recipient.mail(self.mail_job, self.recipient_id, actor.id, target.id) + recipient.mail(mail_job, recipient_id, actor.id, target.id) end def set_read_state( read_state ) @@ -45,50 +21,35 @@ class Notification < ActiveRecord::Base end def mail_job - raise NotImplementedError.new('Subclass this.') + raise NotImplementedError.new("Subclass this.") end - def effective_target - self.popup_translation_key == "notifications.mentioned" ? self.target.post : self.target + def linked_object + target end -private - def self.concatenate_or_create(recipient, target, actor, notification_type) - return nil if suppress_notification?(recipient, target) - - if n = notification_type.where(:target_id => target.id, - :target_type => target.class.base_class, - :recipient_id => recipient.id, - :unread => true).first + def self.concatenate_or_create(recipient, target, actor) + return nil if suppress_notification?(recipient, actor) - begin - n.actors = n.actors | [actor] - n.unread = true - # Explicitly touch the notification to update updated_at whenever new actor is inserted in notification. - n.touch - n.save! - rescue ActiveRecord::RecordNotUnique - nil + find_or_initialize_by(recipient: recipient, target: target, unread: true).tap do |notification| + notification.actors |= [actor] + # Explicitly touch the notification to update updated_at whenever new actor is inserted in notification. + if notification.new_record? || notification.changed? + notification.save! + else + notification.touch end - n - else - make_notification(recipient, target, actor, notification_type) end end + def self.create_notification(recipient, target, actor) + return nil if suppress_notification?(recipient, actor) - def self.make_notification(recipient, target, actor, notification_type) - return nil if suppress_notification?(recipient, target) - n = notification_type.new(:target => target, - :recipient_id => recipient.id) - n.actors = n.actors | [actor] - n.unread = false if target.is_a? Request - n.save! - n + create(recipient: recipient, target: target, actors: [actor]) end - def self.suppress_notification?(recipient, post) - post.is_a?(Post) && recipient.is_shareable_hidden?(post) + private_class_method def self.suppress_notification?(recipient, actor) + recipient.blocks.where(person: actor).exists? end def self.types diff --git a/app/models/notifications/also_commented.rb b/app/models/notifications/also_commented.rb index 7b698cd36ebf53cfcf101487253d7ae3ee05d50f..a345566f3e922596596794299dd90f0487111899 100644 --- a/app/models/notifications/also_commented.rb +++ b/app/models/notifications/also_commented.rb @@ -1,17 +1,27 @@ -class Notifications::AlsoCommented < Notification - def mail_job - Workers::Mail::AlsoCommented - end - - def popup_translation_key - 'notifications.also_commented' - end +module Notifications + class AlsoCommented < Notification + def mail_job + Workers::Mail::AlsoCommented + end - def deleted_translation_key - 'notifications.also_commented_deleted' - end + def popup_translation_key + "notifications.also_commented" + end + + def deleted_translation_key + "notifications.also_commented_deleted" + end + + def self.notify(comment, _recipient_user_ids) + actor = comment.author + commentable = comment.commentable + recipient_ids = commentable.participants.local.where.not(id: [commentable.author_id, actor.id]).pluck(:owner_id) + + User.where(id: recipient_ids).find_each do |recipient| + next if recipient.is_shareable_hidden?(commentable) - def linked_object - Post.where(:id => self.target_id).first + concatenate_or_create(recipient, commentable, actor).try(:email_the_user, comment, actor) + end + end end end diff --git a/app/models/notifications/comment_on_post.rb b/app/models/notifications/comment_on_post.rb index 63131788083e4d7a020bac1958b8ff7e6b9baa42..df23b558e26fcf7bf56288fdc20a4f4d77f498d6 100644 --- a/app/models/notifications/comment_on_post.rb +++ b/app/models/notifications/comment_on_post.rb @@ -1,17 +1,24 @@ -class Notifications::CommentOnPost < Notification - def mail_job - Workers::Mail::CommentOnPost - end +module Notifications + class CommentOnPost < Notification + def mail_job + Workers::Mail::CommentOnPost + end - def popup_translation_key - 'notifications.comment_on_post' - end + def popup_translation_key + "notifications.comment_on_post" + end - def deleted_translation_key - 'notifications.also_commented_deleted' - end + def deleted_translation_key + "notifications.also_commented_deleted" + end + + def self.notify(comment, _recipient_user_ids) + actor = comment.author + commentable_author = comment.commentable.author + + return unless commentable_author.local? && actor != commentable_author - def linked_object - Post.where(:id => self.target_id).first + concatenate_or_create(commentable_author.owner, comment.commentable, actor).email_the_user(comment, actor) + end end end diff --git a/app/models/notifications/liked.rb b/app/models/notifications/liked.rb index 05607b10004bac58a3bd02367d4b090700bf6b45..00b33113a5deee2a5d87d9ee148dc48f78ee1bbd 100644 --- a/app/models/notifications/liked.rb +++ b/app/models/notifications/liked.rb @@ -1,19 +1,24 @@ -class Notifications::Liked < Notification - def mail_job - Workers::Mail::Liked - end - - def popup_translation_key - 'notifications.liked' - end +module Notifications + class Liked < Notification + def mail_job + Workers::Mail::Liked + end - def deleted_translation_key - 'notifications.liked_post_deleted' - end - - def linked_object - post = self.target - post = post.target if post.is_a? Like - post + def popup_translation_key + "notifications.liked" + end + + def deleted_translation_key + "notifications.liked_post_deleted" + end + + def self.notify(like, _recipient_user_ids) + actor = like.author + target_author = like.target.author + + return unless like.target_type == "Post" && target_author.local? && actor != target_author + + concatenate_or_create(target_author.owner, like.target, actor).email_the_user(like, actor) + end end end diff --git a/app/models/notifications/mentioned.rb b/app/models/notifications/mentioned.rb index 16482ace724c475a646b7de27a0450e0017dcd16..bede65ee4afca849c1cd405e61c8b25aa90e9072 100644 --- a/app/models/notifications/mentioned.rb +++ b/app/models/notifications/mentioned.rb @@ -1,17 +1,31 @@ -class Notifications::Mentioned < Notification - def mail_job - Workers::Mail::Mentioned - end - - def popup_translation_key - 'notifications.mentioned' - end +module Notifications + class Mentioned < Notification + def mail_job + Workers::Mail::Mentioned + end - def deleted_translation_key - 'notifications.mentioned_deleted' - end + def popup_translation_key + "notifications.mentioned" + end + + def deleted_translation_key + "notifications.mentioned_deleted" + end + + def linked_object + target.post + end + + def self.notify(mentionable, recipient_user_ids) + actor = mentionable.author + + mentionable.mentions.select {|mention| mention.person.local? }.each do |mention| + recipient = mention.person + + next if recipient == actor || !(mentionable.public || recipient_user_ids.include?(recipient.owner_id)) - def linked_object - Mention.find(self.target_id).post + create_notification(recipient.owner, mention, actor).try(:email_the_user, mention, actor) + end + end end end diff --git a/app/models/notifications/private_message.rb b/app/models/notifications/private_message.rb index 4ef273041a24d82802316c5bbd70e11d6fa83ad7..89bf0d5fdb99460fad2b4dfe17fcaa5cc6fb7771 100644 --- a/app/models/notifications/private_message.rb +++ b/app/models/notifications/private_message.rb @@ -1,15 +1,28 @@ -class Notifications::PrivateMessage < Notification - def mail_job - Workers::Mail::PrivateMessage - end - def popup_translation_key - 'notifications.private_message' - end - def self.make_notification(recipient, target, actor, notification_type) - n = notification_type.new(:target => target, - :recipient_id => recipient.id) - target.increase_unread(recipient) - n.actors << actor - n +module Notifications + class PrivateMessage < Notification + def mail_job + Workers::Mail::PrivateMessage + end + + def popup_translation_key + "notifications.private_message" + end + + def self.notify(object, _recipient_user_ids) + case object + when Conversation + object.messages.each {|message| notify_message(message) } + when Message + notify_message(object) + end + end + + private_class_method def self.notify_message(message) + recipient_ids = message.conversation.participants.local.where.not(id: message.author_id).pluck(:owner_id) + User.where(id: recipient_ids).find_each do |recipient| + message.increase_unread(recipient) + new(recipient: recipient).email_the_user(message, message.author) + end + end end end diff --git a/app/models/notifications/request_accepted.rb b/app/models/notifications/request_accepted.rb deleted file mode 100644 index 3651a32f034c8dc1b6461ab33e1deff29153ddcc..0000000000000000000000000000000000000000 --- a/app/models/notifications/request_accepted.rb +++ /dev/null @@ -1,8 +0,0 @@ -class Notifications::RequestAccepted < Notification - def mail_job - Workers::Mail::RequestAcceptance - end - def popup_translation_key - 'notifications.request_accepted' - end -end diff --git a/app/models/notifications/reshared.rb b/app/models/notifications/reshared.rb index fb9559d6f42fd357fb89854a932014f9fdc95d34..0b438a483eb9204dc8ad45b6975105df38691714 100644 --- a/app/models/notifications/reshared.rb +++ b/app/models/notifications/reshared.rb @@ -1,17 +1,22 @@ -class Notifications::Reshared < Notification - def mail_job - Workers::Mail::Reshared - end +module Notifications + class Reshared < Notification + def mail_job + Workers::Mail::Reshared + end - def popup_translation_key - 'notifications.reshared' - end + def popup_translation_key + "notifications.reshared" + end - def deleted_translation_key - 'notifications.reshared_post_deleted' - end + def deleted_translation_key + "notifications.reshared_post_deleted" + end + + def self.notify(reshare, _recipient_user_ids) + return unless reshare.root.present? && reshare.root.author.local? - def linked_object - self.target + actor = reshare.author + concatenate_or_create(reshare.root.author.owner, reshare.root, actor).try(:email_the_user, reshare, actor) + end end end diff --git a/app/models/notifications/started_sharing.rb b/app/models/notifications/started_sharing.rb index ff4975be5416db08bfb4090c5213f0a8af540c85..dfe6dfd55944a9236968efc535e790e2caca52bc 100644 --- a/app/models/notifications/started_sharing.rb +++ b/app/models/notifications/started_sharing.rb @@ -1,20 +1,20 @@ -class Notifications::StartedSharing < Notification - def mail_job - Workers::Mail::StartedSharing - end +module Notifications + class StartedSharing < Notification + def mail_job + Workers::Mail::StartedSharing + end - def popup_translation_key - 'notifications.started_sharing' - end + def popup_translation_key + "notifications.started_sharing" + end - def email_the_user(target, actor) - super(target.sender, actor) - end + def self.notify(contact, _recipient_user_ids) + sender = contact.person + create_notification(contact.user, sender, sender).try(:email_the_user, sender, sender) + end - private - - def self.make_notification(recipient, target, actor, notification_type) - super(recipient, target.sender, actor, notification_type) + def contact + recipient.contact_for(target) + end end - end diff --git a/app/models/participation.rb b/app/models/participation.rb index b3608342849096e110e2221a273b4e277750d3e9..94d82fb95c7929449f22124cb176cc976a57dbb2 100644 --- a/app/models/participation.rb +++ b/app/models/participation.rb @@ -1,7 +1,12 @@ -class Participation < Federated::Relayable - class Generator < Federated::Generator +class Participation < ActiveRecord::Base + include Diaspora::Federated::Base + include Diaspora::Fields::Guid + include Diaspora::Fields::Author + include Diaspora::Fields::Target + + class Generator < Diaspora::Federated::Generator def self.federated_class - Participation + Participation end def relayable_options @@ -9,6 +14,19 @@ class Participation < Federated::Relayable end end + def unparticipate! + if count == 1 + destroy + else + update!(count: count.pred) + end + end + + # @return [Array<Person>] + def subscribers + [target.author] + end + # NOTE API V1 to be extracted acts_as_api api_accessible :backbone do |t| diff --git a/app/models/person.rb b/app/models/person.rb index f338daf3ba22e76f3a5f05fd134df545634e8ab8..3ff161f43cc327569228b44ae682af6c768dd25b 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -3,9 +3,7 @@ # the COPYRIGHT file. class Person < ActiveRecord::Base - include ROXML - include Encryptor::Public - include Diaspora::Guid + include Diaspora::Fields::Guid # NOTE API V1 to be extracted acts_as_api @@ -23,15 +21,10 @@ class Person < ActiveRecord::Base }, :as => :avatar end - xml_attr :diaspora_handle - xml_attr :url - xml_attr :profile, :as => Profile - xml_attr :exported_key - has_one :profile, dependent: :destroy delegate :last_name, :image_url, :tag_string, :bio, :location, :gender, :birthday, :formatted_birthday, :tags, :searchable, - to: :profile + :public_details?, to: :profile accepts_nested_attributes_for :profile before_validation :downcase_diaspora_handle @@ -50,20 +43,22 @@ class Person < ActiveRecord::Base has_many :roles belongs_to :owner, :class_name => 'User' + belongs_to :pod has_many :notification_actors has_many :notifications, :through => :notification_actors has_many :mentions, :dependent => :destroy - before_validation :clean_url - - validates :url, :presence => true + validate :owner_xor_pod + validate :other_person_with_same_guid, on: :create validates :profile, :presence => true validates :serialized_public_key, :presence => true validates :diaspora_handle, :uniqueness => true - scope :searchable, -> { joins(:profile).where(:profiles => {:searchable => true}) } + scope :searchable, -> (user) { + joins(:profile).where("profiles.searchable = true OR contacts.user_id = ?", user.id) + } scope :remote, -> { where('people.owner_id IS NULL') } scope :local, -> { where('people.owner_id IS NOT NULL') } scope :for_json, -> { @@ -150,27 +145,23 @@ class Person < ActiveRecord::Base [where_clause, q_tokens] end - def self.search(query, user) - return self.where("1 = 0") if query.to_s.blank? || query.to_s.length < 2 + def self.search(search_str, user, only_contacts: false) + search_str.strip! + return none if search_str.blank? || search_str.size < 2 - sql, tokens = self.search_query_string(query) + sql, tokens = search_query_string(search_str) - Person.searchable.where(sql, *tokens).joins( - "LEFT OUTER JOIN contacts ON contacts.user_id = #{user.id} AND contacts.person_id = people.id" - ).includes(:profile - ).order(search_order) - end + query = if only_contacts + joins(:contacts).where(contacts: {user_id: user.id}) + else + joins( + "LEFT OUTER JOIN contacts ON contacts.user_id = #{user.id} AND contacts.person_id = people.id" + ).searchable(user) + end - # @return [Array<String>] postgreSQL and mysql deal with null values in orders differently, it seems. - def self.search_order - @search_order ||= Proc.new { - order = if AppConfig.postgres? - "ASC" - else - "DESC" - end - ["contacts.user_id #{order}", "profiles.last_name ASC", "profiles.first_name ASC"] - }.call + query.where(sql, *tokens) + .includes(:profile) + .order(["contacts.user_id IS NULL", "profiles.last_name ASC", "profiles.first_name ASC"]) end def name(opts = {}) @@ -199,14 +190,16 @@ class Person < ActiveRecord::Base @username ||= owner ? owner.username : diaspora_handle.split("@")[0] end + def author + self + end + def owns?(obj) self.id == obj.author_id end def url url_to "/" - rescue - self[:url] end def profile_url @@ -221,6 +214,12 @@ class Person < ActiveRecord::Base url_to "/receive/users/#{guid}" end + # @param path [String] + # @return [String] + def url_to(path) + local? ? AppConfig.url_to(path) : pod.url_to(path) + end + def public_key_hash Base64.encode64(OpenSSL::Digest::SHA256.new(serialized_public_key).to_s) end @@ -239,30 +238,20 @@ class Person < ActiveRecord::Base end # discovery (webfinger) - def self.find_or_fetch_by_identifier(account) + def self.find_or_fetch_by_identifier(diaspora_id) # exiting person? - person = by_account_identifier(account) + person = by_account_identifier(diaspora_id) return person if person.present? && person.profile.present? # create or update person from webfinger - logger.info "webfingering #{account}, it is not known or needs updating" - DiasporaFederation::Discovery::Discovery.new(account).fetch_and_save - - by_account_identifier(account) - end + logger.info "webfingering #{diaspora_id}, it is not known or needs updating" + DiasporaFederation::Discovery::Discovery.new(diaspora_id).fetch_and_save - # database calls - def self.by_account_identifier(identifier) - identifier = identifier.strip.downcase.sub("acct:", "") - find_by(diaspora_handle: identifier) + by_account_identifier(diaspora_id) end - def self.find_local_by_diaspora_handle(handle) - where(diaspora_handle: handle, closed_account: false).where.not(owner: nil).take - end - - def self.find_local_by_guid(guid) - where(guid: guid, closed_account: false).where.not(owner: nil).take + def self.by_account_identifier(diaspora_id) + find_by(diaspora_handle: diaspora_id.strip.downcase) end def remote? @@ -290,23 +279,6 @@ class Person < ActiveRecord::Base json end - # Update an array of people given a url, and set it as the new destination_url - # @param people [Array<People>] - # @param url [String] - def self.url_batch_update(people, url) - people.each do |person| - person.update_url(url) - end - end - - # @param person [Person] - # @param url [String] - def update_url(url) - @uri = URI.parse(url) - @uri.path = "/" - update_attributes(:url => @uri.to_s) - end - def lock_access! self.closed_account = true self.save @@ -317,32 +289,20 @@ class Person < ActiveRecord::Base self end - protected - - def clean_url - if self.url - self.url = 'http://' + self.url unless self.url.match(/https?:\/\//) - self.url = self.url + '/' if self.url[-1, 1] != '/' - end - end - private - # @return [URI] - def uri - @uri ||= URI.parse(self[:url]) - @uri.dup - end - - # @param path [String] - # @return [String] - def url_to(path) - uri.tap {|uri| uri.path = path }.to_s - end - def fix_profile logger.info "fix profile for account: #{diaspora_handle}" DiasporaFederation::Discovery::Discovery.new(diaspora_handle).fetch_and_save reload end + + def owner_xor_pod + errors.add(:base, "Specify an owner or a pod, not both") unless owner.blank? ^ pod.blank? + end + + def other_person_with_same_guid + diaspora_id = Person.where(guid: guid).where.not(diaspora_handle: diaspora_handle).pluck(:diaspora_handle).first + errors.add(:base, "Person with same GUID already exists: #{diaspora_id}") if diaspora_id + end end diff --git a/app/models/photo.rb b/app/models/photo.rb index f3826362096e6e3fcbb64dee567e7eca461c71d1..17e9b9ff87fa7f2217bef07a08ef3e49bfdd171a 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -3,7 +3,7 @@ # the COPYRIGHT file. class Photo < ActiveRecord::Base - include Diaspora::Federated::Shareable + include Diaspora::Federated::Base include Diaspora::Commentable include Diaspora::Shareable @@ -15,28 +15,28 @@ class Photo < ActiveRecord::Base t.add :created_at t.add :author t.add lambda { |photo| - { :small => photo.url(:thumb_small), - :medium => photo.url(:thumb_medium), - :large => photo.url(:scaled_full) } + { + small: photo.url(:thumb_small), + medium: photo.url(:thumb_medium), + large: photo.url(:scaled_full) + } }, :as => :sizes t.add lambda { |photo| - { :height => photo.height, - :width => photo.width } - }, :as => :dimensions + { + height: photo.height, + width: photo.width + } + }, as: :dimensions + t.add lambda { |photo| + { + id: photo.status_message.id + } if photo.status_message + }, as: :status_message end mount_uploader :processed_image, ProcessedImage mount_uploader :unprocessed_image, UnprocessedImage - xml_attr :remote_photo_path - xml_attr :remote_photo_name - - xml_attr :text - xml_attr :status_message_guid - - xml_attr :height - xml_attr :width - belongs_to :status_message, :foreign_key => :status_message_guid, :primary_key => :guid validates_associated :status_message delegate :author_name, to: :status_message, prefix: true @@ -72,18 +72,11 @@ class Photo < ActiveRecord::Base end end - def self.diaspora_initialize(params = {}) - photo = self.new params.to_hash.slice(:text, :pending) - photo.author = params[:author] - photo.public = params[:public] if params[:public] - photo.pending = params[:pending] if params[:pending] - photo.diaspora_handle = photo.author.diaspora_handle - + def self.diaspora_initialize(params={}) + photo = new(params.to_hash.stringify_keys.slice(*column_names, "author")) photo.random_string = SecureRandom.hex(10) - if photo.author.local? - photo.unprocessed_image.strip_exif = photo.author.owner.strip_exif - end + photo.unprocessed_image.strip_exif = photo.author.owner.strip_exif if params[:user_file] image_file = params.delete(:user_file) @@ -142,16 +135,12 @@ class Photo < ActiveRecord::Base Workers::ProcessPhoto.perform_async(self.id) end - def mutable? - true - end - def self.visible(current_user, person, limit=:all, max_time=nil) photos = if current_user current_user.photos_from(person, limit: limit, max_time: max_time) else Photo.where(author_id: person.id, public: true) end - photos.order("created_at desc") + photos.where(pending: false).order("created_at DESC") end end diff --git a/app/models/pod.rb b/app/models/pod.rb index dcd23b310d42b6dd505e2773ea8ed6803514dc65..a424566220b3fbdfde6c4da8abb110437caab139 100644 --- a/app/models/pod.rb +++ b/app/models/pod.rb @@ -1,11 +1,135 @@ class Pod < ActiveRecord::Base - def self.find_or_create_by(opts) # Rename this method to not override an AR method - u = URI.parse(opts.fetch(:url)) - pod = self.find_or_initialize_by(host: u.host) - unless pod.persisted? - pod.ssl = (u.scheme == 'https')? true : false - pod.save - end - pod + enum status: %i( + unchecked + no_errors + dns_failed + net_failed + ssl_failed + http_failed + version_failed + unknown_error + ) + + ERROR_MAP = { + ConnectionTester::AddressFailure => :dns_failed, + ConnectionTester::DNSFailure => :dns_failed, + ConnectionTester::NetFailure => :net_failed, + ConnectionTester::SSLFailure => :ssl_failed, + ConnectionTester::HTTPFailure => :http_failed, + ConnectionTester::NodeInfoFailure => :version_failed + } + + # this are only the most common errors, the rest will be +unknown_error+ + CURL_ERROR_MAP = { + couldnt_resolve_host: :dns_failed, + couldnt_connect: :net_failed, + operation_timedout: :net_failed, + ssl_cipher: :ssl_failed, + ssl_cacert: :ssl_failed + }.freeze + + DEFAULT_PORTS = [URI::HTTP::DEFAULT_PORT, URI::HTTPS::DEFAULT_PORT] + + has_many :people + + scope :check_failed, lambda { + where(arel_table[:status].gt(Pod.statuses[:no_errors])).where.not(status: Pod.statuses[:version_failed]) + } + + validate :not_own_pod + + class << self + def find_or_create_by(opts) # Rename this method to not override an AR method + uri = URI.parse(opts.fetch(:url)) + port = DEFAULT_PORTS.include?(uri.port) ? nil : uri.port + find_or_initialize_by(host: uri.host, port: port).tap do |pod| + pod.ssl ||= (uri.scheme == "https") + pod.save + end + end + + # don't consider a failed version reading to be fatal + def offline_statuses + [Pod.statuses[:dns_failed], + Pod.statuses[:net_failed], + Pod.statuses[:ssl_failed], + Pod.statuses[:http_failed], + Pod.statuses[:unknown_error]] + end + + def check_all! + Pod.find_in_batches(batch_size: 20) {|batch| batch.each(&:test_connection!) } + end + end + + def offline? + Pod.offline_statuses.include?(Pod.statuses[status]) + end + + def was_offline? + Pod.offline_statuses.include?(Pod.statuses[status_was]) + end + + def test_connection! + result = ConnectionTester.check uri.to_s + logger.debug "tested pod: '#{uri}' - #{result.inspect}" + + transaction do + update_from_result(result) + end + end + + # @param path [String] + # @return [String] + def url_to(path) + uri.tap {|uri| uri.path = path }.to_s + end + + def update_offline_since + if offline? + touch(:offline_since) unless was_offline? + else + self.offline_since = nil + end + end + + private + + def update_from_result(result) + self.status = status_from_result(result) + update_offline_since + logger.warn "OFFLINE #{result.failure_message}" if offline? + + attributes_from_result(result) + touch(:checked_at) + + save + end + + def attributes_from_result(result) + self.ssl ||= result.ssl + self.error = result.failure_message[0..254] if result.error? + self.software = result.software_version[0..254] if result.software_version.present? + self.response_time = result.rt + end + + def status_from_result(result) + if result.error? + ERROR_MAP.fetch(result.error.class, :unknown_error) + else + :no_errors + end + end + + # @return [URI] + def uri + @uri ||= (ssl ? URI::HTTPS : URI::HTTP).build(host: host, port: port) + @uri.dup + end + + def not_own_pod + pod_uri = AppConfig.pod_uri + pod_port = DEFAULT_PORTS.include?(pod_uri.port) ? nil : pod_uri.port + errors.add(:base, "own pod not allowed") if pod_uri.host == host && pod_port == port end end diff --git a/app/models/poll.rb b/app/models/poll.rb index cf6f0f452ad7b69f42be3586dcd534cd1f6e0df3..fa90335775fad549f5c4704491d77443d6df2161 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -1,16 +1,14 @@ class Poll < ActiveRecord::Base include Diaspora::Federated::Base - include Diaspora::Guid + include Diaspora::Fields::Guid belongs_to :status_message has_many :poll_answers, -> { order 'id ASC' } has_many :poll_participations - - xml_attr :question - xml_attr :poll_answers, :as => [PollAnswer] + has_one :author, through: :status_message #forward some requests to status message, because a poll is just attached to a status message and is not sharable itself - delegate :author, :author_id, :diaspora_handle, :public?, :subscribers, to: :status_message + delegate :author_id, :diaspora_handle, :public?, :subscribers, to: :status_message validate :enough_poll_answers validates :question, presence: true diff --git a/app/models/poll_answer.rb b/app/models/poll_answer.rb index 93aec82aba6b34fad1b244684bb76fc9e796b82c..3387efe092f4b3cac9e6fd69d606e029cd260a14 100644 --- a/app/models/poll_answer.rb +++ b/app/models/poll_answer.rb @@ -1,15 +1,11 @@ class PollAnswer < ActiveRecord::Base - include Diaspora::Federated::Base - include Diaspora::Guid - + include Diaspora::Fields::Guid + belongs_to :poll has_many :poll_participations - xml_attr :answer - validates :answer, presence: true self.include_root_in_json = false - end diff --git a/app/models/poll_participation.rb b/app/models/poll_participation.rb index 64dd32ac519a3b563985c882d576887cf2198c1f..8dba27465734bedc519ae111a4c0d761e610b90b 100644 --- a/app/models/poll_participation.rb +++ b/app/models/poll_participation.rb @@ -1,43 +1,21 @@ class PollParticipation < ActiveRecord::Base - include Diaspora::Federated::Base - - include Diaspora::Guid + include Diaspora::Fields::Guid + include Diaspora::Fields::Author include Diaspora::Relayable + belongs_to :poll belongs_to :poll_answer, counter_cache: :vote_count - belongs_to :author, :class_name => 'Person', :foreign_key => :author_id - xml_attr :diaspora_handle - xml_attr :poll_answer_guid - xml_convention :underscore - validate :not_already_participated - - def parent_class - Poll - end - - def parent - self.poll - end - def poll_answer_guid - poll_answer.guid - end + has_one :signature, class_name: "PollParticipationSignature", dependent: :delete - def poll_answer_guid= new_poll_answer_guid - self.poll_answer = PollAnswer.where(:guid => new_poll_answer_guid).first - end + alias_attribute :parent, :poll - def parent= parent - self.poll = parent - end - - def diaspora_handle - self.author.diaspora_handle - end + validates :poll_answer, presence: true + validate :not_already_participated - def diaspora_handle= nh - self.author = Person.find_or_fetch_by_identifier(nh) + def poll_answer_guid=(new_poll_answer_guid) + self.poll_answer_id = PollAnswer.where(guid: new_poll_answer_guid).ids.first end def not_already_participated @@ -49,7 +27,7 @@ class PollParticipation < ActiveRecord::Base end end - class Generator < Federated::Generator + class Generator < Diaspora::Federated::Generator def self.federated_class PollParticipation end diff --git a/app/models/poll_participation_signature.rb b/app/models/poll_participation_signature.rb new file mode 100644 index 0000000000000000000000000000000000000000..90701f286cab6bdddaa2a061f69996d92fb5fa07 --- /dev/null +++ b/app/models/poll_participation_signature.rb @@ -0,0 +1,7 @@ +class PollParticipationSignature < ActiveRecord::Base + include Diaspora::Signature + + self.primary_key = :poll_participation_id + belongs_to :poll_participation + validates :poll_participation, presence: true +end diff --git a/app/models/post.rb b/app/models/post.rb index da0461b89986fcee25412a4195c60ce4d3c2a652..3ad235f0fa4444042ee43ec5e1aeeb0149859f40 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -7,30 +7,29 @@ class Post < ActiveRecord::Base include ApplicationHelper - include Diaspora::Federated::Shareable + include Diaspora::Federated::Base include Diaspora::Likeable include Diaspora::Commentable include Diaspora::Shareable has_many :participations, dependent: :delete_all, as: :target, inverse_of: :target + has_many :participants, class_name: "Person", through: :participations, source: :author attr_accessor :user_like - xml_attr :provider_display_name + has_many :reports, as: :item - has_many :mentions, :dependent => :destroy + has_many :mentions, dependent: :destroy - has_many :reshares, :class_name => "Reshare", :foreign_key => :root_guid, :primary_key => :guid - has_many :resharers, :class_name => 'Person', :through => :reshares, :source => :author + has_many :reshares, class_name: "Reshare", foreign_key: :root_guid, primary_key: :guid + has_many :resharers, class_name: "Person", through: :reshares, source: :author belongs_to :o_embed_cache belongs_to :open_graph_cache validates_uniqueness_of :id - validates :author, presence: true - after_create do self.touch(:interacted_at) end @@ -44,6 +43,7 @@ class Post < ActiveRecord::Base ) #note should include root and photos, but i think those are both on status_message } + scope :all_public, -> { where(public: true) } scope :commented_by, ->(person) { select('DISTINCT posts.*') @@ -55,20 +55,11 @@ class Post < ActiveRecord::Base joins(:likes).where(:likes => {:author_id => person.id}) } - def self.visible_from_author(author, current_user=nil) - if current_user.present? - current_user.posts_from(author) - else - author.posts.all_public - end - end - def post_type self.class.name end def root; end - def raw_message; ""; end def mentioned_people; []; end def photos; []; end @@ -103,11 +94,17 @@ class Post < ActiveRecord::Base excluding_blocks(user).excluding_hidden_shareables(user) end - def self.for_a_stream(max_time, order, user=nil) + def self.for_a_stream(max_time, order, user=nil, ignore_blocks=false) scope = self.for_visible_shareable_sql(max_time, order). includes_for_a_stream - scope = scope.excluding_hidden_content(user) if user.present? + if user.present? + if ignore_blocks + scope = scope.excluding_hidden_shareables(user) + else + scope = scope.excluding_hidden_content(user) + end + end scope end @@ -124,22 +121,13 @@ class Post < ActiveRecord::Base ############# - def self.diaspora_initialize(params) - new_post = self.new params.to_hash.stringify_keys.slice(*self.column_names) - new_post.author = params[:author] - new_post.public = params[:public] if params[:public] - new_post.pending = params[:pending] if params[:pending] - new_post.diaspora_handle = new_post.author.diaspora_handle - new_post - end - - # @return Returns true if this Post will accept updates (i.e. updates to the caption of a photo). - def mutable? - false + # @return [Integer] + def update_reshares_counter + self.class.where(id: id).update_all(reshares_count: reshares.count) end - def activity_streams? - false + def self.diaspora_initialize(params) + new(params.to_hash.stringify_keys.slice(*column_names, "author")) end def comment_email_subject @@ -150,20 +138,9 @@ class Post < ActiveRecord::Base self.author.profile.nsfw? end - def self.find_public(id) - where(post_key(id) => id).includes(:author, comments: :author).first.tap do |post| - raise ActiveRecord::RecordNotFound.new("could not find a post with id #{id}") unless post - raise Diaspora::NonPublic unless post.public? + def subscribers + super.tap do |subscribers| + subscribers.concat(resharers).concat(participants) if public? end end - - def self.find_non_public_by_guid_or_id_with_user(id, user) - user.find_visible_shareable_by_id(Post, id, key: post_key(id)).tap do |post| - raise ActiveRecord::RecordNotFound.new("could not find a post with id #{id}") unless post - end - end - - def self.post_key(id) - id.to_s.length <= 8 ? :id : :guid - end end diff --git a/app/models/profile.rb b/app/models/profile.rb index 5626f058be41adc98a9250e0ad700495b8b9a0d5..573dcb6f384c556b57584c1ad738dd955a5ba2bf 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -13,20 +13,6 @@ class Profile < ActiveRecord::Base extract_tags_from :tag_string validates :tag_list, :length => { :maximum => 5 } - xml_attr :diaspora_handle - xml_attr :first_name - xml_attr :last_name - xml_attr :image_url - xml_attr :image_url_small - xml_attr :image_url_medium - xml_attr :birthday - xml_attr :gender - xml_attr :bio - xml_attr :location - xml_attr :searchable - xml_attr :nsfw - xml_attr :tag_string - before_save :strip_names after_validation :strip_names @@ -50,17 +36,8 @@ class Profile < ActiveRecord::Base self.construct_full_name end - def subscribers(user) - Person.joins(:contacts).where(:contacts => {:user_id => user.id}) - end - - def receive(user, person) - person.reload # make sure to have old profile referenced - logger.info "event=receive payload_type=profile sender=#{person.diaspora_handle} to=#{user.diaspora_handle}" - profiles_attr = self.attributes.merge('tag_string' => self.tag_string).slice('diaspora_handle', 'first_name', 'last_name', 'image_url', 'image_url_small', 'image_url_medium', 'birthday', 'gender', 'bio', 'location', 'searchable', 'nsfw', 'tag_string') - person.profile.update_attributes(profiles_attr) - - person.profile + def subscribers + Person.joins(:contacts).where(contacts: {user_id: person.owner_id}) end def diaspora_handle @@ -138,12 +115,7 @@ class Profile < ActiveRecord::Base end def tag_string - if @tag_string - @tag_string - else - tags = self.tags.pluck(:name) - tags.inject(""){|string, tag| string << "##{tag} " } - end + @tag_string ||= tags.pluck(:name).map {|tag| "##{tag}" }.join(" ") end # Constructs a full name by joining #first_name and #last_name diff --git a/app/models/report.rb b/app/models/report.rb index 36356c48f51b3c5b52890bbd9a5bf89046055c1d..a116e90834298079af8ab48fc8fac867bfcba3e6 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -1,8 +1,8 @@ class Report < ActiveRecord::Base validates :user_id, presence: true validates :item_id, presence: true - validates :item_type, presence: true, :inclusion => { :in => %w(post comment), - :message => 'Type should match `post` or `comment`!'} + validates :item_type, presence: true, inclusion: { + in: %w(Post Comment), message: "Type should match `Post` or `Comment`!"} validates :text, presence: true validate :entry_does_not_exist, :on => :create @@ -11,9 +11,14 @@ class Report < ActiveRecord::Base belongs_to :user belongs_to :post belongs_to :comment + belongs_to :item, polymorphic: true after_commit :send_report_notification, :on => :create + def reported_author + item.author if item + end + def entry_does_not_exist if Report.where(item_id: item_id, item_type: item_type).exists?(user_id: user_id) errors[:base] << 'You cannot report the same post twice.' @@ -27,34 +32,23 @@ class Report < ActiveRecord::Base end def destroy_reported_item - if item_type == 'post' - delete_post - elsif item_type == 'comment' - delete_comment - end - mark_as_reviewed - end - - def delete_post - if post = Post.where(id: item_id).first - if post.author.local? - post.author.owner.retract(post) + case item + when Post + if item.author.local? + item.author.owner.retract(item) else - post.destroy + item.destroy end - end - end - - def delete_comment - if comment = Comment.where(id: item_id).first - if comment.author.local? - comment.author.owner.retract(comment) - elsif comment.parent.author.local? - comment.parent.author.owner.retract(comment) + when Comment + if item.author.local? + item.author.owner.retract(item) + elsif item.parent.author.local? + item.parent.author.owner.retract(item) else - comment.destroy + item.destroy end end + mark_as_reviewed end def mark_as_reviewed @@ -62,6 +56,6 @@ class Report < ActiveRecord::Base end def send_report_notification - Workers::Mail::ReportWorker.perform_async(self.item_type, self.item_id) + Workers::Mail::ReportWorker.perform_async(id) end end diff --git a/app/models/reshare.rb b/app/models/reshare.rb index 1781595e987b0d9e78d198d0d8ebfbb80553e1bd..bb914d40146ee966423bae6f9887fa5a37db3145 100644 --- a/app/models/reshare.rb +++ b/app/models/reshare.rb @@ -3,16 +3,12 @@ # the COPYRIGHT file. class Reshare < Post - belongs_to :root, :class_name => 'Post', :foreign_key => :root_guid, :primary_key => :guid validate :root_must_be_public validates_presence_of :root, :on => :create validates_uniqueness_of :root_guid, :scope => :author_id delegate :author, to: :root, prefix: true - xml_attr :root_diaspora_id - xml_attr :root_guid - before_validation do self.public = true end @@ -33,8 +29,8 @@ class Reshare < Post :message, :nsfw, to: :absolute_root, allow_nil: true - def raw_message - absolute_root.try(:raw_message) || super + def text + absolute_root.try(:text) || "" end def mentioned_people @@ -45,50 +41,40 @@ class Reshare < Post absolute_root.try(:photos) || super end - def address - absolute_root.try(:location).try(:address) + def post_location + { + address: absolute_root.try(:location).try(:address), + lat: absolute_root.try(:location).try(:lat), + lng: absolute_root.try(:location).try(:lng) + } end def poll absolute_root.try(:poll) || super end - def receive(recipient, sender) - local_reshare = Reshare.where(:guid => self.guid).first - if local_reshare && local_reshare.root.author_id == recipient.person.id - recipient.participate! self - return unless recipient.has_contact_for?(sender) - end - super(recipient, sender) - end - def comment_email_subject I18n.t('reshares.comment_email_subject', :resharer => author.name, :author => root.author_name) end - def notification_type(user, person) - Notifications::Reshared if root.try(:author) == user.person - end - def absolute_root @absolute_root ||= self @absolute_root = @absolute_root.root while @absolute_root.is_a? Reshare @absolute_root end - private + def receive(recipient_user_ids) + super(recipient_user_ids) - def after_parse - if root.blank? - self.root = Diaspora::Fetcher::Single.find_or_fetch_from_remote root_guid, @root_diaspora_id do |fetched_post, author| - # why do we check this? - if fetched_post.diaspora_handle != author.diaspora_handle - raise Diaspora::PostNotFetchable, "Diaspora ID (#{fetched_post.diaspora_handle}) in the root does not match the Diaspora ID (#{author.diaspora_handle}) specified in the reshare!" - end - end - end + root.author.owner.participate!(self) if root.author.local? + end + + def subscribers + super.tap {|people| root.try {|root| people << root.author } } end + private + def root_must_be_public if self.root && !self.root.public errors[:base] << "Only posts which are public may be reshared." diff --git a/app/models/service.rb b/app/models/service.rb index 4e443cf5069cee36bba05b1dddd0fc749acb4d1e..57322ce8c9e422d4c4970dd2c523c17dddddfea4 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -12,8 +12,8 @@ class Service < ActiveRecord::Base nil end - def delete_post(post) - #don't do anything (should be overriden by service extensions) + def post_opts(post) + # don't do anything (should be overridden by service extensions) end class << self diff --git a/app/models/services/facebook.rb b/app/models/services/facebook.rb index e15b9ecba90fd06ecc9b64c79e1eaf5b309a76b6..cb6c83aa6b79e2420e13b5e3908ce1e26d943e8c 100644 --- a/app/models/services/facebook.rb +++ b/app/models/services/facebook.rb @@ -37,11 +37,13 @@ class Services::Facebook < Service "https://graph.facebook.com/#{self.uid}/picture?type=large&access_token=#{URI.escape(self.access_token)}" end - def delete_post(post) - if post.present? && post.facebook_id.present? - logger.debug "event=delete_from_service type=facebook sender_id=#{user_id} post=#{post.guid}" - delete_from_facebook("https://graph.facebook.com/#{post.facebook_id}/", {:access_token => self.access_token}) - end + def post_opts(post) + {facebook_id: post.facebook_id} if post.facebook_id.present? + end + + def delete_from_service(opts) + logger.debug "event=delete_from_service type=facebook sender_id=#{user_id} facebook_id=#{opts[:facebook_id]}" + delete_from_facebook("https://graph.facebook.com/#{opts[:facebook_id]}/", access_token: access_token) end def delete_from_facebook(url, body) diff --git a/app/models/services/tumblr.rb b/app/models/services/tumblr.rb index 52c7f8d6aeb3b81f6f17274220b135cf95393eec..675fe579932b3be86bd590c009e3bb1c10b940d8 100644 --- a/app/models/services/tumblr.rb +++ b/app/models/services/tumblr.rb @@ -43,13 +43,15 @@ class Services::Tumblr < Service html << "\n\n[original post](#{url})" end - def delete_post(post) - if post.present? && post.tumblr_ids.present? - logger.debug "event=delete_from_service type=tumblr sender_id=#{user_id} post=#{post.guid}" - tumblr_posts = JSON.parse(post.tumblr_ids) - tumblr_posts.each do |blog_name,post_id| - delete_from_tumblr(blog_name, post_id) - end + def post_opts(post) + {tumblr_ids: post.tumblr_ids} if post.tumblr_ids.present? + end + + def delete_from_service(opts) + logger.debug "event=delete_from_service type=tumblr sender_id=#{user_id} tumblr_ids=#{opts[:tumblr_ids]}" + tumblr_posts = JSON.parse(opts[:tumblr_ids]) + tumblr_posts.each do |blog_name, post_id| + delete_from_tumblr(blog_name, post_id) end end diff --git a/app/models/services/twitter.rb b/app/models/services/twitter.rb index 17e51a619431de8bedb7c0ac29413c57aef09dfa..d973a726856c0c49196061f8402901875e36563a 100644 --- a/app/models/services/twitter.rb +++ b/app/models/services/twitter.rb @@ -20,11 +20,13 @@ class Services::Twitter < Service client.user(nickname).profile_image_url_https "original" end - def delete_post post - if post.present? && post.tweet_id.present? - logger.debug "event=delete_from_service type=twitter sender_id=#{user_id} post=#{post.guid}" - delete_from_twitter post.tweet_id - end + def post_opts(post) + {tweet_id: post.tweet_id} if post.tweet_id.present? + end + + def delete_from_service(opts) + logger.debug "event=delete_from_service type=twitter sender_id=#{user_id} tweet_id=#{opts[:tweet_id]}" + delete_from_twitter(opts[:tweet_id]) end private diff --git a/app/models/share_visibility.rb b/app/models/share_visibility.rb index 060f65cd2ff435c518463195d9997790fc909cb1..4dbe526bf0496e1a5a102edc1b9cae6cf466cfa6 100644 --- a/app/models/share_visibility.rb +++ b/app/models/share_visibility.rb @@ -3,47 +3,42 @@ # the COPYRIGHT file. class ShareVisibility < ActiveRecord::Base - belongs_to :contact - belongs_to :shareable, :polymorphic => :true + belongs_to :user + belongs_to :shareable, polymorphic: :true - scope :for_a_users_contacts, ->(user) { - where(:contact_id => user.contacts.map {|c| c.id}) - } - - scope :for_contacts_of_a_person, ->(person) { - where(:contact_id => person.contacts.map {|c| c.id}) + scope :for_a_user, ->(user) { + where(user_id: user.id) } validate :not_public - # Perform a batch import, given a set of contacts and a shareable + # Perform a batch import, given a set of users and a shareable # @note performs a bulk insert in mySQL; performs linear insertions in postgres - # @param contacts [Array<Contact>] Recipients + # @param user_ids [Array<Integer>] Recipients # @param share [Shareable] # @return [void] - def self.batch_import(contact_ids, share) - return false unless ShareVisibility.new(:shareable_id => share.id, :shareable_type => share.class.to_s).valid? + def self.batch_import(user_ids, share) + return false unless ShareVisibility.new(shareable_id: share.id, shareable_type: share.class.to_s).valid? if AppConfig.postgres? - contact_ids.each do |contact_id| + user_ids.each do |user_id| ShareVisibility.find_or_create_by( - contact_id: contact_id, - shareable_id: share.id, + user_id: user_id, + shareable_id: share.id, shareable_type: share.class.base_class.to_s ) end else - new_share_visibilities_data = contact_ids.map do |contact_id| - [contact_id, share.id, share.class.base_class.to_s] + new_share_visibilities_data = user_ids.map do |user_id| + [user_id, share.id, share.class.base_class.to_s] end - ShareVisibility.import([:contact_id, :shareable_id, :shareable_type], new_share_visibilities_data) + ShareVisibility.import(%i(user_id shareable_id shareable_type), new_share_visibilities_data) end end private + def not_public - if shareable.public? - errors[:base] << "Cannot create visibility for a public object" - end + errors[:base] << "Cannot create visibility for a public object" if shareable.public? end end diff --git a/app/models/signature_order.rb b/app/models/signature_order.rb new file mode 100644 index 0000000000000000000000000000000000000000..83cbfb51a9a1c0e14da3fc6e0e64328584218b5d --- /dev/null +++ b/app/models/signature_order.rb @@ -0,0 +1,3 @@ +class SignatureOrder < ActiveRecord::Base + validates :order, presence: true, uniqueness: true +end diff --git a/app/models/status_message.rb b/app/models/status_message.rb index 4dacee42c535205378b9ea29a7b2462699e7c062..de858152f9f22154a462d8d7eb614e65aa630eec 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -8,33 +8,21 @@ class StatusMessage < Post include PeopleHelper acts_as_taggable_on :tags - extract_tags_from :raw_message + extract_tags_from :text validates_length_of :text, :maximum => 65535, :message => proc {|p, v| I18n.t('status_messages.too_long', :count => 65535, :current_length => v[:value].length)} # don't allow creation of empty status messages - validate :presence_of_content, on: :create, if: proc {|sm| sm.author && sm.author.local? } - - xml_name :status_message - xml_attr :raw_message - xml_attr :photos, :as => [Photo] - xml_attr :location, :as => Location - xml_attr :poll, :as => Poll + validate :presence_of_content, on: :create has_many :photos, :dependent => :destroy, :foreign_key => :status_message_guid, :primary_key => :guid has_one :location has_one :poll, autosave: true - - # a StatusMessage is federated before its photos are so presence_of_content() fails erroneously if no text is present - # therefore, we put the validation in a before_destory callback instead of a validation - before_destroy :absence_of_content - attr_accessor :oembed_url attr_accessor :open_graph_url - before_create :filter_mentions after_create :create_mentions after_commit :queue_gather_oembed_data, :on => :create, :if => :contains_oembed_url_in_text? after_commit :queue_gather_open_graph_data, :on => :create, :if => :contains_open_graph_url_in_text? @@ -49,42 +37,30 @@ class StatusMessage < Post end def self.user_tag_stream(user, tag_ids) - owned_or_visible_by_user(user). - tag_stream(tag_ids) + owned_or_visible_by_user(user).tag_stream(tag_ids) end def self.public_tag_stream(tag_ids) - all_public. - tag_stream(tag_ids) - end - - def raw_message - read_attribute(:text) - end - - def raw_message=(text) - write_attribute(:text, text) + all_public.tag_stream(tag_ids) end - def attach_photos_by_ids(photo_ids) - return [] unless photo_ids.present? - self.photos << Photo.where(:id => photo_ids, :author_id => self.author_id) + def self.tag_stream(tag_ids) + joins(:taggings).where("taggings.tag_id IN (?)", tag_ids) end def nsfw - self.raw_message.match(/#nsfw/i) || super + text.try(:match, /#nsfw/i) || super end def message - @message ||= Diaspora::MessageRenderer.new raw_message, mentioned_people: mentioned_people + @message ||= Diaspora::MessageRenderer.new(text, mentioned_people: mentioned_people) end def mentioned_people if self.persisted? - create_mentions if self.mentions.empty? self.mentions.includes(:person => :profile).map{ |mention| mention.person } else - Diaspora::Mentionable.people_from_string(self.raw_message) + Diaspora::Mentionable.people_from_string(text) end end @@ -96,7 +72,7 @@ class StatusMessage < Post ## ---- ---- def create_mentions - ppl = Diaspora::Mentionable.people_from_string(self.raw_message) + ppl = Diaspora::Mentionable.people_from_string(text) ppl.each do |person| self.mentions.find_or_create_by(person_id: person.id) end @@ -106,28 +82,6 @@ class StatusMessage < Post mentioned_people.include? person end - def notify_person(person) - self.mentions.where(:person_id => person.id).first.try(:notify_recipient) - end - - def after_dispatch(sender) - self.update_and_dispatch_attached_photos(sender) - end - - def update_and_dispatch_attached_photos(sender) - if self.photos.any? - logger.info "dispatch photos for StatusMessage:#{guid}" - Photo.where(status_message_guid: guid).update_all(:public => self.public) - self.photos.each do |photo| - if photo.pending - sender.add_to_streams(photo, self.aspects) - sender.dispatch_post(photo) - end - end - Photo.where(status_message_guid: guid).update_all(:pending => false) - end - end - def comment_email_subject message.title end @@ -137,7 +91,7 @@ class StatusMessage < Post end def text_and_photos_blank? - self.raw_message.blank? && self.photos.blank? + text.blank? && photos.blank? end def queue_gather_oembed_data @@ -158,40 +112,18 @@ class StatusMessage < Post self.open_graph_url = self.message.urls[0] end - def address - location.try(:address) - end - - protected - def presence_of_content - if text_and_photos_blank? - errors[:base] << "Cannot create a StatusMessage without content" - end - end - - def absence_of_content - unless text_and_photos_blank? - errors[:base] << "Cannot destory a StatusMessage with text and/or photos present" - end - end - - def filter_mentions - return if self.public? || self.aspects.empty? - - author_usr = self.author.try(:owner) - aspect_ids = self.aspects.map(&:id) - - self.raw_message = Diaspora::Mentionable.filter_for_aspects(self.raw_message, author_usr, *aspect_ids) + def post_location + { + address: location.try(:address), + lat: location.try(:lat), + lng: location.try(:lng) + } end private - def self.tag_stream(tag_ids) - joins(:taggings).where('taggings.tag_id IN (?)', tag_ids) - end - def after_parse - # Make sure already received photos don't invalidate the model - self.photos = photos.select(&:valid?) + def presence_of_content + errors[:base] << "Cannot create a StatusMessage without content" if text_and_photos_blank? end end diff --git a/app/models/user.rb b/app/models/user.rb index f183c3867a816b316c933ab02ff6ebf6b846e4ad..e2243d73b0e7b727db6aa74a79215057cc1399c0 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,7 +3,6 @@ # the COPYRIGHT file. class User < ActiveRecord::Base - include Encryptor::Private include Connecting include Querying include SocialActions @@ -15,7 +14,7 @@ class User < ActiveRecord::Base scope :daily_actives, ->(time = Time.now) { logged_in_since(time - 1.day) } scope :yearly_actives, ->(time = Time.now) { logged_in_since(time - 1.year) } scope :halfyear_actives, ->(time = Time.now) { logged_in_since(time - 6.month) } - scope :active, -> { joins(:person).where(people: {closed_account: false}).where.not(username: nil) } + scope :active, -> { joins(:person).where(people: {closed_account: false}) } devise :token_authenticatable, :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, @@ -23,21 +22,25 @@ class User < ActiveRecord::Base before_validation :strip_and_downcase_username before_validation :set_current_language, :on => :create + before_validation :set_default_color_theme, on: :create validates :username, :presence => true, :uniqueness => true validates_format_of :username, :with => /\A[A-Za-z0-9_]+\z/ validates_length_of :username, :maximum => 32 validates_exclusion_of :username, :in => AppConfig.settings.username_blacklist validates_inclusion_of :language, :in => AVAILABLE_LANGUAGE_CODES + validates :color_theme, inclusion: {in: AVAILABLE_COLOR_THEME_CODES}, allow_blank: true validates_format_of :unconfirmed_email, :with => Devise.email_regexp, :allow_blank => true - validates_presence_of :person, :unless => proc {|user| user.invitation_token.present?} + validate :unconfirmed_email_quasiuniqueness + + validates :person, presence: true validates_associated :person validate :no_person_with_same_username serialize :hidden_shareables, Hash - has_one :person, :foreign_key => :owner_id + has_one :person, inverse_of: :owner, foreign_key: :owner_id has_one :profile, through: :person delegate :guid, :public_key, :posts, :photos, :owns?, :image_url, @@ -45,8 +48,6 @@ class User < ActiveRecord::Base :first_name, :last_name, :gender, :participations, to: :person delegate :id, :guid, to: :person, prefix: true - has_many :invitations_from_me, :class_name => 'Invitation', :foreign_key => :sender_id - has_many :invitations_to_me, :class_name => 'Invitation', :foreign_key => :recipient_id has_many :aspects, -> { order('order_id ASC') } belongs_to :auto_follow_back_aspect, :class_name => 'Aspect' @@ -74,8 +75,15 @@ class User < ActiveRecord::Base has_many :reports - before_save :guard_unconfirmed_email, - :save_person! + has_many :pairwise_pseudonymous_identifiers, class_name: "Api::OpenidConnect::PairwisePseudonymousIdentifier" + has_many :authorizations, class_name: "Api::OpenidConnect::Authorization" + has_many :o_auth_applications, through: :authorizations, class_name: "Api::OpenidConnect::OAuthApplication" + + has_many :share_visibilities + + before_save :guard_unconfirmed_email + + after_save :remove_invalid_unconfirmed_emails def self.all_sharing_with_person(person) User.joins(:contacts).where(:contacts => {:person_id => person.id}) @@ -89,21 +97,11 @@ class User < ActiveRecord::Base ConversationVisibility.where(person_id: self.person_id).sum(:unread) end - #@deprecated - def ugly_accept_invitation_code - begin - self.invitations_to_me.first.sender.invitation_code - rescue Exception => e - nil - end - end - def process_invite_acceptence(invite) self.invited_by = invite.user - invite.use! + invite.use! unless AppConfig.settings.enable_registrations? end - def invitation_code InvitationCode.find_or_create_by(user_id: self.id) end @@ -198,6 +196,10 @@ class User < ActiveRecord::Base self.language = I18n.locale.to_s if self.language.blank? end + def set_default_color_theme + self.color_theme ||= AppConfig.settings.default_color_theme + end + # This override allows a user to enter either their email address or their username into the username field. # @return [User] The user that matches the username/email condition. # @return [nil] if no user matches that condition. @@ -216,16 +218,9 @@ class User < ActiveRecord::Base save end - ######### Aspects ###################### - def add_contact_to_aspect(contact, aspect) - return true if AspectMembership.exists?(:contact_id => contact.id, :aspect_id => aspect.id) - contact.aspect_memberships.create!(:aspect => aspect) - end - ######## Posting ######## def build_post(class_name, opts={}) - opts[:author] = self.person - opts[:diaspora_handle] = opts[:author].diaspora_handle + opts[:author] = person model_class = class_name.to_s.camelize.constantize model_class.diaspora_initialize(opts) @@ -233,7 +228,7 @@ class User < ActiveRecord::Base def dispatch_post(post, opts={}) logger.info "user:#{id} dispatching #{post.class}:#{post.guid}" - Postzord::Dispatcher.defer_build_and_post(self, post, opts) + Diaspora::Federation::Dispatcher.defer_dispatch(self, post, opts) end def update_post(post, post_hash={}) @@ -243,12 +238,6 @@ class User < ActiveRecord::Base end end - def notify_if_mentioned(post) - return unless self.contact_for(post.author) && post.respond_to?(:mentions?) - - post.notify_person(self.person) if post.mentions? self.person - end - def add_to_streams(post, aspects_to_insert) aspects_to_insert.each do |aspect| aspect << post @@ -323,34 +312,7 @@ class User < ActiveRecord::Base end def perform_export_photos! - temp_zip = Tempfile.new([username, '_photos.zip']) - begin - Zip::OutputStream.open(temp_zip.path) do |zos| - photos.each do |photo| - begin - photo_file = photo.unprocessed_image.file - if photo_file - photo_data = photo_file.read - zos.put_next_entry(photo.remote_photo_name) - zos.print(photo_data) - else - logger.info "Export photos error: No file for #{photo.remote_photo_name} not found" - end - rescue Errno::ENOENT - logger.info "Export photos error: #{photo.unprocessed_image.file.path} not found" - end - end - end - ensure - temp_zip.close - end - - begin - update exported_photos_file: temp_zip, exported_photos_at: Time.zone.now if temp_zip.present? - ensure - restore_attributes if invalid? || temp_zip.present? - update exporting_photos: false - end + PhotoExporter.new(self).perform end ######### Mailer ####################### @@ -367,26 +329,10 @@ class User < ActiveRecord::Base end ######### Posts and Such ############### - def retract(target, opts={}) - if target.respond_to?(:relayable?) && target.relayable? - retraction = RelayableRetraction.build(self, target) - elsif target.is_a? Post - retraction = SignedRetraction.build(self, target) - else - retraction = Retraction.for(target) - end - - if target.is_a?(Post) - opts[:additional_subscribers] = target.resharers - opts[:services] = self.services - end - - mailman = Postzord::Dispatcher.build(self, retraction, opts) - mailman.post - - retraction.perform(self) - - retraction + def retract(target) + retraction = Retraction.for(target, self) + retraction.defer_dispatch(self) + retraction.perform end ########### Profile ###################### @@ -412,8 +358,8 @@ class User < ActiveRecord::Base update_profile( self.profile.from_omniauth_hash( user_info ) ) end - def deliver_profile_update - Postzord::Dispatcher.build(self, profile).post + def deliver_profile_update(opts={}) + Diaspora::Federation::Dispatcher.defer_dispatch(self, profile, opts) end def basic_profile_present? @@ -432,6 +378,8 @@ class User < ActiveRecord::Base self.email = opts[:email] self.language = opts[:language] self.language ||= I18n.locale.to_s + self.color_theme = opts[:color_theme] + self.color_theme ||= AppConfig.settings.default_color_theme self.valid? errors = self.errors errors.delete :person @@ -442,7 +390,6 @@ class User < ActiveRecord::Base end def set_person(person) - person.url = AppConfig.pod_uri.to_s person.diaspora_handle = "#{self.username}#{User.diaspora_id_host}" self.person = person end @@ -471,10 +418,10 @@ class User < ActiveRecord::Base conversation = sender.build_conversation( participant_ids: [sender.person.id, person.id], subject: AppConfig.settings.welcome_message.subject.get, - message: {text: AppConfig.settings.welcome_message.text.get % {username: username}}) - if conversation.save - Postzord::Dispatcher.build(sender, conversation).post - end + message: {text: AppConfig.settings.welcome_message.text.get % {username: username}} + ) + + Diaspora::Federation::Dispatcher.build(sender, conversation).dispatch if conversation.save end def encryption_key @@ -502,6 +449,13 @@ class User < ActiveRecord::Base end + # Ensure that the unconfirmed email isn't already someone's email + def unconfirmed_email_quasiuniqueness + if User.exists?(["id != ? AND email = ?", id, unconfirmed_email]) + errors.add(:unconfirmed_email, I18n.t("errors.messages.taken")) + end + end + def guard_unconfirmed_email self.unconfirmed_email = nil if unconfirmed_email.blank? || unconfirmed_email == email @@ -510,27 +464,22 @@ class User < ActiveRecord::Base end end + # Whenever email is set, clear all unconfirmed emails which match + def remove_invalid_unconfirmed_emails + User.where(unconfirmed_email: email).update_all(unconfirmed_email: nil) if email_changed? + end + # Generate public/private keys for User and associated Person def generate_keys - key_size = (Rails.env == 'test' ? 512 : 4096) + key_size = (Rails.env == "test" ? 512 : 4096) - self.serialized_private_key = OpenSSL::PKey::RSA::generate(key_size).to_s if self.serialized_private_key.blank? + self.serialized_private_key = OpenSSL::PKey::RSA.generate(key_size).to_s if serialized_private_key.blank? if self.person && self.person.serialized_public_key.blank? self.person.serialized_public_key = OpenSSL::PKey::RSA.new(self.serialized_private_key).public_key.to_s end end - # Sometimes we access the person in a strange way and need to do this - # @note we should make this method depricated. - # - # @return [Person] - def save_person! - self.person.save if self.person && self.person.changed? - self.person - end - - def no_person_with_same_username diaspora_id = "#{self.username}#{User.diaspora_id_host}" if self.username_changed? && Person.exists?(:diaspora_handle => diaspora_id) @@ -593,12 +542,10 @@ class User < ActiveRecord::Base private def clearable_fields - self.attributes.keys - ["id", "username", "encrypted_password", - "created_at", "updated_at", "locked_at", - "serialized_private_key", "getting_started", - "disable_mail", "show_community_spotlight_in_stream", - "strip_exif", "email", "remove_after", - "export", "exporting", "exported_at", - "exported_photos_file", "exporting_photos", "exported_photos_at"] + attributes.keys - %w(id username encrypted_password created_at updated_at locked_at + serialized_private_key getting_started + disable_mail show_community_spotlight_in_stream + strip_exif email remove_after export exporting exported_at + exported_photos_file exporting_photos exported_photos_at) end end diff --git a/app/models/user/connecting.rb b/app/models/user/connecting.rb index 333e6bd5edc351cf9cb57d46a1d25a4b91dd83d9..0781745f468926821ddde9a4dc08fb7f09a2d470 100644 --- a/app/models/user/connecting.rb +++ b/app/models/user/connecting.rb @@ -2,70 +2,59 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -module User::Connecting - # This will create a contact on the side of the sharer and the sharee. - # @param [Person] person The person to start sharing with. - # @param [Aspect] aspect The aspect to add them to. - # @return [Contact] The newly made contact for the passed in person. - def share_with(person, aspect) - contact = self.contacts.find_or_initialize_by(person_id: person.id) - return false unless contact.valid? - - unless contact.receiving? - contact.dispatch_request +class User + module Connecting + # This will create a contact on the side of the sharer and the sharee. + # @param [Person] person The person to start sharing with. + # @param [Aspect] aspect The aspect to add them to. + # @return [Contact] The newly made contact for the passed in person. + def share_with(person, aspect) + contact = contacts.find_or_initialize_by(person_id: person.id) + return false unless contact.valid? + + needs_dispatch = !contact.receiving? contact.receiving = true - end + contact.aspects << aspect + contact.save + + if needs_dispatch + Diaspora::Federation::Dispatcher.defer_dispatch(self, contact) + deliver_profile_update(subscriber_ids: [person.id]) unless person.local? + end - contact.aspects << aspect - contact.save + Notifications::StartedSharing.where(recipient_id: id, target: person.id, unread: true) + .update_all(unread: false) - if notification = Notification.where(:target_id => person.id).first - notification.update_attributes(:unread=>false) + contact end - deliver_profile_update - register_share_visibilities(contact) - contact - end + def disconnect(contact) + logger.info "event=disconnect user=#{diaspora_handle} target=#{contact.person.diaspora_handle}" - # This puts the last 100 public posts by the passed in contact into the user's stream. - # @param [Contact] contact - # @return [void] - def register_share_visibilities(contact) - #should have select here, but proven hard to test - posts = Post.where(:author_id => contact.person_id, :public => true).limit(100) - p = posts.map do |post| - ShareVisibility.new(:contact_id => contact.id, :shareable_id => post.id, :shareable_type => 'Post') - end - ShareVisibility.import(p) unless posts.empty? - nil - end + if contact.person.local? + contact.person.owner.disconnected_by(contact.user.person) + else + Retraction.for(contact).defer_dispatch(self) + end + + contact.aspect_memberships.delete_all - def remove_contact(contact, opts={:force => false, :retracted => false}) - if !contact.mutual? || opts[:force] - contact.destroy - elsif opts[:retracted] - contact.update_attributes(:sharing => false) - else - contact.update_attributes(:receiving => false) + disconnect_contact(contact, direction: :receiving, destroy: !contact.sharing) end - end - def disconnect(bad_contact, opts={}) - person = bad_contact.person - logger.info "event=disconnect user=#{diaspora_handle} target=#{person.diaspora_handle}" - retraction = Retraction.for(self) - retraction.subscribers = [person]#HAX - Postzord::Dispatcher.build(self, retraction).post + def disconnected_by(person) + logger.info "event=disconnected_by user=#{diaspora_handle} target=#{person.diaspora_handle}" + contact_for(person).try {|contact| disconnect_contact(contact, direction: :sharing, destroy: !contact.receiving) } + end - AspectMembership.where(:contact_id => bad_contact.id).delete_all - remove_contact(bad_contact, opts) - end + private - def disconnected_by(person) - logger.info "event=disconnected_by user=#{diaspora_handle} target=#{person.diaspora_handle}" - if contact = self.contact_for(person) - remove_contact(contact, :retracted => true) + def disconnect_contact(contact, direction:, destroy:) + if destroy + contact.destroy + else + contact.update_attributes(direction => false) + end end end end diff --git a/app/models/user/querying.rb b/app/models/user/querying.rb index 20d52df4545008b1e8df005ee3b2f281506c80b2..f9ff0f001e0baf498500feae4b493681fe12a732 100644 --- a/app/models/user/querying.rb +++ b/app/models/user/querying.rb @@ -13,90 +13,12 @@ module User::Querying def visible_shareables(klass, opts={}) opts = prep_opts(klass, opts) shareable_ids = visible_shareable_ids(klass, opts) - klass.where(:id => shareable_ids).select('DISTINCT '+klass.to_s.tableize+'.*').limit(opts[:limit]).order(opts[:order_with_table]).order(klass.table_name+".id DESC") + klass.where(id: shareable_ids).select("DISTINCT #{klass.table_name}.*") + .limit(opts[:limit]).order(opts[:order_with_table]) end def visible_shareable_ids(klass, opts={}) - opts = prep_opts(klass, opts) - visible_ids_from_sql(klass, opts) - end - - # @return [Array<Integer>] - def visible_ids_from_sql(klass, opts={}) - opts = prep_opts(klass, opts) - opts[:klass] = klass - opts[:by_members_of] ||= self.aspect_ids - - post_ids = klass.connection.select_values(visible_shareable_sql(klass, opts)).map(&:to_i) - post_ids += klass.connection.select_values("#{construct_public_followings_sql(opts).to_sql} LIMIT #{opts[:limit]}").map {|id| id.to_i } - end - - def visible_shareable_sql(klass, opts={}) - table = klass.table_name - opts = prep_opts(klass, opts) - opts[:klass] = klass - - shareable_from_others = construct_shareable_from_others_query(opts) - shareable_from_self = construct_shareable_from_self_query(opts) - - "(#{shareable_from_others.to_sql} LIMIT #{opts[:limit]}) UNION ALL (#{shareable_from_self.to_sql} LIMIT #{opts[:limit]}) ORDER BY #{opts[:order]} LIMIT #{opts[:limit]}" - end - - def ugly_select_clause(query, opts) - klass = opts[:klass] - select_clause ='DISTINCT %s.id, %s.updated_at AS updated_at, %s.created_at AS created_at' % [klass.table_name, klass.table_name, klass.table_name] - query.select(select_clause).order(opts[:order_with_table]).where(klass.arel_table[opts[:order_field]].lt(opts[:max_time])) - end - - def construct_shareable_from_others_query(opts) - conditions = { - :pending => false, - :share_visibilities => {:hidden => opts[:hidden]}, - :contacts => {:user_id => self.id, :receiving => true} - } - - conditions[:type] = opts[:type] if opts.has_key?(:type) - - query = opts[:klass].joins(:contacts).where(conditions) - - if opts[:by_members_of] - query = query.joins(:contacts => :aspect_memberships).where( - :aspect_memberships => {:aspect_id => opts[:by_members_of]}) - end - - ugly_select_clause(query, opts) - end - - def construct_public_followings_sql(opts) - logger.debug "[EVIL-QUERY] user.construct_public_followings_sql" - - # For PostgreSQL and MySQL/MariaDB we use a different query - # see issue: https://github.com/diaspora/diaspora/issues/5014 - if AppConfig.postgres? - query = opts[:klass].where(:author_id => Person.in_aspects(opts[:by_members_of]).select("people.id"), :public => true, :pending => false) - else - aspects = Aspect.where(:id => opts[:by_members_of]) - person_ids = Person.connection.select_values(people_in_aspects(aspects).select("people.id").to_sql) - query = opts[:klass].where(:author_id => person_ids, :public => true, :pending => false) - end - - unless(opts[:klass] == Photo) - query = query.where(:type => opts[:type]) - end - - ugly_select_clause(query, opts) - end - - def construct_shareable_from_self_query(opts) - conditions = {:pending => false, :author_id => self.person_id } - conditions[:type] = opts[:type] if opts.has_key?(:type) - query = opts[:klass].where(conditions) - - if opts[:by_members_of] - query = query.joins(:aspect_visibilities).where(:aspect_visibilities => {:aspect_id => opts[:by_members_of]}) - end - - ugly_select_clause(query, opts) + visible_ids_from_sql(klass, prep_opts(klass, opts)) end def contact_for(person) @@ -144,18 +66,91 @@ module User::Querying end def posts_from(person) - ::EvilQuery::ShareablesFromPerson.new(self, Post, person).make_relation! + Post.from_person_visible_by_user(self, person).order("posts.created_at desc") end def photos_from(person, opts={}) opts = prep_opts(Photo, opts) - ::EvilQuery::ShareablesFromPerson.new(self, Photo, person).make_relation! + Photo.from_person_visible_by_user(self, person) .by_max_time(opts[:max_time]) .limit(opts[:limit]) end protected + # @return [Array<Integer>] + def visible_ids_from_sql(klass, opts) + opts[:klass] = klass + opts[:by_members_of] ||= aspect_ids + + klass.connection.select_values(visible_shareable_sql(opts)).map(&:to_i) + end + + def visible_shareable_sql(opts) + shareable_from_others = construct_shareable_from_others_query(opts) + shareable_from_self = construct_shareable_from_self_query(opts) + + "(#{shareable_from_others.to_sql} LIMIT #{opts[:limit]}) " \ + "UNION ALL (#{shareable_from_self.to_sql} LIMIT #{opts[:limit]}) " \ + "ORDER BY #{opts[:order]} LIMIT #{opts[:limit]}" + end + + def construct_shareable_from_others_query(opts) + logger.debug "[EVIL-QUERY] user.construct_shareable_from_others_query" + + query = visible_shareables_query(posts_from_aspects_query(opts), opts) + + query = query.where(type: opts[:type]) unless opts[:klass] == Photo + + ugly_select_clause(query, opts) + end + + # For PostgreSQL and MySQL/MariaDB we use a different query + # see issue: https://github.com/diaspora/diaspora/issues/5014 + def posts_from_aspects_query(opts) + if AppConfig.postgres? + opts[:klass].where(author_id: Person.in_aspects(opts[:by_members_of]).select("people.id")) + else + person_ids = Person.connection.select_values(Person.in_aspects(opts[:by_members_of]).select("people.id").to_sql) + opts[:klass].where(author_id: person_ids) + end + end + + def visible_shareables_query(query, opts) + query.with_visibility.where( + visible_private_shareables(opts).or(opts[:klass].arel_table[:public].eq(true)) + ) + end + + def visible_private_shareables(opts) + ShareVisibility.arel_table[:user_id].eq(id) + .and(ShareVisibility.arel_table[:shareable_type].eq(opts[:klass].to_s)) + .and(ShareVisibility.arel_table[:hidden].eq(opts[:hidden])) + end + + def construct_shareable_from_self_query(opts) + conditions = {author_id: person_id} + conditions[:type] = opts[:type] if opts.has_key?(:type) + query = opts[:klass].where(conditions) + + unless opts[:all_aspects?] + query = query.with_aspects.where( + AspectVisibility.arel_table[:aspect_id].in(opts[:by_members_of]) + .or(opts[:klass].arel_table[:public].eq(true)) + ) + end + + ugly_select_clause(query, opts) + end + + def ugly_select_clause(query, opts) + klass = opts[:klass] + table = klass.table_name + select_clause = "DISTINCT %s.id, %s.updated_at AS updated_at, %s.created_at AS created_at" % [table, table, table] + query.select(select_clause).order(opts[:order_with_table]) + .where(klass.arel_table[opts[:order_field]].lt(opts[:max_time])) + end + # @return [Hash] def prep_opts(klass, opts) defaults = { diff --git a/app/models/user/social_actions.rb b/app/models/user/social_actions.rb index 65ddafdc329d55ed9912355dc70866a0d38dcecd..a01789a3cb43ae33740d9baf631a922bb70e1d9d 100644 --- a/app/models/user/social_actions.rb +++ b/app/models/user/social_actions.rb @@ -1,7 +1,7 @@ module User::SocialActions def comment!(target, text, opts={}) Comment::Generator.new(self, target, text).create!(opts).tap do - find_or_create_participation!(target) + update_or_create_participation!(target) end end @@ -11,28 +11,24 @@ module User::SocialActions def like!(target, opts={}) Like::Generator.new(self, target).create!(opts).tap do - find_or_create_participation!(target) + update_or_create_participation!(target) end end def participate_in_poll!(target, answer, opts={}) PollParticipation::Generator.new(self, target, answer).create!(opts).tap do - find_or_create_participation!(target) + update_or_create_participation!(target) end end def reshare!(target, opts={}) build_post(:reshare, :root_guid => target.guid).tap do |reshare| reshare.save! - find_or_create_participation!(target) - Postzord::Dispatcher.defer_build_and_post(self, reshare) + update_or_create_participation!(target) + Diaspora::Federation::Dispatcher.defer_dispatch(self, reshare) end end - def build_comment(options={}) - Comment::Generator.new(self, options.delete(:post), options.delete(:text)).build(options) - end - def build_conversation(opts={}) Conversation.new do |c| c.author = self.person @@ -51,7 +47,13 @@ module User::SocialActions ) end - def find_or_create_participation!(target) - participations.where(:target_id => target).first || participate!(target) + def update_or_create_participation!(target) + return if target.author == person + participation = participations.where(target_id: target).first + if participation.present? + participation.update!(count: participation.count.next) + else + participate!(target) + end end end diff --git a/app/presenters/avatar_presenter.rb b/app/presenters/avatar_presenter.rb index f612c9c077ad811e1ba95a4048b05d6647e3cffc..c342769e894dc8423837df5548a3a08a05368929 100644 --- a/app/presenters/avatar_presenter.rb +++ b/app/presenters/avatar_presenter.rb @@ -4,9 +4,21 @@ class AvatarPresenter < BasePresenter def base_hash { - small: image_url(:thumb_small) || DEFAULT_IMAGE, - medium: image_url(:thumb_medium) || DEFAULT_IMAGE, - large: image_url || DEFAULT_IMAGE + small: small, + medium: medium, + large: large } end + + def small + image_url(:thumb_small) || DEFAULT_IMAGE + end + + def medium + image_url(:thumb_medium) || DEFAULT_IMAGE + end + + def large + image_url || DEFAULT_IMAGE + end end diff --git a/app/presenters/base_presenter.rb b/app/presenters/base_presenter.rb index 122a505b6508875a216a721d7fff340792fad1e7..3c79290e3cfb2cb02a543aa0182069805403ce3e 100644 --- a/app/presenters/base_presenter.rb +++ b/app/presenters/base_presenter.rb @@ -1,5 +1,6 @@ class BasePresenter attr_reader :current_user + include Rails.application.routes.url_helpers class << self def new(*args) @@ -26,4 +27,10 @@ class BasePresenter nil end end + + private + + def default_url_options + {host: AppConfig.pod_uri.host, port: AppConfig.pod_uri.port} + end end diff --git a/app/presenters/contact_presenter.rb b/app/presenters/contact_presenter.rb index 6c3463a9d545b24dc1f48ee221a5373d93babd7a..ae448bbe9d8795b916da16725ce55dc929b6411f 100644 --- a/app/presenters/contact_presenter.rb +++ b/app/presenters/contact_presenter.rb @@ -12,6 +12,12 @@ class ContactPresenter < BasePresenter end def full_hash_with_person - full_hash.merge(person: PersonPresenter.new(person, current_user).full_hash_with_profile) + full_hash.merge(person: person_without_contact) + end + + private + + def person_without_contact + PersonPresenter.new(person, current_user).as_json.except!(:contact) end end diff --git a/app/presenters/hovercard_presenter.rb b/app/presenters/hovercard_presenter.rb deleted file mode 100644 index 148f20d1589e474ae5548d2e366ff799696254c5..0000000000000000000000000000000000000000 --- a/app/presenters/hovercard_presenter.rb +++ /dev/null @@ -1,39 +0,0 @@ -class HovercardPresenter - - attr_accessor :person - - # initialize the presenter with the given Person object - def initialize(person) - raise ArgumentError, "the given object is not a Person" unless person.class == Person - - self.person = person - end - - # returns the json representation of the Person object for use with the - # hovercard UI - def to_json(options={}) - { :id => person.id, - :avatar => avatar('medium'), - :url => profile_url, - :name => person.name, - :handle => person.diaspora_handle, - :tags => person.tags.map { |t| "#"+t.name } - }.to_json(options) - end - - # get the image url of the profile avatar for the given size - # possible sizes: 'small', 'medium', 'large' - def avatar(size="medium") - if !["small", "medium", "large"].include?(size) - raise ArgumentError, "the given parameter is not a valid size" - end - - person.image_url("thumb_#{size}".to_sym) - end - - # return the (relative) url to the user profile page. - # uses the 'person_path' url helper from the rails routes - def profile_url - Rails.application.routes.url_helpers.person_path(person) - end -end diff --git a/app/presenters/person_presenter.rb b/app/presenters/person_presenter.rb index 6ca7351ee6cd5bde81a5f2e40a0932d7b9cb44b4..63685cb51036239240549edf3eb67a6704cca8fe 100644 --- a/app/presenters/person_presenter.rb +++ b/app/presenters/person_presenter.rb @@ -9,42 +9,35 @@ class PersonPresenter < BasePresenter end def full_hash - base_hash.merge( - relationship: relationship, - block: is_blocked? ? BlockPresenter.new(current_user_person_block).base_hash : false, - contact: (!own_profile? && has_contact?) ? {id: current_user_person_contact.id} : false, - is_own_profile: own_profile? + base_hash_with_contact.merge( + relationship: relationship, + block: is_blocked? ? BlockPresenter.new(current_user_person_block).base_hash : false, + is_own_profile: own_profile?, + show_profile_info: public_details? || own_profile? || person_is_following_current_user ) end - def full_hash_with_avatar - full_hash.merge(avatar: AvatarPresenter.new(profile).base_hash) + def as_json(_options={}) + full_hash_with_profile end - def full_hash_with_profile - attrs = full_hash - - if own_profile? || person_is_following_current_user - attrs.merge!(profile: ProfilePresenter.new(profile).private_hash) - else - attrs.merge!(profile: ProfilePresenter.new(profile).public_hash) - end - - attrs + def hovercard + base_hash_with_contact.merge(profile: ProfilePresenter.new(profile).for_hovercard) end - def as_json(_options={}) - attrs = full_hash_with_avatar - - if own_profile? || person_is_following_current_user - attrs.merge!( - location: @presentable.location, - birthday: @presentable.formatted_birthday, - bio: @presentable.bio - ) - end - - attrs + def metas_attributes + { + keywords: {name: "keywords", content: comma_separated_tags}, + description: {name: "description", content: description}, + og_title: {property: "og:title", content: title}, + og_description: {property: "og:title", content: description}, + og_url: {property: "og:url", content: url}, + og_image: {property: "og:image", content: image_url}, + og_type: {property: "og:type", content: "profile"}, + og_profile_username: {property: "og:profile:username", content: name}, + og_profile_firstname: {property: "og:profile:first_name", content: first_name}, + og_profile_lastname: {property: "og:profile:last_name", content: last_name} + } end protected @@ -71,6 +64,28 @@ class PersonPresenter < BasePresenter contact && contact.sharing? end + def base_hash_with_contact + base_hash.merge( + contact: (!own_profile? && has_contact?) ? contact_hash : false + ) + end + + def full_hash_with_profile + attrs = full_hash + + if attrs[:show_profile_info] + attrs.merge!(profile: ProfilePresenter.new(profile).private_hash) + else + attrs.merge!(profile: ProfilePresenter.new(profile).public_hash) + end + + attrs + end + + def contact_hash + ContactPresenter.new(current_user_person_contact).full_hash + end + private def current_user_person_block @@ -88,4 +103,25 @@ class PersonPresenter < BasePresenter def is_blocked? current_user_person_block.present? end + + def title + name + end + + def comma_separated_tags + profile.tags.map(&:name).join(", ") if profile.tags + end + + def url + url_for(@presentable) + end + + def description + public_details? ? bio : "" + end + + def image_url + return AppConfig.url_to @presentable.image_url if @presentable.image_url[0] == "/" + @presentable.image_url + end end diff --git a/app/presenters/pod_presenter.rb b/app/presenters/pod_presenter.rb new file mode 100644 index 0000000000000000000000000000000000000000..7f08b3770c410503089df39e0056c77eafa7a449 --- /dev/null +++ b/app/presenters/pod_presenter.rb @@ -0,0 +1,20 @@ +class PodPresenter < BasePresenter + def base_hash(*_arg) + { + id: id, + host: host, + port: port, + ssl: ssl, + status: status, + checked_at: checked_at, + response_time: response_time, + offline: offline?, + offline_since: offline_since, + created_at: created_at, + software: software, + error: error + } + end + + alias_method :as_json, :base_hash +end diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb index 7eb4581bd962219b3a8e8164a3173421a76083e2..ba1609c8a454b9d72c277e33b94e401536c96bff 100644 --- a/app/presenters/post_presenter.rb +++ b/app/presenters/post_presenter.rb @@ -1,21 +1,42 @@ class PostPresenter < BasePresenter include PostsHelper + include MetaDataHelper attr_accessor :post - def initialize(post, current_user=nil) - @post = post - @current_user = current_user + def initialize(presentable, current_user=nil) + @post = presentable + super end def as_json(_options={}) - @post.as_json(only: directly_retrieved_attributes).merge(non_directly_retrieved_attributes) + @post.as_json(only: directly_retrieved_attributes) + .merge(non_directly_retrieved_attributes) + end + + def metas_attributes + { + keywords: {name: "keywords", content: comma_separated_tags}, + description: {name: "description", content: description}, + og_url: {property: "og:url", content: url}, + og_title: {property: "og:title", content: title}, + og_image: {property: "og:image", content: images}, + og_description: {property: "og:description", content: description}, + og_article_tag: {property: "og:article:tag", content: tags}, + og_article_author: {property: "og:article:author", content: author_name}, + og_article_modified: {property: "og:article:modified_time", content: modified_time_iso8601}, + og_article_published: {property: "og:article:published_time", content: published_time_iso8601} + } + end + + def page_title + post_page_title @post end private def directly_retrieved_attributes - %i(id guid public created_at interacted_at provider_display_name image_url object_url) + %i(id guid public created_at interacted_at provider_display_name) end def non_directly_retrieved_attributes @@ -30,7 +51,7 @@ class PostPresenter < BasePresenter photos: build_photos_json, root: root, title: title, - address: @post.address, + location: @post.post_location, poll: @post.poll, already_participated_in_poll: already_participated_in_poll, participation: participate?, @@ -38,11 +59,15 @@ class PostPresenter < BasePresenter } end + def title + @post.message.present? ? @post.message.title : I18n.t("posts.presenter.title", name: @post.author_name) + end + def build_text if @post.message @post.message.plain_text_for_json else - @post.raw_message + @post.text end end @@ -58,10 +83,6 @@ class PostPresenter < BasePresenter @post.photos.map {|p| p.as_api_response(:backbone) } end - def title - @post.message.present? ? @post.message.title : I18n.t("posts.presenter.title", name: @post.author_name) - end - def root if @post.respond_to?(:absolute_root) && @post.absolute_root.present? PostPresenter.new(@post.absolute_root, current_user).as_json @@ -103,4 +124,33 @@ class PostPresenter < BasePresenter def person current_user.person end + + def images + photos.any? ? photos.map(&:url) : default_image_url + end + + def published_time_iso8601 + created_at.to_time.iso8601 + end + + def modified_time_iso8601 + updated_at.to_time.iso8601 + end + + def tags + tags = @post.is_a?(Reshare) ? @post.absolute_root.try(:tags) : @post.tags + tags ? tags.map(&:name) : [] + end + + def comma_separated_tags + tags.join(", ") + end + + def url + post_url @post + end + + def description + message.try(:plain_text_without_markdown, truncate: 1000) + end end diff --git a/app/presenters/profile_presenter.rb b/app/presenters/profile_presenter.rb index 71e624fcbc667bc443005d74a58be795475fbd82..d4e38884d90e53cac1b87dfb3911c70a689aef3b 100644 --- a/app/presenters/profile_presenter.rb +++ b/app/presenters/profile_presenter.rb @@ -15,6 +15,13 @@ class ProfilePresenter < BasePresenter ) end + def for_hovercard + { + avatar: AvatarPresenter.new(@presentable).medium, + tags: tags.pluck(:name) + } + end + def private_hash public_hash.merge( bio: bio_message.plain_text_for_json, diff --git a/app/presenters/social_relay_presenter.rb b/app/presenters/social_relay_presenter.rb new file mode 100644 index 0000000000000000000000000000000000000000..43af94cd1081b63f4695e5051071854685b41883 --- /dev/null +++ b/app/presenters/social_relay_presenter.rb @@ -0,0 +1,24 @@ +class SocialRelayPresenter + def as_json(*) + { + "subscribe" => AppConfig.relay.inbound.subscribe?, + "scope" => AppConfig.relay.inbound.scope, + "tags" => tags + } + end + + def tags + return [] unless AppConfig.relay.inbound.scope == "tags" + tags = AppConfig.relay.inbound.pod_tags.present? ? AppConfig.relay.inbound.pod_tags.split(",").map(&:strip) : [] + add_user_tags(tags) + tags.uniq + end + + def add_user_tags(tags) + if AppConfig.relay.inbound.include_user_tags? + user_ids = User.halfyear_actives.pluck(:id) + tag_ids = TagFollowing.where(user: user_ids).select(:tag_id).distinct.pluck(:tag_id) + tags.concat ActsAsTaggableOn::Tag.where(id: tag_ids).pluck(:name) + end + end +end diff --git a/app/presenters/statistics_presenter.rb b/app/presenters/statistics_presenter.rb index be74f3b2e2eb403b47468483803ece03c45ef561..e6382850ca97cacd50f783fdbffcda7f26748f86 100644 --- a/app/presenters/statistics_presenter.rb +++ b/app/presenters/statistics_presenter.rb @@ -12,7 +12,6 @@ class StatisticsPresenter < NodeInfoPresenter base_data.merge(user_counts) .merge(post_counts) .merge(comment_counts) - .merge(legacy_services) end def base_data @@ -47,10 +46,4 @@ class StatisticsPresenter < NodeInfoPresenter "local_comments" => local_comments } end - - def legacy_services - Configuration::KNOWN_SERVICES.each_with_object({}) {|service, result| - result[service.to_s] = AppConfig.show_service?(service, nil) - } - end end diff --git a/app/presenters/tag_stream_presenter.rb b/app/presenters/tag_stream_presenter.rb new file mode 100644 index 0000000000000000000000000000000000000000..2a3dea229487d585953ca10de14959c07524491f --- /dev/null +++ b/app/presenters/tag_stream_presenter.rb @@ -0,0 +1,25 @@ +class TagStreamPresenter < BasePresenter + def title + @presentable.display_tag_name + end + + def metas_attributes + { + keywords: {name: "keywords", content: tag_name}, + description: {name: "description", content: description}, + og_url: {property: "og:url", content: url}, + og_title: {property: "og:title", content: title}, + og_description: {property: "og:description", content: description} + } + end + + private + + def description + I18n.t("streams.tags.title", tags: tag_name) + end + + def url + tag_url tag_name + end +end diff --git a/app/presenters/user_application_presenter.rb b/app/presenters/user_application_presenter.rb new file mode 100644 index 0000000000000000000000000000000000000000..0bc2ea9d4872d3fb7d47c49f88a77e2861733f80 --- /dev/null +++ b/app/presenters/user_application_presenter.rb @@ -0,0 +1,47 @@ +class UserApplicationPresenter + attr_reader :scopes + + def initialize(application, scopes, authorization_id=nil) + @app = application + @scopes = scopes + @authorization_id = authorization_id + end + + def id + @authorization_id + end + + def name + @app.client_name + end + + def image + @app.image_uri + end + + def terms_of_services + @app.tos_uri + end + + def policy + @app.policy_uri + end + + def name? + @app.client_name.present? + end + + def terms_of_services? + @app.tos_uri.present? + end + + def policy? + @app.policy_uri.present? + end + + def url + client_redirect = URI(@app.redirect_uris[0]) + client_redirect.path = "/" + client_redirect.to_s + end +end diff --git a/app/presenters/user_applications_presenter.rb b/app/presenters/user_applications_presenter.rb new file mode 100644 index 0000000000000000000000000000000000000000..f04b97394032f4cb592f9e06d3eb600e94ff6f0c --- /dev/null +++ b/app/presenters/user_applications_presenter.rb @@ -0,0 +1,20 @@ +class UserApplicationsPresenter + def initialize(user) + @user = user + end + + def user_applications + @applications ||= @user.o_auth_applications.map do |app| + authorization = Api::OpenidConnect::Authorization.find_by_client_id_and_user(app.client_id, @user) + UserApplicationPresenter.new app, authorization.scopes, authorization.id + end + end + + def applications_count + user_applications.size + end + + def applications? + applications_count > 0 + end +end diff --git a/app/serializers/export/post_serializer.rb b/app/serializers/export/post_serializer.rb index 77a79c3e52ea637d9dce1d2f3821130860e29103..84b6a91ed23c312b854e826fcfda9e3a86e590c7 100644 --- a/app/serializers/export/post_serializer.rb +++ b/app/serializers/export/post_serializer.rb @@ -5,9 +5,6 @@ module Export :public, :diaspora_handle, :type, - :image_url, - :image_height, - :image_width, :likes_count, :comments_count, :reshares_count, diff --git a/app/serializers/export/user_serializer.rb b/app/serializers/export/user_serializer.rb index a7563cc2729f29dc19c43fe2519cf8a98550ca9a..7e3b6b42ddc1707ac1937e9f3d321d86df768d85 100644 --- a/app/serializers/export/user_serializer.rb +++ b/app/serializers/export/user_serializer.rb @@ -4,6 +4,7 @@ module Export :email, :language, :username, + :serialized_private_key, :disable_mail, :show_community_spotlight_in_stream, :auto_follow_back, diff --git a/app/serializers/notification_serializer.rb b/app/serializers/notification_serializer.rb new file mode 100644 index 0000000000000000000000000000000000000000..c873a9e70d2b28d901d808d221ba55226ba25397 --- /dev/null +++ b/app/serializers/notification_serializer.rb @@ -0,0 +1,20 @@ +class NotificationSerializer < ActiveModel::Serializer + attributes :id, + :target_type, + :target_id, + :recipient_id, + :unread, + :created_at, + :updated_at, + :note_html + + def note_html + context.render_to_string(partial: "notifications/notification", locals: {note: object, no_aspect_dropdown: true}) + end + + def initialize(*_) + super + self.polymorphic = true + self.root = false + end +end diff --git a/app/serializers/user_info_serializer.rb b/app/serializers/user_info_serializer.rb new file mode 100644 index 0000000000000000000000000000000000000000..4ef29f3b7c69a7fa0a11682b6abe10166d10f7d5 --- /dev/null +++ b/app/serializers/user_info_serializer.rb @@ -0,0 +1,24 @@ +class UserInfoSerializer < ActiveModel::Serializer + attributes :sub, :name, :nickname, :profile, :picture + + def sub + auth = serialization_options[:authorization] + Api::OpenidConnect::SubjectIdentifierCreator.create(auth) + end + + def name + (object.first_name || "") + (object.last_name || "") + end + + def nickname + object.name + end + + def profile + File.join(AppConfig.environment.url, "people", object.guid).to_s + end + + def picture + File.join(AppConfig.environment.url, object.image_url).to_s + end +end diff --git a/app/services/comment_service.rb b/app/services/comment_service.rb index a571db3757f9e54fa5fe3c7e68866e955efdf2ee..4ec3b8835ebdf6327296faf2d55584af20f1f696 100644 --- a/app/services/comment_service.rb +++ b/app/services/comment_service.rb @@ -1,43 +1,32 @@ class CommentService - attr_reader :post, :comments - - def initialize(params) - @user = params[:user] - @post_id = params[:post_id] - @comment_id = params[:comment_id] - @text = params[:text] - - @post = find_post! if @post_id - @comments = @post.comments.for_a_stream if @post + def initialize(user=nil) + @user = user end - def create_comment - @user.comment!(post, @text) if @post + def create(post_id, text) + post = post_service.find!(post_id) + user.comment!(post, text) end - def destroy_comment - @comment = Comment.find(@comment_id) - if @user.owns?(@comment) || @user.owns?(@comment.parent) - @user.retract(@comment) + def destroy(comment_id) + comment = Comment.find(comment_id) + if user.owns?(comment) || user.owns?(comment.parent) + user.retract(comment) true else false end end + def find_for_post(post_id) + post_service.find!(post_id).comments.for_a_stream + end + private - def find_post! - find_post.tap do |post| - raise(ActiveRecord::RecordNotFound) unless post - end - end + attr_reader :user - def find_post - if @user - @user.find_visible_shareable_by_id(Post, @post_id) - else - Post.find_by_id_and_public(@post_id, true) - end + def post_service + @post_service ||= PostService.new(user) end end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb new file mode 100644 index 0000000000000000000000000000000000000000..d356a021118e4421c018113ef6c48f84cc1f8676 --- /dev/null +++ b/app/services/notification_service.rb @@ -0,0 +1,21 @@ +class NotificationService + NOTIFICATION_TYPES = { + Comment => [Notifications::CommentOnPost, Notifications::AlsoCommented], + Like => [Notifications::Liked], + StatusMessage => [Notifications::Mentioned], + Conversation => [Notifications::PrivateMessage], + Message => [Notifications::PrivateMessage], + Reshare => [Notifications::Reshared], + Contact => [Notifications::StartedSharing] + }.freeze + + def notify(object, recipient_user_ids) + notification_types(object).each {|type| type.notify(object, recipient_user_ids) } + end + + private + + def notification_types(object) + NOTIFICATION_TYPES.fetch(object.class, []) + end +end diff --git a/app/services/post_service.rb b/app/services/post_service.rb index 1408d064297cb471770aa34a8c647fac728f9823..140c33a0de918658291e967fc58a6d9f49503eab 100644 --- a/app/services/post_service.rb +++ b/app/services/post_service.rb @@ -1,65 +1,66 @@ class PostService - attr_reader :post - - def initialize(params) - @id = params[:id] - @user = params[:user] - @oembed = params[:oembed] || {} - assign_post + def initialize(user=nil) + @user = user end - def assign_post + def find(id) if user - @post = Post.find_non_public_by_guid_or_id_with_user(id, user) + user.find_visible_shareable_by_id(Post, id) else - @post = Post.find_public(id) + Post.find_by_id_and_public(id, true) end end - def present_json - PostPresenter.new(post, user) - end - - def present_interactions_json - PostInteractionPresenter.new(post, user) - end - - def present_oembed - OEmbedPresenter.new(post, oembed) + def find!(id_or_guid) + if user + find_non_public_by_guid_or_id_with_user!(id_or_guid) + else + find_public!(id_or_guid) + end end - def mark_user_notifications - mark_corresponding_notifications_read if user + def mark_user_notifications(post_id) + return unless user + mark_comment_reshare_like_notifications_read(post_id) + mark_mention_notifications_read(post_id) end - def retract_post - raise Diaspora::NotMine unless user_owns_post? - user.retract(@post) + def destroy(post_id) + post = find!(post_id) + raise Diaspora::NotMine unless post.author == user.person + user.retract(post) end private - attr_reader :user, :id, :oembed + attr_reader :user + + def find_public!(id_or_guid) + Post.where(post_key(id_or_guid) => id_or_guid).first.tap do |post| + raise ActiveRecord::RecordNotFound, "could not find a post with id #{id_or_guid}" unless post + raise Diaspora::NonPublic unless post.public? + end + end - def user_owns_post? - post.author == user.person + def find_non_public_by_guid_or_id_with_user!(id_or_guid) + user.find_visible_shareable_by_id(Post, id_or_guid, key: post_key(id_or_guid)).tap do |post| + raise ActiveRecord::RecordNotFound, "could not find a post with id #{id_or_guid} for user #{user.id}" unless post + end end - def mark_corresponding_notifications_read - mark_comment_reshare_like_notifications_read - mark_mention_notifications_read + # We can assume a guid is at least 16 characters long as we have guids set to hex(8) since we started using them. + def post_key(id_or_guid) + id_or_guid.to_s.length < 16 ? :id : :guid end - def mark_comment_reshare_like_notifications_read - notification = Notification.where(recipient_id: user.id, target_type: "Post", target_id: post.id, unread: true) - notification.each do |notification| - notification.set_read_state(true) - end + def mark_comment_reshare_like_notifications_read(post_id) + Notification.where(recipient_id: user.id, target_type: "Post", target_id: post_id, unread: true) + .update_all(unread: false) end - def mark_mention_notifications_read - mention = post.mentions.where(person_id: user.person_id).first - Notification.where(recipient_id: user.id, target_type: "Mention", target_id: mention.id, unread: true) - .first.try(:set_read_state, true) if mention + def mark_mention_notifications_read(post_id) + mention_id = Mention.where(post_id: post_id, person_id: user.person_id).pluck(:id) + Notification.where(recipient_id: user.id, target_type: "Mention", target_id: mention_id, unread: true) + .update_all(unread: false) if mention_id end end diff --git a/app/services/status_message_creation_service.rb b/app/services/status_message_creation_service.rb index 3f0093bca1a414ac74fe90a858bd29e67a2389b1..b541d194d1a9a983949fc5d8b47598c88e424538 100644 --- a/app/services/status_message_creation_service.rb +++ b/app/services/status_message_creation_service.rb @@ -1,89 +1,82 @@ class StatusMessageCreationService include Rails.application.routes.url_helpers - attr_reader :status_message + def initialize(user) + @user = user + end - def initialize(params, user) - normalize_params(params, user) - status_message_initial = user.build_post(:status_message, params[:status_message]) - @status_message = add_attachments(params, status_message_initial) - @status_message.save - process_status_message(user) + def create(params) + build_status_message(params).tap do |status_message| + add_attachments(status_message, params) + status_message.save + process(status_message, params[:aspect_ids], params[:services]) + end end private - attr_reader :services, :destination_aspect_ids - - def normalize_params(params, user) - normalize_aspect_ids(params) - normalize_public_flag!(params) - @services = [*params[:services]].compact - @destination_aspect_ids = destination_aspect_ids(params, user) - end - - def normalize_aspect_ids(params) - params[:status_message][:aspect_ids] = [*params[:aspect_ids]] - end + attr_reader :user - def normalize_public_flag!(params) - sm = params[:status_message] - public_flag_string = (sm[:aspect_ids] && sm[:aspect_ids].first == "public") || sm[:public] - public_flag = public_flag_string.to_s.match(/(true)|(on)/) ? true : false - params[:status_message][:public] = public_flag + def build_status_message(params) + public = params[:public] || false + filter_mentions params + user.build_post(:status_message, params[:status_message].merge(public: public)) end - def destination_aspect_ids(params, user) - if params[:status_message][:public] || params[:status_message][:aspect_ids].first == "all_aspects" - user.aspect_ids - else - params[:aspect_ids] + def filter_mentions(params) + unless params[:public] + params[:status_message][:text] = Diaspora::Mentionable.filter_for_aspects( + params[:status_message][:text], + user, + *params[:aspect_ids] + ) end end - def add_attachments(params, status_message_initial) - status_message_with_location = add_location(params, status_message_initial) - status_message_with_poll = add_poll(params, status_message_with_location) - add_photos(params, status_message_with_poll) + def add_attachments(status_message, params) + add_location(status_message, params[:location_address], params[:location_coords]) + add_poll(status_message, params) + add_photos(status_message, params[:photos]) end - def add_location(params, status_message) - address = params[:location_address] - coordinates = params[:location_coords] + def add_location(status_message, address, coordinates) status_message.build_location(address: address, coordinates: coordinates) if address.present? - status_message end - def add_poll(params, status_message) + def add_poll(status_message, params) if params[:poll_question].present? status_message.build_poll(question: params[:poll_question]) [*params[:poll_answers]].each do |poll_answer| status_message.poll.poll_answers.build(answer: poll_answer) end end - status_message end - def add_photos(params, status_message) - status_message.attach_photos_by_ids(params[:photos]) - status_message + def add_photos(status_message, photos) + if photos.present? + status_message.photos << Photo.where(id: photos, author_id: status_message.author_id) + status_message.photos.each do |photo| + photo.public = status_message.public + photo.pending = false + end + end end - def process_status_message(user) - add_status_message_to_streams(user) - dispatch_status_message(user) - user.participate!(@status_message) + def process(status_message, aspect_ids, services) + add_to_streams(status_message, aspect_ids) unless status_message.public + dispatch(status_message, services) end - def add_status_message_to_streams(user) - aspects = user.aspects_from_ids(@destination_aspect_ids) - user.add_to_streams(@status_message, aspects) + def add_to_streams(status_message, aspect_ids) + aspects = user.aspects_from_ids(aspect_ids) + user.add_to_streams(status_message, aspects) + status_message.photos.each {|photo| user.add_to_streams(photo, aspects) } end - def dispatch_status_message(user) - receiving_services = Service.titles(@services) - user.dispatch_post(@status_message, - url: short_post_url(@status_message.guid, host: AppConfig.environment.url), + def dispatch(status_message, services) + receiving_services = services ? Service.titles(services) : [] + user.dispatch_post(status_message, + url: short_post_url(status_message.guid, host: AppConfig.environment.url), service_types: receiving_services) end end diff --git a/app/views/admins/_admin_bar.haml b/app/views/admins/_admin_bar.haml index a00e0c542ec4d9db76eae03d7d5155e5edf1b933..c2187bf4e24a93d12ac1b7fe3cf4c321057151dd 100644 --- a/app/views/admins/_admin_bar.haml +++ b/app/views/admins/_admin_bar.haml @@ -1,14 +1,21 @@ - - content_for :head do = stylesheet_link_tag :admin -#admin_nav - %h2 - = t('.pages') - %ul - %li= link_to t('.user_search'), user_search_path - %li= link_to t('.weekly_user_stats'), weekly_user_stats_path - %li= link_to t('.pod_stats'), pod_stats_path - %li= link_to t('.report'), report_index_path - %li= link_to t('.sidekiq_monitor'), sidekiq_path +%h2= t(".pages") + +%ul#admin_nav.nav.nav-pills.nav-stacked + %li{role: "presentation", class: current_page?(admin_dashboard_path) && "active"} + = link_to t(".dashboard"), admin_dashboard_path + %li{role: "presentation", class: current_page?(user_search_path) && "active"} + = link_to t(".user_search"), user_search_path + %li{role: "presentation", class: current_page?(weekly_user_stats_path) && "active"} + = link_to t(".weekly_user_stats"), weekly_user_stats_path + %li{role: "presentation", class: current_page?(pod_stats_path) && "active"} + = link_to t(".pod_stats"), pod_stats_path + %li{role: "presentation", class: current_page?(report_index_path) && "active"} + = link_to t(".report"), report_index_path + %li{role: "presentation", class: current_page?(admin_pods_path) && "active"} + = link_to t(".pod_network"), admin_pods_path + %li{role: "presentation", class: current_page?(sidekiq_path) && "active"} + = link_to t(".sidekiq_monitor"), sidekiq_path diff --git a/app/views/admins/_user_entry.haml b/app/views/admins/_user_entry.haml index 5fa76beaa721e094f1ca56afd0e45ea81d12ec41..13ac091b03d4c417f9e98f70edc8c2942ac10abf 100644 --- a/app/views/admins/_user_entry.haml +++ b/app/views/admins/_user_entry.haml @@ -3,11 +3,11 @@ %div.pull-left - if user.person %span.media-object - = person_image_tag(user.person) + = person_image_tag(user.person, size: :thumb_small) %div.media-body.row %div.pull-right - %span.label + %span.label.label-default = t('.id') = user.id %span.label.label-info @@ -18,20 +18,20 @@ = user.person.name if user.person %div.pull-right - %ul.unstyled.text-right.actions - %li= link_to t('admins.user_search.view_profile'), person_path(user.person), class: 'btn btn-mini' - %li= link_to t('admins.user_search.add_invites'), add_invites_path(user.invitation_code), class: 'btn btn-info btn-mini' + .unstyled.text-right.actions + = link_to t('admins.user_search.view_profile'), person_path(user.person), class: 'btn btn-default btn-block btn-xs' + = link_to t('admins.user_search.add_invites'), add_invites_path(user.invitation_code), class: 'btn btn-info btn-block btn-xs' - unless user.person.closed_account - %li= link_to t('admins.user_search.close_account'), admin_close_account_path(user), method: :post, data: { confirm: t('admins.user_search.are_you_sure') }, class: 'btn btn-danger btn-mini' + = link_to t('admins.user_search.close_account'), admin_close_account_path(user), method: :post, data: { confirm: t('admins.user_search.are_you_sure') }, class: 'btn btn-danger btn-block btn-xs' - unless user.closed_account? - unless user.access_locked? - %li= link_to t('admins.user_search.lock_account'), admin_lock_account_path(user), method: :post, data: { confirm: t('admins.user_search.are_you_sure_lock_account') }, class: 'btn btn-danger btn-mini' + = link_to t('admins.user_search.lock_account'), admin_lock_account_path(user), method: :post, data: { confirm: t('admins.user_search.are_you_sure_lock_account') }, class: 'btn btn-danger btn-block btn-xs' - else - %li= link_to t('admins.user_search.unlock_account'), admin_unlock_account_path(user), method: :post, data: { confirm: t('admins.user_search.are_you_sure_unlock_account') }, class: 'btn btn-danger btn-mini' - + = link_to t('admins.user_search.unlock_account'), admin_unlock_account_path(user), method: :post, data: { confirm: t('admins.user_search.are_you_sure_unlock_account') }, class: 'btn btn-danger btn-block btn-xs' + %div.row - %div.span5 + %div.col-md-5 %dl.dl-horizontal %dt= t('username') %dd= user.username @@ -47,15 +47,15 @@ %dt= t('.account_closed') %dd - if user.person.closed_account - %span.badge.badge-warning= t('.yes') + %span.label.label-warning= t('.yes') - else - %span.badge.badge-success= t('.no') + %span.label.label-success= t('.no') %dt= t('.nsfw') %dd - if user.person.profile.nsfw - %span.badge.badge-warning= t('.yes') + %span.label.label-warning= t('.yes') - else - %span.badge.badge-success= t('.no') + %span.label.label-success= t('.no') %h4= t('layouts.header.profile') diff --git a/app/views/admins/dashboard.html.haml b/app/views/admins/dashboard.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..bf7fd1089d57503350a207a408b83130060083bc --- /dev/null +++ b/app/views/admins/dashboard.html.haml @@ -0,0 +1,10 @@ +.container + .row + .col-md-3 + = render partial: "admins/admin_bar" + .col-md-9 + #pod-status + %h2 + = t(".pod_status") + .alert.alert-info{role: "alert"} + = t(".fetching_diaspora_version") diff --git a/app/views/admins/pods.html.haml b/app/views/admins/pods.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..cb70585438e0dd418f06ac703527c44f1cb9e4c0 --- /dev/null +++ b/app/views/admins/pods.html.haml @@ -0,0 +1,14 @@ +.container + .row + .col-md-3 + = render partial: "admins/admin_bar" + + .col-md-9 + %h2 + = t(".pod_network") + + #pod-alerts + / filled by backbonejs + + #pod-list + / filled by backbonejs diff --git a/app/views/admins/stats.html.haml b/app/views/admins/stats.html.haml index 470ce97b249aacd6c59b8ec96813b1ba4a003243..8f9082ef6933cabc2991796e1fa25a6a59d627af 100644 --- a/app/views/admins/stats.html.haml +++ b/app/views/admins/stats.html.haml @@ -1,56 +1,56 @@ .container - %div - = render :partial => 'admins/admin_bar' - - %h1 - = t('.usage_statistic') - - %div.pull-right - = form_tag('/admins/stats', :method => 'get', class: 'form-inline') do - %select{:name => 'range'} - %option{:value => 'daily', :selected => ('selected' if params[:range] == 'daily')} - = t('.daily') - %option{:value => 'week', :selected => ('selected' if params[:range] == 'week')} - = t('.week') - %option{:value => '2weeks', :selected => ('selected' if params[:range] == '2weeks')} - = t('.2weeks') - %option{:value => 'month', :selected => ('selected' if params[:range] == 'month')} - = t('.month') - - = submit_tag t('.go'), class: 'btn btn-primary' - - %h3 - != t('.display_results', :segment => @segment) - - %div.row - - [:posts, :comments, :aspect_memberships, :users].each do |name| - - model = eval("@#{name.to_s}") - - if name == :aspect_memberships - - name = t('.shares', :count => model[:yesterday]) - - if name == :posts - - name = t('.posts', :count => model[:yesterday]) - - if name == :comments - - name = t('.comments', :count => model[:yesterday]) - - if name == :users - - name = t('.users', :count => model[:yesterday]) - - .span3 - %h2{:style => 'font-weight:bold;'} - = name.to_s - %h4 - = model[:day_before] - %span.percent_change{:class => (model[:change] > 0 ? "green" : "red")} - = "(#{model[:change]}%)" - - %div.row - %div.span12 - %p.alert.alert-info.text-center - != t('.current_segment', :post_yest => @posts[:yesterday]/@user_count.to_f, :post_day => @posts[:day_before]/@user_count.to_f) - - %div.row - %div.span12 - %h3= t('.50_most') - %ul - - @popular_tags.each do |name,count| - %li - != t('.tag_name', :name_tag => name, :count_tag => count) + .row + .col-md-3 + = render partial: "admins/admin_bar" + .col-md-9 + %h1= t('.usage_statistic') + + .pull-right + = form_tag('/admins/stats', :method => 'get', class: 'form-inline') do + %select.form-control{name: "range"} + %option{:value => 'daily', :selected => ('selected' if params[:range] == 'daily')} + = t('.daily') + %option{:value => 'week', :selected => ('selected' if params[:range] == 'week')} + = t('.week') + %option{:value => '2weeks', :selected => ('selected' if params[:range] == '2weeks')} + = t('.2weeks') + %option{:value => 'month', :selected => ('selected' if params[:range] == 'month')} + = t('.month') + + = submit_tag t('.go'), class: 'btn btn-primary' + + %h3 + != t('.display_results', :segment => @segment) + + .row + - [:posts, :comments, :aspect_memberships, :users].each do |name| + - model = eval("@#{name.to_s}") + - if name == :aspect_memberships + - name = t('.shares', :count => model[:yesterday]) + - if name == :posts + - name = t('.posts', :count => model[:yesterday]) + - if name == :comments + - name = t('.comments', :count => model[:yesterday]) + - if name == :users + - name = t('.users', :count => model[:yesterday]) + + .col-md-3 + %h2{:style => 'font-weight:bold;'} + = name.to_s + %h4 + = model[:day_before] + %span.percent_change{:class => (model[:change] > 0 ? "green" : "red")} + = "(#{model[:change]}%)" + + .row + .col-md-12 + %p.alert.alert-info.text-center{role: "alert"} + != t('.current_segment', :post_yest => @posts[:yesterday]/@user_count.to_f, :post_day => @posts[:day_before]/@user_count.to_f) + + .row + .col-md-12 + %h3= t('.50_most') + %ul + - @popular_tags.each do |name,count| + %li + != t('.tag_name', :name_tag => name, :count_tag => count) diff --git a/app/views/admins/user_search.html.haml b/app/views/admins/user_search.html.haml index 1db5ea218f00274abb053460a78acd2910d52a5b..4be69152fd4ae8455cb32d90c37d399b38a62aeb 100644 --- a/app/views/admins/user_search.html.haml +++ b/app/views/admins/user_search.html.haml @@ -1,49 +1,60 @@ .container - %div - = render :partial => 'admins/admin_bar' - - %div.row - %div.user_search.span9 - %h3= t('admins.admin_bar.user_search') - = form_for @search, url: {action: 'user_search'}, html: {method: :get, class: 'form-horizontal'} do |f| - %div.control-group - = f.label :username, t('username'), class: 'control-label' - %div.controls - = f.text_field :username - - %div.control-group - = f.label :email, t('email'), class: 'control-label' - %div.controls - = f.text_field :email - - %div.control-group - = f.label :guid, t('admins.user_entry.guid'), class: 'control-label' - %div.controls - = f.text_field :guid - - %div.control-group - %div.controls - = f.label :under13 do - = f.check_box :under13 - = t(".under_13") - = submit_tag t("admins.stats.go"), class: "btn btn-primary" - - %div.more_invites.span3 - %h3= t("shared.invitations.invites") - - != t(".you_currently", count: current_user.invitation_code.count, link: link_to(t(".add_invites"), add_invites_path(current_user.invitation_code))) - - = form_tag "admin_inviter", method: :get do - = t(".email_to") - = text_field_tag "identifier" - = submit_tag t("services.remote_friend.invite"), class: "btn btn-default" - - %div.row - %div.span12 - %div.alert.alert-info.text-center= t('.users', :count => @users.count) - - %div.row - %div.users.span12 - %ul.media-list - - @users.each do |user| - = render partial: 'user_entry', locals: { user: user } + .row + .col-md-3 + = render partial: "admins/admin_bar" + .col-md-9 + .row + .user_search.col-md-8 + %h3= t('admins.admin_bar.user_search') + = form_for @search, url: {action: 'user_search'}, html: {method: :get, class: 'form-horizontal'} do |f| + .form-group + = f.label :username, t('username'), class: 'col-sm-2 control-label' + .col-sm-10 + = f.text_field :username, class: "form-control" + + .form-group + = f.label :email, t('email'), class: 'col-sm-2 control-label' + .col-sm-10 + = f.text_field :email, class: "form-control" + + .form-group + = f.label :guid, t('admins.user_entry.guid'), class: 'col-sm-2 control-label' + .col-sm-10 + = f.text_field :guid, class: "form-control" + + .form-group + .col-sm-offset-2.col-sm-10 + = f.label :under13 do + = f.check_box :under13 + = t(".under_13") + .form-group + .clearfix.col-sm-12 + = submit_tag t("admins.stats.go"), class: "btn btn-primary pull-right" + + .more_invites.col-md-4 + %h3= t("shared.invitations.invites") + #add-invites-section.clearfix + != t(".you_currently", count: current_user.invitation_code.count, + link: link_to(t(".add_invites"), add_invites_path(current_user.invitation_code), + class: "btn btn-link pull-right")) + + = form_tag "admin_inviter", method: :get, class: "form-horizontal" do + .form-group + %label.col-sm-4.control-label + = t(".email_to") + .col-sm-8 + = text_field_tag "identifier", nil, class: "form-control" + .form-group + .clearfix.col-md-12 + = submit_tag t(".invite"), class: "btn btn-default pull-right" + + .row + .col-md-12 + .alert.alert-info.text-center{role: "alert"} + = t(".users", count: @users.count) + + .row + .users.col-md-12 + %ul.media-list + - @users.each do |user| + = render partial: 'user_entry', locals: { user: user } diff --git a/app/views/admins/weekly_user_stats.haml b/app/views/admins/weekly_user_stats.haml index 901933a97c9f421f9c284b93fa6d26f1d0c995f4..fe2f88e35deba4a5a7e12b76b0a0bcae57879052 100644 --- a/app/views/admins/weekly_user_stats.haml +++ b/app/views/admins/weekly_user_stats.haml @@ -1,17 +1,18 @@ .container - %div - = render :partial => 'admins/admin_bar' + .row + .col-md-3 + = render partial: "admins/admin_bar" + .col-md-9 + %h2 + = t('.current_server', date: Time.now.to_date) - %h2 - = t('.current_server', date: Time.now.to_date) + .pull-right + = form_tag('/admins/weekly_user_stats', method: 'get', class: 'form-inline') do + = select_tag(:week, options_for_select(@created_users_by_week.keys.reverse, @selected_week), class: "form-control") + = submit_tag t('admins.stats.go'), class: 'btn btn-primary' - %div.pull-right - = form_tag('/admins/weekly_user_stats', method: 'get', class: 'form-inline') do - = select_tag(:week, options_for_select(@created_users_by_week.keys.reverse, @selected_week)) - = submit_tag t('admins.stats.go'), class: 'btn btn-primary' - - = t('.amount_of', count: @counter) - %br - - @created_users_by_week[@selected_week].each do |m| - = link_to m, "/u/#{m}" - %br + = t('.amount_of', count: @counter) + %br + - @created_users_by_week[@selected_week].each do |m| + = link_to m, "/u/#{m}" + %br diff --git a/app/views/api/openid_connect/authorizations/_grants_list.haml b/app/views/api/openid_connect/authorizations/_grants_list.haml new file mode 100644 index 0000000000000000000000000000000000000000..63d59211f0deca489fe5e4eb86aee5aacc751dfa --- /dev/null +++ b/app/views/api/openid_connect/authorizations/_grants_list.haml @@ -0,0 +1,31 @@ +.application-img + - if app.image + = image_tag app.image, class: "img-responsive", id: "js-app-logo" + - else + %i.entypo-browser +.application-authorizations + - if app.scopes.count > 0 + %h4 + = t("api.openid_connect.authorizations.new.access", name: user_application_name(app)).html_safe + %ul + - app.scopes.each do |scope| + %li + %strong= t("api.openid_connect.scopes.#{scope}.name") + %p= t("api.openid_connect.scopes.#{scope}.description") + - else + .well + = t("api.openid_connect.authorizations.new.no_requirement", name: user_application_name(app)).html_safe + + .small-horizontal-spacer + .application-tos-policy + - if app.terms_of_services? + %strong= link_to t("api.openid_connect.user_applications.tos"), app.terms_of_services + + - if app.policy? && app.terms_of_services? + | + + - if app.policy? + %strong= link_to t("api.openid_connect.user_applications.policy"), app.policy + + - if app.policy? || app.terms_of_services? + .small-horizontal-spacer diff --git a/app/views/api/openid_connect/authorizations/new.html.haml b/app/views/api/openid_connect/authorizations/new.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..e7bc330289dbef06e630e1393c3ee882dafaf55a --- /dev/null +++ b/app/views/api/openid_connect/authorizations/new.html.haml @@ -0,0 +1,13 @@ +.user-consent.col-md-10.col-md-offset-1 + %ul.list-group + %li.list-group-item.authorized-application.clearfix + = render "grants_list", app: @app + + .clearfix.pull-right + = form_tag api_openid_connect_authorizations_path, class: "approval-button" do + = submit_tag t(".deny"), class: "btn btn-danger" + = hidden_field_tag :approve, false + + = form_tag api_openid_connect_authorizations_path, class: "approval-button"do + = submit_tag t(".approve"), class: "btn btn-primary" + = hidden_field_tag :approve, true diff --git a/app/views/api/openid_connect/error/_error.html.haml b/app/views/api/openid_connect/error/_error.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..de8d782b051677c0bb9941634bd76b82641a2fbc --- /dev/null +++ b/app/views/api/openid_connect/error/_error.html.haml @@ -0,0 +1,11 @@ +.container-fluid + .row + .api-error.col-sm-6.col-sm-offset-3 + %h4 + %b= t("api.openid_connect.error_page.title") + %div{id: "openid_connect_error_description"} + %p= @error_description + - unless @detailed_error.nil? + %p= t("api.openid_connect.error_page.contact_developer") + %pre= @detailed_error + diff --git a/app/views/api/openid_connect/error/error.html.haml b/app/views/api/openid_connect/error/error.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..a9b15dbd092443e32795e022e85f78da6113e446 --- /dev/null +++ b/app/views/api/openid_connect/error/error.html.haml @@ -0,0 +1 @@ += render partial: "api/openid_connect/error/error" diff --git a/app/views/api/openid_connect/error/error.mobile.haml b/app/views/api/openid_connect/error/error.mobile.haml new file mode 100644 index 0000000000000000000000000000000000000000..dcfd1f5f897698f9abdd2c6050faa97e5c194d30 --- /dev/null +++ b/app/views/api/openid_connect/error/error.mobile.haml @@ -0,0 +1,8 @@ +.landing + %h1.session + = pod_name + += render partial: "api/openid_connect/error/error" + +%footer + = link_to t("layouts.application.toggle"), toggle_mobile_path diff --git a/app/views/api/openid_connect/user_applications/_add_remove_applications.haml b/app/views/api/openid_connect/user_applications/_add_remove_applications.haml new file mode 100644 index 0000000000000000000000000000000000000000..ff467c3f24f07f685572faad433871df35fb4f11 --- /dev/null +++ b/app/views/api/openid_connect/user_applications/_add_remove_applications.haml @@ -0,0 +1,14 @@ +- if @user_apps.applications? + %ul.list-group + - @user_apps.user_applications.each do |app| + %li.list-group-item.authorized-application + = render "grants_list", app: app + = form_for "application", url: "#{api_openid_connect_authorization_path(app.id)}", + html: {method: :delete, class: "form-horizontal"} do |f| + .clearfix= f.submit t("api.openid_connect.user_applications.revoke_autorization"), + class: "btn btn-danger pull-right app-revoke" + +- else + .well + %h4 + = t("api.openid_connect.user_applications.no_applications") diff --git a/app/views/api/openid_connect/user_applications/_grants_list.haml b/app/views/api/openid_connect/user_applications/_grants_list.haml new file mode 100644 index 0000000000000000000000000000000000000000..210a8a0fec980f23dbbaec6f510b03a4b686816b --- /dev/null +++ b/app/views/api/openid_connect/user_applications/_grants_list.haml @@ -0,0 +1,30 @@ +.application-img + - if app.image + = image_tag app.image, class: "img-responsive", id: "js-app-logo" + - else + %i.entypo-browser +.application-authorizations + - if app.scopes.count > 0 + %h4= t("api.openid_connect.user_applications.index.access", name: user_application_name(app)).html_safe + %ul + - app.scopes.each do |scope| + %li + %b= t("api.openid_connect.scopes.#{scope}.name") + %p= t("api.openid_connect.scopes.#{scope}.description") + - else + .well + = t("api.openid_connect.user_applications.index.no_requirement", name: user_application_name(app)).html_safe + + .small-horizontal-spacer + .application-tos-policy + - if app.terms_of_services? + %b= link_to t("api.openid_connect.user_applications.tos"), app.terms_of_services + + - if app.policy? && app.terms_of_services? + | + + - if app.policy? + %b= link_to t("api.openid_connect.user_applications.policy"), app.policy + + - if app.policy? || app.terms_of_services? + .small-horizontal-spacer diff --git a/app/views/api/openid_connect/user_applications/index.html.haml b/app/views/api/openid_connect/user_applications/index.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..b90082995ab17fb6cb461835b5620b91d02240e8 --- /dev/null +++ b/app/views/api/openid_connect/user_applications/index.html.haml @@ -0,0 +1,14 @@ +- content_for :page_title do + = t(".edit_applications") + +.container-fluid.applications-page + .row + .col-md-3 + .sidebar + = render "shared/settings_nav" + .col-md-9 + .framed-content.clearfix + %h3= t(".title") + .row + .col-md-12 + = render "add_remove_applications" diff --git a/app/views/api/openid_connect/user_applications/index.mobile.haml b/app/views/api/openid_connect/user_applications/index.mobile.haml new file mode 100644 index 0000000000000000000000000000000000000000..39690d6616474e606fb4e5c17071a899a779bcc3 --- /dev/null +++ b/app/views/api/openid_connect/user_applications/index.mobile.haml @@ -0,0 +1,9 @@ +.container-fluid.settings_container.applications-page + .row + .col-md-12 + - content_for :page_title do + = t(".edit_applications") + = render "shared/settings_nav" + .row + .col-md-12 + = render "add_remove_applications" diff --git a/app/views/aspect_memberships/_aspect_membership_dropdown.haml b/app/views/aspect_memberships/_aspect_membership_dropdown.haml index ba4ee2fd1f41df98c0e0efbd1768f01399a8bf76..0274ba91dc8081697f7a00a24df49ba3a72d5c2e 100644 --- a/app/views/aspect_memberships/_aspect_membership_dropdown.haml +++ b/app/views/aspect_memberships/_aspect_membership_dropdown.haml @@ -1,31 +1 @@ -.btn-group.aspect_dropdown.aspect_membership_dropdown - %button.btn.dropdown-toggle{:class => button_class, "data-toggle" => "dropdown", :tabindex => '0'} - %span.text - - if selected_aspects.size == all_aspects.size - = t('all_aspects') - - elsif selected_aspects.size == 1 - = selected_aspects.first.name - - else - = t('shared.aspect_dropdown.toggle', :count => selected_aspects.size) - %span.caret - - %ul.dropdown-menu{:class => ["pull-#{hang}", defined?(dropdown_class) && dropdown_class], :unSelectable => 'on', 'data-person_id' => (person.id if defined?(person) && person), 'data-service_uid' => (service_uid if defined?(service_uid)), 'data-person-short-name' => (person.first_name if defined?(person) && person)} - - for aspect in all_aspects - %li.aspect_selector{ :class => ('selected' if aspect_membership_ids[aspect.id].present?), 'data-aspect_id' => aspect.id, 'data-membership_id' => aspect_membership_ids[aspect.id], :tabindex => '0' } - %a - %span.status_indicator - %i.icon-ok - %i.icon-refresh - %span.text - = aspect.name - - - if (dropdown_may_create_new_aspect && defined?(person) && person) - %li.divider - %li.newItem - .add_aspect - %a{ href: "#" } - = t("contacts.index.add_a_new_aspect") - - - if (dropdown_may_create_new_aspect && defined?(person) && person) - .newAspectContainer - -# JS +.placeholder.aspect_membership_dropdown diff --git a/app/views/aspect_memberships/_aspect_membership_dropdown.mobile.haml b/app/views/aspect_memberships/_aspect_membership_dropdown.mobile.haml index b7a8ffc1eede0f397ce90dde5b2761910db23d57..02ebe2e48319e90efa1e48de93395fe4215640a1 100644 --- a/app/views/aspect_memberships/_aspect_membership_dropdown.mobile.haml +++ b/app/views/aspect_memberships/_aspect_membership_dropdown.mobile.haml @@ -1,13 +1,13 @@ %div - %select{:name => 'user_aspects', :class => 'user_aspects', 'data-person-id' => @person.id} - %option{:value => 'list_cover', :class => 'list_cover', :disabled => 'true', :selected => 'true'} - = t("add_contact") + %select.aspect_dropdown.form-control.user_aspects{"name" => "user_aspects", "data-person-id" => @person.id} + %option{value: 'list_cover', class: 'list_cover', disabled: 'true', selected: 'true'} + = t("contacts.index.add_contact") - contact = current_user.contact_for(@person) - current_user.aspects.each do |aspect| - if contact.try(:in_aspect?, aspect) - - membership_id = contact.aspect_memberships.where(:aspect_id => aspect.id).limit(1).pluck(:id).first - %option{:value => aspect.id, 'data-name' => aspect.name, 'data-membership_id' => membership_id, :class => 'selected'} + - membership_id = contact.aspect_memberships.where(aspect_id: aspect.id).limit(1).pluck(:id).first + %option{value: aspect.id, 'data-name' => aspect.name, 'data-membership_id' => membership_id, class: 'selected'} = "✓ #{t('shared.aspect_dropdown.mobile_row_checked', name: aspect.name)}" - else - %option{:value => aspect.id, 'data-name' => aspect.name} + %option{value: aspect.id, 'data-name' => aspect.name} = "– #{t('shared.aspect_dropdown.mobile_row_unchecked', name: aspect.name)}" diff --git a/app/views/aspects/_aspect_listings.haml b/app/views/aspects/_aspect_listings.haml index 4cae09865827802efdd0edba6ddd3bda83471158..447dbf9b555424b8d5ae41d1f3987f8a44c9673e 100644 --- a/app/views/aspects/_aspect_listings.haml +++ b/app/views/aspects/_aspect_listings.haml @@ -4,3 +4,4 @@ = link_to t('streams.aspects.title'), aspects_path, :class => 'hoverable', :rel => 'backbone', :data => {:stream => 'aspects'} %ul#aspects_list + -# JS diff --git a/app/views/aspects/_aspect_stream.haml b/app/views/aspects/_aspect_stream.haml index 87e6af9150112611226dfe15bcb942918f8a3520..62c4a481107e7bbf99a12ea2c4c1d033fea02829 100644 --- a/app/views/aspects/_aspect_stream.haml +++ b/app/views/aspects/_aspect_stream.haml @@ -2,19 +2,20 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -- if user_signed_in? && @person != current_user.person - %h3#aspect_stream_header.stream_title - = stream.title +.container-fluid.main-stream-publisher + .pull-left.hidden-xs + = owner_image_link + = render "publisher/publisher", publisher_aspects_for(stream) -= render 'publisher/publisher', publisher_aspects_for(stream) -= render 'aspects/no_posts_message' - -#gs-shim{:title => popover_with_close_html("3. #{t('.stay_updated')}"), 'data-content' => t('.stay_updated_explanation')} - -#main_stream.stream +- if current_user.getting_started? + .stream#main_stream{:title => popover_with_close_html("3. #{t('.stay_updated')}"), + "data-content" => t(".stay_updated_explanation")} +- else + .stream#main_stream #paginate %span.loader.hidden + .spinner - if current_user.contacts.size < 2 = render 'aspects/no_contacts_message' diff --git a/app/views/aspects/_no_contacts_message.haml b/app/views/aspects/_no_contacts_message.haml index a3977ddc1441190ce5a674bf81913c78d198e520..733db4135426e4f42fcb0a4981de458654820b4c 100644 --- a/app/views/aspects/_no_contacts_message.haml +++ b/app/views/aspects/_no_contacts_message.haml @@ -3,10 +3,15 @@ -# the COPYRIGHT file. #no_contacts.empty_message - = t('.you_should_add_some_more_contacts') - %br - %br - = t('.try_adding_some_more_contacts') - - if AppConfig.settings.community_spotlight.enable? - != t('.or_spotlight', :link => link_to(t(".community_spotlight") , community_spotlight_path)) + %p.lead + = t(".you_should_add_some_more_contacts") + + %p + != t(".try_adding_some_more_contacts", + invite_link: link_to(t(".invite_link_text"), + "#", + class: "invitations-link", + data: {toggle: "modal"})) + - if AppConfig.settings.community_spotlight.enable? + != t(".or_spotlight", link: link_to(t(".community_spotlight"), community_spotlight_path)) diff --git a/app/views/aspects/_no_posts_message.haml b/app/views/aspects/_no_posts_message.haml deleted file mode 100644 index 7e0b41b378ea271060278c45daf85d4fe048340b..0000000000000000000000000000000000000000 --- a/app/views/aspects/_no_posts_message.haml +++ /dev/null @@ -1,6 +0,0 @@ --# Copyright (c) 2010-2011, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - -#no_posts.hidden.empty_message - = t('.start_talking') diff --git a/app/views/comments/_comment.mobile.haml b/app/views/comments/_comment.mobile.haml index 24b5fc98bae13b10c4aab62aa3ca02e5fb753f6c..79cf8bc9cc393f98ad04de5891e0e391582a5867 100644 --- a/app/views/comments/_comment.mobile.haml +++ b/app/views/comments/_comment.mobile.haml @@ -2,18 +2,22 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -%li.comment{:data=>{:guid=>comment.id}, :class => ("hidden" if(defined? hidden))} +%li.comment{data:{guid:comment.id}, class: ("hidden" if(defined? hidden))} .content - .remove_comment - .right - - if user_signed_in? && comment.author == current_user.person - = link_to(image_tag("mobile/deletelabel.png"), comment_path(comment), method: :delete, data: { confirm: "#{t('are_you_sure')}" }, class: "remove") - .from - = person_image_link(comment.author) - = person_link(comment.author) - .info - %span - = timeago(comment.created_at ? comment.created_at : Time.now) + .media + .media-left + = person_image_link(comment.author, size: :thumb_small, class: "media-object") + .media-body + .from.pull-left + = person_link(comment.author) + .info + %span + = timeago(comment.created_at ? comment.created_at : Time.now) + .remove_comment + .pull-right + - if user_signed_in? && comment.author == current_user.person + = link_to(raw("<i class='entypo-trash'></i>"), comment_path(comment), method: :delete, + data: { confirm: "#{t('are_you_sure')}" }, class: "remove") - %div{:class => direction_for(comment.text)} + %div{class: direction_for(comment.text)} = comment.message.markdownified diff --git a/app/views/comments/_new_comment.mobile.haml b/app/views/comments/_new_comment.mobile.haml index 97705fb482a0360d3d519a5a974f65544766064d..5cae5295029e576f63de43491c1898725943310c 100644 --- a/app/views/comments/_new_comment.mobile.haml +++ b/app/views/comments/_new_comment.mobile.haml @@ -2,9 +2,14 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -= form_tag( post_comments_path(post_id), :id => "new_comment_on_#{post_id}", :class => 'new_comment', :autocomplete => "off") do - %fieldset - .control-group - = hidden_field_tag :post_id, post_id, :id => "post_id_on_#{post_id}" - = text_area_tag :text, nil, :class => "span12 comment_box", :id => "comment_text_on_#{post_id}", :placeholder => t('.comment'), :autofocus => true - = submit_tag t('.comment'), :id => "comment_submit_#{post_id}", 'data-disable-with' => t('.commenting'), :class => "btn primary" +.add_comment_bottom_link_container + - if user_signed_in? + = form_tag(post_comments_path(post_id), id: "new-comment-on-#{post_id}", + class: "new_comment", autocomplete: "off") do + %fieldset + = hidden_field_tag :post_id, post_id, id: "post-id-on-#{post_id}" + .form-group.clearfix + = text_area_tag :text, nil, class: "col-md-12 comment_box form-control", + id: "comment-text-on-#{post_id}", placeholder: t(".comment") + = submit_tag t(".comment"), :id => "comment-submit-#{post_id}", "data-disable-with" => t(".commenting"), + "data-reset-with" => t(".comment"), :class => "btn btn-primary btn-block comment-button" diff --git a/app/views/comments/_post_stats.mobile.haml b/app/views/comments/_post_stats.mobile.haml new file mode 100644 index 0000000000000000000000000000000000000000..106ef8ae89abf8d89306ecbd3ded39fe20551131 --- /dev/null +++ b/app/views/comments/_post_stats.mobile.haml @@ -0,0 +1,13 @@ +.post-stats + - if post.public? + .icon-count-group + .post-action= mobile_reshare_icon(post) + %span.reshare-count.count= post.reshares.size + + .icon-count-group + .post-action= mobile_comment_icon(post) + %span.comment-count.count= post.comments.size + + .icon-count-group + .post-action= mobile_like_icon(post) + %span.like-count.count= post.likes.size diff --git a/app/views/comments/index.mobile.haml b/app/views/comments/index.mobile.haml index b644ae77a06888009676633c675189ac15c7d726..bbb26073a74fa39a4a5efc57f466990f36e4a517 100644 --- a/app/views/comments/index.mobile.haml +++ b/app/views/comments/index.mobile.haml @@ -1 +1,3 @@ -= render :partial => 'shared/post_stats', :locals => { :post => @post} \ No newline at end of file +.comment-container + %ul.comments + = render partial: "comments/comment", collection: comments diff --git a/app/views/comments/new.mobile.haml b/app/views/comments/new.mobile.haml index 453a092c9c923dfee9e46165c1dcd1f5008012e6..4788ace61961183d2f43adc1212f8a3bb8664e5c 100644 --- a/app/views/comments/new.mobile.haml +++ b/app/views/comments/new.mobile.haml @@ -1 +1 @@ -= render :partial => 'new_comment', :locals =>{:post_id => params[:post_id]} += render partial: "new_comment", locals: {post_id: params[:post_id]} diff --git a/app/views/contacts/_aspect_listings.haml b/app/views/contacts/_aspect_listings.haml index 450b433d2e654b6c9c94cd55da5ed096c17a2be7..0c0ba59278109d7986f46dc02f153b5073b6944c 100644 --- a/app/views/contacts/_aspect_listings.haml +++ b/app/views/contacts/_aspect_listings.haml @@ -1,34 +1,28 @@ #aspect_nav - %ul.nav.nav-tabs.nav-stacked.ui-sortable - %li.all_contacts{:class => ("active" if params["set"] == "all")} - %a{:href => contacts_path(:set => "all")} - = t('contacts.index.all_contacts') - .badge.badge-default.pull-right - = all_contacts_count + %ul.list-group.ui-sortable + %a.list-group-item.ui-sortable-handle.all_contacts{class: ("active" if params["set"] == "all"), href: contacts_path(set: "all")} + = t('contacts.index.all_contacts') + .badge.badge-default.pull-right + = all_contacts_count - %li.all_aspects{:class => ("active" if !params["set"] && !params["a_id"] && !@spotlight)} - %a{:href => contacts_path} - = t('contacts.index.my_contacts') - .badge.badge-default.pull-right - = my_contacts_count + %a.list-group-item.ui-sortable-handle.all_aspects{class: ("active" if !params["set"] && !params["a_id"] && !@spotlight), href: contacts_path} + = t('contacts.index.my_contacts') + .badge.badge-default.pull-right + = my_contacts_count - all_aspects.each do |aspect| - %li.aspect{:data => {:aspect_id => aspect.id}, :class => ("active" if params["a_id"].to_i == aspect.id)} - %a{:href => contacts_path(:a_id => aspect.id)} - .badge.badge-default.pull-right - = aspect.contacts.size - .name - = aspect - - %li.new_aspect - %a{ "data-toggle" => "modal", "data-target" => "#newAspectModal", href: "#"} - = t("aspects.aspect_listings.add_an_aspect") + %a.list-group-item.ui-sortable-handle.aspect{data: {aspect_id: aspect.id}, class: ("active" if params["a_id"].to_i == aspect.id), href: contacts_path(a_id: aspect.id)} + .badge.badge-default.pull-right + = aspect.contacts.size + .name + = aspect - #newAspectContainer - -# JS + %a.list-group-item.ui-sortable-handle.new_aspect{ data: { toggle: "modal", target: "#newAspectModal" }, href: "#"} + = t('aspects.aspect_listings.add_an_aspect') + #newAspectContainer + -# JS - %li.only_sharing{:class => ("active" if params["set"] == "only_sharing")} - %a{:href => contacts_path(:set => "only_sharing")} - = t('contacts.index.only_sharing_with_me') - .badge.badge-default.pull-right - = only_sharing_count + %a.list-group-item.ui-sortable-handle.only_sharing{ class: ("active" if params["set"] == "only_sharing"), href: contacts_path(set: "only_sharing")} + = t('contacts.index.only_sharing_with_me') + .badge.badge-default.pull-right + = only_sharing_count diff --git a/app/views/contacts/_header.html.haml b/app/views/contacts/_header.html.haml index 6d879c1abc40900609f75ea45e1cf983524f75b1..d8d323fb121907ac3cd381f57b233a80073519aa 100644 --- a/app/views/contacts/_header.html.haml +++ b/app/views/contacts/_header.html.haml @@ -1,37 +1,48 @@ -.header +.header.clearfix - if @aspect - #aspect_controls.pull-right + .aspect-controls.pull-right#aspect_controls - if @aspect.contacts.size > 0 && @aspect.contacts.size < 20 = start_a_conversation_link(@aspect, @aspect.contacts.size) = link_to aspect_toggle_contact_visibility_path(@aspect), id: "contacts_visibility_toggle", class: "contacts_button", method: :put, remote: true do -if @aspect.contacts_visible? - %i.entypo.lock-open.contacts-header-icon{:title => t('aspects.edit.aspect_list_is_visible')} + %i.entypo-lock-open.contacts-header-icon{title: t("aspects.edit.aspect_list_is_visible")} -else - %i.entypo.lock.contacts-header-icon{:title => t('aspects.edit.aspect_list_is_not_visible')} + %i.entypo-lock.contacts-header-icon{title: t("aspects.edit.aspect_list_is_not_visible")} -if AppConfig.chat.enabled? = link_to aspect_toggle_chat_privilege_path(@aspect), id: "chat_privilege_toggle", class: "contacts_button", method: :put, remote: true do -if @aspect.chat_enabled? - %i.entypo.chat.enabled.contacts-header-icon{:title => t('aspects.edit.aspect_chat_is_enabled')} + %i.entypo-chat.enabled.contacts-header-icon{title: t("javascripts.contacts.aspect_chat_is_enabled")} -else - %i.entypo.chat.contacts-header-icon{:title => t('aspects.edit.aspect_chat_is_not_enabled')} + %i.entypo-chat.contacts-header-icon{title: t("javascripts.contacts.aspect_chat_is_not_enabled")} - = link_to @aspect, method: "delete", data: { confirm: t('aspects.edit.confirm_remove_aspect') }, class: 'delete contacts_button', id: 'delete_aspect' do - %i.entypo.trash.contacts-header-icon{:title => t('delete')} - .pull-right - = search_field_tag :contact_search, "", id: "contact_list_search", class: "search-query", placeholder: t('contacts.index.user_search') + = link_to @aspect, method: "delete", data: { confirm: t("aspects.edit.confirm_remove_aspect") }, class: "delete contacts_button", id: "delete_aspect" do + %i.entypo-trash.contacts-header-icon{title: t("delete")} + .pull-right.contact-list-search + %form#contact-search-form{role: "search", method: "get", action: "/search"} + = search_field_tag :q, "", + id: "contact_list_search", + class: "search-query form-control", + placeholder: t("contacts.index.user_search") %h3 %span#aspect_name = @aspect.name %span#change_aspect_name.contacts_button - %i.entypo.pencil.contacts-header-icon{:title => t('aspects.edit.rename')} + %i.entypo-pencil.contacts-header-icon{title: t("aspects.edit.rename")} #aspect_name_form - = form_for @aspect, :remote => true do |aspect| - = aspect.text_field :name, :maxlength => 20 - = aspect.submit t('aspects.edit.update'), 'data-disable-with' => t('aspects.edit.updating'), :class => "btn" + = form_for @aspect, remote: true, html: { class: "form-inline edit_aspect"} do |aspect| + = aspect.text_field :name, class: "form-control", :maxlength => 20 + = aspect.submit t('aspects.edit.update'), 'data-disable-with' => t('aspects.edit.updating'), class: "btn btn-default" - else + .pull-right.contact-list-search + %form#contact-search-form{role: "search", method: "get", action: "/search"} + = search_field_tag :q, "", + id: "contact_list_search", + class: "search-query form-control", + placeholder: t("contacts.index.user_search") + %h3 - case params["set"] - when "only_sharing" diff --git a/app/views/contacts/_sidebar.html.haml b/app/views/contacts/_sidebar.html.haml index 5b9411a02956765adca01717d75b374245f55de1..8ed81bd57fc98d458d4cd36f7ccd036a9366b841 100644 --- a/app/views/contacts/_sidebar.html.haml +++ b/app/views/contacts/_sidebar.html.haml @@ -1,12 +1,13 @@ -%h3 - = t("contacts.index.title") +.sidebar-header.clearfix + %h3 + = t("contacts.index.title") = render "contacts/aspect_listings" %hr - if AppConfig.settings.community_spotlight.enable? .text-center.spotlight = link_to t("contacts.spotlight.community_spotlight"), community_spotlight_path, class: "btn btn-link" .text-center - .btn.btn-link{ "data-toggle" => "modal", "data-target" => "#invitationsModal"} + #invitations-button.btn.btn-link{ "data-toggle" => "modal" } = t("invitations.new.invite_someone_to_join") = render "shared/modal", path: new_user_invitation_path, diff --git a/app/views/contacts/index.html.haml b/app/views/contacts/index.html.haml index 44d6232b60d686aead3c1e07c7a4ae78cbbe603c..2a8de4f3265af6941543513f12cf5728e30c3730 100644 --- a/app/views/contacts/index.html.haml +++ b/app/views/contacts/index.html.haml @@ -2,12 +2,13 @@ = t('.title') .container-fluid#contacts_container - .row-fluid - .span3 - = render 'contacts/sidebar' + .row + .col-md-3 + .sidebar + = render "contacts/sidebar" - .span9 - #people_stream.stream.contacts + .col-md-9 + .stream.contacts.framed-content#people_stream = render 'contacts/header' - if @contacts_size > 0 @@ -25,9 +26,13 @@ != t('.no_contacts_message', :community_spotlight => link_to(t('.community_spotlight'), community_spotlight_path)) %p - .btn.btn-link{ 'data-toggle' => 'modal', 'data-target' => '#invitationsModal'} + .btn.btn-link{ 'data-toggle' => 'modal' } = t('invitations.new.invite_someone_to_join') + #paginate + %span.loader.hidden + .spinner + -if @aspect #new_conversation_pane = render 'shared/modal', diff --git a/app/views/contacts/index.mobile.haml b/app/views/contacts/index.mobile.haml index 3bf6e537ed4848996be3d3401f474cde24378f2b..0e27e5dbb928b69325691781da879cfe5c4eca6f 100644 --- a/app/views/contacts/index.mobile.haml +++ b/app/views/contacts/index.mobile.haml @@ -3,19 +3,17 @@ -# the COPYRIGHT file. - content_for :page_title do - = t('.title') + = t(".title") #section_header %h2 - = t('.title') - -.span-18.last - #people_stream.stream.contacts - - if @contacts.size > 0 - - for contact in @contacts - = render 'people/person', :person => contact.person, :contact => contact - = will_paginate @contacts, :renderer => WillPaginate::ActionView::BootstrapLinkRenderer - - else - %h3.no_contacts - = t('.no_contacts') + = t(".title") +#people_stream.stream.contacts + - if @contacts.size > 0 + - for contact in @contacts + = render "people/person", person: contact.person, contact: contact + = will_paginate @contacts, renderer: WillPaginate::ActionView::BootstrapLinkRenderer + - else + %h3.no_contacts + = t(".no_contacts") diff --git a/app/views/contacts/spotlight.haml b/app/views/contacts/spotlight.haml index 3b69b12f02c15ffc1afff53c42e3d0a9f4588013..47767a4825971ec84093fa938e7243750e2adf9a 100644 --- a/app/views/contacts/spotlight.haml +++ b/app/views/contacts/spotlight.haml @@ -1,15 +1,15 @@ - content_for :page_title do = t('contacts.spotlight.community_spotlight') +.container#contacts_container + .row + .col-md-3 + .sidebar + = render "contacts/sidebar" -.container-fluid#contacts_container - .row-fluid - .span3 - = render 'contacts/sidebar' - - .span9 - #people_stream.stream.contacts - .header + .col-md-9 + .stream.contacts.framed-content#people_stream + .header.clearfix - if AppConfig.settings.community_spotlight.suggest_email.present? .pull-right = link_to t('contacts.spotlight.suggest_member'), "mailto:#{AppConfig.settings.community_spotlight.suggest_email}", :class => "btn btn-default", :id => "suggest_member" @@ -17,9 +17,9 @@ = t('contacts.spotlight.community_spotlight') #community_spotlight - - unless @people.blank? + - if @people.blank? + .well + = t("contacts.spotlight.no_members") + - else - @people.each do |person| = render 'people/person', :person => person, :contact => current_user.contact_for(person) - - -# if @contacts_size > 0 - = render @contacts diff --git a/app/views/conversations/_conversation.haml b/app/views/conversations/_conversation.haml index 17899a543b188d55fbfead18d20d99e515a0c95d..5299debbdeb28b28e74ec051b4f75bba90408244 100644 --- a/app/views/conversations/_conversation.haml +++ b/app/views/conversations/_conversation.haml @@ -16,10 +16,10 @@ = other_participants.count - 1 .bg - .badge.badge-dafault.message_count + .badge.badge-default.message-count.pull-right = conversation.messages.size - if visibility.unread > 0 - .badge.badge-important.unread_message_count + .badge.badge-important.unread-message-count.pull-right = visibility.unread .subject %div{ :class => direction_for(conversation.subject) } @@ -32,7 +32,7 @@ .last_message - if conversation.messages.present? %em - = conversation.messages.last.text + = conversation.messages.last.message.plain_text_without_markdown - if other_participants.count > 1 .participants - other_participants.drop(1).take(15).each do |participant| diff --git a/app/views/conversations/_conversation.mobile.haml b/app/views/conversations/_conversation.mobile.haml index 90378c45f5a25e84766a5704a4cfd6a532612d49..cce4df2ef8266d87758e38d2d0231199737b27bb 100644 --- a/app/views/conversations/_conversation.mobile.haml +++ b/app/views/conversations/_conversation.mobile.haml @@ -3,7 +3,7 @@ .stream_element.conversation{data: {guid: conversation.id}, class: ("unread" if visibility.unread > 0)} .media .img - = person_image_tag(conversation.author) + = person_image_tag(conversation.author, size: :thumb_small) .bg = render partial: "conversation_subject", diff --git a/app/views/conversations/_conversation_subject.haml b/app/views/conversations/_conversation_subject.haml index cde73f0ed311a3912fd13afeffc3ff061b87dcb0..dc0a4ad0bcc59eb1e5303f1528c8dfd9184e5cdc 100644 --- a/app/views/conversations/_conversation_subject.haml +++ b/app/views/conversations/_conversation_subject.haml @@ -1,8 +1,8 @@ .subject - .badge.badge-dafault.message_count + .badge.badge-default.message-count.pull-right = conversation.messages.size - if unread_count > 0 - .badge.badge-important.unread_message_count + .badge.badge-important.unread-message-count.pull-right = unread_count %div{ :class => direction_for(conversation.subject) } diff --git a/app/views/messages/_message.haml b/app/views/conversations/_message.haml similarity index 51% rename from app/views/messages/_message.haml rename to app/views/conversations/_message.haml index 94b23aaa17f46b90b4ceb1c4234d7da3723cae04..996ae3bc528bed3cb43ca103e2dc746681325c95 100644 --- a/app/views/messages/_message.haml +++ b/app/views/conversations/_message.haml @@ -2,13 +2,14 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.stream_element{:data=>{:guid=>message.id}, :id => ('first_unread' if @first_unread_message_id == message.id)} +.stream_element.message{data: {guid: message.id}, id: ("first_unread" if @first_unread_message_id == message.id)} .media - .img - = person_image_link(message.author, :size => :thumb_small) - .bd + .media-left + = person_image_link(message.author, size: :thumb_small, class: "media-object") + .media-body = person_link(message.author, :class => 'author from') = timeago(message.created_at) %div{ :class => direction_for(message.text) } - = message.message.markdownified + .message-content + = message.message.markdownified diff --git a/app/views/conversations/_messages.haml b/app/views/conversations/_messages.haml new file mode 100644 index 0000000000000000000000000000000000000000..3b678160021ddc6259cb4d4b6ca7e740117e87da --- /dev/null +++ b/app/views/conversations/_messages.haml @@ -0,0 +1,22 @@ +.stream + = render partial: "message", collection: conversation.messages + + .stream_element.new-message + .media + .media-left + = owner_image_tag(:thumb_small) + .media-body + = form_for [conversation, Message.new], html: {class: "control-group"} do |message| + .form-group + %label#messageLabel.sr-only{for: "message_text"} + = t("conversations.new.message") + = message.text_area :text, + rows: 5, + tabindex: 1, + class: "form-control form-group", + aria: {labelledby: "messageLabel"} + + = message.submit t("conversations.show.reply"), + "data-disable-with" => t("conversations.show.replying"), + class: "btn btn-primary pull-right", tabindex: 2 + .clearfix diff --git a/app/views/conversations/_new.haml b/app/views/conversations/_new.haml index bc5a559f57d45cb2749e9c4ede16a212cdc76f13..2358b8b199864e16000376d239e1c75660acb798 100644 --- a/app/views/conversations/_new.haml +++ b/app/views/conversations/_new.haml @@ -1,18 +1,22 @@ -= form_for Conversation.new, html: {class: "form-horizontal form_do_not_clear"}, remote: true do |conversation| - .control-group - %label.control-label{:for => 'contact_ids'} - = t('.to') - .controls - = text_field_tag "contact_autocomplete" - .control-group - %label.control-label{:for => 'conversation_subject'} - = t('.subject') - .controls - = conversation.text_field :subject, :class => 'input-block-level' - .control-group - .controls - = text_area_tag "conversation[text]", '', :rows => 5, :class => 'input-block-level' - .control-group - .controls - .pull-right - = conversation.submit t('.send'), 'data-disable-with' => t('.sending'), :class => 'btn btn-primary creation' +.container-fluid + = form_for Conversation.new, html: {class: "form-horizontal form_do_not_clear"}, remote: true do |conversation| + .form-group + %label#toLabel{for: "contact_ids"} + = t(".to") + = text_field_tag "contact_autocomplete", nil, class: "form-control" + .form-group + %label#subjectLabel{for: "conversation_subject"} + = t(".subject") + = conversation.text_field :subject, + class: "input-block-level form-control", + aria: {labelledby: "subjectLabel"} + .form-group + %label#messageLabel.sr-only{for: "conversation_text"} + = t(".message") + = text_area_tag "conversation[text]", + "", + rows: 5, + class: "input-block-level form-control", + aria: {labelledby: "messageLabel"} + .form-group + = conversation.submit t('.send'), 'data-disable-with' => t('.sending'), class: 'btn btn-primary pull-right' diff --git a/app/views/conversations/_show.haml b/app/views/conversations/_show.haml index 122f2e1ce0cdec3523504831635f180f14fe4a1f..3611d661368eebad4a47a2de009e7bc7f9d7405e 100644 --- a/app/views/conversations/_show.haml +++ b/app/views/conversations/_show.haml @@ -2,22 +2,22 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.conversation_participants +.conversation-participants.framed-content.clearfix .control-icons.pull-right - if conversation.participants.count > 1 - = link_to(content_tag(:i, nil, :class => 'entypo cross'), + = link_to content_tag(:i, nil, class: "entypo-cross"), conversation_visibility_path(conversation), - :method => 'delete', - :data => { :confirm => "#{t('.hide')}?" }, - :title => t('.hide'), - :class => 'hide_conversation') + method: "delete", + data: {confirm: "#{t('.hide')}?"}, + title: t(".hide"), + class: "hide_conversation" - else - = link_to(content_tag(:i, nil, :class => 'entypo trash'), + = link_to content_tag(:i, nil, class: "entypo-trash"), conversation_visibility_path(conversation), - :method => 'delete', - :data => { :confirm => "#{t('.delete')}?" }, - :title => t('.delete'), - :class => 'delete_conversation') + method: "delete", + data: {confirm: "#{t('.delete')}?"}, + title: t(".delete"), + class: "delete_conversation" %h3{ :class => direction_for(conversation.subject) } = conversation.subject @@ -26,14 +26,4 @@ = person_image_link(participant, :size => :thumb_small) .stream - = render :partial => 'messages/message', :collection => conversation.messages - - .stream_element.new_message - .media - .img - = owner_image_tag(:thumb_small) - - .bd - = form_for [conversation, Message.new] do |message| - = message.text_area :text, :class => 'span12', :rows => 5, :tabindex => 1 - = message.submit t('.reply').capitalize, 'data-disable-with' => t('.replying'), class: 'btn btn-primary pull-right creation', tabindex: 2 + = render partial: 'messages', locals: { conversation: conversation } diff --git a/app/views/conversations/_show.mobile.haml b/app/views/conversations/_show.mobile.haml index 2a8a574e9e4be37c4dafae927bdd7a79a9d370d4..d95f78932c46d08cb9b5237ca5b88b001e4c23e7 100644 --- a/app/views/conversations/_show.mobile.haml +++ b/app/views/conversations/_show.mobile.haml @@ -2,26 +2,21 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.conversation_participants - .right - = link_to(image_tag("mobile/deletelabel.png"), conversation_visibility_path(conversation), method: :delete, data: { confirm: "#{t('.delete')}?" }, class: "remove") +.conversation + .conversation-participants.header-full-width + .delete_conversation.pull-right + = link_to(raw("<i class='entypo-trash'></i>"), conversation_visibility_path(conversation), + method: 'delete', data: { confirm: "#{t('.delete')}?" }, class: "remove") - %h3{ :class => direction_for(conversation.subject) } - = conversation.subject + %h3 + = conversation.subject + .last-message-timeago + != t('.last_message', timeago: timeago(conversation.updated_at)) - - for participant in conversation.participants - = person_image_link(participant, :size => :thumb_small) + .avatars + - for participant in conversation.participants + .avatar + = person_image_link(participant, size: :thumb_small) + .clear -.span-15.last - .stream - = render :partial => 'messages/message', :collection => conversation.messages - - .stream_element.new_message - .media - .img - = owner_image_tag(:thumb_small) - - .bd - = form_for [conversation, Message.new] do |message| - = message.text_area :text, :rows => 5, :tabindex => 1 - = message.submit t('.reply').capitalize, 'data-disable-with' => t('.replying'), :class => 'button creation', :tabindex => 2 + = render partial: 'messages', locals: { conversation: conversation } diff --git a/app/views/conversations/create.js.erb b/app/views/conversations/create.js.erb index 21912cebcb8df7ae360199eaf16a7028bdbdf15c..92ae238e2a3cc032995912da86b2a01d0df80be9 100644 --- a/app/views/conversations/create.js.erb +++ b/app/views/conversations/create.js.erb @@ -2,10 +2,11 @@ var response = <%= raw @response.to_json %>; <% if session[:mobile_view] %> window.location.href = "<%= conversations_path(conversation_id: @conversation.id) %>"; <% else %> - Diaspora.page.flashMessages.render({ 'success':response.success, 'notice':response.message }); if(response.success){ + app.flashMessages.success(response.message); $("#new_conversation").removeClass('form_do_not_clear').clearForm(); - $.facebox.close(); window.location.href = "<%= conversations_path(conversation_id: @conversation.id) %>"; + } else { + app.flashMessages.error(response.message); } -<% end %> \ No newline at end of file +<% end %> diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index e6f09a4c96bcce1d89970e422013a99f877409ae..31297c79e5182d1951b94449f2c7f2267779183f 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -5,35 +5,37 @@ = t('.conversations_inbox') .container-fluid#conversations_container - .row-fluid - .span4 - #left_pane - #left_pane_header + .row + .col-md-4 + .sidebar#left_pane + .sidebar-header.clearfix#left_pane_header + .pull-right + = link_to t(".new_conversation"), conversations_path, class: "btn btn-default" %h3 - .pull-right{ class: ("hidden" unless @visibilities)} - = link_to t('.new_conversation'), conversations_path, class: 'btn btn-default' - = t('.inbox') + = t(".inbox") - #conversation_inbox + .conversation-inbox#conversation_inbox .stream.conversations - if @visibilities.count > 0 - = render partial: "conversations/conversation", collection: @visibilities, as: :visibility, locals: {authors: @authors, ordered_participants: @ordered_participants, unread_counts: @unread_counts, selected_conversation_id: @conversation.try(:id)} + = render partial: "conversations/conversation", collection: @visibilities, as: :visibility - else - #no_conversations + .no-conversations = t('.no_messages') - = will_paginate @visibilities, previous_label: "«", next_label: "»",inner_window: 1, - renderer: WillPaginate::ActionView::BootstrapLinkRenderer + .pagination-container + = will_paginate @visibilities, previous_label: "«", next_label: "»", inner_window: 1, + renderer: WillPaginate::ActionView::BootstrapLinkRenderer - .span8 + + .col-md-8 - if @conversation .stream_container #conversation_show - = render 'conversations/show', :conversation => @conversation + = render 'conversations/show', conversation: @conversation - else .stream_container.hidden #conversation_show - #conversation_new.row-fluid - %h3.text-center - = t('conversations.index.new_conversation') - .span10.offset - = render 'conversations/new' + .framed-content.clearfix#conversation_new + .new-conversation + %h3.text-center + = t("conversations.index.new_conversation") + = render "conversations/new" diff --git a/app/views/conversations/index.mobile.haml b/app/views/conversations/index.mobile.haml index 885bfd38c6167799cfe1ea93eab321e615d7372f..89dfd53d32fc30a7cdc9508ed6f5494538735d1f 100644 --- a/app/views/conversations/index.mobile.haml +++ b/app/views/conversations/index.mobile.haml @@ -2,30 +2,24 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.right - = link_to t('.new_conversation'), new_conversation_path, :class => 'btn' +.clearfix.conversations-title + %h3= t(".inbox") + = link_to t(".new_conversation"), new_conversation_path, class: "btn btn-default pull-right" - flash.each do |name, msg| - %div{:id => "flash_#{name}", :class => "expose"} + %div{ id: "flash_#{name}", class: "expose" } .message= msg .stream - %p{:class => "conversation_#{name}"}= msg - -%h3 - = t('.inbox') + %p{ class: "conversation_#{name}" }= msg #conversation_inbox .stream.conversations - if @visibilities.count > 0 - = render partial: "conversations/conversation", collection: @visibilities, as: :visibility, locals: {authors: @authors, unread_counts: @unread_counts} + = render partial: "conversations/conversation", collection: @visibilities, as: :visibility - else - %br - %br - %br - %br - %div{:style => 'text-align:center;'} + .no-messages %i - = t('.no_messages') + = t(".no_messages") = will_paginate @visibilities, previous_label: "«", next_label: "»", inner_window: 1, outer_window: 0, renderer: WillPaginate::ActionView::BootstrapLinkRenderer diff --git a/app/views/conversations/new.mobile.haml b/app/views/conversations/new.mobile.haml index 160059c8d753a73220df49f1f7e3f04f03ccc3e0..d7c6fe94ee23a90a1ca4c2e13621028cb45dd6df 100644 --- a/app/views/conversations/new.mobile.haml +++ b/app/views/conversations/new.mobile.haml @@ -24,28 +24,9 @@ autocompleteInput.focus(); }); -.span6#new_conversation_pane - .span5#facebox_header +.col-md-6#new_conversation_pane + .container-fluid.row %h3 = t('conversations.index.new_conversation') - = form_for Conversation.new, html: {class: "new_conversation form_do_not_clear"}, remote: true do |conversation| - - .span1 - %h4 - = t('.to') - .span4 - = text_field_tag "contact_autocomplete" - .clearfix - %br - .span1 - %h4 - = t('.subject') - .span4 - = conversation.text_field :subject - %br - .span4.offset1 - = text_area_tag "conversation[text]", '', :rows => 5 - .clearfix - .bottom_submit_section - = conversation.submit t('.send'), 'data-disable-with' => t('.sending'), :class => 'button creation' + = render 'conversations/new' diff --git a/app/views/conversations/show.js.erb b/app/views/conversations/show.js.erb index 70e2a0ed5cb5acd8d3c6a6b48f49ffd04196c5ca..c07578ee45f2e4faaa64e7cd8c7f0c93868a51e0 100644 --- a/app/views/conversations/show.js.erb +++ b/app/views/conversations/show.js.erb @@ -1,7 +1,6 @@ if($('.stream_container').hasClass('hidden')){ $('#conversation_new').hide(); $('.stream_container').removeClass('hidden'); - $('#left_pane_header .pull-right').removeClass('hidden'); } $('#conversation_show').html("<%= escape_javascript(render('conversations/show', :conversation => @conversation)) %>"); diff --git a/app/views/devise/passwords/edit.haml b/app/views/devise/passwords/edit.haml index 732ffa90f745bc38567f55de27469977b7e4a423..126ae62f49195f44110c4953b8f019d414824087 100644 --- a/app/views/devise/passwords/edit.haml +++ b/app/views/devise/passwords/edit.haml @@ -2,7 +2,7 @@ = "#{AppConfig.settings.pod_name} - #{t('devise.passwords.edit.change_password')}" #reset_password - .container-fluid + .container .text-center .logos-asterisk %h1 @@ -11,21 +11,34 @@ = form_for(resource, as: resource_name, url: password_path(resource_name), html: {class: "form-horizontal block-form", method: :put }, autocomplete: 'off') do |f| = f.error_messages - %fieldset - %label{for: "user_password"} - = t('devise.passwords.edit.new_password') - %i.entypo.lock - = f.password_field :password, class: "input-block-level form-control", required: true, placeholder: t('devise.passwords.edit.new_password'), autocapitalize: "none", autocorrect: "off", autofocus: true + %fieldset.form + %label#passwordLabel.sr-only{for: "user_password"} + = t("devise.passwords.edit.new_password") + %i.entypo-lock + = f.password_field :password, + class: "input-block-level form-control", + required: true, + placeholder: t("devise.passwords.edit.new_password"), + autocapitalize: "none", + autocorrect: "off", + autofocus: true, + aria: {labelledby: "passwordLabel"} = f.hidden_field :reset_password_token - %label{for: "user_password_confirmation"} - = t('devise.passwords.edit.confirm_password') - %i.entypo.lock - = f.password_field :password_confirmation, class: "input-block-level form-control", required: true, placeholder: t('devise.passwords.edit.confirm_password'), autocapitalize: "none", autocorrect: "off" + %label#passwordConfirmationLabel.sr-only{for: "user_password_confirmation"} + = t("devise.passwords.edit.confirm_password") + %i.entypo-lock + = f.password_field :password_confirmation, + class: "input-block-level form-control", + required: true, + placeholder: t("devise.passwords.edit.confirm_password"), + autocapitalize: "none", + autocorrect: "off", + aria: {labelledby: "passwordConfirmationLabel"} = hidden_field(:user, :remember_me, value: 1) - = f.submit t('devise.passwords.edit.change_password'), class: "btn btn-block" + = f.submit t("devise.passwords.edit.change_password"), class: "btn btn-block btn-primary" .text-center - = link_to t('devise.shared.links.sign_in'), new_session_path(resource_name) + = link_to t("devise.shared.links.sign_in"), new_session_path(resource_name) diff --git a/app/views/devise/passwords/edit.mobile.haml b/app/views/devise/passwords/edit.mobile.haml index 18c97e63686538e4ee2c7673fa1a50d5b50d6d0a..2ac3ff92ac2f30c3061ea34fbfee65c14ac23b54 100644 --- a/app/views/devise/passwords/edit.mobile.haml +++ b/app/views/devise/passwords/edit.mobile.haml @@ -5,25 +5,25 @@ #main_stream.stream #login_form .login-container - = form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| + = form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| = devise_error_messages! = f.hidden_field :reset_password_token %fieldset %legend - =t('devise.passwords.edit.change_password') + = t("devise.passwords.edit.change_password") .control-group - = f.label :password, t('devise.passwords.edit.new_password'), :class => "control-label" + = f.label :password, t("devise.passwords.edit.new_password"), class: "control-label" .controls = f.password_field :password .control-group - = f.label :password_confirmation, t('devise.passwords.edit.confirm_password'), :class => "control-label" + = f.label :password_confirmation, t("devise.passwords.edit.confirm_password"), class: "control-label" .controls = f.password_field :password_confirmation .controls - = f.submit t('devise.passwords.edit.change_password'), :class => 'btn primary' + = f.submit t("devise.passwords.edit.change_password"), class: "btn btn-primary" %footer - = link_to t('layouts.application.toggle'), toggle_mobile_path + = link_to t("layouts.application.toggle"), toggle_mobile_path diff --git a/app/views/devise/passwords/new.haml b/app/views/devise/passwords/new.haml index 9486f50357d398074f015603aa50f189f0f2c1d7..eccb259a26d3f784fa39ed70bbca15c80135ea04 100644 --- a/app/views/devise/passwords/new.haml +++ b/app/views/devise/passwords/new.haml @@ -2,7 +2,7 @@ = "#{AppConfig.settings.pod_name} - #{t('devise.passwords.new.forgot_password')}" #forgot_password - .container-fluid + .container .text-center .logos-asterisk %h1 @@ -14,11 +14,19 @@ %i = t('devise.passwords.new.no_account') # this is an error message and should not be displayed as a legend %fieldset - %label{for: "user_email"} - = t('devise.passwords.new.email') - %i.entypo.mail - = f.text_field :email, class: "input-block-level form-control", required: true, autocapitalize: "off", placeholder: t('devise.passwords.new.email'), autocorrect: "off", autofocus: true - = f.submit t('devise.passwords.new.send_password_instructions'), class: "btn btn-block" + %label#emailLabel.sr-only{for: "user_email"} + = t("devise.passwords.new.email") + %i.entypo-mail + = f.text_field :email, + class: "input-block-level form-control", + required: true, + autocapitalize: "off", + placeholder: t("devise.passwords.new.email"), + autocorrect: "off", + autofocus: true, + aria: {labelledby: "passwordLabel"} + + = f.submit t("devise.passwords.new.send_password_instructions"), class: "btn btn-block btn-primary" .text-center = link_to t('devise.shared.links.sign_in'), new_session_path(resource_name) diff --git a/app/views/devise/passwords/new.mobile.haml b/app/views/devise/passwords/new.mobile.haml index dee951b4e2ee640afdf95f2e7035f91425be981a..241a1d70c1d9daf6eeda263401b59f8fea71c607 100644 --- a/app/views/devise/passwords/new.mobile.haml +++ b/app/views/devise/passwords/new.mobile.haml @@ -18,10 +18,10 @@ = f.text_field :email .controls - = f.submit t('devise.passwords.new.send_password_instructions'), :class => 'btn' + = f.submit t("devise.passwords.new.send_password_instructions"), class: "btn btn-primary" %footer - - if display_registration_link? + - if display_registration_link? = link_to t('devise.shared.links.sign_up'), new_registration_path(resource_name) = link_to t('devise.sessions.new.sign_in'), new_user_session_path() diff --git a/app/views/errors/error_404.haml b/app/views/errors/error_404.haml index e66451207f8fa9976ac8f4346c5f179e65edb660..847b92ef61e6065fcfc891c1e491147045f0dfaa 100644 --- a/app/views/errors/error_404.haml +++ b/app/views/errors/error_404.haml @@ -1,9 +1,9 @@ - content_for(:page_title) do The page you were looking for doesn't exist (404) -#big-number.transparent +.transparent.big-number 404 -%p +%h3 These are not the kittens you're looking for. Move along. %p %a{href: "javascript:history.back()"} diff --git a/app/views/errors/error_422.haml b/app/views/errors/error_422.haml index f602b05d0a92f5f7ab18a4dc82b510de49a5ede4..cd3af7d46853322adfda0047ce8d4f67885b8892 100644 --- a/app/views/errors/error_422.haml +++ b/app/views/errors/error_422.haml @@ -1,8 +1,13 @@ - content_for(:page_title) do The change you wanted was rejected (422) -.dialog - %h1 - The change you wanted was rejected. - %p - Maybe you tried to change something you didn't have access to. +.transparent.big-number + 422 +%h3 + The change you wanted was rejected. +%p + Maybe you tried to change something you didn't have access to. + +%p + %a{href: "javascript:history.back()"} + Go Back? diff --git a/app/views/errors/error_500.haml b/app/views/errors/error_500.haml index 6b454301290c6ad0aa17990f21115943575fa1dc..d566b86cabf90d239a27540ab83f3c8ed380f321 100644 --- a/app/views/errors/error_500.haml +++ b/app/views/errors/error_500.haml @@ -1,12 +1,10 @@ - content_for(:page_title) do We're sorry, but something went wrong (500) -%header - = image_tag "branding/logos/white2x.png", id: "diaspora_logo" - -%h1 - 500: Internal server error. +.transparent.big-number + 500 %h3 + Internal server error. Our bad! Sorry about that. :( - if AppConfig.admins.podmin_email? diff --git a/app/views/errors/not_public.haml b/app/views/errors/not_public.haml deleted file mode 100644 index c330cb28e9c7d91fafb4b0ac908c304f0101f8f3..0000000000000000000000000000000000000000 --- a/app/views/errors/not_public.haml +++ /dev/null @@ -1,14 +0,0 @@ --# Copyright (c) 2010-2012, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - -- content_for :head do - = stylesheet_link_tag :error_pages, :media => 'all' - -#big-number.transparent - 404 - -#content - = t('error_messages.post_not_public_or_not_exist') - %br - = t('error_messages.login_try_again', :login_link => new_user_session_path).html_safe diff --git a/app/views/home/default.haml b/app/views/home/default.haml index c08fa9f65b890cce462468be0f989bef8fc3b843..2a7a789c7a417e3804fd41daa8ff9861b56deee8 100644 --- a/app/views/home/default.haml +++ b/app/views/home/default.haml @@ -1,64 +1,27 @@ -- content_for(:head) do - = stylesheet_link_tag :home, media: "all" - -#page.container - %header#header - %a#login-link.btn{href: "login"} Log In - = image_tag "branding/logos/logo.png" - - #banner.row - %h1 Welcome, friend. - %h3 You're about to change the Internet. Let's get you set up, shall we? - - #steps.row - .span4 - %h2 - Configure your - %abbr.helpful{title: "A Diaspora installation"} pod - = image_tag "landing/cog.png" - - %p - Look at - %code.helpful{title: "General pod configuration (location to upload photos, SSL certs, etc.)"} - config/diaspora.yml.example - and - %code.helpful{title: "MySQL username/password"} - config/database.yml.example - for help. - - .span4 - %h2 Try it out - = image_tag "landing/smiley_laughing.png" - - %p - Start by - = link_to "creating an account", new_user_registration_path - - .span4 - %h2 Make a contribution! - = image_tag "landing/pen_write.png" - - %p - Make Diaspora even better! Fork the project on - = link_to "Github", "http://github.com/diaspora/diaspora" - make some changes, and submit a pull request. - - %footer - %h3 Useful Resources - %ul#links - %ul.section - %li= link_to "Codebase", "http://github.com/diaspora/diaspora", title: "Git repository" - %li= link_to "Documentation", "http://wiki.diasporafoundation.org", title: "Project wiki" - %ul.section - %li= link_to "IRC - General", "http://webchat.freenode.net/?channels=diaspora", title: "#diaspora" - %li= link_to "IRC - Development", "http://webchat.freenode.net/?channels=diaspora-dev", title: "#diaspora-dev" - %ul.section - %li= link_to "Discussion - General", "http://groups.google.com/group/diaspora-discuss", title: "General discussion mailing list" - %li= link_to "Discussion - Development", "http://groups.google.com/group/diaspora-dev", title: "Dev mailing list" - %ul.section - %li= link_to "Find & Report bugs", "https://github.com/diaspora/diaspora/issues", title: "Bug tracker" - %li= link_to "Learn more about Ruby On Rails!", "http://guides.rubyonrails.org/" - - #change-page - This page can be changed to a custom landing page by creating - %code app/views/home/_show.html.haml +.dandelion-background + .jumbotron + .container-fluid.home-user + .row + .col-md-8.text-center + %h1= t("home.default.headline", pod_name: pod_name) + %h2= t("home.default.byline") + .col-md-4.login-form + = render partial: "sessions/form", locals: {mobile: false, resource: User.new, resource_name: :user} + +.container-fluid + .row + .col-md-4 + .landing-info-card + %h3.text-center + = t(".own_your_data") + = t(".own_your_data_info") + .col-md-4 + .landing-info-card + %h3.text-center + = t(".choose_your_audience") + = t(".choose_your_audience_info") + .col-md-4 + .landing-info-card + %h3.text-center + = t(".be_who_you_want_to_be") + = t(".be_who_you_want_to_be_info") diff --git a/app/views/home/podmin.haml b/app/views/home/podmin.haml new file mode 100644 index 0000000000000000000000000000000000000000..ecf1f2a0382897ec476d43e3225dc7c5e027b0e0 --- /dev/null +++ b/app/views/home/podmin.haml @@ -0,0 +1,61 @@ +.dandelion-background + .jumbotron + .container-fluid.home-podmin + .row + .col-md-12.text-center + %h1= t(".headline") + %h2= t(".byline") + +.container-fluid + .row + .col-md-4 + .landing-info-card + %h3.text-center + .entypo-tools + = t(".configure_your_pod") + != t(".configuration_info", + database_path: content_tag(:code, "config/database.yml"), + diaspora_path: content_tag(:code, "config/diaspora.yml")) + + .col-md-4 + .landing-info-card + %h3.text-center + .entypo-add-user + = t(".create_an_account") + != t(".create_an_account_info", + sign_up_link: link_to(t("devise.shared.links.sign_up"), new_user_registration_path)) + + .col-md-4 + .landing-info-card + %h3.text-center + .entypo-key + = t(".make_yourself_an_admin") + != t(".make_yourself_an_admin_info", + wiki: link_to("diaspora* wiki", "https://wiki.diasporafoundation.org/FAQ_for_pod_maintainers#What_are_roles_and_how_do_I_use_them.3F_.2F_Make_yourself_an_admin"), + admin_panel: link_to(t(".admin_panel"), "/admin_panel")) + + .row + .col-md-4 + .landing-info-card + %h3.text-center + .entypo-new + = t(".update_your_pod") + != t(".update_your_pod_info", + update_instructions: link_to(t(".update_instructions"), "https://wiki.diasporafoundation.org/Updating")) + + .col-md-4 + .landing-info-card + %h3.text-center + .entypo-lifebuoy + = t(".getting_help") + != t(".getting_help_info", + faq: link_to(t(".faq_for_podmins"), "https://wiki.diasporafoundation.org/FAQ_for_pod_maintainers"), + irc: link_to(t(".contact_irc"), "https://wiki.diasporafoundation.org/How_We_Communicate#IRC")) + + .col-md-4 + .landing-info-card + %h3.text-center + .entypo-code + = t(".contribute") + != t(".contribute_info", + report_bugs: link_to(t(".report_bugs"), "https://wiki.diasporafoundation.org/How_to_report_a_bug")) diff --git a/app/views/invitations/new.html.haml b/app/views/invitations/new.html.haml index b39bb12b073ec45de449fecdbf499da83f4ca030..187a6fa12a91c01280ee1c07e603af0eea027ba6 100644 --- a/app/views/invitations/new.html.haml +++ b/app/views/invitations/new.html.haml @@ -1,29 +1,32 @@ #paste_link = t('.paste_link') %span#codes_left - = '(' + t('.codes_left', :count => @invite_code.count) + ')' + = "(" + t(".codes_left", count: @invite_code.count) + ")" unless AppConfig.settings.enable_registrations? .form-horizontal .control-group - .controls - = invite_link(@invite_code) + = invite_link(@invite_code) #email_invitation - = form_tag new_user_invitation_path, :class => 'form-horizontal' do - - .control-group - %label.control-label{ :for => 'email_inviter_emails' } + = form_tag new_user_invitation_path, class: 'form-horizontal' do + + .form-group + %label.col-sm-2.control-label{ for: 'email_inviter_emails' } = t('email') - .controls - = text_field_tag 'email_inviter[emails]', @invalid_emails, :title => t('.comma_separated_plz'), :placeholder => 'foo@bar.com, max@foo.com...' + .col-sm-10 + = text_field_tag 'email_inviter[emails]', @invalid_emails, title: t('.comma_separated_plz'), + placeholder: 'foo@bar.com, max@foo.com...', class: "form-control" #already_sent - = t('invitations.create.note_already_sent', :emails => @valid_emails) unless @valid_emails.empty? - - .control-group - %label.control-label{ :for => 'email_inviter_locale' } + = t("invitations.create.note_already_sent", emails: @valid_emails) unless @valid_emails.empty? + + .form-group + %label.col-sm-2.control-label{ for: 'email_inviter_locale' } = t('.language') - .controls - = select_tag('email_inviter[locale]', options_from_collection_for_select(available_language_options, "second", "first", :selected => current_user.language)) - - .control-group - .controls - = submit_tag t('.send_an_invitation'), class: 'btn btn-primary creation', data: {disable_with: t('.sending_invitation')} + .col-sm-10 + = select_tag 'email_inviter[locale]', options_from_collection_for_select(available_language_options, + "second", "first", selected: current_user.language), class: "form-control" + + .form-group + .pull-right.col-md-12 + = submit_tag t('.send_an_invitation'), class: 'btn btn-primary pull-right', + data: {disable_with: t('.sending_invitation')} + .clearfix diff --git a/app/views/layouts/_drawer.mobile.haml b/app/views/layouts/_drawer.mobile.haml new file mode 100644 index 0000000000000000000000000000000000000000..d676a2084f3ab47bc1dfa449d27fd69456696153 --- /dev/null +++ b/app/views/layouts/_drawer.mobile.haml @@ -0,0 +1,35 @@ +#drawer + %header + #global-search + = form_tag("/search", :method => "get", :class => "search_form", "accept-charset" => "UTF-8") do + %div + = hidden_field_tag "utf8", "✓" + = search_field_tag "q", nil, id: "q", placeholder: t("search"), results: "5", + autocomplete: "off", class: "ac_input form-control" + %nav.navbar-inverse + %ul + %li= link_to t("streams.activity.title"), activity_stream_path + %li= link_to t("streams.mentions.title"), mentioned_stream_path + %li#all_aspects + = link_to t("streams.aspects.title"), "#" + %li.no-border.hide + %ul + - current_user.aspects.each do |aspect| + %li= link_to aspect.name, aspects_stream_path(a_ids: [aspect.id]) + %li#followed_tags + = link_to t("streams.followed_tag.title"), "#" + %li.no-border.hide + %ul + - current_user.followed_tags.each do |tag| + %li= tag_link(tag) + - if current_user.followed_tags.length > 0 + %li.manage-followed-tags + = link_to t("tag_followings.manage.title"), manage_tag_followings_path + %li + = link_to user_profile_path(current_user.username) do + = t("layouts.header.profile") + = person_image_tag(current_user, size: :thumb_small) + %li= link_to t("_contacts"), contacts_path + %li= link_to t("layouts.header.settings"), edit_user_path + %li= link_to t("layouts.application.toggle"), toggle_mobile_path + %li= link_to t("layouts.header.logout"), destroy_user_session_path, method: :delete diff --git a/app/views/layouts/_footer.html.haml b/app/views/layouts/_footer.html.haml index 12236d9562efb2a63571604042b3c16dd819ad0d..ab8263507269361d69971bb227a76ba97a7a0947 100644 --- a/app/views/layouts/_footer.html.haml +++ b/app/views/layouts/_footer.html.haml @@ -1,5 +1,7 @@ -%footer +%footer.footer .container - .logos-powered_by_diaspora - %ul#footer_nav + .pull-left + .powered-by-diaspora + =t("layouts.application.powered_by") + %ul#footer_nav.pull-right = render :partial =>'shared/links' diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index 654dececbc8c5d094b436751ba206c9592e28232..b5a82390cec4519e0b94d8993c56389f0ee5e792 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -4,18 +4,19 @@ %header - unless current_user - .container{style: "position:relative;"} - = link_to content_tag(:div, nil, class: 'diaspora_header_logo logos-header-logo'), root_path + .dark-header + %nav.navbar.navbar-inverse.navbar-fixed-top + .container-fluid + .row + .col-md-12 + .navbar-header + %button.navbar-toggle.collapsed{type: "button", data: {toggle: "collapse", target: "#navbar-collapse"}} + %span.sr-only + = t("layouts.header.toggle_navigation") + %span.icon-bar + %span.icon-bar + %span.icon-bar + = link_to AppConfig.settings.pod_name, root_path, class: "navbar-brand" - %ul#landing_nav - - if AppConfig.settings.enable_registrations? && !current_page?(controller: '/registrations', action: :new) - %li= link_to t('devise.shared.links.sign_up'), new_user_registration_path, class: 'login' - %li= link_to t('devise.shared.links.sign_in'), new_user_session_path, class: 'login' - #lightbox - #lightbox-content - %a#lightbox-close-link(href='#') - [x] - =t('javascripts.header.close') - %img#lightbox-image - #lightbox-imageset - #lightbox-backdrop + .collapse.navbar-collapse#navbar-collapse + = render "layouts/header_not_connected" diff --git a/app/views/layouts/_header.mobile.haml b/app/views/layouts/_header.mobile.haml new file mode 100644 index 0000000000000000000000000000000000000000..30c7790988885765194b7934cdcb4c190dec2c44 --- /dev/null +++ b/app/views/layouts/_header.mobile.haml @@ -0,0 +1,39 @@ +.nav.navbar-inverse.navbar-fixed-top#main-nav + .container-fluid + .navbar + = link_to(image_tag("branding/logos/asterisk_white_mobile.png", class: "img-responsive"), + stream_path, id: "header-title", class: "navbar-brand") + + - if user_signed_in? + %ul.nav.navbar-nav#nav-badges + -# Notifications + %li + = link_to notifications_path, class: "badge-link", id: "notification-badge" do + %i.entypo-bell + - if current_user.unread_notifications.size > 0 + %span.badge.badge-important#notification + = current_user.unread_notifications.size + + -# Conversations + %li + = link_to conversations_path, class: "badge-link", id: "conversations-badge" do + %i.entypo-mail + - if current_user.unread_message_count > 0 + %span.badge.badge-important#conversation + = current_user.unread_message_count + + -# Publisher + %li + = link_to new_status_message_path, class: "badge-link", id: "compose-badge" do + %i.diaspora-custom-compose + + -# Menu + %li + %button.navbar-toggle#menu-badge{type: "button"} + %span.sr-only + %span.icon-bar + %span.icon-bar + %span.icon-bar + + - else + = render "layouts/header_not_connected" diff --git a/app/views/layouts/_header_not_connected.haml b/app/views/layouts/_header_not_connected.haml new file mode 100644 index 0000000000000000000000000000000000000000..a3d1bcae37da33d02f4244d522c77efea23542ba --- /dev/null +++ b/app/views/layouts/_header_not_connected.haml @@ -0,0 +1,4 @@ +%ul.nav.navbar-nav.navbar-right + - if AppConfig.settings.enable_registrations? && !current_page?(controller: "/registrations", action: :new) + %li= link_to t("devise.shared.links.sign_up"), new_user_registration_path, class: "login" + %li= link_to t("devise.shared.links.sign_in"), new_user_session_path, class: "login" diff --git a/app/views/layouts/_open_graph.haml b/app/views/layouts/_open_graph.haml deleted file mode 100644 index ff70913dfea3087d2fbbc4e21acd307796f50a91..0000000000000000000000000000000000000000 --- a/app/views/layouts/_open_graph.haml +++ /dev/null @@ -1,5 +0,0 @@ -- if @post.present? - %link{:rel => 'alternate', :type => "application/json+oembed", :href => "#{oembed_url(:url => post_url(@post))}"} - = og_page_post_tags(@post) -- else - = og_general_tags diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 12b09b55973de07c7e35547e61fa1a67a9b7b587..a1ab3aa8479d24f655446e3618d522f5f1b9361b 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -3,29 +3,28 @@ -# the COPYRIGHT file. !!! -%html{:lang => I18n.locale.to_s, :dir => (rtl?) ? 'rtl' : 'ltr'} - %head{:prefix => og_prefix} +%html{lang: I18n.locale.to_s, dir: (rtl?) ? 'rtl' : 'ltr'} + %head{prefix: og_prefix} %title = page_title yield(:page_title) - %meta{:charset => 'utf-8'}/ - %meta{"http-equiv"=>"Content-Type", :content=>"text/html; charset=utf-8"}/ - %meta{:name => "description", :content => "diaspora*"}/ - %meta{:name => "author", :content => "Diaspora, Inc."}/ + %meta{charset: 'utf-8'}/ + %meta{"http-equiv" => "Content-Type", :content=>"text/html; charset=utf-8"}/ + %meta{name: "viewport", content: "width=device-width, initial-scale=1"}/ + = content_for?(:meta_data) ? yield(:meta_data) : metas_tags - %link{:rel => 'shortcut icon', :href => "#{image_path('favicon.png')}" } - %link{:rel => 'apple-touch-icon', :href => "#{image_path('apple-touch-icon.png')}"} - - = render 'layouts/open_graph' + %link{rel: 'shortcut icon', href: "#{image_path('favicon.png')}" } = chartbeat_head_block = include_mixpanel - = include_base_css_framework - = stylesheet_link_tag 'application', :media => 'all' + = include_color_theme - if rtl? - = stylesheet_link_tag :rtl, :media => 'all' + = stylesheet_link_tag :rtl, media: 'all' + + - if Rails.env.test? + = stylesheet_link_tag :poltergeist_disable_transition, media: "all" = old_browser_js_support <!--[if IE]> @@ -33,10 +32,8 @@ <![endif]--> = jquery_include_tag - - - unless @landing_page - = javascript_include_tag :main, :templates - = load_javascript_locales + = javascript_include_tag :main, :templates + = load_javascript_locales = translation_missing_warnings = current_user_atom_tag @@ -45,16 +42,32 @@ = csrf_meta_tag - = include_gon(:camel_case => true) - - %body{ :class => "page-#{controller_name} action-#{action_name}" } - = flash_messages + = include_gon(camel_case: true) + %body{ class: "page-#{controller_name} action-#{action_name}" } = yield :before_content + %noscript + .noscript + %h3= t("error_messages.need_javascript") + = content_for?(:content) ? yield(:content) : yield = yield :after_content = include_chartbeat = include_mixpanel_guid + + .blueimp-gallery.blueimp-gallery-controls#blueimp-gallery + .slides + %h3.title + %a.prev + .entypo-chevron-small-left + %a.next + .entypo-chevron-small-right + %a.close + .entypo-cross + %a.play-pause + %ol.indicator + + #flash-container= flash_messages diff --git a/app/views/layouts/application.mobile.haml b/app/views/layouts/application.mobile.haml index 405e27201cc29ceb270909a0c77ecb2a5ef347d9..7c272bcde6b608c99b53ff79d80bf127c2b288f0 100644 --- a/app/views/layouts/application.mobile.haml +++ b/app/views/layouts/application.mobile.haml @@ -4,7 +4,7 @@ !!! %html{:lang => I18n.locale.to_s, :dir => (rtl?) ? 'rtl' : 'ltr'} - %head{:prefix => og_prefix} + %head %title = pod_name @@ -23,19 +23,20 @@ %link{rel: "apple-touch-icon", href: image_path("apple-touch-icon.png")} / For Nokia devices %link{rel: "shortcut icon", href: image_path("apple-touch-icon.png")} + / For desktop + %link{rel: 'shortcut icon', href: image_path("favicon.png")} / iOS mobile web app indicator / NOTE(we will enable these once we don't have to rely on back/forward buttons anymore) /%meta{:name => "apple-mobile-web-app-capable", :content => "yes"} /%link{:rel => "apple-touch-startup-image", :href => "/images/apple-splash.png"} - - = render 'layouts/open_graph' + = yield :meta_data = chartbeat_head_block / Stylesheets - = stylesheet_link_tag 'mobile/mobile', :format => 'all' + = include_color_theme "mobile" = yield(:custom_css) @@ -44,75 +45,17 @@ - if rtl? = stylesheet_link_tag :rtl, :media => 'all' + - if Rails.env.test? + = stylesheet_link_tag :poltergeist_disable_transition, media: "all" + = yield(:head) = include_gon(:camel_case => true) %body #app + = render "layouts/header" - if user_signed_in? - %header#main_nav - #nav_badges - -# Notifications - = link_to notifications_path, class: "badge", id: "notification_badge" do - = image_tag("mobile/notifications_white.png") - - if current_user.unread_notifications.size > 0 - %span.badge_count{id: "notification"} - = current_user.unread_notifications.size - -# Conversations - = link_to conversations_path, class: "badge", id: "conversations_badge" do - = image_tag("mobile/mail_white.png", id: "conversation_icon") - - if current_user.unread_message_count > 0 - %span.badge_count{id: "conversation"} - = current_user.unread_message_count - -# Publisher - = link_to(image_tag("mobile/compose_mobile.png"), new_status_message_path, class: "badge", id: "compose_badge") - -# Menu - = link_to(image_tag("mobile/menu.png"), "#", id: "menu_badge", class: "badge") - = link_to(image_tag("mobile/asterisk_white_mobile.png"), stream_path, id: "header_title") - - - if user_signed_in? - #drawer - %header - #global_search - = form_tag('/search', method: 'get', class: 'search_form', "accept-charset" => "UTF-8") do - %div - = hidden_field_tag "utf8", "✓" - = search_field_tag "q", nil, id: "q", placeholder: t("search"), results: "5", autocomplete: "off", class: "ac_input" - %nav - %ul - %li - = link_to t("streams.activity.title"), activity_stream_path - %li - = link_to t("streams.mentions.title"), mentioned_stream_path - %li#all_aspects - = link_to t('streams.aspects.title'), "#" - %li.no_border.hide - %ul - - current_user.aspects.each do |aspect| - %li - = link_to aspect.name, aspects_stream_path(a_ids: [aspect.id]) - %li#followed_tags - = link_to t('streams.followed_tag.title'), "#" - %li.no_border.hide - %ul - - current_user.followed_tags.each do |tag| - %li - = tag_link(tag) - - if current_user.followed_tags.length > 0 - %li.manage_followed_tags - = link_to t("tag_followings.manage.title"), manage_tag_followings_path - %li - = link_to user_profile_path(current_user.username) do - = t('layouts.header.profile') - = person_image_tag(current_user) - %li - = link_to t('_contacts'), contacts_path - %li - = link_to t('layouts.header.settings'), users_edit_path - %li - = link_to t('layouts.application.toggle'), toggle_mobile_path - %li - = link_to t('layouts.header.logout'), destroy_user_session_path, method: :delete + = render "layouts/drawer" #main{:role => "main"} - if current_page?(:activity_stream) diff --git a/app/views/layouts/error_page.haml b/app/views/layouts/error_page.haml index 5f7fee3d20d38de4c00aa19ce6ab216a88328822..97543be53fb835640625a6e999943797b2931dfc 100644 --- a/app/views/layouts/error_page.haml +++ b/app/views/layouts/error_page.haml @@ -10,5 +10,5 @@ = yield(:head) - %body{id: "error_#{@code}"} + %body{class: "error-#{@code}", id: "error_#{@code}"} = yield diff --git a/app/views/likes/_likes.haml b/app/views/likes/_likes.haml index a2e89298d0c4d49f5085ca39c775a82f14166ce4..a960df44747de82ddd50df23e9f2f54907499ba7 100644 --- a/app/views/likes/_likes.haml +++ b/app/views/likes/_likes.haml @@ -3,5 +3,4 @@ -# the COPYRIGHT file. - @people[0..17].each do |person| - = person_image_link(person) - + = person_image_link(person, size: :thumb_small) diff --git a/app/views/node_info/_statistic.haml b/app/views/node_info/_statistic.haml index 130dc6c1af515916bb7c498969efb0eebb969220..9032c0aea2b94c5f614669af81857531380afc83 100644 --- a/app/views/node_info/_statistic.haml +++ b/app/views/node_info/_statistic.haml @@ -1,5 +1,5 @@ -.span-3 - %h3{:class => activated} +.statistic + %h3{class: activated} = name .data - = value \ No newline at end of file + = value diff --git a/app/views/node_info/_statistics.haml b/app/views/node_info/_statistics.haml index 6e5b44c08fea14526664084039b8079ac42fe25b..4c3d46c2f30b02f33752702270e4538891a113f5 100644 --- a/app/views/node_info/_statistics.haml +++ b/app/views/node_info/_statistics.haml @@ -3,20 +3,29 @@ -# the COPYRIGHT file. .container-fluid - .row-fluid + .row %h1= t("_statistics") - = render "statistic", name: t("statistics.name"), value: @statistics.name, activated: "serv-enabled" - = render "statistic", name: t("statistics.version"), value: @statistics.version, activated: "serv-enabled" - = render "statistic", name: t("statistics.registrations"), value: registrations_status(@statistics), activated: registrations_status_class(@statistics) + .col-md-3 + = render "statistic", name: t("statistics.name"), value: @statistics.name, activated: "serv-enabled" + .col-md-3 + = render "statistic", name: t("statistics.version"), value: @statistics.version, activated: "serv-enabled" + .col-md-3 + = render "statistic", name: t("statistics.registrations"), value: registrations_status(@statistics), activated: registrations_status_class(@statistics) - if @statistics.expose_user_counts? - = render "statistic", name: t("statistics.total_users"), value: @statistics.total_users, activated: "serv-enabled" - = render "statistic", name: t("statistics.active_users_halfyear"), value: @statistics.halfyear_users, activated: "serv-enabled" - = render "statistic", name: t("statistics.active_users_monthly"), value: @statistics.monthly_users, activated: "serv-enabled" + .col-md-3 + = render "statistic", name: t("statistics.total_users"), value: @statistics.total_users, activated: "serv-enabled" + .col-md-3 + = render "statistic", name: t("statistics.active_users_halfyear"), value: @statistics.halfyear_users, activated: "serv-enabled" + .col-md-3 + = render "statistic", name: t("statistics.active_users_monthly"), value: @statistics.monthly_users, activated: "serv-enabled" - if @statistics.expose_posts_counts? - = render "statistic", name: t("statistics.local_posts"), value: @statistics.local_posts, activated: "serv-enabled" + .col-md-3 + = render "statistic", name: t("statistics.local_posts"), value: @statistics.local_posts, activated: "serv-enabled" - if @statistics.expose_comment_counts? - = render "statistic", name: t("statistics.local_comments"), value: @statistics.local_comments, activated: "serv-enabled" - .row-fluid + .col-md-3 + = render "statistic", name: t("statistics.local_comments"), value: @statistics.local_comments, activated: "serv-enabled" + .row %h1= t("statistics.services") - Configuration::KNOWN_SERVICES.each do |service| - = render "statistic", name: "#{service.capitalize}", value: service_status(service, @statistics.available_services), activated: service_class(service, @statistics.available_services) + .col-md-3 + = render "statistic", name: "#{service.capitalize}", value: service_status(service, @statistics.available_services), activated: service_class(service, @statistics.available_services) diff --git a/app/views/notifications/_notification.haml b/app/views/notifications/_notification.haml index 651c2291b1a2e98e6d76c3caa15a90b595ff5150..0302216467e2d718d6b5c6b0f5219ca49f02c9b5 100644 --- a/app/views/notifications/_notification.haml +++ b/app/views/notifications/_notification.haml @@ -1,9 +1,11 @@ .media.stream_element{:data=>{:guid => note.id, :type => (Notification.types.key(note.type) || '') }, :class => (note.unread ? 'unread' : 'read')} .unread-toggle.pull-right - %i.entypo.eye{ :title => (note.unread ? t('notifications.index.mark_read') : t('notifications.index.mark_unread')) } - - if note.type == "Notifications::StartedSharing" && contact = current_user.contact_for(note.effective_target) - .pull-right - = aspect_membership_dropdown(contact, note.effective_target, 'left') + %i.entypo-eye{title: (note.unread ? t("notifications.index.mark_read") : t("notifications.index.mark_unread"))} + - if note.type == "Notifications::StartedSharing" && (!defined?(no_aspect_dropdown) || !no_aspect_dropdown) + - if note.target.present? + - gon_load_contact(note.contact) + .pull-right + .aspect_membership_dropdown.placeholder{data: {person_id: note.target.id}} .media-object.pull-left = person_image_link note.actors.first, :size => :thumb_small, :class => 'hovercardable' diff --git a/app/views/notifications/_notification.mobile.haml b/app/views/notifications/_notification.mobile.haml index 5c18ed6cd5820527defc9449fb824ed363d5db05..2b88255056b65b9b04b4fc256912956f15309c0d 100644 --- a/app/views/notifications/_notification.mobile.haml +++ b/app/views/notifications/_notification.mobile.haml @@ -1,6 +1,6 @@ .notification_element{:data=>{:guid => note.id, :type => (Notification.types.key(note.type) || '')}, :class => (note.unread ? "unread" : "read")} .pull-right.unread-toggle - %i.entypo.eye{ :title => (note.unread ? t('notifications.index.mark_read') : t('notifications.index.mark_unread')) } + %i.entypo-eye{title: (note.unread ? t("notifications.index.mark_read") : t("notifications.index.mark_unread"))} = person_image_tag note.actors.first, :thumb_small .notification_message = notification_message_for(note) diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml index 4d3d4cde0f58dfeb60cc735d93bffd69f6239cf0..fde543ffccc14fab2a2a2a974e090a4b9c702cd8 100644 --- a/app/views/notifications/index.html.haml +++ b/app/views/notifications/index.html.haml @@ -1,72 +1,76 @@ .container-fluid#notifications_container - .row-fluid - .span3 - %h3 - = t('.notifications') - %ul.nav.nav-tabs.nav-stacked - %li{ :class => ('active' unless params[:type] && @grouped_unread_notification_counts.has_key?(params[:type])) } - %a{ :href => '/notifications' + (params[:show] == 'unread' ? '?show=unread' : '') } - %span.pull-right.badge{:class => (@unread_notification_count > 0 ? 'badge-important' : 'badge-default')} + .row + .col-md-3 + .sidebar + .sidebar-header.clearfix + %h3 + = t(".notifications") + .list-group + %a.list-group-item{href: "/notifications" + (params[:show] == "unread" ? "?show=unread" : ""), + class: ("active" unless params[:type] && @grouped_unread_notification_counts.has_key?(params[:type]))} + %span.pull-right.badge{class: ("hidden" unless @unread_notification_count > 0)} = @unread_notification_count - = t('.all_notifications') - - @grouped_unread_notification_counts.each do |key, count| - %li{ :class => ('active' if params[:type] == key), :data => { :type => key } } - %a{ :href => '/notifications?type=' + key + (params[:show] == 'unread' ? '&show=unread' : '') } - %span.pull-right.badge{ :class => (count > 0 ? 'badge-important' :'badge-default') } + = t(".all_notifications") + - @grouped_unread_notification_counts.each do |key, count| + %a.list-group-item{class: ("active" if params[:type] == key), + data: {type: key}, + href: "/notifications?type=" + key + (params[:show] == "unread" ? "&show=unread" : "")} + %span.pull-right.badge{class: ("hidden" unless count > 0)} = count - case key - - when 'also_commented', 'comment_on_post' - %i.entypo.comment - - when 'liked' - %i.entypo.heart - - when 'mentioned' + - when "also_commented", "comment_on_post" + %i.entypo-comment + - when "liked" + %i.entypo-heart + - when "mentioned" %span.mentionIcon @ - - when 'reshared' - %i.entypo.retweet - - when 'started_sharing' - %i.entypo.add-user - = t('.'+key) + - when "reshared" + %i.entypo-reshare + - when "started_sharing" + %i.entypo-add-user + = t("." + key) - .span9.stream.notifications - .row-fluid.header - .span12 - .btn-toolbar.pull-right - .btn-group - %a.btn.btn-default{ :class => ('active' unless params[:show] == 'unread'), :href => '/notifications' + (params[:type] ? '?type=' + params[:type] : '') } - = t('.show_all') - %a.btn.btn-default{ :class => ('active' if params[:show] == 'unread'), :href => '/notifications?show=unread' + (params[:type] ? '&type=' + params[:type] : '') } - = t('.show_unread') - %a.btn.btn-default{:href => read_all_notifications_path(:type => params[:type] ), :class => ('disabled' unless @unread_notification_count > 0)} - -if params[:type] - = t('.mark_all_shown_as_read') - -else - = t('.mark_all_as_read') - - if @group_days.length > 0 - - year = nil - - @group_days.each do |date, notes| - - if display_year?(year, date) - - year = the_year(date) - .row-fluid.year_container - .span4.offset4.year= year + .col-md-9.stream.notifications + .framed-content + .row + .col-md-12 + .header.clearfix + .btn-toolbar.pull-right + .btn-group + %a.btn.btn-default{class: ("active" unless params[:show] == "unread"), + href: "/notifications" + (params[:type] ? "?type=" + params[:type] : "")} + = t(".show_all") + %a.btn.btn-default{class: ("active" if params[:show] == "unread"), + href: "/notifications?show=unread" + (params[:type] ? "&type=" + params[:type] : "")} + = t(".show_unread") + %a.btn.btn-default.btn-group{href: read_all_notifications_path(type: params[:type]), + class: ("disabled" unless @unread_notification_count > 0)} + - if params[:type] + = t(".mark_all_shown_as_read") + - else + = t(".mark_all_as_read") + - if @group_days.length > 0 + - year = nil + - @group_days.each do |date, notes| + - if display_year?(year, date) + - year = the_year(date) + .row.year_container + .col-md-4.col-md-offset-4.year= year - .day_group.row-fluid - .date.span2 - .day= the_day(date) - .month= the_month(date) + .day_group.row + .date.col-md-2 + .day= the_day(date) + .month= the_month(date) - .notifications_for_day.span10 - - notes.each do |note| - = render :partial => 'notifications/notification', :locals => { :note => note } + .notifications_for_day.col-md-10 + - notes.each do |note| + = render partial: "notifications/notification", locals: {note: note} - = will_paginate @notifications, :renderer => WillPaginate::ActionView::BootstrapLinkRenderer + .center-block.text-center + = will_paginate @notifications, renderer: WillPaginate::ActionView::BootstrapLinkRenderer - - else - .no_notifications.well - %h4 - = t('.no_notifications') - -:javascript - $(document).ready(function(){ - new app.views.Notifications({ el: '#notifications_container' }); - }); + - else + .no-notifications.well + %h4 + = t(".no_notifications") diff --git a/app/views/notifications/index.mobile.haml b/app/views/notifications/index.mobile.haml index 67e5426181fc236c1434bd74384708836852c64b..4d68b7911dddc55ca54c97e5ddb85d8361ca11c8 100644 --- a/app/views/notifications/index.mobile.haml +++ b/app/views/notifications/index.mobile.haml @@ -1,25 +1,28 @@ %h3 - = t('.notifications') + = t(".notifications") -.right +.pull-right -if params[:type] - = link_to t('.mark_all_shown_as_read'), read_all_notifications_path(:type => params[:type] ), :class => 'btn' + = link_to t(".mark_all_shown_as_read"), read_all_notifications_path(type: params[:type] ), class: "btn btn-default" -else - = link_to t('.mark_all_as_read'), read_all_notifications_path, :class => 'btn' + = link_to t(".mark_all_as_read"), read_all_notifications_path, class: "btn btn-default" %ul.notifications - @group_days.each do |date, notes| %li .notification_day_header - %span.label + %span.label.label-default = locale_date(date) %ul.notifications_for_day - notes.each do |note| - .stream_element{:data=>{:guid => note.id}, :class => "#{note.unread ? 'unread' : 'read'}"} + .stream_element{data: {guid: note.id}, class: "#{note.unread ? "unread" : "read"}"} .content.from - =person_image_link(note.actors.last) - = notification_message_for(note) - .time_notif - = timeago(note.created_at) + .media + .media-left + = person_image_link(note.actors.last, size: :thumb_small, class: "media-object") + .media-body + = notification_message_for(note) + .time_notif + = timeago(note.created_at) = will_paginate @notifications, previous_label: "«", diff --git a/app/views/people/_add_contact.haml b/app/views/people/_add_contact.haml index 13e1184bb0ec76622049c5c136964872cd05467a..5180ee22a710f4aa5b8437c5645056ab57d6ec81 100644 --- a/app/views/people/_add_contact.haml +++ b/app/views/people/_add_contact.haml @@ -1,8 +1,10 @@ .well - = t('.invited_by') + %strong + = t(".invited_by") .media .pull-right - = aspect_membership_dropdown(contact, inviter, false) - = person_image_link(inviter, :size => :thumb_small, :class => 'img') - .bd - = person_link(inviter) + = render partial: "aspect_memberships/aspect_membership_dropdown" + .media-left + = person_image_link(@person, size: :thumb_small, class: "media-object") + .media-body + = person_link(@person) diff --git a/app/views/people/_aspect_membership_dropdown.haml b/app/views/people/_aspect_membership_dropdown.haml deleted file mode 100644 index a66b4c54e38582817c3670caa51219d7e2e6b588..0000000000000000000000000000000000000000 --- a/app/views/people/_aspect_membership_dropdown.haml +++ /dev/null @@ -1 +0,0 @@ -= aspect_membership_dropdown(@contact, @person, 'right', nil, size) diff --git a/app/views/people/_person.html.haml b/app/views/people/_person.html.haml index 15f4ca690b54c60cab601ae43899467878b0ac20..48e543d2dace8c50b2f103279a46be0b40c44c06 100644 --- a/app/views/people/_person.html.haml +++ b/app/views/people/_person.html.haml @@ -1,13 +1,14 @@ -.media.stream_element{:id => person.id} +.media.stream_element{id: person.id} .pull-right - = render :partial => 'people/relationship_action', - :locals => { :person => person, :contact => contact, + = render partial: 'people/relationship_action', + locals: { person: person, :current_user => current_user } .media-object.pull-left - = person_image_link(person) + = person_image_link(person, size: :thumb_small) .media-body = person_link(person) .info.diaspora_handle = person.diaspora_handle .info.tags = Diaspora::Taggable.format_tags(person.profile.tag_string) + .clearfix diff --git a/app/views/people/_person.mobile.haml b/app/views/people/_person.mobile.haml index 806dd2c2dcfc925bcfea5a6468fbec8cc40ebfe1..ace474342c581c6b0d914e5702cb0d4f252b0df3 100644 --- a/app/views/people/_person.mobile.haml +++ b/app/views/people/_person.mobile.haml @@ -2,12 +2,13 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.stream_element{:id => person.id} - +.stream_element{id: person.id} .content - =person_image_link(person) - %span.from - =person_link(person) - - .info - = link_to person.diaspora_handle, local_or_remote_person_path(person), :class => 'black' + .media + .media-left + = person_image_link(person, size: :thumb_small, class: "media-object") + .media-body + %span.from + = person_link(person, size: :thumb_small) + .info + = link_to person.diaspora_handle, local_or_remote_person_path(person), class: "black" diff --git a/app/views/people/_relationship_action.haml b/app/views/people/_relationship_action.haml index b4ab1df04d414015335d6b97f3b9a6605ef722c6..01593dec7f98e715dfe873bcef4ed5a2c6aeacd7 100644 --- a/app/views/people/_relationship_action.haml +++ b/app/views/people/_relationship_action.haml @@ -1,7 +1,5 @@ - unless person == current_user.person - - contact = current_user.contacts.find_by_person_id(person.id) - - contact ||= Contact.new(:person => person) - = aspect_membership_dropdown(contact, person, 'right') + .aspect_membership_dropdown.placeholder{data: {person_id: person.id}} -else %span.thats_you - = t('people.person.thats_you') + = t("people.person.thats_you") diff --git a/app/views/people/contacts.haml b/app/views/people/contacts.haml index 4046fdb47525101043d783f05ec224cd21d651da..34da8821502dfc7e67d89f03fc4ca425d2ce365c 100644 --- a/app/views/people/contacts.haml +++ b/app/views/people/contacts.haml @@ -1,41 +1,34 @@ --# TODO this should happen in the js app -- content_for :head do - - if user_signed_in? && @person != current_user.person - :javascript - Mentions.options.prefillMention = Mentions._contactToMention(#{j @person.to_json}); - - content_for :page_title do = @person.name .container-fluid#profile_container - .row-fluid - .span3 + .row + .col-md-3 #profile -# here be JS - .span9 + .col-md-9 .profile_header -# more JS .stream_container #people_stream.stream - @hashes.each do |hash| - = render :partial => 'people/person', :locals => hash - = will_paginate @contacts_of_contact, :renderer => WillPaginate::ActionView::BootstrapLinkRenderer + = render partial: 'people/person', locals: hash + = will_paginate @contacts_of_contact, renderer: WillPaginate::ActionView::BootstrapLinkRenderer - %a{:id=>"back-to-top", :title=>"#{t('layouts.application.back_to_top')}", :href=>"#"} - ⇧ + %a.entypo-chevron-up.back-to-top#back-to-top{title: "#{t('layouts.application.back_to_top')}", href: "#"} -if user_signed_in? && @person #new_status_message_pane = render 'shared/modal', - :path => new_status_message_path(:person_id => @person.id), - :title => t('status_messages.new.mentioning', :person => @person.name), - :id => 'mentionModal' + path: new_status_message_path(:person_id => @person.id), + title: t('status_messages.new.mentioning', person: @person.name), + id: 'mentionModal' -if @contact #new_conversation_pane = render 'shared/modal', - :path => new_conversation_path(:contact_id => @contact.id, :name => @contact.person.name, :modal => true), - :title => t('conversations.index.new_conversation'), - :id => 'conversationModal' + path: new_conversation_path(:contact_id => @contact.id, name: @contact.person.name, modal: true), + title: t('conversations.index.new_conversation'), + id: 'conversationModal' diff --git a/app/views/people/index.html.haml b/app/views/people/index.html.haml index a4a90ee7c333bddbdb22fed97059fae08fe31a85..5dd55ddbf707b46113f12a5d3e9619c9495ed4a2 100644 --- a/app/views/people/index.html.haml +++ b/app/views/people/index.html.haml @@ -8,12 +8,12 @@ - content_for :head do = javascript_include_tag 'contact-list' -.container-fluid#people_search - .row-fluid +.container#people_search + .row .page-header = search_header - .row-fluid - .span8 + .row + .col-md-8 #people_stream.stream - if @hashes.empty? - if @background_query.present? @@ -25,21 +25,21 @@ } ); %p - = t('.searching') - = image_tag('static-loader.png', :class => 'loader') + = t(".searching") + .loader + .spinner - else %p = t('.no_one_found') - else - for hash in @hashes - = render :partial => 'people/person', :locals => hash + = render partial: 'people/person', locals: hash - = will_paginate(@people) + = will_paginate @people, renderer: WillPaginate::ActionView::BootstrapLinkRenderer - %a{:id=>"back-to-top", :title=>"#{t('layouts.application.back_to_top')}", :href=>"#"} - ⇧ + %a.entypo-chevron-up.back-to-top#back-to-top{title: "#{t('layouts.application.back_to_top')}", href: "#"} - .span4 + .col-md-4 - if AppConfig.settings.invitations.open? %h4 = t('.couldnt_find_them') diff --git a/app/views/people/show.html.haml b/app/views/people/show.html.haml index 3c5c9836c5e9ceea42b4f17072d62e132d5c3ba9..f1fe794ca805983a28cd91121c6e010adc9309c0 100644 --- a/app/views/people/show.html.haml +++ b/app/views/people/show.html.haml @@ -2,22 +2,19 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. --# TODO this should happen in the js app -- content_for :head do - - if user_signed_in? && @person != current_user.person - :javascript - Mentions.options.prefillMention = Mentions._contactToMention(#{j @person.to_json}); - - content_for :page_title do - = @person.name + = @presenter.name + +- content_for :meta_data do + = metas_tags @presenter.metas_attributes .container-fluid#profile_container - .row-fluid - .span3 - #profile + .row + .col-md-3 + .sidebar.profile-sidebar#profile -# here be JS - .span9 + .col-md-9 .profile_header -# more JS @@ -26,25 +23,25 @@ - if user_signed_in? && current_user.person.id == @person.id && !current_page?(person_photos_path(@person)) = render 'publisher/publisher', publisher_aspects_for(nil) - #main_stream.stream + .stream.clearfix#main_stream -# JS #paginate %span.loader.hidden + .spinner - %a{:id=>"back-to-top", :title=>"#{t('layouts.application.back_to_top')}", :href=>"#"} - ⇧ + %a.entypo-chevron-up.back-to-top#back-to-top{title: "#{t('layouts.application.back_to_top')}", href: "#"} -if user_signed_in? && @person #new_status_message_pane = render 'shared/modal', - :path => new_status_message_path(:person_id => @person.id), - :title => t('status_messages.new.mentioning', :person => @person.name), - :id => 'mentionModal' + path: new_status_message_path(:person_id => @person.id), + title: t('status_messages.new.mentioning', person: @person.name), + id: 'mentionModal' -if @contact #new_conversation_pane = render 'shared/modal', - :path => new_conversation_path(:contact_id => @contact.id, :name => @contact.person.name, :modal => true), - :title => t('conversations.index.new_conversation'), - :id => 'conversationModal' + path: new_conversation_path(:contact_id => @contact.id, name: @contact.person.name, modal: true), + title: t('conversations.index.new_conversation'), + id: 'conversationModal' diff --git a/app/views/people/show.mobile.haml b/app/views/people/show.mobile.haml index 426fe088669289f120b9e1e7d6ca23784c3cd284..29120725b30c094b97532a3034172ff56c288398 100644 --- a/app/views/people/show.mobile.haml +++ b/app/views/people/show.mobile.haml @@ -2,33 +2,28 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.span12 - #author_info - = person_image_tag @person, :thumb_medium - .content - %h2 - = @person.name - %span.description - = @person.diaspora_handle - - if user_signed_in? && @person != current_user.person - = render 'aspect_memberships/aspect_membership_dropdown' - .clear - .bottom_bar - - if !@person.tag_string.blank? && user_signed_in? - = Diaspora::Taggable.format_tags(@person.tag_string) +#author_info.header-full-width + = person_image_tag @person, :thumb_medium + .content + %h2 + = @person.name + %span.description + = @person.diaspora_handle + - if user_signed_in? && @person != current_user.person + = render 'aspect_memberships/aspect_membership_dropdown' + .clear + .bottom-bar + - if !@person.tag_string.blank? && user_signed_in? + = Diaspora::Taggable.format_tags(@person.tag_string) -.span12.profile_stream - - if @post_type == :photos - = render "photos/index", photos: @posts - - else +- if @post_type == :photos + = render "photos/index", photos: @posts +- else + .stream#main_stream - if @stream.stream_posts.length > 0 - #main_stream.stream - = render "shared/stream", posts: @stream.stream_posts - = render "shared/stream_more_button" + = render "shared/stream", posts: @stream.stream_posts + = render "shared/stream_more_button" - else - #main_stream - .dull - - if @block.present? - = t(".ignoring", name: @person.first_name) - - elsif user_signed_in? && (current_user.person != @person) - = t(".has_not_shared_with_you_yet", name: @person.first_name) + .dull + - if user_signed_in? && (current_user.person != @person) + = t(".has_not_shared_with_you_yet", name: @person.first_name) diff --git a/app/views/people/tag_index.js.erb b/app/views/people/tag_index.js.erb deleted file mode 100644 index c30450e3ead782375f44f0e47f33b95f96720b48..0000000000000000000000000000000000000000 --- a/app/views/people/tag_index.js.erb +++ /dev/null @@ -1 +0,0 @@ -$("#people_stream").html("<%= escape_javascript(render("index", :people => @people)) %>"); diff --git a/app/views/photos/_index.mobile.haml b/app/views/photos/_index.mobile.haml index c28e76c7d087b6ad5b9e5b9aa1d8801f333f91fc..0ab13e289daa9609b0e0b745a3685b954d4d73f1 100644 --- a/app/views/photos/_index.mobile.haml +++ b/app/views/photos/_index.mobile.haml @@ -2,7 +2,6 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -#thumbnails.span-15.last +#main_stream - for photo in photos - = link_to (image_tag photo.url(:thumb_large), "data-message-guid" => photo.status_message_guid ), person_photo_path(photo.author, photo) + = link_to image_tag(photo.url(:thumb_large)), person_photo_path(photo.author, photo), class: "thumbnail" diff --git a/app/views/photos/_new_profile_photo.haml b/app/views/photos/_new_profile_photo.haml index af526be04123a8e09535f7d93045bd54ed37b8e3..585028add4032b2c05483c9654547e459749cc50 100644 --- a/app/views/photos/_new_profile_photo.haml +++ b/app/views/photos/_new_profile_photo.haml @@ -29,23 +29,24 @@ $('#file-upload').addClass("loading"); $("#profile_photo_upload").find(".avatar").addClass('loading'); $("#file-upload-spinner").removeClass("hidden"); + $("#fileInfo").show(); }, onComplete: function(id, fileName, responseJSON){ $("#file-upload-spinner").addClass("hidden"); - $('#fileInfo').text(fileName + ' completed').fadeOut(2000); + $("#fileInfo").text(Diaspora.I18n.t("photo_uploader.completed", {"file": fileName})); $('#file-upload').removeClass("loading"); /* flash message prompt */ var message = Diaspora.I18n.t("photo_uploader.looking_good"); - Diaspora.page.flashMessages.render({success: true, notice: message}); + if(app.flashMessages) { app.flashMessages.success(message); } var id = responseJSON.data.photo.id; var url = responseJSON.data.photo.unprocessed_image.url; var oldPhoto = $('#photo_id'); if(oldPhoto.length == 0) { $('#update_profile_form').prepend("<input type='hidden' value='" + id + "' id='photo_id' name='photo_id'/>"); - }else{ + } else { oldPhoto.val(id); } @@ -57,17 +58,15 @@ } window.onload = createUploader; -#profile_photo_upload +.profile-photo-upload#profile_photo_upload = owner_image_tag(:thumb_large) - + .small-horizontal-spacer .clearfix - - #file-upload.btn - =t('.upload') + .text-center + #file-upload.btn.btn-primary + =t('.upload') = image_tag('mobile-spinner.gif', :class => 'hidden', :style => "z-index:-1", :id => 'file-upload-spinner') %p #fileInfo - - #publisher_photo_upload diff --git a/app/views/photos/_new_profile_photo.mobile.haml b/app/views/photos/_new_profile_photo.mobile.haml deleted file mode 100644 index 5677f4ed55f4f20d25fc34210f5b1d5cf8dfad52..0000000000000000000000000000000000000000 --- a/app/views/photos/_new_profile_photo.mobile.haml +++ /dev/null @@ -1,54 +0,0 @@ --# Copyright (c) 2010-2011, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - -- content_for :head do - :javascript - function createUploader(){ - var uploader = new qq.FileUploaderBasic({ - element: document.getElementById('file-upload'), - params: {'photo' : {'pending' : true, 'aspect_ids' : "all", 'set_profile_photo': true}}, - allowedExtensions: ['jpg', 'jpeg', 'png'], - action: "#{photos_path}", - button: document.getElementById('file-upload'), - sizeLimit: 4194304, - - onProgress: function(id, fileName, loaded, total){ - var progress = Math.round(loaded / total * 100 ); - $('#fileInfo').text(fileName + ' ' + progress + '%'); - }, - - messages: { - typeError: "#{t('photos.new_photo.invalid_ext')}", - sizeError: "#{t('photos.new_photo.size_error')}", - emptyError: "#{t('photos.new_photo.empty')}" - }, - - onSubmit: function(id, fileName){ - $('#file-upload').addClass("loading"); - $("#profile_photo_upload").find(".avatar").addClass('loading'); - $("#file-upload-spinner").removeClass("hidden"); - }, - - onComplete: function(id, fileName, result){ - $("#file-upload-spinner").addClass("hidden"); - $('#fileInfo').text(fileName + ' completed').fadeOut(2000); - $('#file-upload').removeClass("loading"); - location.reload(); - } - }); - } - window.onload = createUploader; - -#profile_photo_upload - = owner_image_tag(:thumb_medium) - - #file-upload.button - =t('.upload') - - = image_tag('mobile-spinner.gif', :class => 'hidden', :style => "z-index:-1", :id => 'file-upload-spinner') - - %p - #fileInfo - - #publisher_photo_upload diff --git a/app/views/photos/_photo.haml b/app/views/photos/_photo.haml deleted file mode 100644 index e80287c5305417582de01e88720e16ad5b0cf0dc..0000000000000000000000000000000000000000 --- a/app/views/photos/_photo.haml +++ /dev/null @@ -1,14 +0,0 @@ --# Copyright (c) 2010-2011, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - -= link_to (image_tag post.url(:thumb_large)), person_photo_path(post.author, post), :class => 'stream_photo' - -%h1 - = post.pending - -%p.photo_description - = post.text - -= link_to t('.view_all', :name => post.author_name), person_photos_path(post.author), :class => "small_text" - diff --git a/app/views/photos/edit.html.haml b/app/views/photos/edit.html.haml deleted file mode 100644 index bb78ea0f896cd2463c01c26c482b3d89c179f48c..0000000000000000000000000000000000000000 --- a/app/views/photos/edit.html.haml +++ /dev/null @@ -1,15 +0,0 @@ --# Copyright (c) 2010-2011, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - -%h2= "#{t('.editing')} #{@photo.processed_image}" - -%div{:id => @photo.id} - #show_photo - = image_tag @photo.url(:scaled_full) - - = form_for @photo do |photo| - = photo.label :text - = photo.text_field :text, :value => @photo.text - = photo.submit - diff --git a/app/views/photos/show.mobile.haml b/app/views/photos/show.mobile.haml index 4b5c3a3eaf9784b4d08cde4fe984a06913f719ed..9428f9ec331da872622cff70e955fe509d3619bd 100644 --- a/app/views/photos/show.mobile.haml +++ b/app/views/photos/show.mobile.haml @@ -10,22 +10,25 @@ = image_tag photo.url(:scaled_full) .stream_element{:class => "photo_mobile"} .content - .from - = person_image_link(photo.author, :size => :thumb_small) - = person_link(photo.author) - .info - %span - = link_to(post_path(photo)) do - = timeago(photo.created_at) + .from.media + .media-left + = person_image_link(photo.author, class: "media-object", size: :thumb_small) + .media-body + = person_link(photo.author) + .info + %span + = link_to(post_path(photo)) do + = timeago(photo.created_at) -if additional_photos && additional_photos.length > 1 #photo_controls - %table - %tr - %td - - if previous_photo != additional_photos.last - = link_to(image_tag("mobile/arrow-left.png", id: "arrow-left"), person_photo_path(previous_photo.author, previous_photo), rel: "prefetch", class: "arrow", id: "left") - %td{:width => '100%'} - %td - - if next_photo == additional_photos[additional_photos.index(photo)+1] - = link_to(image_tag("mobile/arrow-right.png", id: "arrow-right"), person_photo_path(next_photo.author, next_photo), rel: "prefetch", class: "arrow", id: "right") + - if previous_photo != additional_photos.last + = link_to(content_tag(:i, nil, id: "arrow-left", class: "entypo-chevron-left"), + person_photo_path(previous_photo.author, previous_photo), + rel: "prefetch", + class: "arrow left") + - if next_photo == additional_photos[additional_photos.index(photo)+1] + = link_to(content_tag(:i, nil, id: "arrow-right", class: "entypo-chevron-right"), + person_photo_path(next_photo.author, next_photo), + rel: "prefetch", + class: "arrow right") diff --git a/app/views/posts/_photo.html.haml b/app/views/posts/_photo.html.haml index 9ee149c97578580b9ccec2abdee875d38578a885..8518320204907040fc5572c109c5c57dab89b4e6 100644 --- a/app/views/posts/_photo.html.haml +++ b/app/views/posts/_photo.html.haml @@ -6,7 +6,7 @@ = javascript_include_tag :photos #author_info - = person_image_link(post.author) + = person_image_link(post.author, :size => :thumb_small) .from %h2 = post.author_name diff --git a/app/views/posts/destroy.js.erb b/app/views/posts/destroy.js.erb deleted file mode 100644 index 5a0c3dd8320e7cd5d111721a26c7fd7cbb415879..0000000000000000000000000000000000000000 --- a/app/views/posts/destroy.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -var target = $("#<%= @post.guid %>") -target.hide('blind', { direction: 'vertical' }, 300, function(){ target.remove() }); diff --git a/app/views/posts/show.html.haml b/app/views/posts/show.html.haml index 6b09af4df97b2decaf688237c55572fc77b8682f..56a2f9c2f72145dd96833fe5188c286d7cbae5eb 100644 --- a/app/views/posts/show.html.haml +++ b/app/views/posts/show.html.haml @@ -3,7 +3,10 @@ -# the COPYRIGHT file. - content_for :page_title do - = post_page_title @post + = post.page_title + +- content_for :meta_data do + = metas_tags post.metas_attributes - content_for :content do #container.container-fluid diff --git a/app/views/posts/show.mobile.haml b/app/views/posts/show.mobile.haml index 63bf093765e1b3aea25a0307cdf774e546a90e65..61d8556e811ebee79d089869ccb8f6590d5d3aad 100644 --- a/app/views/posts/show.mobile.haml +++ b/app/views/posts/show.mobile.haml @@ -3,6 +3,6 @@ -# the COPYRIGHT file. .stream - = render :partial => 'shared/stream_element', - :locals => {:post => @post, :commenting_disabled => commenting_disabled?(@post), :expanded_info => true} + = render partial: "shared/stream_element", + locals: {post: post, commenting_disabled: commenting_disabled?(post), expanded_info: true} diff --git a/app/views/profiles/_edit.haml b/app/views/profiles/_edit.haml deleted file mode 100644 index 6c1f63dce302b208492c57441821fbca86efca93..0000000000000000000000000000000000000000 --- a/app/views/profiles/_edit.haml +++ /dev/null @@ -1,69 +0,0 @@ --# Copyright (c) 2010-2011, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - -- content_for :page_title do - = t('.edit_profile') - -= form_tag profile_path, :method => :put, :multipart => true, :id => 'update_profile_form' do - = render 'profiles/edit_public', :profile => profile, :aspect => aspect, :person => person - - %hr - - %h3 - = t('profiles.edit.your_private_profile') - - %h4 - = t('profiles.edit.your_bio') - = text_area_tag 'profile[bio]', profile.bio, :rows => 5, :placeholder => t('fill_me_out'), :class => 'span12' - - .small-horizontal-spacer - - %h4 - = t('profiles.edit.your_location') - = text_field_tag 'profile[location]', profile.location, :placeholder => t('fill_me_out'), :class => 'span12' - - .small-horizontal-spacer - - %h4 - = t('profiles.edit.your_gender') - = text_field_tag 'profile[gender]', profile.gender, :placeholder => t("fill_me_out"), :class => 'span12' - - .small-horizontal-spacer - - %h4 - = t('profiles.edit.your_birthday') - - .row-fluid - = select_date profile.birthday, { :prompt => true, :default => true, :order => t('date.order'), :start_year => upper_limit_date_of_birth, :end_year => lower_limit_date_of_birth, :prefix => 'profile[date]' }, { :class => 'span4' } - - .small-horizontal-spacer - - %h4 - = t('search') - - .well.enclosed-checkbox - = label_tag 'profile[searchable]', :class => "checkbox" do - = check_box_tag 'profile[searchable]', true, profile.searchable - = t('profiles.edit.allow_search') - - .small-horizontal-spacer - - %h4 - = t('nsfw') - %p - = t('profiles.edit.nsfw_explanation') - .well.enclosed-checkbox - = label_tag 'profile[nsfw]', :class => "checkbox" do - = check_box_tag 'profile[nsfw]', true, profile.nsfw? - = t('profiles.edit.nsfw_check') - - .small-horizontal-spacer - - = t('profiles.edit.nsfw_explanation2') - - .small-horizontal-spacer - - .submit_block - =yield(:submit_block) - diff --git a/app/views/profiles/_edit.mobile.haml b/app/views/profiles/_edit.mobile.haml deleted file mode 100644 index b4a5badbd6c4bdcc5158224809626242786086d2..0000000000000000000000000000000000000000 --- a/app/views/profiles/_edit.mobile.haml +++ /dev/null @@ -1,57 +0,0 @@ --# Copyright (c) 2010-2011, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - -- content_for :page_title do - = t('.edit_profile') - -= form_tag profile_path, :method => :put, :multipart => true, :id => 'update_profile_form' do - = render 'profiles/edit_public', :profile => profile, :aspect => aspect, :person => person - - %hr - %h4 - = t('profiles.edit.your_private_profile') - - - %h4 - = t('profiles.edit.your_bio') - = text_area_tag 'profile[bio]', profile.bio, :rows => 5, :placeholder => t('fill_me_out') - - %h4 - = t('profiles.edit.your_location') - = text_field_tag 'profile[location]', profile.location, :placeholder => t('fill_me_out') - - - %br - - %h4 - = t('profiles.edit.your_gender') - = text_field_tag 'profile[gender]', profile.gender, :placeholder => t("fill_me_out") - - %br - - %h4 - = t('profiles.edit.your_birthday') - = select_date profile.birthday, :prompt => true, - :default => true, :order => t('date.order'), :start_year => 2000, :end_year => 1930, :prefix => 'profile[date]' - - %h4 - = t('search') - - %p{:class=>"checkbox_select"} - = label_tag 'profile[searchable]', t('profiles.edit.allow_search') - = check_box_tag 'profile[searchable]', true, profile.searchable - %br - - %h4 - = t('nsfw') - = t('profiles.edit.nsfw_explanation') - %p{:class=>"checkbox_select"} - = check_box_tag 'profile[nsfw]', true, profile.nsfw - = label_tag 'profile[nsfw]', t('profiles.edit.nsfw_check') - = t('profiles.edit.nsfw_explanation2') - %br - %br - - .submit_block - =yield(:submit_block) diff --git a/app/views/profiles/_edit_private.haml b/app/views/profiles/_edit_private.haml new file mode 100644 index 0000000000000000000000000000000000000000..42e29375a14d814a8b267df5585bff3e94c1bfaf --- /dev/null +++ b/app/views/profiles/_edit_private.haml @@ -0,0 +1,69 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + +%hr +%h3.inline + = t("profiles.edit.extended") += t("profiles.edit.extended_visibility_text") += check_box_tag "profile[public_details]", true, profile.public_details, {"data-size" => "mini", "data-on-text" => t("profiles.edit.public"), "data-off-text" => t("profiles.edit.limited")} +%span.profile-visibility-hint{ title: t("profiles.edit.extended_hint") } + %i.entypo-circled-help.visibility-hint-icon +.small-horizontal-spacer + +%h4= t('profiles.edit.your_bio') + +.clearfix + = text_area_tag 'profile[bio]', profile.bio, rows: 5, placeholder: t('fill_me_out'), class: 'col-md-12 form-control' + +.small-horizontal-spacer +.row + .col-md-6 + %h4= t('profiles.edit.your_location') + = text_field_tag 'profile[location]', profile.location, placeholder: t('fill_me_out'), class: 'col-md-12 form-control' + .col-md-6 + %h4= t('profiles.edit.your_gender') + = text_field_tag 'profile[gender]', profile.gender, placeholder: t("fill_me_out"), class: 'col-md-12 form-control' + +.small-horizontal-spacer + +%h4= t('profiles.edit.your_birthday') + +#birth-date.form-inline + = select_date profile.birthday, { prompt: true, default: true, order: t('date.order'), + start_year: upper_limit_date_of_birth, end_year: lower_limit_date_of_birth, prefix: 'profile[date]' }, + { class: 'form-control'} + +.small-horizontal-spacer + +%hr +%h3.inline + = t('profiles.edit.settings') + +.small-horizontal-spacer + +%h4= t('search') + +.well.checkbox + = label_tag 'profile[searchable]', class: "checkbox-inline" do + = check_box_tag 'profile[searchable]', true, profile.searchable + = t('profiles.edit.allow_search') + +.small-horizontal-spacer + +%h4= t('nsfw') +%p + = t('profiles.edit.nsfw_explanation') +.well.checkbox + = label_tag 'profile[nsfw]', class: "checkbox-inline" do + = check_box_tag 'profile[nsfw]', true, profile.nsfw? + = t('profiles.edit.nsfw_check') + +.small-horizontal-spacer + += t('profiles.edit.nsfw_explanation2') + +.small-horizontal-spacer + +.submit_block.form-group + = yield(:submit_block) diff --git a/app/views/profiles/_edit_public.haml b/app/views/profiles/_edit_public.haml index 83e46ba8543e6c55d9e1b6e84ffbffd68604ebeb..c909ca841a06ca5e86b966904d286ada934bb376 100644 --- a/app/views/profiles/_edit_public.haml +++ b/app/views/profiles/_edit_public.haml @@ -1,4 +1,6 @@ - content_for :head do + - if mobile + = javascript_include_tag :jquery :javascript $(document).ready(function () { var data = $.parseJSON( '#{@tags_array.to_json.gsub("'", "\\\\'")}' ), @@ -19,7 +21,7 @@ }); autocompleteInput.bind('keydown', function(evt){ - if(evt.keyCode == 13 || evt.keyCode == 9 || evt.keyCode == 32){ + if(evt.which === Keycodes.ENTER || evt.which === Keycodes.TAB || evt.which === Keycodes.SPACE) { evt.preventDefault(); if( $('li.as-result-item.active').length == 0 ){ $('li.as-result-item').first().click(); @@ -28,34 +30,40 @@ }); }); -%h3 - = t('profiles.edit.your_public_profile') +- if mobile + .stream + - flash.each do |name, msg| + %div{:id => "flash_#{name}", :class => "expose"} + .message= msg + .stream + %p{:class => "conversation_#{name}"}= msg + +%h3.inline + = t("profiles.edit.basic") + %span{ :title => t("profiles.edit.basic_hint") } + %i.entypo.circled-help.visibility-hint-icon +.small-horizontal-spacer = error_messages_for profile -%h4 - = t('profiles.edit.your_name') +%h4= t('profiles.edit.your_name') -.row-fluid - .span6 +.row + .col-md-6 = label_tag 'profile[first_name]', t('profiles.edit.first_name') - = text_field_tag 'profile[first_name]', profile.first_name, :class => 'span12' - .span6 + = text_field_tag 'profile[first_name]', profile.first_name, class: 'form-control' + .col-md-6 = label_tag 'profile[last_name]', t('profiles.edit.last_name') - = text_field_tag 'profile[last_name]', profile.last_name, :class => 'span12' + = text_field_tag 'profile[last_name]', profile.last_name, class: 'form-control' .small-horizontal-spacer -%h4 - = t('profiles.edit.your_tags') +%h4= t('profiles.edit.your_tags') -= text_field_tag 'profile[tag_string]', "", :placeholder => t('profiles.edit.your_tags_placeholder') += text_field_tag 'profile[tag_string]', "", placeholder: t('profiles.edit.your_tags_placeholder'),class: "form-control" .small-horizontal-spacer -%h4 - = t('profiles.edit.your_photo') +%h4= t('profiles.edit.your_photo') -= render 'photos/new_profile_photo', :aspect => aspect, :person => person - -.small-horizontal-spacer += render 'photos/new_profile_photo', aspect: aspect, person: person diff --git a/app/views/profiles/_edit_public.mobile.haml b/app/views/profiles/_edit_public.mobile.haml deleted file mode 100644 index 186f429bf92fcce59fa3a371d3a1437ae47cda1e..0000000000000000000000000000000000000000 --- a/app/views/profiles/_edit_public.mobile.haml +++ /dev/null @@ -1,71 +0,0 @@ --# Copyright (c) 2010-2011, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - -- content_for :head do - = javascript_include_tag :jquery - - :javascript - $(document).ready(function () { - var data = $.parseJSON( '#{@tags_array.to_json.gsub("'", "\\\\'")}' ), - autocompleteInput = $("#profile_tag_string"); - - autocompleteInput.autoSuggest("#{tags_path}", { - selectedItemProp: "name", - selectedValuesProp: "name", - searchObjProps: "name", - asHtmlID: "tags", - neverSubmit: true, - retrieveLimit: 10, - minChars: 2, - keyDelay: 200, - startText: "", - emptyText: "#{t('no_results')}", - preFill: data - }); - - autocompleteInput.bind('keydown', function(evt){ - if(evt.keyCode == 13 || evt.keyCode == 9 || evt.keyCode == 32){ - evt.preventDefault(); - if( $('li.as-result-item.active').length == 0 ){ - $('li.as-result-item').first().click(); - } - } - }); - }); - -.stream - - flash.each do |name, msg| - %div{:id => "flash_#{name}", :class => "expose"} - .message= msg - .stream - %p{:class => "conversation_#{name}"}= msg - -%h4 - = t('profiles.edit.your_public_profile') - -= error_messages_for profile - -%h4 - = t('profiles.edit.your_name') -= label_tag 'profile[first_name]', t('profiles.edit.first_name') -= text_field_tag 'profile[first_name]', profile.first_name - -= label_tag 'profile[first_name]', t('profiles.edit.last_name') -= text_field_tag 'profile[last_name]', profile.last_name - -%br - -%h4 - = t('profiles.edit.your_tags') - -= text_field_tag 'profile[tag_string]', "", :placeholder => t('profiles.edit.your_tags_placeholder') - -%br - -%h4 - = t('profiles.edit.your_photo') - -= render 'photos/new_profile_photo', :aspect => aspect, :person => person - -%br diff --git a/app/views/profiles/edit.haml b/app/views/profiles/edit.haml index 4dc0bc84678f1bd9006bdd74398cc5154988458a..043cbfe88e0bc99a0e125451d5767df956706d41 100644 --- a/app/views/profiles/edit.haml +++ b/app/views/profiles/edit.haml @@ -2,21 +2,17 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.container - .row-fluid - .span12 - #section_header - %h2 - = t("settings") +.container-fluid + .row + .col-md-3 + .sidebar = render "shared/settings_nav" + .col-md-9 + .framed-content.clearfix + - content_for :submit_block do + = link_to t("cancel"), local_or_remote_person_path(current_user.person), class: "btn btn-default" + = submit_tag t(".update_profile"), class: "btn btn-primary pull-right", id: "update_profile" -.container - .row-fluid - .span3 - .span6 - - content_for :submit_block do - = link_to t("cancel"), local_or_remote_person_path(current_user.person), :class => "btn" - = submit_tag t(".update_profile"), class: "btn creation", id: "update_profile" - = render partial: "edit", locals: {person: @person, profile: @profile, aspect: @aspect, step: @step} - .span3 - + = form_tag profile_path, method: :put, multipart: true, id: "update_profile_form" do + = render "edit_public", profile: @profile, aspect: @aspect, person: @person, mobile: false + = render "edit_private", person: @person, profile: @profile, aspect: @aspect, step: @step diff --git a/app/views/profiles/edit.mobile.haml b/app/views/profiles/edit.mobile.haml index e0df905771afdbc3568cc020cde83815019b3453..333985f7ac6e8112a74b1ceef5cc01127792b369 100644 --- a/app/views/profiles/edit.mobile.haml +++ b/app/views/profiles/edit.mobile.haml @@ -2,15 +2,17 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. +.settings_container.container-fluid + .row + .col-md-12 + = render "shared/settings_nav" -#section_header - %h3 - = t('settings') - = render 'shared/settings_nav' + .row + .col-md-12 + - content_for :submit_block do + = link_to t("cancel"), local_or_remote_person_path(current_user.person), class: "btn btn-default" + = submit_tag t(".update_profile"), class: "btn btn-primary pull-right", id: "update_profile" -.span-12.prepend-5.last - - content_for :submit_block do - = link_to t('cancel'), local_or_remote_person_path(current_user.person), :class => "button" - = submit_tag t('.update_profile'), :class => "btn", :id => "update_profile" - = render :partial => 'edit', :locals => {:person => @person, - :profile => @profile, :aspect => @aspect, :step => @step} + = form_tag profile_path, method: :put, multipart: true, id: "update_profile_form" do + = render "edit_public", profile: @profile, aspect: @aspect, person: @person, mobile: true + = render "edit_private", person: @person, profile: @profile, aspect: @aspect, step: @step diff --git a/app/views/publisher/_aspect_dropdown.html.haml b/app/views/publisher/_aspect_dropdown.html.haml index 792a76e87e533f5218b560bdc0f268cbc4fb2f37..e97e50426e3d15a248f1441b0ebe1ddb9cd1bfcb 100644 --- a/app/views/publisher/_aspect_dropdown.html.haml +++ b/app/views/publisher/_aspect_dropdown.html.haml @@ -1,11 +1,11 @@ .btn-group.aspect_dropdown - %button.btn.btn-default.dropdown-toggle{ ! current_user.getting_started? ? {'data-toggle' => 'dropdown'} : {'data-toggle' => 'dropdown', :title => popover_with_close_html("2. #{t('shared.public_explain.control_your_audience')}"), 'data-content'=> t('shared.public_explain.visibility_dropdown')} } + %button.btn.btn-default.dropdown-toggle{ ! current_user.getting_started? ? {'data-toggle' => 'dropdown'} : {'data-toggle' => 'dropdown', title: popover_with_close_html("2. #{t('shared.public_explain.control_your_audience')}"), 'data-content'=> t('shared.public_explain.visibility_dropdown')} } - if publisher_public - %i#visibility-icon.entypo.small.globe + %i#visibility-icon.entypo-globe.small %span.text = t('public') - else - %i#visibility-icon.entypo.small.lock + %i#visibility-icon.entypo-lock.small %span.text - if all_aspects_selected?(selected_aspects) = t('all_aspects') @@ -14,25 +14,25 @@ - else = t('shared.aspect_dropdown.toggle', count: selected_aspects.size) %span.caret - %ul.dropdown-menu.pull-right{ :unSelectable => 'on' } + %ul.dropdown-menu.pull-right{ unSelectable: 'on' } - %li.public.radio{"data-aspect_id" => "public", :class => ("selected" if publisher_public)} + %li.public.radio{"data-aspect_id" => "public", class: ("selected" if publisher_public)} %a %span.status_indicator - %i.icon-ok + %i.glyphicon.glyphicon-ok %span.text = t('public') - %li.all_aspects.radio{"data-aspect_id" => "all_aspects", :class => ("selected" if (!publisher_public && all_aspects_selected?(selected_aspects)))} + %li.all_aspects.radio{"data-aspect_id" => "all_aspects", class: ("selected" if (!publisher_public && all_aspects_selected?(selected_aspects)))} %a %span.status_indicator - %i.icon-ok + %i.glyphicon.glyphicon-ok %span.text = t('all_aspects') %li.divider - for aspect in all_aspects - %li.aspect_selector{ 'data-aspect_id' => aspect.id, :class => !all_aspects_selected?(selected_aspects) && selected_aspects.include?(aspect) ? "selected" : "" } + %li.aspect_selector{ 'data-aspect_id' => aspect.id, class: !all_aspects_selected?(selected_aspects) && selected_aspects.include?(aspect) ? "selected" : "" } %a %span.status_indicator - %i.icon-ok + %i.glyphicon.glyphicon-ok %span.text = aspect.name diff --git a/app/views/publisher/_publisher.html.haml b/app/views/publisher/_publisher.html.haml index 64b4bb19432611ae32cbcfbaffa3d1dac16bbfa8..4d85b029049e6f5954ed435b3931bf09228a91db 100644 --- a/app/views/publisher/_publisher.html.haml +++ b/app/views/publisher/_publisher.html.haml @@ -4,77 +4,73 @@ if( app.publisher ) app.publisher.triggerGettingStarted(); }); -.row-fluid#publisher{:class => ((aspect == :profile || publisher_open) ? "mention_popup" : "closed")} +.row.publisher#publisher{class: ((aspect == :profile || publisher_open) ? "mention_popup" : "closed")} .content_creation = form_for(StatusMessage.new) do |status| = status.error_messages %params - #publisher_textarea_wrapper - - if current_user.getting_started? - = status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text), :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}...", - 'data-title' => popover_with_close_html( '1. ' + t('shared.public_explain.share') ), - 'data-content' => t('shared.public_explain.new_user_welcome_message') - - else - = status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text), :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}..." - = status.hidden_field :text, :value => h(publisher_hidden_text), :class => 'clear_on_submit' + .publisher-textarea-wrapper#publisher_textarea_wrapper + .mentions-input-box + .mentions-box + .mentions + - if current_user.getting_started? + = status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text), + :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}...", + "data-title" => popover_with_close_html("1. " + t("shared.public_explain.share")), + "data-content" => t("shared.public_explain.new_user_welcome_message"), + "class" => "form-control" + - else + = status.text_area :fake_text, :rows => 2, :value => h(publisher_formatted_text), + :tabindex => 1, :placeholder => "#{t('contacts.index.start_a_conversation')}...", + "class" => "form-control" + %input.typeahead-mention-box.hidden{type: "text"} + = status.hidden_field :text, value: h(publisher_hidden_text), class: "clear_on_submit" - .row-fluid#photodropzone_container + .container-fluid.photodropzone-container#photodropzone_container %ul#photodropzone - .row-fluid#location_container + .location-container.form-group{style: "padding: 4px 6px;"} = hidden_field :location, :coords - .row-fluid#poll_creator_container + .poll-creator-container#poll_creator_container -# handlebars template - .row-fluid#button_container - #publisher-images.pull-right - #poll_creator.btn.btn-link{:title => t('shared.publisher.poll.add_a_poll')} - %i.entypo.bar-graph - #file-upload.btn.btn-link{:title => t('shared.publisher.upload_photos')} - %i.entypo.camera.publisher_image - #locator.btn.btn-link{:title => t('shared.publisher.get_location')} - %i.entypo.location.publisher_image - #hide_location.btn.btn-link{:title => t('shared.publisher.remove_location')} - %i.entypo.cross.publisher_image - %span.help-block.markdownIndications - != t('shared.publisher.formatWithMarkdown', markdown_link: link_to(t('help.markdown'), 'https://diasporafoundation.org/formatting', target: :blank)) + #button_container + .publisher-buttonbar#publisher-images + .btn.btn-link.poll-creator#poll_creator{title: t("shared.publisher.poll.add_a_poll")} + %i.entypo-bar-graph + .btn.btn-link.file-upload#file-upload{title: t("shared.publisher.upload_photos")} + %i.entypo-camera.publisher_image + .btn.btn-link.locator#locator{title: t("shared.publisher.get_location")} + %i.entypo-location.publisher_image + .btn.btn-link.hide-location#hide_location{title: t("shared.publisher.remove_location")} + %i.entypo-cross.publisher_image + %span.markdownIndications + != t("shared.publisher.formatWithMarkdown", markdown_link: link_to(t("help.markdown"), + "https://diasporafoundation.org/formatting", target: :blank)) - if publisher_public - = hidden_field_tag 'aspect_ids[]', "public" + = hidden_field_tag "aspect_ids[]", "public" - elsif all_aspects_selected?(selected_aspects) - = hidden_field_tag 'aspect_ids[]', "all_aspects" + = hidden_field_tag "aspect_ids[]", "all_aspects" - else - for aspect_id in aspect_ids - = hidden_field_tag 'aspect_ids[]', aspect_id.to_s - - .row-fluid#publisher_spinner{:class => 'hidden'} - = image_tag 'ajax-loader.gif' - .row-fluid.options_and_submit - .public_toggle - .btn.btn-default.pull-left#hide_publisher{:title => t('shared.publisher.discard_post')} - %span.text - =t('cancel') + = hidden_field_tag "aspect_ids[]", aspect_id.to_s + .hidden#publisher_spinner + .loader + .spinner + .options_and_submit.col-sm-12 + .public_toggle.clearfix .btn-toolbar.pull-right - %span#publisher_service_icons - - if current_user.services - - for service in current_user.services - = service_button(service) - %a.btn.btn-link{ :href => "#question_mark_pane", :class => 'question_mark', :rel => 'facebox', :title => t('shared.public_explain.manage') } - %i.entypo.small.cog - - = render :partial => "publisher/aspect_dropdown", :locals => { :selected_aspects => selected_aspects } - - %button{:class => 'btn btn-default post_preview_button'} - %span.text - = t('shared.publisher.preview') - - %button#submit.btn.btn-primary.creation{:tabindex => 2} - %span.text - = t('shared.publisher.share') + = render partial: "publisher/aspect_dropdown", locals: {selected_aspects: selected_aspects} + %button.btn.btn-group.btn-primary#submit= t("shared.publisher.share") - .facebox_content - #question_mark_pane - = render 'shared/public_explain' - = link_to '', contacts_path(:aspect_ids => aspect_ids), :class => 'selected_contacts_link hidden' + .btn-toolbar.pull-right#publisher-service-icons + - if current_user.services + - current_user.services.each do |service| + = service_button(service) + .btn.btn-link.question_mark{title: t("shared.public_explain.manage"), + data: {toggle: "modal", target: "#publicExplainModal"}} + %i.entypo-cog + = link_to "", contacts_path(aspect_ids: aspect_ids), class: "selected_contacts_link hidden" - #publisher_photo_upload += render "shared/public_explain" diff --git a/app/views/publisher/_publisher.mobile.haml b/app/views/publisher/_publisher.mobile.haml index ea8355e023ffc0eac6ddf1edcfba8495a81d50bf..4399b7c13b69484d74d308a9cdc3e0367f804da0 100644 --- a/app/views/publisher/_publisher.mobile.haml +++ b/app/views/publisher/_publisher.mobile.haml @@ -2,25 +2,28 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -= form_for StatusMessage.new, {:data => {:ajax => false}} do |status| - = status.hidden_field :provider_display_name, :value => 'mobile' - = status.text_area :text, :placeholder => t('shared.publisher.whats_on_your_mind'), :rows => 4, :autofocus => "autofocus" += form_for StatusMessage.new, html: {class: "control-group", data: {ajax: false}} do |status| + .form-group + = status.hidden_field :provider_display_name, value: 'mobile' + = status.text_area :text, placeholder: t('shared.publisher.whats_on_your_mind'), rows: 4, autofocus: "autofocus", class: "form-control" - %fieldset - %span#publisher_service_icons + .form-group + %span#publisher-service-icons - if current_user.services - for service in current_user.services - = image_tag "social_media_logos/#{service.provider}-32x32.png", :title => service.provider.titleize, :class => "service_icon dim", :id =>"#{service.provider}", :maxchar => "#{service.class::MAX_CHARACTERS}" + = image_tag "social-media-logos/#{service.provider}-32x32.png", + title: service.provider.titleize, class: "service_icon dim", + id: "#{service.provider}", maxchar: "#{service.class::MAX_CHARACTERS}" - %select{:id => "aspect_ids_", :name => "aspect_ids[]"} - %option{:value => 'public'} + %select{id: "aspect_ids_", class: "form-control", name: "aspect_ids[]"} + %option{value: 'public'} = t('public') - %option{:value => 'all_aspects', :selected => true} + %option{value: 'all_aspects', selected: true} = t('all_aspects') - current_user.aspects.each do |aspect| - %option{:value => aspect.id} + %option{value: aspect.id} = "· #{aspect.name}" .clear @@ -28,12 +31,11 @@ %ul#photodropzone #fileInfo-publisher - #file-upload-publisher{:title => t('shared.publisher.upload_photos'), :class => 'btn'} - = image_tag "mobile/camera.png", alt: t("shared.publisher.upload_photos").titleize + #file-upload-publisher{title: t('shared.publisher.upload_photos'), class: 'btn btn-default'} + %i.entypo-camera.middle #publisher_mobile = submit_tag t("shared.publisher.share"), - class: "btn primary", + class: "btn btn-primary", id: "submit_new_message", data: {"disable-with" => t("shared.publisher.posting")} - - #publisher_photo_upload + .clearfix diff --git a/app/views/registrations/_form.haml b/app/views/registrations/_form.haml index f4a90429417ac1f352e64b1c508812bba935facf..56bbb04fbb6288eca298248c5a0f3f4a0d87414e 100644 --- a/app/views/registrations/_form.haml +++ b/app/views/registrations/_form.haml @@ -1,39 +1,81 @@ = form_for(resource, url: registration_path(resource_name), html: {class: "form-horizontal block-form", autocomplete: "off"}) do |f| %fieldset - %label - = f.label :user_email, t("registrations.new.email"), class: "control-label" - %i.entypo.mail + - if mobile + %legend + = image_tag("branding/logos/header-logo2x.png", height: 40, width: 40) + = t("aspects.aspect_stream.make_something") + + - if mobile + = f.label :email, t("registrations.new.email"), class: "control-label", id: "emailLabel" + - else + = f.label :email, t("registrations.new.email"), class: "sr-only control-label", id: "emailLabel" + %i.entypo-mail = f.email_field :email, - autofocus: true, - class: "input-block-level form-control", - data: {content: t("users.edit.your_email_private")}, - placeholder: t("registrations.new.email"), - required: true, - title: t("registrations.new.enter_email") - - %label.control-label{for: "user_username"} - = t('registrations.new.username') - %i.entypo.user - = f.text_field :username, class: "input-block-level form-control", placeholder: t('registrations.new.username'), title: t('registrations.new.enter_username'), required: true, pattern: "[A-Za-z0-9_]+" - - %label.control-label{for: "user_password"} - = t('registrations.new.password') - %i.entypo.lock - = f.password_field :password, class: "input-block-level form-control", placeholder: t('registrations.new.password'), title: t('registrations.new.enter_password'), required: true, pattern: "......+" - - %label.control-label{for: "user_password_confirmation"} - = t('registrations.new.password_confirmation') - %i.entypo.lock - = f.password_field :password_confirmation, class: "input-block-level form-control", placeholder: t('registrations.new.password_confirmation'), title: t('registrations.new.enter_password_again'), required: true, pattern: "......+" + autofocus: true, + class: "input-block-level form-control", + data: {content: t("users.edit.your_email_private")}, + placeholder: t("registrations.new.email"), + required: true, + title: t("registrations.new.enter_email"), + aria: {labelledby: "emailLabel"} + + - if mobile + %label.control-label#usernameLabel{for: "user_username"} + = t("registrations.new.username") + - else + %label.sr-only.control-label#usernameLabel{for: "user_username"} + = t("registrations.new.username") + %i.entypo-user + = f.text_field :username, + class: "input-block-level form-control", + placeholder: t("registrations.new.username"), + title: t("registrations.new.enter_username"), + required: true, + pattern: "[A-Za-z0-9_]+", + aria: {labelledby: "usernameLabel"} + + - if mobile + %label.control-label#passwordLabel{for: "user_password"} + = t("registrations.new.password") + - else + %label.sr-only.control-label#passwordLabel{for: "user_password"} + = t("registrations.new.password") + %i.entypo-lock + = f.password_field :password, + class: "input-block-level form-control", + placeholder: t("registrations.new.password"), + title: t("registrations.new.enter_password"), + required: true, + pattern: "......+", + aria: {labelledby: "passwordLabel"} + + - if mobile + %label.control-label#passwordConfirmationLabel{for: "user_password_confirmation"} + = t("registrations.new.password_confirmation") + - else + %label.sr-only.control-label#passwordConfirmationLabel{for: "user_password_confirmation"} + = t("registrations.new.password_confirmation") + %i.entypo-lock + = f.password_field :password_confirmation, + class: "input-block-level form-control", + placeholder: t("registrations.new.password_confirmation"), + title: t("registrations.new.enter_password_again"), + required: true, + pattern: "......+", + aria: {labelledby: "passwordConfirmationLabel"} - if AppConfig.settings.captcha.enable? - = show_simple_captcha :object => 'user', :code_type => 'numeric' + = show_simple_captcha object: "user", + code_type: "numeric", + class: "simple-captcha-image", + input_html: {class: "form-control captcha-input"} = invite_hidden_tag(invite) - if AppConfig.settings.terms.enable? - %p#terms.text-center + %p.terms.text-center#terms = t('registrations.new.terms', terms_link: link_to(t('registrations.new.terms_link'), terms_path, target: "_blank")).html_safe - = f.submit t('registrations.new.sign_up'), class: "btn btn-block btn-large", data: {disable_with: t('registrations.new.submitting')} + = f.submit t("registrations.new.sign_up"), class: "btn btn-block btn-large btn-primary", + data: {disable_with: t("registrations.new.submitting")} diff --git a/app/views/registrations/new.haml b/app/views/registrations/new.haml index 6164b1d468f700155fe6934a925f52662f8ddba6..96f9c27334fd8af2af621c5f838925af6f492ab5 100644 --- a/app/views/registrations/new.haml +++ b/app/views/registrations/new.haml @@ -1,12 +1,12 @@ #registration - .container-fluid - .row-fluid - .span10.offset1 - .span7.hidden-phone + .container + .row + .col-md-10.offset1 + .col-md-7.hidden-phone %h1.ball - .span5.v-center + .col-md-5.v-center .content.text-center %h2#pod-name = AppConfig.settings.pod_name - = render partial: 'form' + = render partial: "form", locals: {mobile: false} diff --git a/app/views/registrations/new.mobile.haml b/app/views/registrations/new.mobile.haml index 8be870e29380ee7b7de16a64fda205b96b8273d0..efec569c9d8b7c17ed37f57b4b507a758e35670c 100644 --- a/app/views/registrations/new.mobile.haml +++ b/app/views/registrations/new.mobile.haml @@ -2,55 +2,17 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -:css - div.navbar.navbar-fixed-top{ display:none;} - -.registrations -.stream +.stream#main_stream - flash.each do |name, msg| - %p{:class => "registrations_#{name}"}= msg - #flash_alert.expose - %div{:class => "message", :id => "session"}= msg + .expose#flash-container + .flash-message{class: "message alert alert-#{flash_class name}", role: "alert"} + = msg #login_form .login-container - = form_for(resource, :as => resource_name, :html => {:class => 'new_user_form'}, :url => registration_path(resource_name)) do |f| - %fieldset - %legend - = image_tag("branding/logos/header-logo2x.png", height: 40, width: 40) - = t('aspects.aspect_stream.make_something') - - .control-group - = f.label :username, t('username') - .controls - = f.text_field :username, :placeholder => "jedi_guy" - - .control-group - = f.label :email, t('email') - .controls - = f.text_field :email, :placeholder => "luke@hoth.net" - - .control-group - = f.label :password, t('password') - .controls - = f.password_field :password, :placeholder => "••••••••" - - .control-group - = f.label :password_confirmation, t('password_confirmation') - .controls - = f.password_field :password_confirmation, :placeholder => "••••••••" - - - if AppConfig.settings.captcha.enable? - = show_simple_captcha(:object => 'user', :code_type => 'numeric') - - = invite_hidden_tag(invite) - - - if AppConfig.settings.terms.enable? - = t('registrations.new.terms', terms_link: link_to(t('registrations.new.terms_link'), terms_path, target: "_blank")).html_safe - - .controls - = f.submit t('registrations.new.create_my_account'), :class => 'btn primary', :disable_with => t('registrations.new.submitting') - = link_to t('devise.sessions.new.sign_in'), new_user_session_path(), :class => 'btn btn-link', :style => "float: right;" + = render partial: "form", locals: {mobile: true} -%footer - = link_to t('layouts.application.toggle'), toggle_mobile_path +%footer.footer + %ul + %li= link_to t("devise.shared.links.sign_in"), new_session_path(resource_name) + %li= link_to t("layouts.application.toggle"), toggle_mobile_path diff --git a/app/views/report/index.html.haml b/app/views/report/index.html.haml index 69645271f983db3ce00058cbca4f98fe781dc70b..2df36adf88d8d25e6ab74e2c74f6c34d99c9a86a 100644 --- a/app/views/report/index.html.haml +++ b/app/views/report/index.html.haml @@ -2,32 +2,43 @@ = stylesheet_link_tag :admin .container - %div - - if current_user.admin? - = render :partial => 'admins/admin_bar' + .row + .col-md-3 + - if current_user.admin? + = render partial: "admins/admin_bar" + .col-md-9 + #reports + %h1 + = t("report.title") + - @reports.each do |report| + - if report.item + .panel.panel-default + - username = report.user.username + .panel-heading + .reporter.pull-right + = raw t("report.reported_label", person: link_to(username, user_profile_path(username))) + .title + = report_content(report) + .panel-body + .reason + = t("report.reason_label", text: report.text) - %div.row - %div.span12 - %h1 - = t('report.title') - %div#reports - - @reports.each do |r| - - username = User.find_by_id(r.user_id).username - %div.content - %span.text - = report_content(r.item_id, r.item_type) - %span - = raw t('report.reported_label', person: link_to(username, user_profile_path(username))) - %span - = t('report.reason_label', text: r.text) - %div.options.text-right - %span - = button_to t('report.review_link'), report_path(r.id, :type => r.item_type), - :class => "btn btn-info btn-small", - method: :put - %span - = button_to t('report.delete_link'), report_path(r.id, :type => r.item_type), - :data => { :confirm => t('report.confirm_deletion') }, - :class => "btn btn-danger btn-small", - method: :delete - %div.clear + = button_to t("report.reported_user_details"), + user_search_path(admins_controller_user_search: {guid: report.reported_author.guid}), + class: "btn pull-left btn-info btn-small", method: :post + = button_to t("report.review_link"), report_path(report.id, type: report.item_type), + class: "btn pull-left btn-info btn-small", method: :put + = button_to t("report.delete_link"), report_path(report.id, type: report.item_type), + data: {confirm: t("report.confirm_deletion")}, + class: "btn pull-right btn-danger btn-small", method: :delete + - else + .panel.panel-default + - username = report.user.username + .panel-heading + .reporter.pull-right + = raw t("report.reported_label", person: link_to(username, user_profile_path(username))) + .title + = report_content(report) + .panel-body + = button_to t("report.review_link"), report_path(report.id, type: report.item_type), + class: "btn pull-left btn-info btn-small", method: :put diff --git a/app/views/report/report_email.markerb b/app/views/report/report_email.markerb index ba787d56a352436ea6ab02df266000a9dd999cc0..2729aa96b37945a470b956556ee63147d74b8bcc 100644 --- a/app/views/report/report_email.markerb +++ b/app/views/report/report_email.markerb @@ -1,2 +1,5 @@ -<%= t('notifier.report_email.body', url: resource[:url], type: resource[:type], id: resource[:id]) %> - +<%= t("notifier.report_email.body", + url: resource[:url], + type: resource[:type], + id: resource[:id], + reason: resource[:reason]) %> diff --git a/app/views/reshares/_reshare.mobile.haml b/app/views/reshares/_reshare.mobile.haml index 36ee8c2e6b4f88ab0a1e06df1ee65885e7da4869..871791cff88fe6e067998252a05c5bf79d35e169 100644 --- a/app/views/reshares/_reshare.mobile.haml +++ b/app/views/reshares/_reshare.mobile.haml @@ -4,17 +4,21 @@ .reshare - if post - = render 'shared/photo_area', :post => post + .nsfw-hidden + = render "shared/photo_area", post: post .content - = render 'shared/post_info', :post => post + = render "shared/post_info", post: post - - if !post.activity_streams? - = render 'status_messages/status_message', :post => post, :photos => post.photos + - unless post.is_a?(Reshare) + = render "shared/nsfw_shield", post: post + + .nsfw-hidden + = render "status_messages/status_message", post: post, photos: post.photos - else .content - = t('.deleted') + = t(".deleted") .reshare_via %span - = t('.reshared_via') + = t(".reshared_via") diff --git a/app/views/services/index.html.haml b/app/views/services/index.html.haml index cea937b11265fe163e228808aac81ccbc4423324..432dafdb32d2e650c0d8806bfc33aa79c63a3711 100644 --- a/app/views/services/index.html.haml +++ b/app/views/services/index.html.haml @@ -3,20 +3,21 @@ -# the COPYRIGHT file. - content_for :page_title do - = t('.edit_services') + = t(".edit_services") -.container - .row-fluid - .span12 - #section_header - %h2 - = t('settings') - = render 'shared/settings_nav' +.container-fluid + .row + .col-md-3 + .sidebar + = render "shared/settings_nav" + .col-md-9 + .framed-content.clearfix + %h3= t(".title") + .row + .col-md-12 + = render "add_remove_services" - .row-fluid - .span7 - = render 'add_remove_services' - - .span5 - %p - = t('.services_explanation') + .row + .col-md-12 + %p + = t(".services_explanation") diff --git a/app/views/services/index.mobile.haml b/app/views/services/index.mobile.haml new file mode 100644 index 0000000000000000000000000000000000000000..a74e7167c315b6080c8967f4fde77ed9dac9f997 --- /dev/null +++ b/app/views/services/index.mobile.haml @@ -0,0 +1,20 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + +- content_for :page_title do + = t(".edit_services") + +.settings_container.services_page.container-fluid + .row + .col-md-12 + = render "shared/settings_nav" + + .row + .col-md-12 + = render "add_remove_services" + + .row + .col-md-12 + .services_explanation + = t(".services_explanation") diff --git a/app/views/sessions/_form.haml b/app/views/sessions/_form.haml new file mode 100644 index 0000000000000000000000000000000000000000..ba56cbf0417542de3ca598249128819d590d13db --- /dev/null +++ b/app/views/sessions/_form.haml @@ -0,0 +1,44 @@ += form_for resource, as: resource_name, + url: session_path(resource_name), + html: {class: "block-form"}, + autocomplete: "off" do |f| + %fieldset + - if mobile + %legend + = image_tag("branding/logos/header-logo2x.png", height: 40, width: 40) + = t("devise.sessions.new.login") + + - if mobile + %label#usernameLabel{for: "user_username"} + = t("registrations.new.username") + - else + %label.sr-only#usernameLabel{for: "user_username"} + = t("registrations.new.username") + %i.entypo-user + = f.text_field :username, + placeholder: t("registrations.new.username"), + class: "input-block-level form-control", + required: true, + pattern: "[A-Za-z0-9_.@\-]+", + autocapitalize: "none", + autocorrect: "off", + autofocus: true, + aria: {labelledby: "usernameLabel"} + + - if mobile + %label#passwordLabel{for: "user_password"} + = t("registrations.new.password") + - else + %label.sr-only#passwordLabel{for: "user_password"} + = t("registrations.new.password") + %i.entypo-lock + = f.password_field :password, + placeholder: t("registrations.new.password"), + class: "input-block-level form-control", + required: true, + autocapitalize: "none", + autocorrect: "off", + aria: {labelledby: "passwordLabel"} + + = f.hidden_field :remember_me, value: 1 + = f.submit t("devise.sessions.new.sign_in"), class: "btn btn-large btn-block btn-primary" diff --git a/app/views/sessions/new.html.haml b/app/views/sessions/new.html.haml index 41c251400347ed6c0586f40d91c52c4abc1bab01..fff5c049770333367f5e8552c7ab87bbdacbe3eb 100644 --- a/app/views/sessions/new.html.haml +++ b/app/views/sessions/new.html.haml @@ -1,38 +1,13 @@ - content_for :page_title do = AppConfig.settings.pod_name + " - " + t('devise.sessions.new.sign_in') -.container-fluid#login +.container#login .text-center .logos-asterisk %h1 = AppConfig.settings.pod_name - = form_for resource, as: resource_name, url: session_path(resource_name), html: {class: 'block-form'}, autocomplete: 'off' do |f| - %fieldset - %label{for: "user_username"} - = t('registrations.new.username') - %i.entypo.user - = f.text_field :username, - placeholder: t('registrations.new.username'), - class: 'input-block-level form-control', - required: true, - pattern: '[A-Za-z0-9_.@\-]+', - autocapitalize: 'none', - autocorrect: 'off', - autofocus: true - - %label{for: "user_password"} - = t('registrations.new.password') - %i.entypo.lock - = f.password_field :password, - placeholder: t('registrations.new.password'), - class: 'input-block-level form-control', - required: true, - autocapitalize: 'none', - autocorrect: 'off' - - = f.hidden_field :remember_me, value: 1 - = f.submit t('devise.sessions.new.sign_in'), class: 'btn btn-large btn-block' + = render partial: "form", locals: {mobile: false} .text-center - if display_password_reset_link? diff --git a/app/views/sessions/new.mobile.haml b/app/views/sessions/new.mobile.haml index df996cc46ab6ae7a8bcbf9f180d91e710adab1dc..a4b7d803c5ad7378cc339cfad69c0b21d5393af2 100644 --- a/app/views/sessions/new.mobile.haml +++ b/app/views/sessions/new.mobile.haml @@ -2,46 +2,23 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.session_mobile - .landing - %h1.session - = pod_name - - #main_stream.stream - - flash.each do |name, msg| - %p{class: "login_#{name}"} +.stream#main_stream + - flash.each do |name, msg| + .expose#flash-container + .flash-message{class: "message alert alert-#{flash_class name}", role: "alert"} = msg - #flash_alert.expose - #session.message - = msg - - #login_form - .login-container - = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| - %fieldset - %legend - = image_tag("branding/logos/header-logo2x.png", height: 40, width: 40) - = t("devise.sessions.new.login") - - .control-group - = f.label :username, t("username") - .controls - = f.text_field :username, autofocus: true, autocapitalize: "none", autocorrect: "off" - .control-group - = f.label :password , t("password") - .controls - = f.password_field :password + #login_form + .login-container + = render partial: "form", locals: {mobile: true} - = hidden_field(:user, :remember_me, value: 1) - - .controls - = f.submit t("devise.sessions.new.sign_in"), class: "btn primary" - - if display_registration_link? - = link_to t("devise.shared.links.sign_up"), new_registration_path(resource_name), class: "btn btn-link", style: "float: right;" - - %footer +%footer.footer + %ul - if display_password_reset_link? - = link_to t("devise.passwords.new.forgot_password"), new_password_path(resource_name) - - = link_to t("layouts.application.toggle"), toggle_mobile_path + %li + = link_to t("devise.shared.links.forgot_your_password"), + new_password_path(resource_name), + id: "forgot_password_link" + - if display_registration_link? + %li= link_to t("devise.shared.links.sign_up"), new_registration_path(resource_name) + %li= link_to t("layouts.application.toggle"), toggle_mobile_path diff --git a/app/views/shared/_invitations.haml b/app/views/shared/_invitations.haml index 346f5d572758ba3efeb3cf9fbaf89cd4b74e421a..4c45deee73a66b29accb0d586aedcd39c1fe3395 100644 --- a/app/views/shared/_invitations.haml +++ b/app/views/shared/_invitations.haml @@ -1,9 +1,9 @@ -= t('.share_this') += t(".share_this") = invite_link(current_user.invitation_code) -.btn-link{ 'data-toggle' => 'modal', 'data-target' => '#invitationsModal'} - = t('.by_email') +.invitations-link.btn.btn-link#invitations-button{"data-toggle" => "modal"} + = t(".by_email") -= render 'shared/modal', - :path => new_user_invitation_path, - :id => 'invitationsModal', - :title => t('invitations.new.invite_someone_to_join') += render "shared/modal", + path: new_user_invitation_path, + id: "invitationsModal", + title: t("invitations.new.invite_someone_to_join") diff --git a/app/views/shared/_modal.haml b/app/views/shared/_modal.haml index a102ddfcde4ded1bf3682c4977c7ac6ee5e59ae9..8305ac2915a795817afa77b6d2d9a48ebc8265b8 100644 --- a/app/views/shared/_modal.haml +++ b/app/views/shared/_modal.haml @@ -1,12 +1,17 @@ -.modal.hide.fade{ :id => id, - :tabindex => '-1', - :role => 'dialog', - 'aria-labelledby' => "#{id}Label", - 'aria-hidden' => 'true', - 'data-remote' => path} - .modal-header - %button.close{:type => 'button', 'data-dismiss' => 'modal', 'aria-hidden' => 'true' } - × - %h3{ :id => "#{id}Label"} - = title - .modal-body +.modal.fade{"id" => id, + "tabindex" => "-1", + "role" => "dialog", + "aria-labelledby" => "#{id}Label", + "aria-hidden" => "true", + "href" => path} + .modal-dialog + .modal-content + .modal-header + %button.close{"type" => "button", "data-dismiss" => "modal", "aria-hidden" => "true"} + × + %h3.modal-title{id: "#{id}Label"} + = title + .modal-body + #modalWaiter.text-center + .loader + .spinner diff --git a/app/views/shared/_nsfw_shield.mobile.haml b/app/views/shared/_nsfw_shield.mobile.haml new file mode 100644 index 0000000000000000000000000000000000000000..6fa3eb4e5a00551f7cea79a6028d12a9c3b2e863 --- /dev/null +++ b/app/views/shared/_nsfw_shield.mobile.haml @@ -0,0 +1,6 @@ +- if post.respond_to?(:nsfw) && post.nsfw + .nsfw-shield + .shield + %strong #NSFW + | + = link_to t("javascripts.stream.show_nsfw_post"), "#", class: "toggle_nsfw_state" diff --git a/app/views/shared/_photo_area.mobile.haml b/app/views/shared/_photo_area.mobile.haml index 78ac89a40843831e14b19e5a2e40abfe687fcc89..19417b915513e65f47edbde0e44e3c2bbb7d9cb2 100644 --- a/app/views/shared/_photo_area.mobile.haml +++ b/app/views/shared/_photo_area.mobile.haml @@ -11,6 +11,3 @@ .additional_photo_count = "+ #{post.photos.size-1}" = image_tag post.photos.first.url(:thumb_large), class: "stream-photo big-stream-photo" - - elsif post.activity_streams? - = image_tag post.image_url - diff --git a/app/views/shared/_post_info.mobile.haml b/app/views/shared/_post_info.mobile.haml index cff91d25ae50f836a4ef6bb46078f520fcad8002..1b51261f265e4b0e02bf3c7ff3ac4bbbcb173819 100644 --- a/app/views/shared/_post_info.mobile.haml +++ b/app/views/shared/_post_info.mobile.haml @@ -2,26 +2,32 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.from - = person_image_link(post.author, :size => :thumb_small) - = person_link(post.author) +.from.media + .media-left + = person_image_link(post.author, size: :thumb_small, class: "media-object") + .media-body + .pull-left + = person_link(post.author) - .remove_post - - if user_signed_in? && post.author == current_user.person - = link_to(image_tag("mobile/deletelabel.png"), post_path(post), method: :delete, data: { confirm: "#{t('are_you_sure')}" }, class: "remove") + .remove_post.pull-right + - if user_signed_in? && post.author == current_user.person + = link_to(raw("<i class='entypo-trash'></i>"), post_path(post), method: :delete, + data: { confirm: "#{t('are_you_sure')}" }, class: "remove") + .clearfix - .info - %span - = link_to(post_path(post)) do - = timeago(post.created_at) - %span.via - - if post.activity_streams? - = t('shared.stream_element.via', :link => link_to("#{post.provider_display_name}", post.actor_url)).html_safe - - elsif post.provider_display_name == 'mobile' - = t('shared.stream_element.via_mobile', :link => nil) - – - %span.scope_scope - - if post.public? - = t('public') - - else - = t('limited') + .info + %span + = link_to(post_path(post)) do + = timeago(post.created_at) + %span.via + - if post.provider_display_name == "mobile" + = t('shared.stream_element.via_mobile', link: nil) + – + %span.scope_scope + - if post.public? + = t('public') + - else + = t('limited') + - if !post.is_a?(Reshare) and post.location + .location.nsfw-hidden + = t("posts.show.location", location: post.location.address) diff --git a/app/views/shared/_post_stats.mobile.haml b/app/views/shared/_post_stats.mobile.haml deleted file mode 100644 index eaa514266579d9976efe771aa7903f1dc8e140b8..0000000000000000000000000000000000000000 --- a/app/views/shared/_post_stats.mobile.haml +++ /dev/null @@ -1,21 +0,0 @@ -.comment_container - .post_stats - - if @post.public? - %span.reshare_count - = @post.reshares.size - - %span.comment_count - = @post.comments.size - - %span.like_count - = @post.likes.size - - %ul.comments - = render partial: "comments/comment", collection: @post.comments.for_a_stream, locals: {post: @post} - - %li.comment.add_comment_bottom_link_container - = link_to "#", class: "show_comments bottom_collapse active" do - = image_tag "mobile/arrow_up_small.png" - - - if user_signed_in? - = link_to t("comments.new_comment.comment"), new_post_comment_path(@post), class: "add_comment_bottom_link btn comment_action inactive" diff --git a/app/views/shared/_public_explain.haml b/app/views/shared/_public_explain.haml index 89321a495a277239fa322fd5a4dcb51ff08bac3c..6635866c5579d25c67217340cb70a0b7db6bccaf 100644 --- a/app/views/shared/_public_explain.haml +++ b/app/views/shared/_public_explain.haml @@ -2,22 +2,25 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.span-12.last - .modal_title_bar - %h4=t('.title') - %p - =t('.outside') - %br - %br - = link_to t('.atom_feed'), current_user.atom_url - %br - - if current_user.services - - for service in current_user.services - = t('.logged_in', :service => service.provider) - %br - - = link_to t('.manage'), services_path - - %br - %br - = link_to t('ok'), '#', :class => "button", :onClick => '$.facebox.close();' +.modal.fade{"id" => "publicExplainModal", + "tabindex" => "-1", + "role" => "dialog", + "aria-labelledby" => "publicExplainModalLabel", + "aria-hidden" => "true"} + .modal-dialog + .modal-content + .modal-header + %button.close{"type" => "button", "data-dismiss" => "modal", "aria-hidden" => "true"} + × + %h3.modal-title{id: "publicExplainModalLabel"} + = t(".title") + .modal-body + %p=t('.outside') + %p= link_to t(".atom_feed"), current_user.atom_url + - if current_user.services + - for service in current_user.services + %p= t('.logged_in', :service => service.provider) + %p= link_to t('.manage'), services_path + .modal-footer + .btn.btn-default{type: "button", data: {dismiss: "modal"}, aria: {hidden: "true"}} + = t("ok") diff --git a/app/views/shared/_right_sections.html.haml b/app/views/shared/_right_sections.html.haml deleted file mode 100644 index 13f0e7d109a3138728cc462276aa41f736716bb2..0000000000000000000000000000000000000000 --- a/app/views/shared/_right_sections.html.haml +++ /dev/null @@ -1,100 +0,0 @@ --# Copyright (c) 2010-2011, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - - -- if AppConfig.settings.invitations.open? - .section - .title - %h5.title-header - %i.entypo.plus - = t('shared.invitations.invite_your_friends') - .content - = render "shared/invitations" - -.section - .title - %h5.title-header - %i.entypo.users - = t('aspects.index.new_here.title') - .content - != t('aspects.index.new_here.follow', link: link_to("#"+t('shared.publisher.new_user_prefill.newhere'), tag_path(name: t('shared.publisher.new_user_prefill.newhere')))) - %br - = link_to(t('aspects.index.new_here.learn_more'), "http://wiki.diasporafoundation.org/Welcoming_Committee") - -.section - .title - %h5.title-header - %i.entypo.circled-help - = t('aspects.index.help.need_help') - .content - %p - = t('aspects.index.help.here_to_help') - %p - = t('aspects.index.help.do_you') - %ul - %li - != t('aspects.index.help.have_a_question', :link => link_to("#"+t('aspects.index.help.tag_question'), tag_path(:name => t('aspects.index.help.tag_question')))) - %li - != t('aspects.index.help.find_a_bug', :link => link_to("#"+t('aspects.index.help.tag_bug'), tag_path(:name => t('aspects.index.help.tag_bug')))) - %li - != t('aspects.index.help.feature_suggestion', :link => link_to("#"+t('aspects.index.help.tag_feature'), tag_path(:name => t('aspects.index.help.tag_feature')))) - %p - != t('aspects.index.help.tutorials_and_wiki', - :faq => link_to(t('_help'), help_path), - :tutorial => link_to(t('aspects.index.help.tutorial_link_text'), "https://diasporafoundation.org/tutorials", :target => '_blank'), - :wiki => link_to('Wiki','http://wiki.diasporafoundation.org', :target => '_blank'), :target => '_blank') - -- unless AppConfig.configured_services.blank? || all_services_connected? - .section - .title - %h5.title-header - %i.entypo.cog - = t('aspects.index.services.heading') - .content - %div - = t('aspects.index.services.content') - - #right_service_icons - - AppConfig.configured_services.each do |service| - - if AppConfig.show_service?(service, current_user) - - unless current_user.services.any?{|x| x.provider == service} - = link_to(content_tag(:div, nil, :class => "social_media_logos-#{service.to_s.downcase}-24x24", :title => service.to_s.titleize), "/auth/#{service}") - -.section - .title - %h5.title-header - %i.entypo.bookmark - = t('bookmarklet.heading') - .content - != t('bookmarklet.explanation', :link => link_to(t('bookmarklet.post_something'), bookmarklet_url)) - -- if AppConfig.settings.paypal_donations.enable? || AppConfig.bitcoin_donation_address - .section - .title - %h5.title-header - %i.entypo.heart - = t('aspects.index.donate') - .content - %p - = t('aspects.index.keep_pod_running', :pod => AppConfig.pod_uri.host) - = render 'shared/donatepod' - -- if AppConfig.admins.podmin_email.present? - .section - .title - %h5.title-header - %i.entypo.mail - = t('aspects.index.help.any_problem') - .content - %p - = t('aspects.index.help.contact_podmin') - %p - = link_to t("aspects.index.help.mail_podmin"), "mailto:#{AppConfig.admins.podmin_email}" - -.section - .title - .content - %ul - = render "shared/links" - diff --git a/app/views/shared/_settings_nav.haml b/app/views/shared/_settings_nav.haml index e095322fe5b7bc23cbb0fce3fec69281c1038f15..e54f3e42486b8dcae11caec297475ff8122b8079 100644 --- a/app/views/shared/_settings_nav.haml +++ b/app/views/shared/_settings_nav.haml @@ -1,5 +1,15 @@ -%ul.nav.nav-tabs#settings_nav - %li{class: current_page?(edit_profile_path) && 'active'}= link_to t('profile'), edit_profile_path - %li{class: current_page?(edit_user_path) && 'active'}= link_to t('account'), edit_user_path - %li{class: current_page?(privacy_settings_path) && 'active'}= link_to t('privacy'), privacy_settings_path - %li{class: current_page?(services_path) && 'active'}= link_to t('_services'), services_path +#section_header + .sidebar-header.clearfix + %h3 + = t("settings") + .list-group#settings_nav + = link_to t("profile"), edit_profile_path, + class: current_page?(edit_profile_path) ? "list-group-item active" : "list-group-item" + = link_to t("account"), edit_user_path, + class: request.path == edit_user_path ? "list-group-item active" : "list-group-item" + = link_to t("privacy"), privacy_settings_path, + class: current_page?(privacy_settings_path) ? "list-group-item active" : "list-group-item" + = link_to t("_services"), services_path, + class: current_page?(services_path) ? "list-group-item active" : "list-group-item" + = link_to t("_applications"), api_openid_connect_user_applications_path, + class: current_page?(api_openid_connect_user_applications_path) ? "list-group-item active" : "list-group-item" diff --git a/app/views/shared/_settings_nav.mobile.haml b/app/views/shared/_settings_nav.mobile.haml index 9c673d74c53883f142e180d0d5da852a2491c8ef..aaeb0b319c5f446518513dfd7d3516e7e6645a78 100644 --- a/app/views/shared/_settings_nav.mobile.haml +++ b/app/views/shared/_settings_nav.mobile.haml @@ -1,7 +1,9 @@ -#span-24 - %h3 - #settings_nav - %ul - %li= link_to_unless_current t('profile'), edit_profile_path - | - %li= link_to_unless_current t('account'), edit_user_path +#settings_nav + %h2= t("settings") + %nav + %ul + %li= link_to_unless_current t("profile"), edit_profile_path + %li= link_to_unless_current t("account"), edit_user_path + %li= link_to_unless_current t("privacy"), privacy_settings_path + %li= link_to_unless_current t("_services"), services_path + %li= link_to_unless_current t("_applications"), api_openid_connect_user_applications_path diff --git a/app/views/shared/_stream.haml b/app/views/shared/_stream.haml index 74a06e827ec9ab70463abf0a1209ca72197d2158..c1b49f03c05825010996dabe5c73fd8a1ebee0de 100644 --- a/app/views/shared/_stream.haml +++ b/app/views/shared/_stream.haml @@ -2,6 +2,4 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -= render :partial => 'shared/stream_element', - :collection => posts, - :as => :post += render partial: "shared/stream_element", collection: posts, as: :post diff --git a/app/views/shared/_stream_element.mobile.haml b/app/views/shared/_stream_element.mobile.haml index eda9c75ab556787606b756b8fef6e71ba07a60d0..237a36af6fb8fea559508aa01d7e5c66d46baff6 100644 --- a/app/views/shared/_stream_element.mobile.haml +++ b/app/views/shared/_stream_element.mobile.haml @@ -2,33 +2,38 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.stream_element{data: {guid: post.id}} - - if post.respond_to?(:nsfw) && post.nsfw - .shield_wrapper - .shield - %strong #NSFW - | - = link_to t("javascripts.stream.show_nsfw_post"), "#" - +.stream_element{data: {guid: post.id}, class: post.respond_to?(:nsfw) && post.nsfw ? "shield-active" : ""} - if post.is_a?(Reshare) = render "reshares/reshare", reshare: post, post: post.absolute_root - = render "shared/photo_area", post: post + .nsfw-hidden + = render "shared/photo_area", post: post .content = render "shared/post_info", post: post + - unless post.is_a?(Reshare) + = render "shared/nsfw_shield", post: post + + .nsfw-hidden - if post.is_a?(StatusMessage) = render "status_messages/status_message", post: post, photos: post.photos - .bottom_bar - .floater - = mobile_reshare_icon(post) - = mobile_comment_icon(post) - = mobile_like_icon(post) - - != reactions_link(post) + .bottom-bar.nsfw-hidden{class: ("inactive" unless defined?(expanded_info) && expanded_info)} + = render partial: "comments/post_stats", locals: {post: post} - if defined?(expanded_info) && expanded_info - = render partial: "shared/post_stats", locals: {post: @post} + != reactions_link(post, "active") + .comment-container + %ul.comments + = render partial: "comments/comment", collection: post.comments.for_a_stream, locals: {post: post} + + - else + != reactions_link(post) + + .ajax-loader.hidden + .loader + .spinner + .add-comment-switcher{class: ("hidden" unless defined?(expanded_info) && expanded_info)} + = render partial: "comments/new_comment", locals: {post_id: post.id} diff --git a/app/views/simple_captcha/_simple_captcha.haml b/app/views/simple_captcha/_simple_captcha.haml index f8adfb4681ad90e51ea44786625c7ca3a402aa56..e0ff398bf65906669a713618024b15127336d4fc 100644 --- a/app/views/simple_captcha/_simple_captcha.haml +++ b/app/views/simple_captcha/_simple_captcha.haml @@ -1,3 +1,3 @@ -.captcha_img +.captcha-img = simple_captcha_options[:image] = simple_captcha_options[:field] diff --git a/app/views/simple_captcha/_simple_captcha.mobile.haml b/app/views/simple_captcha/_simple_captcha.mobile.haml index 625fa768d781f76f387bf8e97e36e443d0fa4c5c..53f420b11a0f99d86ad5af39967bb06210b14f19 100644 --- a/app/views/simple_captcha/_simple_captcha.mobile.haml +++ b/app/views/simple_captcha/_simple_captcha.mobile.haml @@ -1,4 +1,3 @@ -.control-group#captcha +.form-group#captcha = simple_captcha_options[:image] - .controls - = simple_captcha_options[:field] \ No newline at end of file + = simple_captcha_options[:field] diff --git a/app/views/status_messages/_poll.mobile.haml b/app/views/status_messages/_poll.mobile.haml new file mode 100644 index 0000000000000000000000000000000000000000..466c6b55c8e52905aa2d5c9acdd447e7994007b2 --- /dev/null +++ b/app/views/status_messages/_poll.mobile.haml @@ -0,0 +1,25 @@ +.poll + .poll-head + .poll-stats.pull-right + = t("polls.votes", count: poll.participation_count) + .question + = poll.question + .poll-content + - poll.poll_answers.each do |answer| + .result-row + .result-head + - percentage = 0 + - if poll.participation_count > 0 + - percentage = (answer.vote_count.to_f / poll.participation_count * 100).round + .percentage.pull-right + = "#{percentage}%" + .answer + = answer.answer + .progress + .progress-bar{role: "progressbar", + aria: {valuenow: "#{percentage}", + valuemin: "0", + valuemax: "100"}, + style: "width: #{percentage}%;"} + %span.sr-only + = "#{percentage}%" diff --git a/app/views/status_messages/_status_message.mobile.haml b/app/views/status_messages/_status_message.mobile.haml index 5aba5358db7eff74c06e492c92db34e250cfd1b4..51881e1da44101891407a97a1d72a8d9d29ea3cc 100644 --- a/app/views/status_messages/_status_message.mobile.haml +++ b/app/views/status_messages/_status_message.mobile.haml @@ -11,13 +11,13 @@ .additional_photo_count = "+ #{post.photos.size-1}" = image_tag post.first_photo_url(:thumb_large), :class => "stream-photo big-stream-photo" - - elsif post.activity_streams? - = image_tag post.image_url %div{:class => direction_for(post.text)} != post.message.markdownified + - if post.poll + = render "status_messages/poll", poll: post.poll - if post.o_embed_cache != o_embed_html post.o_embed_cache - -if post.open_graph_cache + - if post.open_graph_cache .opengraph != og_html post.open_graph_cache diff --git a/app/views/status_messages/bookmarklet.html.haml b/app/views/status_messages/bookmarklet.html.haml index 90958364a97527a75a9c9cb44b99c5503a749b45..393002b8ceaa0dd7194a21f9c7e1c2b6d7e0ffae 100644 --- a/app/views/status_messages/bookmarklet.html.haml +++ b/app/views/status_messages/bookmarklet.html.haml @@ -1,5 +1,7 @@ -.container-fluid#bookmarklet - .row-fluid - %h4 - =t('bookmarklet.post_something') - = render :partial => 'publisher/publisher', :locals => { :aspect => :profile, :selected_aspects => @aspects, :aspect_ids => @aspect_ids } +#bookmarklet + .container + .row + .col-md-12 + %h4 + =t('bookmarklet.post_something') + = render partial: 'publisher/publisher', locals: { aspect: :profile, :selected_aspects => @aspects, :aspect_ids => @aspect_ids } diff --git a/app/views/status_messages/new.html.haml b/app/views/status_messages/new.html.haml index 88e150b9f80c577c3cd175c6a363bb19a56b7109..5eaf54d9dcb7e6482c0e7ed40c2f190ede38eeb1 100644 --- a/app/views/status_messages/new.html.haml +++ b/app/views/status_messages/new.html.haml @@ -4,15 +4,3 @@ :selected_aspects => @aspects_with_person, :person => @person } -:javascript - $(function() { - app.publisher = new app.views.Publisher({ - standalone: true - }); - app.publisher.open(); - $("#publisher").bind('ajax:success', function(){ - $("#mentionModal").modal('hide'); - app.publisher.clear(); - location.reload(); - }); - }); diff --git a/app/views/streams/main_stream.html.haml b/app/views/streams/main_stream.html.haml index f4d963ea6f0465e0434b14673847093a7b7235f0..46f71957d48b47685d3707007d743e52e0c7b8f3 100644 --- a/app/views/streams/main_stream.html.haml +++ b/app/views/streams/main_stream.html.haml @@ -4,56 +4,163 @@ - content_for :head do - if AppConfig.chat.enabled? - = javascript_include_tag :jsxc, :id => 'jsxc', - :data => { :endpoint => get_bosh_endpoint } + = javascript_include_tag :jsxc, id: 'jsxc', + data: { endpoint: get_bosh_endpoint } - if current_user.getting_started? #welcome-to-diaspora .container-fluid - .row-fluid - .span8.offset1 + .row + .col-md-9 %h1 - = t('aspects.index.welcome_to_diaspora', :name => current_user.first_name) + = t('aspects.index.welcome_to_diaspora', name: current_user.first_name) %h3 = t('aspects.index.introduce_yourself') - .span2 + .col-md-3 .pull-right - = link_to '×'.html_safe, getting_started_completed_path, :id => "gs-skip-x", :class => "close" + = link_to '×'.html_safe, getting_started_completed_path, id: "gs-skip-x", class: "close" .container-fluid - .row-fluid - .offset1.span2#leftNavBar - #home_user_badge - = owner_image_link - %h4 - = link_to current_user.first_name, local_or_remote_person_path(current_user.person) - - %ul#stream_selection - %li{data: {stream: "stream"}} - = link_to t("streams.multi.title"), stream_path, rel: "backbone", class: "hoverable" - %li{data: {stream: "activity"}} - = link_to t("streams.activity.title"), activity_stream_path, rel: "backbone", class: "hoverable" - %li{data: {stream: "mentions"}} - = link_to t("streams.mentions.title"), mentioned_stream_path, rel: "backbone", class: "hoverable" - %li.all_aspects - = render "aspects/aspect_listings", stream: @stream - %li - = render "tags/followed_tags_listings" - %li{data: {stream: "public"}} - = link_to t("streams.public.title"), public_stream_path, rel: "backbone", class: "hoverable" - - .span6 - #aspect_stream_container.stream_container - = render 'aspects/aspect_stream', :stream => @stream - - .span2.rightBar - #selected_aspect_contacts.section - .title.no_icon - %h5.stream_title - = @stream.title - .content - - = render 'shared/right_sections' - - %a{:id=>"back-to-top", :title=>"#{t('layouts.application.back_to_top')}", :href=>"#"} - ⇧ + .row + .col-md-3 + .sidebar.left-navbar + %ul#stream_selection + %li{data: {stream: "stream"}} + = link_to t("streams.multi.title"), stream_path, rel: "backbone", class: "hoverable" + %li{data: {stream: "activity"}} + = link_to t("streams.activity.title"), activity_stream_path, rel: "backbone", class: "hoverable" + %li{data: {stream: "mentions"}} + = link_to t("streams.mentions.title"), mentioned_stream_path, rel: "backbone", class: "hoverable" + %li.all-aspects + = render "aspects/aspect_listings", stream: @stream + %li.followed-tags-sidebar + = render "tags/followed_tags_listings" + %li{data: {stream: "public"}} + = link_to t("streams.public.title"), public_stream_path, rel: "backbone", class: "hoverable" + + .sidebar.info-bar.hidden-xs + - if AppConfig.settings.invitations.open? + .section.collapsed + .title + %h5.title-header + .entypo-triangle-right + .entypo-triangle-down + = t("shared.invitations.invite_your_friends") + .content + = render "shared/invitations" + + .section.collapsed + .title + %h5.title-header + .entypo-triangle-right + .entypo-triangle-down + = t("aspects.index.new_here.title") + .content + != t("aspects.index.new_here.follow", + link: link_to("#" + t("shared.publisher.new_user_prefill.newhere"), + tag_path(name: t("shared.publisher.new_user_prefill.newhere")))) + %br + = link_to(t("aspects.index.new_here.learn_more"), + "http://wiki.diasporafoundation.org/Welcoming_Committee") + + .section.collapsed + .title + %h5.title-header + .entypo-triangle-right + .entypo-triangle-down + = t("aspects.index.help.need_help") + .content + %p + = t("aspects.index.help.here_to_help") + %p + = t("aspects.index.help.do_you") + %ul + %li + != t("aspects.index.help.have_a_question", + link: link_to("#" + t("aspects.index.help.tag_question"), + tag_path(name: t("aspects.index.help.tag_question")))) + %li + != t("aspects.index.help.find_a_bug", + link: link_to("#" + t("aspects.index.help.tag_bug"), + tag_path(name: t("aspects.index.help.tag_bug")))) + %li + != t("aspects.index.help.feature_suggestion", + link: link_to("#" + t("aspects.index.help.tag_feature"), + tag_path(name: t("aspects.index.help.tag_feature")))) + %p + != t("aspects.index.help.tutorials_and_wiki", + faq: link_to(t("_help"), help_path), + tutorial: link_to(t("aspects.index.help.tutorial_link_text"), + "https://diasporafoundation.org/tutorials", target: "_blank"), + wiki: link_to("Wiki", "http://wiki.diasporafoundation.org", + target: "_blank"), + target: "_blank") + + - unless AppConfig.configured_services.blank? || all_services_connected? + .section.collapsed + .title + %h5.title-header + .entypo-triangle-right + .entypo-triangle-down + = t("aspects.index.services.heading") + .content + %div + = t("aspects.index.services.content") + + .right-service-icons + - AppConfig.configured_services.each do |service| + - if AppConfig.show_service?(service, current_user) + - unless current_user.services.any? {|x| x.provider == service } + = link_to(content_tag(:div, nil, + class: "social-media-logos-#{service.to_s.downcase}-24x24", + title: service.to_s.titleize), "/auth/#{service}") + + .section.collapsed + .title + %h5.title-header + .entypo-triangle-right + .entypo-triangle-down + = t("bookmarklet.heading") + .content + != t("bookmarklet.explanation", link: link_to(t("bookmarklet.post_something"), bookmarklet_code)) + + - if AppConfig.settings.paypal_donations.enable? || AppConfig.bitcoin_donation_address + .section.collapsed + .title + %h5.title-header + .entypo-triangle-right + .entypo-triangle-down + = t("aspects.index.donate") + .content + %p + = t("aspects.index.keep_pod_running", pod: AppConfig.pod_uri.host) + = render "shared/donatepod" + + - if AppConfig.admins.podmin_email.present? + .section.collapsed + .title + %h5.title-header + .entypo-triangle-right + .entypo-triangle-down + = t("aspects.index.help.any_problem") + .content + %p + = t("aspects.index.help.contact_podmin") + %p + = link_to t("aspects.index.help.mail_podmin"), "mailto:#{AppConfig.admins.podmin_email}" + + .excellence-box + .content + %p + = t("layouts.application.be_excellent") + + .info-links + .content + %ul + = render "shared/links" + + .col-md-9 + .stream_container#aspect_stream_container + = render "aspects/aspect_stream", stream: @stream + + %a.entypo-chevron-up.back-to-top#back-to-top{title: "#{t('layouts.application.back_to_top')}", href: "#"} diff --git a/app/views/streams/main_stream.mobile.haml b/app/views/streams/main_stream.mobile.haml index 2cd8c0dbce0563eb3df51958f8758feeb8aef27a..0ef61801a03b01a087a7bb05f85906872bc265ba 100644 --- a/app/views/streams/main_stream.mobile.haml +++ b/app/views/streams/main_stream.mobile.haml @@ -2,12 +2,6 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -%h2{:style => "padding:0 10px;display:none;"} - - if @stream.for_all_aspects? - = t('all_aspects') - - else - = @stream.aspect - #main_stream.stream - = render 'shared/stream', :posts => @stream.stream_posts + = render 'shared/stream', posts: @stream.stream_posts = render 'shared/stream_more_button' diff --git a/app/views/tags/show.haml b/app/views/tags/show.haml index e65ee419e31be90683bd5d91a4a9420712680892..19e202a38f28a17abf46186c84b661a0d9c86d12 100644 --- a/app/views/tags/show.haml +++ b/app/views/tags/show.haml @@ -3,35 +3,35 @@ -# the COPYRIGHT file. - content_for :page_title do - - if @stream.tag_name - = @stream.display_tag_name - - else - = t('.whatup', :pod => @pod_url) + = @stream.display_tag_name + +- content_for :meta_data do + = metas_tags @stream.metas_attributes .container-fluid#tags_show - .row-fluid - .span3.offset1 - %h4 - = t('.tagged_people', :count => @stream.tagged_people_count, :tag => @stream.display_tag_name) + .row + .col-md-3.hidden-xs + .sidebar + .sidebar-header.clearfix + %h3 + = t(".tagged_people", count: @stream.tagged_people_count, tag: @stream.display_tag_name) - .side_stream.stream - = render :partial => 'people/index', :locals => {:people => @stream.tagged_people} + .side_stream.stream + = render partial: "people/index", locals: {people: @stream.tagged_people} - .span7 + .col-md-9 .stream_container #author_info %h2 = @stream.display_tag_name - if current_user - = render 'publisher/publisher', :selected_aspects => @stream.aspect_ids, :aspect_ids => @stream.aspect_ids, :aspect => @stream.aspect - - %hr + = render 'publisher/publisher', :selected_aspects => @stream.aspect_ids, :aspect_ids => @stream.aspect_ids, aspect: @stream.aspect #main_stream.stream #paginate %span.loader.hidden + .spinner - %a{:id=>"back-to-top", :title=>"#{t('layouts.application.back_to_top')}", :href=>"#"} - ⇧ + %a.entypo-chevron-up.back-to-top#back-to-top{title: "#{t('layouts.application.back_to_top')}", href: "#"} diff --git a/app/views/tags/update.js.erb b/app/views/tags/update.js.erb deleted file mode 100644 index cf75adc4c8959bbbea25c7ec0fba6ebab33dbc11..0000000000000000000000000000000000000000 --- a/app/views/tags/update.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -var tagName = "<%= escape_javascript(@tag.name) %>" -$("#followed_tags_listing").find("#tag-following-"+tagName).slideUp(100); -Diaspora.page.flashMessages.render({success: true, notice: Diaspora.I18n.t("tags.wasnt_that_interesting", {tagName: tagName})}); diff --git a/app/views/terms/default.haml b/app/views/terms/default.haml index 00cf94bc4a4bdb89b5c60d4be132c88366cef963..c872974ea1739d39dd098d0b0d602d0a634697af 100644 --- a/app/views/terms/default.haml +++ b/app/views/terms/default.haml @@ -12,307 +12,309 @@ / These terms of service and privacy policy documents have been forked / from the App.Net ToS repository (https://github.com/appdotnet/terms-of-service). -/ The terms of use and privacy policy are available to you under the +/ The terms of use and privacy policy are available to you under the / CC BY-SA 3.0 Creative Commons license. / If you modify or copy this file, please do not remove this license text. -%div{:class => "container-fluid", :style => "margin-top: 50px;"} - %div{:class => "row-fluid"} - %div{:class => "span3"} - %h3 - Terms of Service - %h4 - %a{:href => "/terms#privacy"} - Privacy Policy - %div{:class => "span9", :style => "margin-top: 20px;"} - %p - Last Updated: 17th August, 2014 +.container#terms + %div{role: "tabpanel"} + .row + .col-md-8.col-md-offset-2 + %ul.nav.nav-tabs.nav-justified{role: "tablist"} + %li.active{role: "presentation"} + %a{href: "#tos", role: "tab", aria: {controls: "tos"}, data: {toggle: "tab"}} + Terms of Service + %li{role: "presentation"} + %a{href: "#privacy", role: "tab", aria: {controls: "privacy"}, data: {toggle: "tab"}} + Privacy Policy - %hr + .row + .col-md-8.col-md-offset-2.tab-content + .tab-pane.active#tos{role: "tabpanel"} + .page-header + %h1 + #{AppConfig.settings.pod_name} - Terms of Service + %small + Last Updated: 17th August, 2014 + + %p + Here are the important things you need to know about accessing and using the <strong>#{AppConfig.settings.pod_name}</strong> (#{AppConfig.environment.url}) website and service (collectively, "Service"). These are our terms of service ("Terms"). Please read them carefully. + + %h2 + Accepting these Terms + + %p + If you access or use the Service, it means you agree to be bound by all of the terms below. So, before you use the Service, please read all of the terms. If you don't agree to all of the terms below, please do not use the Service. + - if AppConfig.admins.podmin_email? + Also, if a term does not make sense to you, please let us know by e-mailing <a href="mailto:#{AppConfig.admins.podmin_email}">#{AppConfig.admins.podmin_email}</a>. + + %h2 + Changes to these Terms + + %p + We reserve the right to modify these Terms at any time. For instance, we may need to change these Terms if we come out with a new feature or for some other reason. - %a{:name => "terms"} - %h1 - #{AppConfig.settings.pod_name} - Terms of Service - - %p - Here are the important things you need to know about accessing and using the <strong>#{AppConfig.settings.pod_name}</strong> (#{AppConfig.environment.url}) website and service (collectively, "Service"). These are our terms of service ("Terms"). Please read them carefully. - - %h2 - Accepting these Terms - - %p - If you access or use the Service, it means you agree to be bound by all of the terms below. So, before you use the Service, please read all of the terms. If you don't agree to all of the terms below, please do not use the Service. - - if AppConfig.admins.podmin_email? - Also, if a term does not make sense to you, please let us know by e-mailing <a href="mailto:#{AppConfig.admins.podmin_email}">#{AppConfig.admins.podmin_email}</a>. - - %h2 - Changes to these Terms + %p + Whenever we make changes to these Terms, the changes are effective six (6) weeks after we post such revised Terms to our website (indicated by revising the date at the top of these Terms), or upon your acceptance if we provide a mechanism for your immediate acceptance of the revised Terms (such as a click-through confirmation or acceptance button). It is your responsibility to check the website regularly for changes to these Terms. - %p - We reserve the right to modify these Terms at any time. For instance, we may need to change these Terms if we come out with a new feature or for some other reason. + %p + If you continue to use the Service after the revised Terms go into effect, then you have accepted the revised Terms. - %p - Whenever we make changes to these Terms, the changes are effective six (6) weeks after we post such revised Terms to our website (indicated by revising the date at the top of these Terms), or upon your acceptance if we provide a mechanism for your immediate acceptance of the revised Terms (such as a click-through confirmation or acceptance button). It is your responsibility to check the website regularly for changes to these Terms. + %h2 + Privacy Policy - %p - If you continue to use the Service after the revised Terms go into effect, then you have accepted the revised Terms. + %p + For information about how we collect and use information about users of the Service, please check out our <a href="#privacy" aria-controls="privacy" data-toggle="tab">privacy policy</a>. - %h2 - Privacy Policy + %h2 + Third-Party Services - %p - For information about how we collect and use information about users of the Service, please check out our <a href="/terms#privacy">privacy policy</a>. + %p + From time to time, we may provide you with links to third party websites or services that we do not own or control. Your use of the Service may also include the use of applications that are developed or owned by a third party. Your use of such third party applications, websites, and services is governed by that party’s own terms of service or privacy policies. We encourage you to read the terms and conditions and privacy policy of any third party application, website or service that you visit or use. Note that while <strong>#{AppConfig.settings.pod_name}</strong> itself does not work directly with advertisers, third party applications may contain advertising or marketing materials provided by such third parties. - %h2 - Third-Party Services + %h2 + Creating Accounts - %p - From time to time, we may provide you with links to third party websites or services that we do not own or control. Your use of the Service may also include the use of applications that are developed or owned by a third party. Your use of such third party applications, websites, and services is governed by that party’s own terms of service or privacy policies. We encourage you to read the terms and conditions and privacy policy of any third party application, website or service that you visit or use. Note that while <strong>#{AppConfig.settings.pod_name}</strong> itself does not work directly with advertisers, third party applications may contain advertising or marketing materials provided by such third parties. + %p + When you create an account, you may use any name (real, fake or otherwise) for other users to see. However, if you create a "parody" account of a real living person, you must clearly label your account as such. Accounts that are not clearly marked as such and that impersonate other people without permission can be deleted without warning. - %h2 - Creating Accounts + %p + When you create an account you also agree to maintain the security of your password and accept all risks of unauthorized access to your account data and any other information you provide to <strong>#{AppConfig.settings.pod_name}</strong>. - %p - When you create an account, you may use any name (real, fake or otherwise) for other users to see. However, if you create a "parody" account of a real living person, you must clearly label your account as such. Accounts that are not clearly marked as such and that impersonate other people without permission can be deleted without warning. + %p + If you discover or suspect any Service security breaches, please let us know as soon as possible. For security holes in the diaspora* software itself, please contact <a href="mailto:security@diasporafoundation.org">the developers directly</a>. - %p - When you create an account you also agree to maintain the security of your password and accept all risks of unauthorized access to your account data and any other information you provide to <strong>#{AppConfig.settings.pod_name}</strong>. + %h2 + Your Content & Conduct - %p - If you discover or suspect any Service security breaches, please let us know as soon as possible. For security holes in the diaspora* software itself, please contact <a href="mailto:security@diasporafoundation.org">the developers directly</a>. + %p + Our Service allows you and other users to post, link and otherwise make available content. You are responsible for the content that you make available to the Service, including its legality, reliability, and appropriateness. - %h2 - Your Content & Conduct + %p + When you post, link or otherwise make available content to the Service, you grant us the right and license to display and distribute your content on or through the Service (including via applications). We may format your content for display throughout the Service, but we will not edit or revise the substance of your content itself. The displaying and distribution of your content happens strictly only according to the visibility rules you have set for the content. We will not modify the visibility of the content you have set. - %p - Our Service allows you and other users to post, link and otherwise make available content. You are responsible for the content that you make available to the Service, including its legality, reliability, and appropriateness. + %p + We cannot be held responsible should a programming or administrative error make your content visible to a larger audience than you had intended. - %p - When you post, link or otherwise make available content to the Service, you grant us the right and license to display and distribute your content on or through the Service (including via applications). We may format your content for display throughout the Service, but we will not edit or revise the substance of your content itself. The displaying and distribution of your content happens strictly only according to the visibility rules you have set for the content. We will not modify the visibility of the content you have set. + %p + Aside from our limited right to your content, you retain all of your rights to the content you post, link and otherwise make available on or through the Service. - %p - We cannot be held responsible should a programming or administrative error make your content visible to a larger audience than you had intended. + %p + You can remove the content that you posted by deleting it. Once you delete your content, it will not appear on the Service, but copies of your deleted content may remain in our system or backups for some period of time. Web server access logs might also be stored for some time in the system. - %p - Aside from our limited right to your content, you retain all of your rights to the content you post, link and otherwise make available on or through the Service. + %p + Since diaspora* is a distributed social network, it is possible, depending on the visibility rules set to your content, that your content has been distributed to other diaspora* pods. When you delete your content, we will request those other pods to also delete the content. Our responsibility on the content being deleted from those other pods ends here. If for some reason, some other pod does not delete the content, we cannot be held responsible. - %p - You can remove the content that you posted by deleting it. Once you delete your content, it will not appear on the Service, but copies of your deleted content may remain in our system or backups for some period of time. Web server access logs might also be stored for some time in the system. + %p + In order to make <strong>#{AppConfig.settings.pod_name}</strong> a great place for all of us, please do not post, link and otherwise make available on or through the Service any of the following: - %p - Since diaspora* is a distributed social network, it is possible, depending on the visibility rules set to your content, that your content has been distributed to other diaspora* pods. When you delete your content, we will request those other pods to also delete the content. Our responsibility on the content being deleted from those other pods ends here. If for some reason, some other pod does not delete the content, we cannot be held responsible. + %ul + %li + Content that is libelous, defamatory, bigoted, fraudulent or deceptive; + %li + Content that is illegal or unlawful, that would otherwise create liability; + %li + Content that may infringe or violate any patent, trademark, trade secret, copyright, right of privacy, right of publicity or other intellectual or other right of any party; + %li + Mass or repeated promotions, political campaigning or commercial messages directed at users who do not follow you (SPAM); + %li + Private information of any third party (e.g., addresses, phone numbers, email addresses, Social Security numbers and credit card numbers); and + %li + Viruses, corrupted data or other harmful, disruptive or destructive files or code. - %p - In order to make <strong>#{AppConfig.settings.pod_name}</strong> a great place for all of us, please do not post, link and otherwise make available on or through the Service any of the following: + %p + Also, you agree that you will not do any of the following in connection with the Service or other users: - %ul - %li - Content that is libelous, defamatory, bigoted, fraudulent or deceptive; - %li - Content that is illegal or unlawful, that would otherwise create liability; - %li - Content that may infringe or violate any patent, trademark, trade secret, copyright, right of privacy, right of publicity or other intellectual or other right of any party; - %li - Mass or repeated promotions, political campaigning or commercial messages directed at users who do not follow you (SPAM); - %li - Private information of any third party (e.g., addresses, phone numbers, email addresses, Social Security numbers and credit card numbers); and - %li - Viruses, corrupted data or other harmful, disruptive or destructive files or code. + %ul + %li + Use the Service in any manner that could interfere with, disrupt, negatively affect or inhibit other users from fully enjoying the Service or that could damage, disable, overburden or impair the functioning of the Service; + %li + Impersonate or post on behalf of any person or entity or otherwise misrepresent your affiliation with a person or entity; + %li + Collect any personal information about other users, or intimidate, threaten, stalk or otherwise harass other users of the Service; + - if AppConfig.settings.terms.minimum_age? + %li + Create an account or post any content if you are not over #{AppConfig.settings.terms.minimum_age} years of age; + %li + Circumvent or attempt to circumvent any filtering, security measures, rate limits or other features designed to protect the Service, users of the Service, or third parties. - %p - Also, you agree that you will not do any of the following in connection with the Service or other users: + %h2 + Source code and materials - %ul - %li - Use the Service in any manner that could interfere with, disrupt, negatively affect or inhibit other users from fully enjoying the Service or that could damage, disable, overburden or impair the functioning of the Service; - %li - Impersonate or post on behalf of any person or entity or otherwise misrepresent your affiliation with a person or entity; - %li - Collect any personal information about other users, or intimidate, threaten, stalk or otherwise harass other users of the Service; - - if AppConfig.settings.terms.minimum_age? - %li - Create an account or post any content if you are not over #{AppConfig.settings.terms.minimum_age} years of age; - %li - Circumvent or attempt to circumvent any filtering, security measures, rate limits or other features designed to protect the Service, users of the Service, or third parties. + %p + This Service runs on a diaspora* social network server. This source code is licensed under an <a href="http://www.gnu.org/licenses/agpl-3.0.html">AGPLv3</a> license which means you are allowed to and even encouraged to take the source code, modify it and use it. - %h2 - Source code and materials + %p + For full details about the diaspora* server <a href="https://github.com/diaspora/diaspora">see here</a>. - %p - This Service runs on a diaspora* social network server. This source code is licensed under an <a href="http://www.gnu.org/licenses/agpl-3.0.html">AGPLv3</a> license which means you are allowed to and even encouraged to take the source code, modify it and use it. + %h2 + Hyperlinks and Third Party Content - %p - For full details about the diaspora* server <a href="https://github.com/diaspora/diaspora">see here</a>. + %p + <strong>#{AppConfig.settings.pod_name}</strong> makes no claim or representation regarding, and accepts no responsibility for third party websites accessible by hyperlink from the Service or websites linking to the Service. When you leave the Service, you should be aware that these Terms and our policies no longer govern. - %h2 - Hyperlinks and Third Party Content + %p + A lot of the content on the Service is from you and others, and we don't review, verify or authenticate it, and it may include inaccuracies or false information. We make no representations, warranties, or guarantees relating to the quality, suitability, truth, accuracy or completeness of any content contained in the Service. You acknowledge sole responsibility for and assume all risk arising from your use of or reliance on any content. - %p - <strong>#{AppConfig.settings.pod_name}</strong> makes no claim or representation regarding, and accepts no responsibility for third party websites accessible by hyperlink from the Service or websites linking to the Service. When you leave the Service, you should be aware that these Terms and our policies no longer govern. + %h2 + Unavoidable Legal Stuff - %p - A lot of the content on the Service is from you and others, and we don't review, verify or authenticate it, and it may include inaccuracies or false information. We make no representations, warranties, or guarantees relating to the quality, suitability, truth, accuracy or completeness of any content contained in the Service. You acknowledge sole responsibility for and assume all risk arising from your use of or reliance on any content. + %p + %strong The Service and any other service and content included on or otherwise made available to you through the Service are provided to you on an as is or as available basis without any representations or warranties of any kind. We disclaim any and all warranties and representations (express or implied, oral or written) with respect to the Service and content included on or otherwise made available to you through the Service whether alleged to arise by operation of law, by reason of custom or usage in the trade, by course of dealing or otherwise. - %h2 - Unavoidable Legal Stuff + %p + %strong In no event will <strong>#{AppConfig.settings.pod_name}</strong> be liable to you or any third party for any special, indirect, incidental, exemplary or consequential damages of any kind arising out of or in connection with the Service or any other service and/or content included on or otherwise made available to you through the Service, regardless of the form of action, whether in contract, tort, strict liability or otherwise, even if we have been advised of the possibility of such damages or are aware of the possibility of such damages. This section will be given full effect even if any remedy specified in this agreement is deemed to have failed of its essential purpose. - %p - %strong The Service and any other service and content included on or otherwise made available to you through the Service are provided to you on an as is or as available basis without any representations or warranties of any kind. We disclaim any and all warranties and representations (express or implied, oral or written) with respect to the Service and content included on or otherwise made available to you through the Service whether alleged to arise by operation of law, by reason of custom or usage in the trade, by course of dealing or otherwise. + %p + You agree to defend, indemnify and hold us harmless from and against any and all costs, damages, liabilities, and expenses (including attorneys' fees, costs, penalties, interest and disbursements) we incur in relation to, arising from, or for the purpose of avoiding, any claim or demand from a third party relating to your use of the Service or the use of the Service by any person using your account, including any claim that your use of the Service violates any applicable law or regulation, or the rights of any third party, and/or your violation of these Terms. - %p - %strong In no event will <strong>#{AppConfig.settings.pod_name}</strong> be liable to you or any third party for any special, indirect, incidental, exemplary or consequential damages of any kind arising out of or in connection with the Service or any other service and/or content included on or otherwise made available to you through the Service, regardless of the form of action, whether in contract, tort, strict liability or otherwise, even if we have been advised of the possibility of such damages or are aware of the possibility of such damages. This section will be given full effect even if any remedy specified in this agreement is deemed to have failed of its essential purpose. + - if AppConfig.settings.terms.jurisdiction? + %h2 + Governing Law - %p - You agree to defend, indemnify and hold us harmless from and against any and all costs, damages, liabilities, and expenses (including attorneys' fees, costs, penalties, interest and disbursements) we incur in relation to, arising from, or for the purpose of avoiding, any claim or demand from a third party relating to your use of the Service or the use of the Service by any person using your account, including any claim that your use of the Service violates any applicable law or regulation, or the rights of any third party, and/or your violation of these Terms. + %p + The validity of these Terms and the rights, obligations, and relations of the parties under these Terms will be construed and determined under and in accordance with the laws of #{AppConfig.settings.terms.jurisdiction}. - - if AppConfig.settings.terms.jurisdiction? - %h2 - Governing Law + %h2 + Jurisdiction & Waiver of Representative Actions - %p - The validity of these Terms and the rights, obligations, and relations of the parties under these Terms will be construed and determined under and in accordance with the laws of #{AppConfig.settings.terms.jurisdiction}. + %p + You expressly agree that exclusive jurisdiction for any dispute with <strong>#{AppConfig.settings.pod_name}</strong>, or in any way relating to your use of the <strong>#{AppConfig.settings.pod_name}</strong> website or Service, resides in the courts of #{AppConfig.settings.terms.jurisdiction} and you further agree and expressly consent to the exercise of personal jurisdiction in the courts of #{AppConfig.settings.terms.jurisdiction} in connection with any such dispute including any claim involving <strong>#{AppConfig.settings.pod_name}</strong>. You further agree that you and <strong>#{AppConfig.settings.pod_name}</strong> will not commence against the other a class action, class arbitration or other representative action or proceeding. - %h2 - Jurisdiction & Waiver of Representative Actions + %h2 + Termination - %p - You expressly agree that exclusive jurisdiction for any dispute with <strong>#{AppConfig.settings.pod_name}</strong>, or in any way relating to your use of the <strong>#{AppConfig.settings.pod_name}</strong> website or Service, resides in the courts of #{AppConfig.settings.terms.jurisdiction} and you further agree and expressly consent to the exercise of personal jurisdiction in the courts of #{AppConfig.settings.terms.jurisdiction} in connection with any such dispute including any claim involving <strong>#{AppConfig.settings.pod_name}</strong>. You further agree that you and <strong>#{AppConfig.settings.pod_name}</strong> will not commence against the other a class action, class arbitration or other representative action or proceeding. + %p + If you breach any of these Terms, we have the right to suspend or disable your access to or use of the Service. - %h2 - Termination + %h2 + Entire Agreement - %p - If you breach any of these Terms, we have the right to suspend or disable your access to or use of the Service. + %p + These Terms constitute the entire agreement between you and <strong>#{AppConfig.settings.pod_name}</strong> regarding the use of the Service, superseding any prior agreements between you and <strong>#{AppConfig.settings.pod_name}</strong> relating to your use of the Service. - %h2 - Entire Agreement + %h2 + Feedback - %p - These Terms constitute the entire agreement between you and <strong>#{AppConfig.settings.pod_name}</strong> regarding the use of the Service, superseding any prior agreements between you and <strong>#{AppConfig.settings.pod_name}</strong> relating to your use of the Service. + %p + We love feedback. Please let us know what you think of the Service, these Terms and, in general, <strong>#{AppConfig.settings.pod_name}</strong>. When you provide us with any feedback, comments or suggestions about the Service, these Terms and, in general, <strong>#{AppConfig.settings.pod_name}</strong>, you irrevocably assign to us all of your right, title and interest in and to your feedback, comments and suggestions. - %h2 - Feedback + - if AppConfig.admins.podmin_email? + %h2 + Questions & Contact Information - %p - We love feedback. Please let us know what you think of the Service, these Terms and, in general, <strong>#{AppConfig.settings.pod_name}</strong>. When you provide us with any feedback, comments or suggestions about the Service, these Terms and, in general, <strong>#{AppConfig.settings.pod_name}</strong>, you irrevocably assign to us all of your right, title and interest in and to your feedback, comments and suggestions. + %p + Questions or comments about the Service may be directed to us at the email address <a href="mailto:#{AppConfig.admins.podmin_email}">#{AppConfig.admins.podmin_email}</a>. - - if AppConfig.admins.podmin_email? - %h2 - Questions & Contact Information + .tab-pane#privacy{role: "tabpanel"} + .page-header + %h1 + #{AppConfig.settings.pod_name} - Privacy Policy - %p - Questions or comments about the Service may be directed to us at the email address <a href="mailto:#{AppConfig.admins.podmin_email}">#{AppConfig.admins.podmin_email}</a>. - %a{:name => "privacy"} + %p + Our privacy policy applies to information we collect when you use or access our website located at #{AppConfig.environment.url} and social networking services, or just interact with us. We may change this privacy policy from time to time. Whenever we make changes to this privacy policy, the changes are effective six (6) weeks after we post the revised privacy policy to our website (as indicated by revising the date at the top of our privacy policy). We encourage you to review our privacy policy whenever you access our services to stay informed about our information practices and the ways you can help protect your privacy. - %hr + %h2 + Collection of Information - %h1 - #{AppConfig.settings.pod_name} - Privacy Policy - - %p - Our privacy policy applies to information we collect when you use or access our website located at #{AppConfig.environment.url} and social networking services, or just interact with us. We may change this privacy policy from time to time. Whenever we make changes to this privacy policy, the changes are effective six (6) weeks after we post the revised privacy policy to our website (as indicated by revising the date at the top of our privacy policy). We encourage you to review our privacy policy whenever you access our services to stay informed about our information practices and the ways you can help protect your privacy. + %h3 + Information You Provide to Us - %h2 - Collection of Information + %p + We collect information you provide directly to us. For example, we collect information when you create an account, subscribe, participate in any interactive features of our services, fill out a form, request customer support or otherwise communicate with us. The types of information we may collect include your name (real of fake), email address and other contact or identifying information you choose to provide. - %h3 - Information You Provide to Us + %h3 + Information We Collect Automatically When You Use the Services - %p - We collect information you provide directly to us. For example, we collect information when you create an account, subscribe, participate in any interactive features of our services, fill out a form, request customer support or otherwise communicate with us. The types of information we may collect include your name (real of fake), email address and other contact or identifying information you choose to provide. + %p + When you access or use our services, we automatically collect information about you, including: - %h3 - Information We Collect Automatically When You Use the Services + %dl + %dt + Log Information + %dd + We may log information about your use of our services, including the type of browser you use, access times, pages viewed, your IP address and the page you visited before navigating to our services. + %dt + Device Information + %dd + We may collect information about the computer you use to access our services, including the hardware model, and operating system and version. - %p - When you access or use our services, we automatically collect information about you, including: + %h2 + Use of Information - %dl - %dt - Log Information - %dd - We may log information about your use of our services, including the type of browser you use, access times, pages viewed, your IP address and the page you visited before navigating to our services. - %dt - Device Information - %dd - We may collect information about the computer you use to access our services, including the hardware model, and operating system and version. + %p + We do not use your information for serving up ads. - %h2 - Use of Information + %p + We may use information about you for various purposes, including to: - %p - We do not use your information for serving up ads. + %ul + %li + Provide, maintain and improve our services; + %li + Send you technical notices, updates, security alerts and support and administrative messages; + %li + Respond to your comments, questions and requests; + %li + Communicate with you about <strong>#{AppConfig.settings.pod_name}</strong>-related news and information; + %li + Monitor and analyze trends, usage and activities in connection with our services; and + %li + Personalize and improve our services. - %p - We may use information about you for various purposes, including to: + %h2 + Sharing of Information - %ul - %li - Provide, maintain and improve our services; - %li - Send you technical notices, updates, security alerts and support and administrative messages; - %li - Respond to your comments, questions and requests; - %li - Communicate with you about <strong>#{AppConfig.settings.pod_name}</strong>-related news and information; - %li - Monitor and analyze trends, usage and activities in connection with our services; and - %li - Personalize and improve our services. + %p + Remember, we don't share your information with advertisers. - %h2 - Sharing of Information + %p + We may share personal information about you as follows: - %p - Remember, we don't share your information with advertisers. + %ul + %li + If we believe disclosure is reasonably necessary to comply with any applicable law, regulation, legal process or governmental request; + %li + To enforce applicable user agreements or policies, including our <a href="/terms#terms">terms of service</a>; and to protect <strong>#{AppConfig.settings.pod_name}</strong>, our users or the public from harm or illegal activities; + %li + In connection with any merger, sale of <strong>#{AppConfig.settings.pod_name}</strong> assets, financing or acquisition of all or a portion of our business to another company or individual; and + %li + If we notify you through our services (or in our privacy policy) that the information you provide will be shared in a particular manner and you provide such information. - %p - We may share personal information about you as follows: + %p + We may also share aggregated or anonymized information that does not directly identify you. - %ul - %li - If we believe disclosure is reasonably necessary to comply with any applicable law, regulation, legal process or governmental request; - %li - To enforce applicable user agreements or policies, including our <a href="/terms#terms">terms of service</a>; and to protect <strong>#{AppConfig.settings.pod_name}</strong>, our users or the public from harm or illegal activities; - %li - In connection with any merger, sale of <strong>#{AppConfig.settings.pod_name}</strong> assets, financing or acquisition of all or a portion of our business to another company or individual; and - %li - If we notify you through our services (or in our privacy policy) that the information you provide will be shared in a particular manner and you provide such information. + %h2 + Third Party Analytics - %p - We may also share aggregated or anonymized information that does not directly identify you. + %p + We may allow third parties to provide analytics services. These third parties may use cookies, web beacons and other technologies to collect information about your use of the services and other websites, including your IP address, web browser, pages viewed, time spent on pages, links clicked and conversion information. This information may be used by the Service and third parties to, among other things, analyze and track data, determine the popularity of certain content and other websites and better understand your online activity. Our privacy policy does not apply to, and we are not responsible for, third party cookies, web beacons or other tracking technologies and we encourage you to check the privacy policies of these third parties to learn more about their privacy practices. - %h2 - Third Party Analytics + %h2 + Security - %p - We may allow third parties to provide analytics services. These third parties may use cookies, web beacons and other technologies to collect information about your use of the services and other websites, including your IP address, web browser, pages viewed, time spent on pages, links clicked and conversion information. This information may be used by the Service and third parties to, among other things, analyze and track data, determine the popularity of certain content and other websites and better understand your online activity. Our privacy policy does not apply to, and we are not responsible for, third party cookies, web beacons or other tracking technologies and we encourage you to check the privacy policies of these third parties to learn more about their privacy practices. + %p + <strong>#{AppConfig.settings.pod_name}</strong> takes reasonable measures to help protect personal information from loss, theft, misuse and unauthorized access, disclosure, alteration and destruction. - %h2 - Security + %h2 + Your Information Choices - %p - <strong>#{AppConfig.settings.pod_name}</strong> takes reasonable measures to help protect personal information from loss, theft, misuse and unauthorized access, disclosure, alteration and destruction. + %h3 + Account Information - %h2 - Your Information Choices + %p + You may update, correct or delete information about you at any time by logging into your online account and modifying your personal profile. You may also delete your account at will via the settings page, but note that we may retain certain information as required by law or for legitimate business purposes. We may also retain cached or archived copies of your information for a certain period of time, for example in backup archives. - %h3 - Account Information + %h3 + Cookies - %p - You may update, correct or delete information about you at any time by logging into your online account and modifying your personal profile. You may also delete your account at will via the settings page, but note that we may retain certain information as required by law or for legitimate business purposes. We may also retain cached or archived copies of your information for a certain period of time, for example in backup archives. + %p + Most web browsers are set to accept cookies by default. If you prefer, you can usually choose to set your browser to remove or reject browser cookies. Please note that if you choose to remove or reject cookies, this could affect the availability and functionality of our services. - %h3 - Cookies + - if AppConfig.admins.podmin_email? + %h2 + Contact Us - %p - Most web browsers are set to accept cookies by default. If you prefer, you can usually choose to set your browser to remove or reject browser cookies. Please note that if you choose to remove or reject cookies, this could affect the availability and functionality of our services. - - - if AppConfig.admins.podmin_email? - %h2 - Contact Us - - %p - If you have any questions about this privacy policy, please contact us at the email address <a href="mailto:#{AppConfig.admins.podmin_email}">#{AppConfig.admins.podmin_email}</a>. + %p + If you have any questions about this privacy policy, please contact us at the email address <a href="mailto:#{AppConfig.admins.podmin_email}">#{AppConfig.admins.podmin_email}</a>. diff --git a/app/views/users/_blocked_person.haml b/app/views/users/_blocked_person.haml new file mode 100644 index 0000000000000000000000000000000000000000..b70d04a8e03f81576c5102a01bc74b1670c3550b --- /dev/null +++ b/app/views/users/_blocked_person.haml @@ -0,0 +1,12 @@ +.media.blocked_person{id: person.id} + .pull-right + = link_to t("users.privacy_settings.stop_ignoring"), block_path(block), class: "btn btn-danger", method: :delete + .media-object.pull-left + = person_image_link(person, size: :thumb_small) + .media-body + = person_link(person) + .info.diaspora_handle + = block.person.diaspora_handle + .info.tags + = Diaspora::Taggable.format_tags(person.profile.tag_string) + .clearfix diff --git a/app/views/users/_close_account_modal.haml b/app/views/users/_close_account_modal.haml index 18d422c847766664ce5261dcb9a5145bc3064ff1..15ef129350b16e18fbc3b9f8193613a2323dcdac 100644 --- a/app/views/users/_close_account_modal.haml +++ b/app/views/users/_close_account_modal.haml @@ -1,41 +1,44 @@ -.modal.hide.fade{ id: "closeAccountModal", tabindex: "-1", role: "dialog", aria: { labelledby: "closeAccountModalLabel", hidden: "true" }} - .modal-header - %button.close{type: "button", data: {dismiss: "modal"}, aria: {hidden: "true" }} - × - %h3{ id:"closeAccountModalLabel"} - = t("users.edit.close_account.dont_go") - .modal-body - .row-fluid - .text-center - = image_tag "sadcat.jpg" - %h4 - %strong - = t("users.edit.close_account.mr_wiggles") - - .small-horizontal-spacer +.modal.fade{ id: "closeAccountModal", + tabindex: "-1", + role: "dialog", + aria: { labelledby: "closeAccountModalLabel", hidden: "true" }} + .modal-dialog + .modal-content + .modal-header + %button.close{type: "button", data: {dismiss: "modal"}, aria: {hidden: "true" }} + × + %h3.modal-title{ id:"closeAccountModalLabel"} + = t("users.edit.close_account.dont_go") + = form_for "user", url: user_path, html: { method: :delete } do |f| + .modal-body + .text-center + = image_tag "sadcat.jpg", class: "img-responsive center-block" + %h4 + %strong + = t("users.edit.close_account.mr_wiggles") - .row-fluid - .span12 - = t("users.edit.close_account.make_diaspora_better") + = t("users.edit.close_account.make_diaspora_better") - .small-horizontal-spacer + %ol + %li + = t("users.edit.close_account.what_we_delete") + %li + = t("users.edit.close_account.locked_out") + %li + = t("users.edit.close_account.lock_username") - %ul - %li - = t("users.edit.close_account.what_we_delete") - %li - = t("users.edit.close_account.locked_out") - %li - = t("users.edit.close_account.lock_username") - %p %strong = t("users.edit.close_account.no_turning_back") - = form_for "user", url: user_path, html: { method: :delete } do |f| + .small-horizontal-spacer = f.error_messages - - %p + .form-group = f.label :close_account_password, t("users.edit.current_password"), for: :close_account_password - = f.password_field :current_password, id: :close_account_password - %p - = f.submit t('users.edit.close_account_text'), class: "btn btn-danger", id: "close_account_confirm", data: { confirm: t("are_you_sure_delete_account") } + = f.password_field :current_password, id: :close_account_password, class: "form-control" + .modal-footer + .btn.btn-default{type: "button", data: {dismiss: "modal"}, aria: {hidden: "true"}} + = t("cancel") + = f.submit t("users.edit.close_account_text"), + class: "btn btn-danger", + id: "close_account_confirm", + data: { confirm: t("are_you_sure_delete_account") } diff --git a/app/views/users/_edit.haml b/app/views/users/_edit.haml new file mode 100644 index 0000000000000000000000000000000000000000..aec5eccc757381c3b7c4a9678a0b45e8ffa8c9b3 --- /dev/null +++ b/app/views/users/_edit.haml @@ -0,0 +1,212 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + +- content_for :page_title do + = t(".edit_account") + +.row + .col-md-12 + .row + .col-md-6 + %h3= t(".your_handle") + + %p + %b= current_user.diaspora_handle + .col-md-6 + %h3 + = t(".your_email") + %i.entypo-lock.gray.settings-visibility{title: t("users.edit.your_email_private")} + + + = form_for "user", url: edit_user_path, + html: {method: :put, class: "form-horizontal col-md-12", id: "email-form"} do |f| + = f.error_messages + .form-group + = f.text_field :email, value: @user.unconfirmed_email || @user.email, class: "col-md-7 form-control" + .clearfix= f.submit t(".change_email"), class: "btn btn-primary pull-right" + - if @user.unconfirmed_email.present? + %div= t(".email_awaiting_confirmation", email: @user.email, unconfirmed_email: @user.unconfirmed_email) + %hr + + .row + .col-md-12 + %h3= t(".change_password") + = form_for @user, url: edit_user_path, html: {method: :put, class: "form-horizontal"} do |f| + - if (@user.errors.keys & %i(password password_confirmation current_password)).present? + = f.error_messages + .form-group + = f.label :current_password, t(".current_password"), class: "col-sm-6 control-label" + .col-sm-6 + = f.password_field :current_password, placeholder: t(".current_password_expl"), + class: "form-control" + .form-group + = f.label :password, t(".new_password"), class: "col-sm-6 control-label" + .col-sm-6 + = f.password_field :password, placeholder: t(".character_minimum_expl"), + class: "form-control" + .form-group + = f.label :password_confirmation, t("registrations.new.password_confirmation"), + class: "col-sm-6 control-label" + .col-sm-6 + = f.password_field :password_confirmation, placeholder: t(".character_minimum_expl"), + class: "form-control" + + .clearfix + = f.submit t(".change_password"), class: "btn btn-primary pull-right", name: "change_password" + %hr + + .row + .col-md-12 + %h3= t(".change_language") + = form_for "user", url: edit_user_path, html: {method: :put} do |f| + .form-inline.clearfix + = f.select :language, available_language_options, {}, class: "form-control form-group" + = f.submit t(".change_language"), class: "btn btn-primary pull-right" + %hr + + .row + .col-md-12 + %h3= t(".change_color_theme") + = form_for "user", url: edit_user_path, html: {method: :put} do |f| + .form-inline.clearfix + = f.select :color_theme, available_color_themes, {}, class: "form-control form-group" + = f.submit t(".change_color_theme"), class: "btn btn-primary pull-right" + %hr + + .row + .col-md-12 + %h3#stream-preferences + = t(".stream_preferences") + = form_for current_user, url: edit_user_path, html: {method: :put} do |f| + + = f.fields_for :stream_preferences do + #stream_prefs + - if AppConfig.settings.community_spotlight.enable? + = f.label :show_community_spotlight_in_stream, class: "checkbox-inline" do + = f.check_box :show_community_spotlight_in_stream + = t(".show_community_spotlight") + + = f.label :getting_started, class: "checkbox-inline" do + = f.check_box :getting_started + = t(".show_getting_started") + + .clearfix= f.submit t(".change"), class: "btn btn-primary pull-right" + %hr + + .row + .col-md-12 + %h3#auto-follow-back-preferences + = t(".following") + = form_for current_user, url: edit_user_path, html: {method: :put, class: "form-horizontal"} do |f| + = f.label :auto_follow_back, class: "checkbox-inline" do + = f.check_box :auto_follow_back + = t(".auto_follow_back") + .small-horizontal-spacer + .form-group.row + %label.col-sm-6.control-label= t(".auto_follow_aspect") + .col-sm-6 + = f.select :auto_follow_back_aspect_id, + aspect_options_for_select(current_user.aspects), + {}, + class: "form-control" + + .small-horizontal-spacer + .clearfix= f.submit t(".change"), class: "btn btn-primary pull-right" + %hr + + + .row + .col-md-12 + %h3 + = t(".receive_email_notifications") + = form_for "user", url: edit_user_path, html: {method: :put} do |f| + = f.fields_for :email_preferences do |type| + #email_prefs + - if current_user.admin? + = type.label :someone_reported, class: "checkbox-inline" do + = type.check_box :someone_reported, {checked: @email_prefs["someone_reported"]}, false, true + = t(".someone_reported") + + .small-horizontal-spacer + + = type.label :started_sharing, class: "checkbox-inline" do + = type.check_box :started_sharing, {checked: @email_prefs["started_sharing"]}, false, true + = t(".started_sharing") + .small-horizontal-spacer + + = type.label :mentioned, class: "checkbox-inline" do + = type.check_box :mentioned, {checked: @email_prefs["mentioned"]}, false, true + = t(".mentioned") + .small-horizontal-spacer + + = type.label :liked, class: "checkbox-inline" do + = type.check_box :liked, {checked: @email_prefs["liked"]}, false, true + = t(".liked") + .small-horizontal-spacer + + = type.label :reshared, class: "checkbox-inline" do + = type.check_box :reshared, {checked: @email_prefs["reshared"]}, false, true + = t(".reshared") + .small-horizontal-spacer + + = type.label :comment_on_post, class: "checkbox-inline" do + = type.check_box :comment_on_post, {checked: @email_prefs["comment_on_post"]}, false, true + = t(".comment_on_post") + .small-horizontal-spacer + + = type.label :also_commented, class: "checkbox-inline" do + = type.check_box :also_commented, {checked: @email_prefs["also_commented"]}, false, true + = t(".also_commented") + .small-horizontal-spacer + + = type.label :private_message, class: "checkbox-inline" do + = type.check_box :private_message, {checked: @email_prefs["private_message"]}, false, true + = t(".private_message") + + .small-horizontal-spacer + + .clearfix= f.submit t(".change"), class: "btn btn-primary pull-right", id: "change_email_preferences" + %hr + + .row + .col-md-6#account_data + %h3= t(".export_data") + .form-group + - if current_user.exporting + .export-in-progress= t(".export_in_progress") + - elsif current_user.export.present? + = link_to t(".request_export_update"), export_profile_user_path, method: :post, + class: "btn btn-default" + .small-horizontal-spacer + = link_to t(".download_export"), download_profile_user_path, + class: "btn btn-success" + .small-horizontal-spacer + %h6 + = t(".last_exported_at", timestamp: current_user.exported_at) + - else + = link_to t(".request_export"), export_profile_user_path, method: :post, + class: "btn btn-default" + + .form-group + - if current_user.exporting_photos + .export-in-progress= t(".export_photos_in_progress") + - elsif current_user.exported_photos_file.present? + = link_to t(".request_export_photos_update"), export_photos_user_path, method: :post, + class: "btn btn-default" + .small-horizontal-spacer + = link_to t(".download_export_photos"), download_photos_user_path, class: "btn btn-success" + .small-horizontal-spacer + %h6 + = t(".last_exported_at", timestamp: current_user.exported_photos_at) + - else + = link_to t(".request_export_photos"), export_photos_user_path, method: :post, + class: "btn btn-default" + + .col-md-6 + %h3 + = t(".close_account_text") + .form-group + .btn.btn-danger{id: "close_account", data: {toggle: "modal", target: "#closeAccountModal"}} + = t(".close_account_text") + = render "close_account_modal" diff --git a/app/views/users/_privacy_settings.haml b/app/views/users/_privacy_settings.haml new file mode 100644 index 0000000000000000000000000000000000000000..9a881bc5128c6aaac5d060cfd1ec20469a4e7581 --- /dev/null +++ b/app/views/users/_privacy_settings.haml @@ -0,0 +1,28 @@ +.row + .col-md-12 + %h3 + = t(".title") + + = form_for current_user, url: update_privacy_settings_path, html: {method: :put} do |f| + = f.error_messages + + = f.fields_for :stream_preferences do + .checkbox#stream_prefs + = f.label :strip_exif do + = f.check_box :strip_exif + = t(".strip_exif") + = f.submit t("users.edit.change"), class: "btn btn-primary pull-right" +%hr + +.row + .col-md-12 + %h3 + = t(".ignored_users") + + - if @blocks.length.zero? + %p + = t(".no_user_ignored_message") + - else + #blocked_people + - @blocks.each do |block| + = render partial: "blocked_person", locals: {block: block, person: block.person} diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index 78f6f8780202d6a3e34a38546e1fe89cce4e2233..0f883935f8496678e66f3b6587769e9ffebd6c2f 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -1,207 +1,8 @@ --# Copyright (c) 2010-2011, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - -- content_for :page_title do - = t('.edit_account') - -.container - .row-fluid - .span12 - #section_header - %h2 - = t('settings') - = render 'shared/settings_nav' - - .row-fluid - .span3 - .span6 - .row-fluid - .span6 - %h3 - = t('.your_handle') - %p - %b= current_user.diaspora_handle - .span6 - %h3 - = t('.your_email') - %i.entypo.lock.gray.settings_visibilty{title: t("users.edit.your_email_private")} - - = form_for 'user', :url => user_path, :html => { :method => :put } do |f| - = f.error_messages - .form-inline - = f.text_field :email, :value => @user.unconfirmed_email || @user.email, :class => "span7" - = f.submit t('.change_email'), :class => "btn" - .small-horizontal-spacer - - if @user.unconfirmed_email.present? - %p= t('.email_awaiting_confirmation', :email => @user.email, :unconfirmed_email => @user.unconfirmed_email) - .small-horizontal-spacer - - %hr - - .row-fluid - .span12 - %h3 - = t('.change_password') - = form_for @user, :url => user_path, :html => { :method => :put } do |f| - - if (@user.errors.keys & [:password, :password_confirmation, :current_password]).present? - = f.error_messages - %p - = f.label :current_password, t('.current_password') - = f.password_field :current_password, :placeholder => t('.current_password_expl') - %p - = f.label :password, t('.new_password') - = f.password_field :password, :placeholder => t('.character_minimum_expl') - %p - = f.label :password_confirmation, t('password_confirmation') - = f.password_field :password_confirmation, :placeholder => t('.character_minimum_expl') - - .submit_block - = link_to t('cancel'), edit_user_path - = t('or') - = f.submit t('.change_password'), class: "btn", name: 'change_password' - - %hr - - .row-fluid - .span-12 - %h3 - = t('.change_language') - = form_for 'user', :url => user_path, :html => { :method => :put } do |f| - .form-inline - = f.select :language, available_language_options - = f.submit t('.change_language'), :class => "btn" - - %hr - - .row-fluid - .span-12 - - %h3#stream-preferences - = t('.stream_preferences') - = form_for current_user, :url => user_path, :html => { :method => :put } do |f| - - = f.fields_for :stream_preferences do |type| - #stream_prefs - - if AppConfig.settings.community_spotlight.enable? - = f.label :show_community_spotlight_in_stream, :class => "checkbox" do - = f.check_box :show_community_spotlight_in_stream - = t('.show_community_spotlight') - - .small-horizontal-spacer - = f.label :getting_started, :class => "checkbox" do - = f.check_box :getting_started - = t('.show_getting_started') - - .small-horizontal-spacer - = f.submit t('.change'), :class => 'btn' - - %hr - - .row-fluid - .span-12 - - %h3#auto-follow-back-preferences - = t('.following') - = form_for current_user, :url => user_path, :html => { :method => :put } do |f| - = f.label :auto_follow_back, :class => "checkbox" do - = f.check_box :auto_follow_back - = t('.auto_follow_back') - .small-horizontal-spacer - %div{:class => "muted"} - = t('.auto_follow_aspect') - = f.select :auto_follow_back_aspect_id, aspect_options_for_select(current_user.aspects) - - .small-horizontal-spacer - = f.submit t('.change'), :class => 'btn' - - %hr - - .row-fluid - .span-12 - %h3 - = t('.receive_email_notifications') - = form_for 'user', :url => user_path, :html => { :method => :put } do |f| - = f.fields_for :email_preferences do |type| - #email_prefs - - if current_user.admin? - = type.label :someone_reported, :class => "checkbox" do - = type.check_box :someone_reported, {:checked => @email_prefs['someone_reported']}, false, true - = t('.someone_reported') - - .small-horizontal-spacer - - = type.label :started_sharing, :class => "checkbox" do - = type.check_box :started_sharing, {:checked => @email_prefs['started_sharing']}, false, true - = t('.started_sharing') - .small-horizontal-spacer - - = type.label :mentioned, :class => "checkbox" do - = type.check_box :mentioned, {:checked => @email_prefs['mentioned']}, false, true - = t('.mentioned') - .small-horizontal-spacer - - = type.label :liked, :class => "checkbox" do - = type.check_box :liked, {:checked => @email_prefs['liked']}, false, true - = t('.liked') - .small-horizontal-spacer - - = type.label :reshared, :class => "checkbox" do - = type.check_box :reshared, {:checked => @email_prefs['reshared']}, false, true - = t('.reshared') - .small-horizontal-spacer - - = type.label :comment_on_post, :class => "checkbox" do - = type.check_box :comment_on_post, {:checked => @email_prefs['comment_on_post']}, false, true - = t('.comment_on_post') - .small-horizontal-spacer - - = type.label :also_commented, :class => "checkbox" do - = type.check_box :also_commented, {:checked => @email_prefs['also_commented']}, false, true - = t('.also_commented') - .small-horizontal-spacer - - = type.label :private_message, :class => "checkbox" do - = type.check_box :private_message, {:checked => @email_prefs['private_message']}, false, true - = t('.private_message') - - .small-horizontal-spacer - - = f.submit t('.change'), :class => "btn", :id => "change_email_preferences" - - %hr - - .row-fluid - #account_data.span6 - %h3 - = t('.export_data') - - if current_user.exporting - .export-in-progress= t('.export_in_progress') - - elsif current_user.export.present? - = link_to t('.download_export'), download_profile_user_path, class: "btn btn-success" - %h6 - = t('.last_exported_at', timestamp: current_user.exported_at) - = link_to t(".request_export_update"), export_profile_user_path, method: :post, class: "btn" - - else - = link_to t(".request_export"), export_profile_user_path, method: :post, class: "btn" - - - if current_user.exporting_photos - .small-horizontal-spacer - .export-in-progress= t('.export_photos_in_progress') - - elsif current_user.exported_photos_file.present? - .small-horizontal-spacer - = link_to t('.download_export_photos'), download_photos_user_path, class: "btn btn-success" - %h6 - = t('.last_exported_at', timestamp: current_user.exported_photos_at) - = link_to t(".request_export_photos_update"), export_photos_user_path, method: :post, class: "btn" - - else - .small-horizontal-spacer - = link_to t(".request_export_photos"), export_photos_user_path, method: :post, class: "btn" - - .span6 - %h3 - = t(".close_account_text") - .btn.btn-danger{ id: "close_account", data: {toggle: "modal", target: "#closeAccountModal"}} - = t(".close_account_text") - - = render "close_account_modal" +.container-fluid + .row + .col-md-3 + .sidebar + = render "shared/settings_nav" + .col-md-9 + .framed-content + = render "edit" diff --git a/app/views/users/edit.mobile.haml b/app/views/users/edit.mobile.haml index 900b7b0b51cc28b554ec19dd39dc4670bc9df2a7..77f9bb52d27c592a9e6293725304023d273e5a56 100644 --- a/app/views/users/edit.mobile.haml +++ b/app/views/users/edit.mobile.haml @@ -1,196 +1,8 @@ --# Copyright (c) 2010-2011, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - -- content_for :page_title do - = t('.edit_account') - -.stream - - flash.each do |name, msg| - %div{:id => "flash_#{name}", :class => "expose"} - .message= msg - .stream - %p{:class => "conversation_#{name}"}= msg - -#section_header - %h3 - = t('settings') - = render 'shared/settings_nav' - -.span-12.prepend-5.last - %hr - - %h4 - = t('.your_handle') - %p - %b= current_user.diaspora_handle - - %h4 - = t('.your_email') - = form_for 'user', :url => user_path, :html => { :method => :put } do |f| - = f.error_messages - %p - = f.text_field :email, :value => @user.unconfirmed_email || @user.email - = f.submit t('.change_email'), :class => "btn" - - if @user.unconfirmed_email.present? - %p= t('.email_awaiting_confirmation', :email => @user.email, :unconfirmed_email => @user.unconfirmed_email) - - %hr - - %h4 - = t('.change_password') - = form_for 'user', :url => user_path, :html => { :method => :put } do |f| - = f.error_messages - %p - = f.label :current_password, t('.current_password') - = f.password_field :current_password, :placeholder => t('.current_password_expl') - %p - = f.label :password, t('.new_password') - = f.password_field :password, :placeholder => t('.character_minimum_expl') - %p - = f.label :password_confirmation, t('password_confirmation') - = f.password_field :password_confirmation, :placeholder => t('.character_minimum_expl') - - .submit_block - = f.submit t('.change_password'), :class => "btn" - - %hr - - %h4 - = t('.change_language') - = form_for 'user', :url => user_path, :html => { :method => :put } do |f| - = f.error_messages - - %p - = f.select :language, available_language_options - = f.submit t('.change_language'), :class => "btn" - - %hr - - %h4#stream-preferences - = t('.stream_preferences') - = form_for current_user, :url => user_path, :html => { :method => :put } do |f| - = f.error_messages - - = f.fields_for :stream_preferences do |type| - #stream_prefs - %p.checkbox_select - = f.label :show_community_spotlight_in_stream, t('.show_community_spotlight') - = f.check_box :show_community_spotlight_in_stream - - %br - %p.checkbox_select - = f.label :getting_started, t('.show_getting_started') - = f.check_box :getting_started - - %br - = f.submit t('.change'), :class => 'button' - - %hr - - %h4#auto-follow-back-preferences - = t('.following') - = form_for current_user, :url => user_path, :html => { :method => :put } do |f| - = f.error_messages - - %p.checkbox_select - = f.label :auto_follow_back, t('.auto_follow_back') - = f.check_box :auto_follow_back - %br - %p.checkbox_select - %span{:style => "color: #999"} - = t('.auto_follow_aspect') - = f.select :auto_follow_back_aspect_id, aspect_options_for_select(current_user.aspects) - %br - = f.submit t('.change'), :class => 'btn' - - %hr - - %h4 - = t('.receive_email_notifications') - = form_for 'user', :url => user_path, :html => { :method => :put } do |f| - = f.error_messages - - = f.fields_for :email_preferences do |type| - #email_prefs - - if current_user.admin? - %p.checkbox_select - = type.label :someone_reported, t('.someone_reported') - = type.check_box :someone_reported, {:checked => @email_prefs['someone_reported']}, false, true - - %br - %p.checkbox_select - = type.label :started_sharing, t('.started_sharing') - = type.check_box :started_sharing, {:checked => @email_prefs['started_sharing']}, false, true - %br - - %p.checkbox_select - = type.label :mentioned, t('.mentioned') - = type.check_box :mentioned, {:checked => @email_prefs['mentioned']}, false, true - %br - - %p.checkbox_select - = type.label :liked, t('.liked') - = type.check_box :liked, {:checked => @email_prefs['liked']}, false, true - %br - - %p.checkbox_select - = type.label :reshared, t('.reshared') - = type.check_box :reshared, {:checked => @email_prefs['reshared']}, false, true - %br - - %p.checkbox_select - = type.label :comment_on_post, t('.comment_on_post') - = type.check_box :comment_on_post, {:checked => @email_prefs['comment_on_post']}, false, true - %br - - %p.checkbox_select - = type.label :also_commented, t('.also_commented') - = type.check_box :also_commented, {:checked => @email_prefs['also_commented']}, false, true - %br - - %p.checkbox_select - = type.label :private_message, t('.private_message') - = type.check_box :private_message, {:checked => @email_prefs['private_message']}, false, true - - %br - = f.submit t('.change'), :class => "button" - - %hr - - #account_data.span-5.append-2 - %h4 - = t('.export_data') - - if current_user.exporting - .export-in-progress= t('.export_in_progress') - - elsif current_user.export.present? - = link_to t('.download_export'), download_profile_user_path, class: "btn btn-success" - %h6 - = t('.last_exported_at', timestamp: current_user.exported_at) - = link_to t('.request_export_update'), export_profile_user_path, class: "btn", method: :post - - else - = link_to t('.request_export'), export_profile_user_path, class: "btn", method: :post - %br - %br - - if current_user.exporting_photos - .export-in-progress= t('.export_photos_in_progress') - - elsif current_user.exported_photos_file.present? - = link_to t('.download_export_photos'), download_photos_user_path, class: "btn btn-success" - %h6 - = t('.last_exported_at', timestamp: current_user.exported_photos_at) - = link_to t('.request_export_photos_update'), export_photos_user_path, class: "btn", method: :post - - else - = link_to t('.request_export_photos'), export_photos_user_path, class: "btn", method: :post - - %hr - .span-5.last - %h4 - = t('.close_account_text') - = form_for "user", url: user_path, html: { method: :delete } do |f| - = f.error_messages - - %p - = f.label :close_account_password, t("users.edit.current_password"), for: :close_account_password - = f.password_field :current_password, id: :close_account_password - %p - = f.submit t('users.edit.close_account_text'), class: "btn btn-danger", id: "close_account_confirm", data: { confirm: t("are_you_sure_delete_account") } +.settings_container.container-fluid + .row + .col-md-12 + = render "shared/settings_nav" + + .row + .col-md-12 + = render "edit" diff --git a/app/views/users/getting_started.haml b/app/views/users/getting_started.haml index 0da1ed832b6aedcc4dbd33e7bd52d7e55a5eef0b..c35c8a9f773f68643d248fbff13da4d44eb3048b 100644 --- a/app/views/users/getting_started.haml +++ b/app/views/users/getting_started.haml @@ -1,6 +1,6 @@ .container .row - %section#hello-there.span12 + %section#hello-there.col-md-12 .hero-unit %h1.text-center = t('.well_hello_there') @@ -9,32 +9,37 @@ = invited_by_message - %h2 + .small-horizontal-spacer + + %h3 = t(".who_are_you") - if AppConfig.configured_services.include? :facebook %p - != t('.connect_to_facebook', :link => link_to(t('.connect_to_facebook_link'), "auth/facebook?callback_url=#{getting_started_url}")) + != t('.connect_to_facebook', link: link_to(t('.connect_to_facebook_link'), "auth/facebook?callback_url=#{getting_started_url}")) - = form_tag profile_path, :method => :put, :remote => true, :id => 'edit_profile' do + = form_tag profile_path, method: :put, remote: true, id: 'edit_profile' do %fieldset - = label_tag 'profile[first_name]', t('profiles.edit.your_name') - = text_field_tag 'profile[first_name]', current_user.first_name - = image_tag 'ajax-loader.gif', :id => "gs-name-form-spinner", :class => "hidden" - = label_tag :your_photo, t('profiles.edit.your_photo') - = render 'photos/new_profile_photo', :aspect => :getting_started, :person => current_user.person - - %h2 + .form-group + = label_tag 'profile[first_name]', t('profiles.edit.your_name') + = text_field_tag 'profile[first_name]', current_user.first_name, class: "form-control" + .form-group + #gs-name-form-spinner.hidden + .loader + .spinner + = label_tag :your_photo, t('profiles.edit.your_photo') + = render 'photos/new_profile_photo', aspect: :getting_started, person: current_user.person + + %h3 = t('.what_are_you_in_to') %p = t('.hashtag_explanation') - = form_tag(tag_followings_path, :method => 'get', :class => "tag_input search_form") do + = form_tag(tag_followings_path, method: 'get', class: "tag_input search_form") do %fieldset = label_tag 'follow_tags', t('.hashtag_suggestions') #tags_list - = text_field_tag 'follow_tags', nil, :class => "nostrap" - - .awesome - = link_to "#{t('.awesome_take_me_to_diaspora')} »", stream_path, :id => "awesome_button", :class => "btn creation" + = text_field_tag 'follow_tags', nil, class: "nostrap form-control" + .text-center.awesome + = link_to "#{t('.awesome_take_me_to_diaspora')} >>", stream_path, id: "awesome_button", class: "btn btn-default btn-lg btn-primary" diff --git a/app/views/users/getting_started.mobile.haml b/app/views/users/getting_started.mobile.haml index c1e008bf1b001a67a7bdd09eebd48989804a4073..2ab3a3f6ce2c5193c1262a8898e49b7f2d3d03e8 100644 --- a/app/views/users/getting_started.mobile.haml +++ b/app/views/users/getting_started.mobile.haml @@ -25,7 +25,7 @@ }); autocompleteInput.bind('keydown', function(evt){ - if(evt.keyCode == 13 || evt.keyCode == 9 || evt.keyCode == 32){ + if(evt.which === Keycodes.ENTER || evt.which === Keycodes.TAB || evt.which === Keycodes.SPACE) { evt.preventDefault(); if( $('li.as-result-item.active').length == 0 ){ $('li.as-result-item').first().click(); @@ -53,19 +53,16 @@ - if AppConfig.configured_services.include? :facebook %p - != t('.connect_to_facebook', :link => link_to(t('.connect_to_facebook_link'), "auth/facebook?callback_url=#{getting_started_url}")) + != t('.connect_to_facebook', link: link_to(t('.connect_to_facebook_link'), "auth/facebook?callback_url=#{getting_started_url}")) - = form_tag profile_path, :method => :put, :remote => true, :id => 'edit_profile' do + = form_tag profile_path, method: :put, remote: true, id: "edit_profile" do %fieldset - = label_tag 'profile[first_name]', t('profiles.edit.your_name'), :class => "bootstrapped" - = text_field_tag 'profile[first_name]', current_user.first_name - = image_tag 'ajax-loader.gif', :id => "gs-name-form-spinner", :class => "hidden" - %span.saved{:class => "hidden"} - = image_tag "mobile/check_yes_ok.png" - = t(".saved") - - = label_tag :your_photo, t('profiles.edit.your_photo'), :class => "bootstrapped" - = render 'photos/new_profile_photo', :aspect => :getting_started, :person => current_user.person + .form-group + = label_tag "profile[first_name]", t("profiles.edit.your_name") + = text_field_tag "profile[first_name]", current_user.first_name, class: "form-control" + .form-group + = label_tag :your_photo, t("profiles.edit.your_photo") + = render "photos/new_profile_photo", aspect: :getting_started, person: current_user.person %h2 = t('.what_are_you_in_to') @@ -73,11 +70,14 @@ %p = t('.hashtag_explanation') - = form_tag(tag_followings_path, :method => 'get', :class => "tag_input search_form") do + = form_tag(tag_followings_path, method: "get", class: "tag_input search_form") do %fieldset - = label_tag 'follow_tags', t('.hashtag_suggestions'), :class => "bootstrapped" - = text_field_tag 'follow_tags', nil, :class => "nostrap" + = label_tag "follow_tags", t(".hashtag_suggestions") + = text_field_tag "follow_tags", nil, class: "nostrap form-control" .center - = link_to "#{t('.awesome_take_me_to_diaspora')} »", stream_path, :id => "awesome_button", :class => "button creation" + = link_to "#{t('.awesome_take_me_to_diaspora')} »", + getting_started_completed_path, + id: "awesome_button", + class: "btn btn-primary" diff --git a/app/views/users/privacy_settings.html.haml b/app/views/users/privacy_settings.html.haml index 82b724f5c1582a8afa24c3be51dd84b80427aeef..fc0fa4c8c2ab40108bd2cbd2ea41d3ef8c223ab5 100644 --- a/app/views/users/privacy_settings.html.haml +++ b/app/views/users/privacy_settings.html.haml @@ -5,47 +5,11 @@ - content_for :page_title do = t('.title') -.container - .row-fluid - .span12 - #section_header - %h2 - = t('privacy') - = render 'shared/settings_nav' - - .row-fluid - .span3 - .span5 - %h3 - = t('.title') - - = form_for current_user, :url => user_path, :html => { :method => :put } do |f| - = f.error_messages - - = f.fields_for :stream_preferences do |type| - #stream_prefs - = f.label :strip_exif, :class => "checkbox" do - = f.check_box :strip_exif - = t('.strip_exif') - - .small-horizontal-spacer - = f.submit t('users.edit.change'), :class => 'btn' - - %hr - - .row-fluid - .span3 - .span5 - %h3 - = t('.ignored_users') - - - if @blocks.length.zero? - = t('.no_user_ignored_message') - - - @blocks.each do |block| - = block.person_name - \- - = link_to t('.stop_ignoring'), block_path(block), - :method => :delete - %br - .span3 +.container-fluid + .row + .col-md-3 + .sidebar + = render "shared/settings_nav" + .col-md-9 + .framed-content + = render "privacy_settings" diff --git a/app/views/users/privacy_settings.mobile.haml b/app/views/users/privacy_settings.mobile.haml new file mode 100644 index 0000000000000000000000000000000000000000..231f164dc5d9fa4d254dd410b8d397f1097880d6 --- /dev/null +++ b/app/views/users/privacy_settings.mobile.haml @@ -0,0 +1,15 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + +- content_for :page_title do + = t(".title") + +.settings_container.container-fluid + .row + .col-md-12 + = render "shared/settings_nav" + + .row + .col-md-12 + = render "privacy_settings" diff --git a/app/workers/base.rb b/app/workers/base.rb index b8a26d31e65518691dc239f1a20258b7a54c6e91..874261e239f0c9a263f55bf3cb8bdd9a308d8db9 100644 --- a/app/workers/base.rb +++ b/app/workers/base.rb @@ -6,28 +6,8 @@ module Workers class Base include Sidekiq::Worker sidekiq_options backtrace: (bt = AppConfig.environment.sidekiq.backtrace.get) && bt.to_i, - retry: (rt = AppConfig.environment.sidekiq.retry.get) && rt.to_i + retry: (rt = AppConfig.environment.sidekiq.retry.get) && rt.to_i include Diaspora::Logging - - # In the long term we need to eliminate the cause of these - def suppress_annoying_errors(&block) - yield - rescue Diaspora::ContactRequiredUnlessRequest, - Diaspora::RelayableObjectWithoutParent, - # Friendica seems to provoke these - Diaspora::AuthorXMLAuthorMismatch, - # We received a private object to our public endpoint, again something - # Friendica seems to provoke - Diaspora::NonPublic, - Diaspora::XMLNotParseable => e - logger.warn "error on receive: #{e.class}" - rescue ActiveRecord::RecordInvalid => e - logger.warn "failed to save received object: #{e.record.errors.full_messages}" - raise e unless [ - "already been taken", - "is ignored by the post author" - ].any? {|reason| e.message.include? reason } - end end end diff --git a/app/workers/clean_cached_files.rb b/app/workers/clean_cached_files.rb index 3497803d825c0a97461c6aad9128c9a735d5c1ca..ddf2e93d3f4ac4fd47319cfee2e3d1957863c761 100644 --- a/app/workers/clean_cached_files.rb +++ b/app/workers/clean_cached_files.rb @@ -1,13 +1,9 @@ module Workers class CleanCachedFiles < Base - include Sidetiq::Schedulable - - sidekiq_options queue: :maintenance - - recurrence { daily } + sidekiq_options queue: :low def perform CarrierWave.clean_cached_files! end - end + end end diff --git a/app/workers/deferred_dispatch.rb b/app/workers/deferred_dispatch.rb index 46fa894c39bf17848790cc07e2dd0859f979ed3c..49d0aa365d4e9418bbb1b2cad55664ea0ebf3dbd 100644 --- a/app/workers/deferred_dispatch.rb +++ b/app/workers/deferred_dispatch.rb @@ -4,19 +4,14 @@ module Workers class DeferredDispatch < Base - sidekiq_options queue: :dispatch + sidekiq_options queue: :high def perform(user_id, object_class_name, object_id, opts) user = User.find(user_id) object = object_class_name.constantize.find(object_id) opts = HashWithIndifferentAccess.new(opts) - opts[:services] = user.services.where(:type => opts.delete(:service_types)) - if opts[:additional_subscribers].present? - opts[:additional_subscribers] = Person.where(:id => opts[:additional_subscribers]) - end - - Postzord::Dispatcher.build(user, object, opts).post + Diaspora::Federation::Dispatcher.build(user, object, opts).dispatch rescue ActiveRecord::RecordNotFound # The target got deleted before the job was run end end diff --git a/app/workers/deferred_retraction.rb b/app/workers/deferred_retraction.rb new file mode 100644 index 0000000000000000000000000000000000000000..5f3b8834a5dae4455327ba48f0a43843a2e365ef --- /dev/null +++ b/app/workers/deferred_retraction.rb @@ -0,0 +1,18 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +module Workers + class DeferredRetraction < Base + sidekiq_options queue: :high + + def perform(user_id, retraction_data, recipient_ids, opts) + user = User.find(user_id) + subscribers = Person.where(id: recipient_ids) + object = Retraction.new(retraction_data.deep_symbolize_keys, subscribers) + opts = HashWithIndifferentAccess.new(opts) + + Diaspora::Federation::Dispatcher.build(user, object, opts).dispatch + end + end +end diff --git a/app/workers/delete_account.rb b/app/workers/delete_account.rb index ef3991f2912e1f3230a5ffab8e1cb717ca7c40cb..e3aa95eff1f96a8ee3ac5fa2866ac6002a76efa1 100644 --- a/app/workers/delete_account.rb +++ b/app/workers/delete_account.rb @@ -5,7 +5,7 @@ module Workers class DeleteAccount < Base - sidekiq_options queue: :delete_account + sidekiq_options queue: :low def perform(account_deletion_id) account_deletion = AccountDeletion.find(account_deletion_id) diff --git a/app/workers/delete_post_from_service.rb b/app/workers/delete_post_from_service.rb index 9efd3bb189cf5c1ab1b0fc0062b86082b45c30f2..7d0bfe1fd5b1714b5958b13f507842dad88a78f0 100644 --- a/app/workers/delete_post_from_service.rb +++ b/app/workers/delete_post_from_service.rb @@ -4,12 +4,12 @@ # module Workers class DeletePostFromService < Base - sidekiq_options queue: :http_service + sidekiq_options queue: :high - def perform(service_id, post_id) + def perform(service_id, opts) service = Service.find_by_id(service_id) - post = Post.find_by_id(post_id) - service.delete_post(post) + opts = HashWithIndifferentAccess.new(opts) + service.delete_from_service(opts) end end end diff --git a/app/workers/export_photos.rb b/app/workers/export_photos.rb index a0f2471e9b07d60f8f67fd958364ec860ce7ad75..3d036462a6ef65a32b4c5fcdd0d2026aa62f621f 100644 --- a/app/workers/export_photos.rb +++ b/app/workers/export_photos.rb @@ -5,7 +5,7 @@ module Workers class ExportPhotos < Base - sidekiq_options queue: :export + sidekiq_options queue: :low def perform(user_id) @user = User.find(user_id) diff --git a/app/workers/export_user.rb b/app/workers/export_user.rb index 2e1e55aa8c67e905a3eed445ff92fbde9b9f5bb4..26fadc1fbafd18a81f6a01a4d33b88a7693ba143 100644 --- a/app/workers/export_user.rb +++ b/app/workers/export_user.rb @@ -5,7 +5,7 @@ module Workers class ExportUser < Base - sidekiq_options queue: :export + sidekiq_options queue: :low def perform(user_id) @user = User.find(user_id) diff --git a/app/workers/fetch_profile_photo.rb b/app/workers/fetch_profile_photo.rb index bea7e104cf3ac65020df26f79b9a924ed1611a13..8eb370ecb631c4f12b3c74138b96442bb3f49047 100644 --- a/app/workers/fetch_profile_photo.rb +++ b/app/workers/fetch_profile_photo.rb @@ -5,7 +5,7 @@ module Workers class FetchProfilePhoto < Base - sidekiq_options queue: :photos + sidekiq_options queue: :medium def perform(user_id, service_id, fallback_image_url = nil) service = Service.find(service_id) diff --git a/app/workers/fetch_public_posts.rb b/app/workers/fetch_public_posts.rb index 8b5ca00c8034db8e863a7591a4bbf5a7b1c41f65..228efe81ee2bc976a99575b00ffb9cd79def33f3 100644 --- a/app/workers/fetch_public_posts.rb +++ b/app/workers/fetch_public_posts.rb @@ -4,7 +4,7 @@ module Workers class FetchPublicPosts < Base - sidekiq_options queue: :http_service + sidekiq_options queue: :medium def perform(diaspora_id) Diaspora::Fetcher::Public.new.fetch!(diaspora_id) diff --git a/app/workers/fetch_webfinger.rb b/app/workers/fetch_webfinger.rb index 3b277824de14ce66f4d3692828413cb76e15da55..182304ef8fd38ccfd3664c11bb8992163ed13308 100644 --- a/app/workers/fetch_webfinger.rb +++ b/app/workers/fetch_webfinger.rb @@ -4,7 +4,7 @@ module Workers class FetchWebfinger < Base - sidekiq_options queue: :socket_webfinger + sidekiq_options queue: :urgent def perform(account) person = Person.find_or_fetch_by_identifier(account) diff --git a/app/workers/gather_o_embed_data.rb b/app/workers/gather_o_embed_data.rb index cb0ad08197fa63524f86c600091d1828df5badc1..e6eb695b215f393f4a51c48a367feff771b4d4f3 100644 --- a/app/workers/gather_o_embed_data.rb +++ b/app/workers/gather_o_embed_data.rb @@ -5,7 +5,7 @@ module Workers class GatherOEmbedData < Base - sidekiq_options queue: :http_service + sidekiq_options queue: :medium def perform(post_id, url, retry_count=1) post = Post.find(post_id) diff --git a/app/workers/gather_open_graph_data.rb b/app/workers/gather_open_graph_data.rb index 18c97ab8b18c85e5d785fcf5e5be5e131cbde522..f962e04119642ccc22f74bf54691b8e4d3080b44 100644 --- a/app/workers/gather_open_graph_data.rb +++ b/app/workers/gather_open_graph_data.rb @@ -5,7 +5,7 @@ module Workers class GatherOpenGraphData < Base - sidekiq_options queue: :http_service + sidekiq_options queue: :medium def perform(post_id, url, retry_count=1) post = Post.find(post_id) diff --git a/app/workers/http_multi.rb b/app/workers/http_multi.rb deleted file mode 100644 index dfc1b95914423c9b14e5463b3ede9165ad1b418a..0000000000000000000000000000000000000000 --- a/app/workers/http_multi.rb +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Workers - class HttpMulti < Base - sidekiq_options queue: :http - - MAX_RETRIES = 3 - ABANDON_ON_CODES=[:peer_failed_verification, # Certificate does not match URL - :ssl_connect_error, # Problem negotiating ssl version or Cert couldn't be verified (often self-signed) - :ssl_cacert, # Expired SSL cert - ] - def perform(user_id, encoded_object_xml, person_ids, dispatcher_class_as_string, retry_count=0) - user = User.find(user_id) - people = Person.where(:id => person_ids) - - dispatcher = dispatcher_class_as_string.constantize - hydra = HydraWrapper.new(user, people, encoded_object_xml, dispatcher) - - hydra.enqueue_batch - - hydra.keep_for_retry_if do |response| - !ABANDON_ON_CODES.include?(response.return_code) - end - - hydra.run - - - unless hydra.people_to_retry.empty? - if retry_count < MAX_RETRIES - Workers::HttpMulti.perform_in(1.hour, user_id, encoded_object_xml, hydra.people_to_retry, dispatcher_class_as_string, retry_count + 1) - else - logger.info "event=http_multi_abandon sender_id=#{user_id} failed_recipient_ids='[#{person_ids.join(', ')}]'" - end - end - end - end -end - - - - diff --git a/app/workers/mail/also_commented.rb b/app/workers/mail/also_commented.rb index 2197c8e25d7ef29f1612d0ca8fe1af4b47151336..52026e737af6b1de743622bb48c056c75d90b281 100644 --- a/app/workers/mail/also_commented.rb +++ b/app/workers/mail/also_commented.rb @@ -1,7 +1,7 @@ module Workers module Mail class AlsoCommented < Base - sidekiq_options queue: :mail + sidekiq_options queue: :low def perform(recipient_id, sender_id, comment_id) if email = Notifier.also_commented(recipient_id, sender_id, comment_id) diff --git a/app/workers/mail/comment_on_post.rb b/app/workers/mail/comment_on_post.rb index fc397518d19c5e0247f5a9c6e6fa205341054d92..070eb8e33a23efbb1dfdc3f4b567c5748c0fc21f 100644 --- a/app/workers/mail/comment_on_post.rb +++ b/app/workers/mail/comment_on_post.rb @@ -1,7 +1,7 @@ module Workers module Mail class CommentOnPost < Base - sidekiq_options queue: :mail + sidekiq_options queue: :low def perform(recipient_id, sender_id, comment_id) Notifier.comment_on_post(recipient_id, sender_id, comment_id).deliver_now diff --git a/app/workers/mail/confirm_email.rb b/app/workers/mail/confirm_email.rb index 05a9cef5e4e13adacc83acbff62732183ac606d4..252f030c61dd83cd9efa87235a010fb6bc3a1ed7 100644 --- a/app/workers/mail/confirm_email.rb +++ b/app/workers/mail/confirm_email.rb @@ -1,7 +1,7 @@ module Workers module Mail class ConfirmEmail < Base - sidekiq_options queue: :mail + sidekiq_options queue: :low def perform(user_id) Notifier.confirm_email(user_id).deliver_now diff --git a/app/workers/mail/invite_email.rb b/app/workers/mail/invite_email.rb index 685d628e54243ad98c648e4336ac2dd24e6e9d5f..0b18841d9e927d669446f35171c2ac553bf317d2 100644 --- a/app/workers/mail/invite_email.rb +++ b/app/workers/mail/invite_email.rb @@ -5,7 +5,7 @@ module Workers module Mail class InviteEmail < Base - sidekiq_options queue: :mail + sidekiq_options queue: :low def perform(emails, inviter_id, options={}) EmailInviter.new(emails, User.find(inviter_id), options).send! diff --git a/app/workers/mail/liked.rb b/app/workers/mail/liked.rb index d2b2748c9dd0a96fd9534121972d0b2f5bb92479..595af3e39fd907821e6ec55196ca9440df93f0f3 100644 --- a/app/workers/mail/liked.rb +++ b/app/workers/mail/liked.rb @@ -1,7 +1,7 @@ module Workers module Mail class Liked < Base - sidekiq_options queue: :mail + sidekiq_options queue: :low def perform(recipient_id, sender_id, like_id) Notifier.liked(recipient_id, sender_id, like_id).deliver_now diff --git a/app/workers/mail/mentioned.rb b/app/workers/mail/mentioned.rb index 06dac676bfc69ca98bca3fe0b7809ab297a71e51..a32f30f11fd8ce423208ac720abec6c2a1744a69 100644 --- a/app/workers/mail/mentioned.rb +++ b/app/workers/mail/mentioned.rb @@ -6,7 +6,7 @@ module Workers module Mail class Mentioned < Base - sidekiq_options queue: :mail + sidekiq_options queue: :low def perform(recipient_id, actor_id, target_id) Notifier.mentioned( recipient_id, actor_id, target_id).deliver_now diff --git a/app/workers/mail/private_message.rb b/app/workers/mail/private_message.rb index 6d48d5dbf94de493c0ef5c9424fa55e76cbd2751..d24ce0296b6b3e3fc82c86f7404577adba1adbaa 100644 --- a/app/workers/mail/private_message.rb +++ b/app/workers/mail/private_message.rb @@ -6,7 +6,7 @@ module Workers module Mail class PrivateMessage < Base - sidekiq_options queue: :mail + sidekiq_options queue: :low def perform(recipient_id, actor_id, target_id) Notifier.private_message( recipient_id, actor_id, target_id).deliver_now diff --git a/app/workers/mail/report_worker.rb b/app/workers/mail/report_worker.rb index ede0f0867f1ba199d60bebae139eb781fa866f2d..8139266e63f35644427bb1d76e337694dc984a8d 100644 --- a/app/workers/mail/report_worker.rb +++ b/app/workers/mail/report_worker.rb @@ -1,10 +1,10 @@ module Workers module Mail class ReportWorker < Base - sidekiq_options queue: :mail + sidekiq_options queue: :low - def perform(type, id) - ReportMailer.new_report(type, id).each(&:deliver_now) + def perform(report_id) + ReportMailer.new_report(report_id).each(&:deliver_now) end end end diff --git a/app/workers/mail/reshared.rb b/app/workers/mail/reshared.rb index 20df36ac02389c8918e5e39e61aa99228a8b4ac8..1144147adf8cd82ee533767abf6816a99c0dc135 100644 --- a/app/workers/mail/reshared.rb +++ b/app/workers/mail/reshared.rb @@ -1,7 +1,7 @@ module Workers module Mail class Reshared < Base - sidekiq_options queue: :mail + sidekiq_options queue: :low def perform(recipient_id, sender_id, reshare_id) Notifier.reshared(recipient_id, sender_id, reshare_id).deliver_now diff --git a/app/workers/mail/started_sharing.rb b/app/workers/mail/started_sharing.rb index 3bc4938c8812b4f17c985c67f1d1ef1d2af5e48e..3618d1527ad3142fd8bb81c26829e072acb5e905 100644 --- a/app/workers/mail/started_sharing.rb +++ b/app/workers/mail/started_sharing.rb @@ -6,7 +6,7 @@ module Workers module Mail class StartedSharing < Base - sidekiq_options queue: :mail + sidekiq_options queue: :low def perform(recipient_id, sender_id, target_id) Notifier.started_sharing(recipient_id, sender_id).deliver_now diff --git a/app/workers/notify_local_users.rb b/app/workers/notify_local_users.rb deleted file mode 100644 index 39c797a9b617bf2b2ba69274c01cd54e6378caec..0000000000000000000000000000000000000000 --- a/app/workers/notify_local_users.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Workers - class NotifyLocalUsers < Base - sidekiq_options queue: :receive_local - - def perform(user_ids, object_klass, object_id, person_id) - - object = object_klass.constantize.find_by_id(object_id) - - users = User.where(:id => user_ids) - person = Person.find_by_id(person_id) - - users.find_each{|user| Notification.notify(user, object, person) } - end - end -end diff --git a/app/workers/post_to_service.rb b/app/workers/post_to_service.rb index 24cf053dbbdeb8d18e4d15927c108445d5dcea32..933913663634fc90878ac570ed27da57e7f96676 100644 --- a/app/workers/post_to_service.rb +++ b/app/workers/post_to_service.rb @@ -4,7 +4,7 @@ # module Workers class PostToService < Base - sidekiq_options queue: :http_service + sidekiq_options queue: :medium def perform(service_id, post_id, url) service = Service.find_by_id(service_id) diff --git a/app/workers/process_photo.rb b/app/workers/process_photo.rb index 2fcdd3943b1c3213d9e242c27663bab1cbb531d8..1686c520205f3520db6d613c0a7828fac4bcb73f 100644 --- a/app/workers/process_photo.rb +++ b/app/workers/process_photo.rb @@ -5,7 +5,7 @@ module Workers class ProcessPhoto < Base - sidekiq_options queue: :photos + sidekiq_options queue: :low def perform(id) photo = Photo.find(id) diff --git a/app/workers/publish_to_hub.rb b/app/workers/publish_to_hub.rb index 0e87c7936c7e6855b8280dca1f6ba8ba42f35e77..7d33daebaff10379d2c553a24f078bfc736bcdee 100644 --- a/app/workers/publish_to_hub.rb +++ b/app/workers/publish_to_hub.rb @@ -4,7 +4,7 @@ module Workers class PublishToHub < Base - sidekiq_options queue: :http_service + sidekiq_options queue: :medium def perform(sender_atom_url) Pubsubhubbub.new(AppConfig.environment.pubsub_server.get).publish(sender_atom_url) diff --git a/app/workers/queue_users_for_removal.rb b/app/workers/queue_users_for_removal.rb index b9565f7a8c8ab72fab16f084d2d3c56f9604cbb4..87c720b3069fba14b5aca6b82cff06b9a6ba54e9 100644 --- a/app/workers/queue_users_for_removal.rb +++ b/app/workers/queue_users_for_removal.rb @@ -4,12 +4,8 @@ module Workers class QueueUsersForRemoval < Base - include Sidetiq::Schedulable - - sidekiq_options queue: :maintenance - - recurrence { daily } - + sidekiq_options queue: :low + def perform # Queue users for removal due to inactivity if AppConfig.settings.maintenance.remove_old_users.enable? @@ -37,5 +33,5 @@ module Workers end end end - end + end end diff --git a/app/workers/receive.rb b/app/workers/receive.rb deleted file mode 100644 index 3eba79442fe90ec837269594f05c8a42e0640c41..0000000000000000000000000000000000000000 --- a/app/workers/receive.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - - -module Workers - class Receive < Base - sidekiq_options queue: :receive - - def perform(user_id, xml, salmon_author_id) - suppress_annoying_errors do - user = User.find(user_id) - salmon_author = Person.find(salmon_author_id) - zord = Postzord::Receiver::Private.new(user, :person => salmon_author) - zord.parse_and_receive(xml) - end - end - end -end diff --git a/app/workers/receive_base.rb b/app/workers/receive_base.rb new file mode 100644 index 0000000000000000000000000000000000000000..aab2082e409b7b8e790fb2fb27b48c2518aa4c70 --- /dev/null +++ b/app/workers/receive_base.rb @@ -0,0 +1,34 @@ +module Workers + class ReceiveBase < Base + sidekiq_options queue: :urgent + + include Diaspora::Logging + + # don't retry for errors that will fail again + def filter_errors_for_retry + yield + rescue DiasporaFederation::Entity::ValidationError, + DiasporaFederation::Entity::InvalidRootNode, + DiasporaFederation::Entity::InvalidEntityName, + DiasporaFederation::Entity::UnknownEntity, + DiasporaFederation::Entities::Relayable::SignatureVerificationFailed, + DiasporaFederation::Entities::Participation::ParentNotLocal, + DiasporaFederation::Federation::Receiver::InvalidSender, + DiasporaFederation::Federation::Receiver::NotPublic, + DiasporaFederation::Salmon::SenderKeyNotFound, + DiasporaFederation::Salmon::InvalidEnvelope, + DiasporaFederation::Salmon::InvalidSignature, + DiasporaFederation::Salmon::InvalidDataType, + DiasporaFederation::Salmon::InvalidAlgorithm, + DiasporaFederation::Salmon::InvalidEncoding, + Diaspora::Federation::AuthorIgnored, + Diaspora::Federation::InvalidAuthor, + # TODO: deprecated + DiasporaFederation::Salmon::MissingMagicEnvelope, + DiasporaFederation::Salmon::MissingAuthor, + DiasporaFederation::Salmon::MissingHeader, + DiasporaFederation::Salmon::InvalidHeader => e + logger.warn "don't retry for error: #{e.class}" + end + end +end diff --git a/app/workers/receive_encrypted_salmon.rb b/app/workers/receive_encrypted_salmon.rb deleted file mode 100644 index ffb3f6df486865cdada8e3b861183a6787612a28..0000000000000000000000000000000000000000 --- a/app/workers/receive_encrypted_salmon.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - - -module Workers - class ReceiveEncryptedSalmon < Base - sidekiq_options queue: :receive_salmon - - def perform(user_id, xml) - suppress_annoying_errors do - user = User.find(user_id) - zord = Postzord::Receiver::Private.new(user, :salmon_xml => xml) - zord.perform! - end - end - end -end - diff --git a/app/workers/receive_local.rb b/app/workers/receive_local.rb new file mode 100644 index 0000000000000000000000000000000000000000..a933329798c92969646a589bdd9ebde789137924 --- /dev/null +++ b/app/workers/receive_local.rb @@ -0,0 +1,14 @@ +module Workers + class ReceiveLocal < Base + sidekiq_options queue: :high + + def perform(object_class_string, object_id, recipient_user_ids) + object = object_class_string.constantize.find(object_id) + + object.receive(recipient_user_ids) if object.respond_to?(:receive) + + NotificationService.new.notify(object, recipient_user_ids) + rescue ActiveRecord::RecordNotFound # Already deleted before the job could run + end + end +end diff --git a/app/workers/receive_local_batch.rb b/app/workers/receive_local_batch.rb deleted file mode 100644 index e243edf5c801c92b1d10141f9810e9aa427812ce..0000000000000000000000000000000000000000 --- a/app/workers/receive_local_batch.rb +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Workers - class ReceiveLocalBatch < Base - sidekiq_options queue: :receive - - def perform(object_class_string, object_id, recipient_user_ids) - object = object_class_string.constantize.find(object_id) - receiver = Postzord::Receiver::LocalBatch.new(object, recipient_user_ids) - receiver.perform! - rescue ActiveRecord::RecordNotFound # Already deleted before the job could run - end - end -end diff --git a/app/workers/receive_private.rb b/app/workers/receive_private.rb new file mode 100644 index 0000000000000000000000000000000000000000..bd78b06b5166bf680ae53cd34adcb40d9b8b1b18 --- /dev/null +++ b/app/workers/receive_private.rb @@ -0,0 +1,15 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +module Workers + class ReceivePrivate < ReceiveBase + def perform(user_id, data, legacy) + filter_errors_for_retry do + user_private_key = User.where(id: user_id).pluck(:serialized_private_key).first + rsa_key = OpenSSL::PKey::RSA.new(user_private_key) + DiasporaFederation::Federation::Receiver.receive_private(data, rsa_key, user_id, legacy) + end + end + end +end diff --git a/app/workers/resend_invitation.rb b/app/workers/receive_public.rb similarity index 50% rename from app/workers/resend_invitation.rb rename to app/workers/receive_public.rb index b2a0cc00e3b5c694c7c782f390a86de6fd076351..3ec918d2d54b30f4b540f6f9d247efa51cd47512 100644 --- a/app/workers/resend_invitation.rb +++ b/app/workers/receive_public.rb @@ -2,14 +2,12 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. - module Workers - class ResendInvitation < Base - sidekiq_options queue: :mail - - def perform(invitation_id) - inv = Invitation.find(invitation_id) - inv.resend + class ReceivePublic < ReceiveBase + def perform(data, legacy=false) + filter_errors_for_retry do + DiasporaFederation::Federation::Receiver.receive_public(data, legacy) + end end end end diff --git a/app/workers/receive_unencrypted_salmon.rb b/app/workers/receive_unencrypted_salmon.rb deleted file mode 100644 index 4340443bc21e91efd171e4cc32eb1b80efcd98a1..0000000000000000000000000000000000000000 --- a/app/workers/receive_unencrypted_salmon.rb +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Workers - class ReceiveUnencryptedSalmon < Base - sidekiq_options queue: :receive - - def perform(xml) - suppress_annoying_errors do - receiver = Postzord::Receiver::Public.new(xml) - receiver.perform! - end - end - end -end diff --git a/app/workers/recurring_pod_check.rb b/app/workers/recurring_pod_check.rb new file mode 100644 index 0000000000000000000000000000000000000000..f6ed65700d62956617af7de58dfd5cde7b85f4dd --- /dev/null +++ b/app/workers/recurring_pod_check.rb @@ -0,0 +1,9 @@ +module Workers + class RecurringPodCheck < Base + sidekiq_options queue: :low + + def perform + Pod.check_all! + end + end +end diff --git a/app/workers/remove_old_user.rb b/app/workers/remove_old_user.rb index d8619b4bf2aa0c53128465b3b9fa64e004a9e14c..444857ec2818b44fafaa6fa8e1863b3670c445dc 100644 --- a/app/workers/remove_old_user.rb +++ b/app/workers/remove_old_user.rb @@ -4,7 +4,7 @@ module Workers class RemoveOldUser < Base - sidekiq_options queue: :maintenance + sidekiq_options queue: :low def safe_remove_after # extra safety time to compare in addition to remove_after @@ -24,4 +24,4 @@ module Workers end end end -end \ No newline at end of file +end diff --git a/app/workers/reset_password.rb b/app/workers/reset_password.rb index 965876e5e368c85d460affbd691f5ccfc1703469..9fdd06bbb0314470c7d5bfd63436614d8aca2bfc 100644 --- a/app/workers/reset_password.rb +++ b/app/workers/reset_password.rb @@ -1,6 +1,6 @@ module Workers class ResetPassword < Base - sidekiq_options queue: :mail + sidekiq_options queue: :urgent def perform(user_id) User.find(user_id).send_reset_password_instructions! diff --git a/app/workers/send_base.rb b/app/workers/send_base.rb new file mode 100644 index 0000000000000000000000000000000000000000..9da921e37e33454f4d553232999013995258c083 --- /dev/null +++ b/app/workers/send_base.rb @@ -0,0 +1,29 @@ +module Workers + class SendBase < Base + sidekiq_options queue: :medium, retry: 0 + + MAX_RETRIES = AppConfig.environment.sidekiq.retry.get.to_i + + protected + + def schedule_retry(retry_count, sender_id, obj_str, failed_urls) + if retry_count < MAX_RETRIES + yield(seconds_to_delay(retry_count), retry_count) + else + logger.warn "status=abandon sender=#{sender_id} obj=#{obj_str} failed_urls='[#{failed_urls.join(', ')}]'" + raise MaxRetriesReached + end + end + + private + + # based on Sidekiq::Middleware::Server::RetryJobs#seconds_to_delay + def seconds_to_delay(count) + ((count + 3)**4) + (rand(30) * (count + 1)) + end + + # send job to the dead job queue + class MaxRetriesReached < RuntimeError + end + end +end diff --git a/app/workers/send_private.rb b/app/workers/send_private.rb new file mode 100644 index 0000000000000000000000000000000000000000..8f87d6b512a868291547e5bbe2e40eea45509746 --- /dev/null +++ b/app/workers/send_private.rb @@ -0,0 +1,13 @@ +module Workers + class SendPrivate < SendBase + def perform(sender_id, obj_str, targets, retry_count=0) + targets_to_retry = DiasporaFederation::Federation::Sender.private(sender_id, obj_str, targets) + + return if targets_to_retry.empty? + + schedule_retry(retry_count + 1, sender_id, obj_str, targets_to_retry.keys) do |delay, new_retry_count| + Workers::SendPrivate.perform_in(delay, sender_id, obj_str, targets_to_retry, new_retry_count) + end + end + end +end diff --git a/app/workers/send_public.rb b/app/workers/send_public.rb new file mode 100644 index 0000000000000000000000000000000000000000..5022eac6f3b3a1a986a84d68607b007caeea2660 --- /dev/null +++ b/app/workers/send_public.rb @@ -0,0 +1,13 @@ +module Workers + class SendPublic < SendBase + def perform(sender_id, obj_str, urls, xml, retry_count=0) + urls_to_retry = DiasporaFederation::Federation::Sender.public(sender_id, obj_str, urls, xml) + + return if urls_to_retry.empty? + + schedule_retry(retry_count + 1, sender_id, obj_str, urls_to_retry) do |delay, new_retry_count| + Workers::SendPublic.perform_in(delay, sender_id, obj_str, urls_to_retry, xml, new_retry_count) + end + end + end +end diff --git a/bin/haml-lint b/bin/haml-lint new file mode 100755 index 0000000000000000000000000000000000000000..db990c1770b67506c73c76bc466f3ecb9e47ebb1 --- /dev/null +++ b/bin/haml-lint @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'haml-lint' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('haml_lint', 'haml-lint') diff --git a/bin/pronto b/bin/pronto new file mode 100755 index 0000000000000000000000000000000000000000..735afc7e013fc3ed71d3ec8089b2c2c96868f802 --- /dev/null +++ b/bin/pronto @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'pronto' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('pronto', 'pronto') diff --git a/bin/scss-lint b/bin/scss-lint new file mode 100755 index 0000000000000000000000000000000000000000..110639c4ba12b63720faf668e9c2f4912d3b6d71 --- /dev/null +++ b/bin/scss-lint @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# +# This file was generated by Bundler. +# +# The application 'scss-lint' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require 'rubygems' +require 'bundler/setup' + +load Gem.bin_path('scss_lint', 'scss-lint') diff --git a/config.ru b/config.ru index e2524860075a6d80a3bed0413e13a1e767f631a3..2f5ac99d8fb0e19f38e70337f727684d08411ebe 100644 --- a/config.ru +++ b/config.ru @@ -5,12 +5,15 @@ # This file is used by Rack-based servers to start the application. require ::File.expand_path("../config/environment", __FILE__) -require ::File.expand_path("../lib/unicorn_killer", __FILE__) require ::File.expand_path("../lib/rack/internet_explorer_version", __FILE__) # Kill unicorn workers really aggressively (at 300mb) if defined?(Unicorn) - use UnicornKiller::Oom, 300 * 1024 + require "unicorn/worker_killer" + oom_min = (280) * (1024**2) + oom_max = (300) * (1024**2) + # Max memory size (RSS) per worker + use Unicorn::WorkerKiller::Oom, oom_min, oom_max end use Rack::Deflater use Rack::InternetExplorerVersion, minimum: 9 diff --git a/config/.jshint.json b/config/.jshint.json deleted file mode 100644 index 72b2a4dea9ad0973164109ead415bcb9b0990c1c..0000000000000000000000000000000000000000 --- a/config/.jshint.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "forin": true, - "freeze": true, - "immed": true, - "indent": 2, - "latedef": true, - "maxlen": 120, - "newcap": true, - "noarg": true, - "noempty": true, - "nonbsp": true, - "nonew": false, - "quotmark": "double", - "undef": true, - "unused": true, - - "asi": false, - "boss": false, - "browser": true, - "devel": true, - "eqnull": true, - "evil": false, - "expr": false, - "jasmine": true, - "jquery": true, - "lastsemic": true, - "laxbreak": false, - "laxcomma": false, - "loopfunc": false, - "notypeof": false, - "scripturl": false, - "sub": false, - "supernew": true, - - "predef": [ - "_", - "Backbone", - "gon", - "Handlebars", - "HandlebarsTemplates", - "ImagePaths", - "jsxc", - "MBP", - "Routes", - "OSM", - "parse_url", - "punycode", - "qq", - - "loginAs", - "logout", - "spec", - "context", - "factory", - "stubView", - "exports", - "spyOn", - - "app", - "Diaspora", - "Mentions", - "PosixBracketExpressions" - ] -} diff --git a/config/.jshint_ignore b/config/.jshint_ignore deleted file mode 100644 index 59dc22151bc2b075ed2603f8a289cc3090878166..0000000000000000000000000000000000000000 --- a/config/.jshint_ignore +++ /dev/null @@ -1,4 +0,0 @@ -vendor/assets/javascripts/**.js -lib/assets/javascripts/fileuploader-custom.js -lib/assets/javascripts/jquery.autoresize.js -lib/assets/javascripts/jquery.mentionsInput.js diff --git a/config/application.rb b/config/application.rb index 68e80dba338e8bf5b2e9254a7e369f7e984165d7..6ef69fdb559c5256ef5d2c5df5b174b120863d17 100644 --- a/config/application.rb +++ b/config/application.rb @@ -70,7 +70,7 @@ module Diaspora contact-list.js ie.js inbox.js - jquery.js + jquery2.js jquery_ujs.js jquery-textchange.js main.js @@ -81,17 +81,11 @@ module Diaspora templates.js validation.js - bootstrap.css - bootstrap-complete.css - bootstrap-responsive.css error_pages.css admin.css - mobile/mobile.css rtl.css - home.css - - # images from facebox gem - facebox/* + color_themes/*/desktop.css + color_themes/*/mobile.css } # Version of your assets, change this if you want to expire all your assets @@ -112,5 +106,12 @@ module Diaspora host: AppConfig.pod_uri.authority } config.action_mailer.asset_host = AppConfig.pod_uri.to_s + + config.action_view.raise_on_missing_translations = true + + config.middleware.use Rack::OAuth2::Server::Resource::Bearer, "OpenID Connect" do |req| + Api::OpenidConnect::OAuthAccessToken + .valid(Time.zone.now.utc).find_by(token: req.access_token) || req.invalid_token! + end end end diff --git a/config/certs/README b/config/certs/README new file mode 100644 index 0000000000000000000000000000000000000000..2e857357494088c70d4e03e8ddb016375906946d --- /dev/null +++ b/config/certs/README @@ -0,0 +1,7 @@ +If you want to encrypt your chat streams with prosody. +Add to `config/certs` your server certificate and key. + +The domain name should be included in the file name e.g.: + +* example.com.crt +* example.com.key diff --git a/config/color_themes.yml b/config/color_themes.yml new file mode 100644 index 0000000000000000000000000000000000000000..6aaa75dfc3ae691cb72559cb38c54fe011b2d61a --- /dev/null +++ b/config/color_themes.yml @@ -0,0 +1,6 @@ +available: + original: "Original Dark" + original_white: "Original White Background" + dark_green: "Dark Green" + magenta: "Magenta" + egyptian_blue: "Egyptian Blue" diff --git a/config/database.yml.example b/config/database.yml.example index f5a1e08cdfe6f6624c0ac86778051d1509fec86d..879572d36b77bdb6b0a791ab34489f65b7c85a8b 100644 --- a/config/database.yml.example +++ b/config/database.yml.example @@ -1,3 +1,11 @@ +postgresql: &postgresql + adapter: postgresql + host: localhost + port: 5432 + username: postgres + password: + encoding: unicode + mysql: &mysql adapter: mysql2 host: "localhost" @@ -8,20 +16,13 @@ mysql: &mysql encoding: utf8mb4 collation: utf8mb4_bin -postgres: &postgres - adapter: postgresql - host: localhost - port: 5432 - username: postgres - password: - encoding: unicode # Comment the the mysql line and uncomment the postgres line # if you want to use postgres common: &common # Choose one of the following - <<: *mysql - #<<: *postgres + <<: *postgresql + #<<: *mysql # Should match environment.sidekiq.concurrency #pool: 25 @@ -32,9 +33,6 @@ common: &common # Normally you don't need to touch anything here -postgres_travis: &postgres_travis - adapter: postgresql - username: postgres combined: &combined <<: *common development: diff --git a/config/defaults.yml b/config/defaults.yml index dee1020d2828b73634b5f9b9a9df33aa65fcac22..624812000e1ae456551af500c8057cd403257b58 100644 --- a/config/defaults.yml +++ b/config/defaults.yml @@ -4,7 +4,7 @@ defaults: version: - number: "0.5.10.2" # Do not touch unless doing a release, do not backport the version number that's in master + number: "0.6.0.0" # Do not touch unless doing a release, do not backport the version number that's in master heroku: false environment: url: "http://localhost:3000/" @@ -13,10 +13,11 @@ defaults: require_ssl: true single_process_mode: false sidekiq: - namespace: concurrency: 5 retry: 10 backtrace: 15 + dead_jobs_limit: 5000 + dead_jobs_timeout: 3628800 # 6 weeks log: 'log/sidekiq.log' s3: enable: false @@ -39,7 +40,6 @@ defaults: sql: false federation: false server: - port: listen: '0.0.0.0:3000' rails_environment: 'development' pid: @@ -53,30 +53,21 @@ defaults: enabled: false server: enabled: true - certs: 'config/vines' - accept_self_signed: false - cross_domain_messages: true - max_offline_msgs: 150 - c2s: - address: '0.0.0.0' - port: 5222 - max_stanza_size: 65536 - max_resources_per_account: 5 - s2s: - address: '0.0.0.0' - port: 5269 - max_stanza_size: 131072 - blacklist: [] + certs: "config/certs" bosh: proxy: false address: '0.0.0.0' port: 5280 bind: '/http-bind' - max_stanza_size: 65536 - max_resources_per_account: 5 log: - file: 'log/vines.log' - level: 'info' + info: 'log/prosody.log' + error: 'log/prosody.err' + debug: false + map: + mapbox: + enabled: false + id: + access_token: privacy: jquery_cdn: false google_analytics_key: @@ -152,6 +143,10 @@ defaults: warn_days: 30 limit_removals_to_per_day: 100 source_url: + default_color_theme: "original" + default_metas: + title: 'diaspora* social network' + description: 'diaspora* is the online social world where you are in control.' services: facebook: enable: false @@ -194,8 +189,15 @@ defaults: admins: account: podmin_email: - # List valid environment variables - redistogo_url: + relay: + outbound: + send: false + url: 'https://relay.iliketoast.net/receive/public' + inbound: + subscribe: false + scope: tags + include_user_tags: false + pod_tags: development: environment: @@ -212,7 +214,8 @@ development: autofollow_on_join: false autofollow_on_join_user: '' production: - i_am_a_dummy: # Remove if you add an actual override + server: + listen: 'unix:tmp/diaspora.sock' test: environment: url: 'http://localhost:9887/' @@ -243,6 +246,7 @@ integration1: integration2: environment: url: 'http://localhost:34658/' + redis: 'redis://localhost:6380' single_process_mode: true assets: serve: true diff --git a/config/diaspora.yml.example b/config/diaspora.yml.example index 0618cc47f77232c9b826becc79a6a7154a274720..7aa0e8f1478fd8e6bd13b465b88de5e9e818652e 100644 --- a/config/diaspora.yml.example +++ b/config/diaspora.yml.example @@ -85,15 +85,25 @@ configuration: ## Section ## Set it to false to disable it completely. #retry: 10 - ## Namespace to use in Redis. Useful if you need to run - ## multiple instances of Diaspora using the same Redis instance. - #namespace: "diaspora" - ## Lines of backtrace that are stored on failure (default=15). - ## Set n to the required value. Set this to false to reduce memory + ## Set n to the required value. Set this to false to reduce Redis memory ## usage (and log size) if you're not interested in this data. #backtrace: 15 + ## Number of jobs to keep in the dead queue (default=5000). + ## Jobs get into the dead queue after they failed and exhausted all retries. + ## Increasing this setting will increase the memory usage of Redis. + ## Once gone from the dead queue, a failed job is permanently lost and + ## cannot be retried manually. + # dead_jobs_limit: 1000 + + ## Number of seconds a job remains in the dead queue (default=3628800 (six weeks)). + ## Jobs get into the dead queue after they failed and exhausted all retries. + ## Increasing this setting will increase the memory usage of Redis. + ## Once gone from the dead queue, a failed job is permanently lost and + ## cannot be retried manually. + # dead_jobs_timeout: 15552000 # 6 months + ## Log file for Sidekiq (default="log/sidekiq.log") #log: "log/sidekiq.log" @@ -162,14 +172,10 @@ configuration: ## Section ## Settings affecting how ./script/server behaves. server: ## Section - ## Where the appserver should listen to (default=0.0.0.0:3000) - #listen: '127.0.0.1:3000' + ## Where the appserver should listen to (default=unix:tmp/diaspora.sock) #listen: 'unix:tmp/diaspora.sock' #listen: 'unix:/run/diaspora/diaspora.sock' - - ## The port on which the appserver should listen (default=none). - ## Note: this setting is deprecated, use listen instead. - #port: 3000 + #listen: '127.0.0.1:3000' ## Set the path for the PID file of the unicorn master process (default=none) #pid: '/run/diaspora/diaspora.pid' @@ -202,102 +208,37 @@ configuration: ## Section ## increase environment.sidekiq.concurrency instead! #sidekiq_workers: 1 - ## Diaspora has an internal XMPP server. If you want to enable the chat + ## Diaspora has an internal XMPP web-client. If you want to enable the chat ## functionality or want to use a custom XMPP server, then you should edit ## the following configuration. - ## - ## The internal XMPP server does not support https - ## and even if we implement it, we would ran into certificate issues. - ## The problem with mixed-content is described here: - ## https://wiki.diasporafoundation.org/Vines#Browser_blocks_mixed-content - ## - ## The easiest way of avoiding certificate and mixed-content issues - ## is to use a proxy, e.g.: - ## - ## Apache: https://wiki.diasporafoundation.org/Vines#Apache2 - ## Nginx: https://wiki.diasporafoundation.org/Vines#Nginx - ## - ## If you configured your proxy correctly, you should adjust - ## the configuration in the BOSH section. chat: ## Section ## Enable the chat service and all its components. + ## + ## Please make sure that you followed the Installation-Instructions first: + ## https://wiki.diasporafoundation.org/Integration/Chat#Installation.2FUpdate #enabled: true ## Custom XMPP server configuration goes here. server: ## Section - ## Start built-in XMPP server (default=true). - ## In case you want to run your own server, you should disable it. + ## Use the configuration bridge to prosody (default=true). + ## In case you want to run your own server or want to configure + ## prosody on your own, you should disable it. #enabled: false ## Set the directory in which to look for virtual hosts TLS certificates. - ## Check documentation on how to generate or configure your existing - ## certficates correctly: - ## - ## https://wiki.diasporafoundation.org/Vines#Certificates - #certs: 'config/vines' - - ## The server accepts by default only valid certificates. - ## Any connection which uses self-signed ones will be closed. - ## If you'd like to accept self-signed certificates - ## on your server, set the next option to true. - #accept_self_signed: true - - ## Only edit the next option if you'd like to deny - ## your users to exchange messages between other XMPP servers. - #cross_domain_messages: false - - ## Set the maximum of offline messages stored per user (default=150). - ## If it exceeds, it will start deleting old messages. You can disable - ## offline message support completely by setting the option to zero. - #max_offline_msgs: 150 - - ## Client to server - c2s: ## Section - - ## Configure the address that vines should listen on. - #address: '0.0.0.0' - - ## Configure the client-to-server port. - ## If your server is behind a router or firewall - ## check documentation on how to forward ports: - ## - ## https://wiki.diasporafoundation.org/Vines#Firewall_Ports - #port: 5222 - - ## The maximum we'd like to allow for stanza size. - #max_stanza_size: 65536 - - ## The max_resources_per_account attribute, limits how many - ## concurrent connections one user can have to the server. - #max_resources_per_account: 5 - - ## Server to server - s2s: ## Section - - ## Configure the address that vines should listen on. - #address: '0.0.0.0' - - ## Configure the server-to-server port. - ## If your server is behind a router or firewall - ## check documentation on how to forward ports: - ## - ## https://wiki.diasporafoundation.org/Vines#Firewall_Ports - #port: 5269 - - ## The max_stanza_size attribute should be - ## much larger than the setting for client-to-server. - #max_stanza_size: 131072 - - ## By default every XMPP server with a valid certificate - ## is able to communicate with your server. In case of a - ## malicious server (e.g. spam reason), you can black-list them. - #blacklist: - # - 'example.com' - # - 'malicous.net' + #certs: 'config/certs' ## XEP-0124 BOSH requests + ## The easiest way of avoiding certificate and mixed-content issues + ## is to use a proxy, e.g.: + ## + ## Apache: https://wiki.diasporafoundation.org/Integration/Chat#Apache2 + ## Nginx: https://wiki.diasporafoundation.org/Integration/Chat#Nginx + ## + ## If you configured your proxy correctly, + ## you should set the proxy option to 'true' bosh: ## Section ## If you'd like to use a proxy, you should set the proxy @@ -314,22 +255,31 @@ configuration: ## Section ## Configure the bind endpoint. #bind: '/http-bind' - ## The maximum we'd like to allow for stanza size. - #max_stanza_size: 65536 - - ## The max_resources_per_account attribute, limits how many - ## concurrent connections one user can have to the server. - #max_resources_per_account: 5 - ## Specify log behaviour here. log: ## Section ## Log file location. - #file: 'log/vines.log' + #info: 'log/prosody.log' + + ## Error log file location. + #error: 'log/prosody.err' - ## Set the logging level to debug, info, warn, error, or fatal. ## The debug level logs all XML sent and received by the server. - #level: 'info' + #debug: false + + ## Displays the location of a post in a map. Per default we are using the map + ## tiles of the Heidelberg University (http://giscience.uni-hd.de). + ## You also have the possibility to use the map tiles of https://www.mapbox.com + ## which is probably more reliable. There you have to create an account to get + ## an ID and an access token which is limited. If you want to get an unlimited + ## account you can write an email to team@diasporafoundation.org. + ## Please enable mapbox and fill out your id and access_token. + map: ##Section + + mapbox: + # enabled: false + # id: 'your.id' + # access_token: 'youraccesstoken' ## Settings potentially affecting the privacy of your users. privacy: ## Section @@ -582,6 +532,22 @@ configuration: ## Section ## If not set your pod will provide a downloadable archive. #source_url: 'https://example.org/username/diaspora' + ## Default color theme + ## You can change which color theme is displayed when a user is not signed in + ## or has not selected any color theme from the available ones. You simply have + ## to enter the name of the theme's folder in "app/assets/stylesheets/color_themes/". + ## ("original" for the theme in "app/assets/stylesheets/color_themes/original/", for + ## example). + #default_color_theme: "original" + + ## Default meta tags + ## You can change here the default meta tags content included on the pages of your pod. + ## Title will be used for the opengraph og:site_name property while description will be used + ## for description and og:description. + default_metas: + #title: 'diaspora* social network' + #description: 'diaspora* is the online social world where you are in control.' + ## Posting from Diaspora to external services (all are disabled by default). services: ## Section @@ -631,8 +597,7 @@ configuration: ## Section #sender_address: 'no-reply@example.org' ## This selects which mailer should be used. Use 'smtp' for a smtp - ## connection, 'sendmail' to use the sendmail binary or - ## 'messagebus' to use the messagebus service. + ## connection or 'sendmail' to use the sendmail binary. #method: 'smtp' ## Ignore if method isn't 'smtp'. @@ -675,9 +640,6 @@ configuration: ## Section ## Use exim and sendmail (default=false) #exim_fix: false - ## Ignore if method isn't 'messagebus' - #message_bus_api_key: 'abcdef' - ## Administrator settings admins: ## Section @@ -690,12 +652,44 @@ configuration: ## Section ## E-mail address to contact the administrator. #podmin_email: 'podmin@example.org' + ## Settings related to relays + relay: ## Section + + ## Relays are applications that exist to push public posts around to + ## pods which want to subscribe to them but would not otherwise + ## receive them due to not having direct contact with the remote pods. + ## + ## See more regarding relays: https://wiki.diasporafoundation.org/Relay_servers_for_public_posts + + outbound: ## Section + ## Enable this setting to send out public posts from this pod to a relay + #send: false + ## Change default remote relay url used for sending out here + #url: 'https://relay.iliketoast.net/receive/public' + + inbound: ## Section + ## Enable this to receive public posts from relays + #subscribe: false + + ## Scope is either 'all' or 'tags' (default). + ## - 'all', means this pod wants to receive all public posts from a relay + ## - 'tags', means this pod wants only posts tagged with certain tags + #scope: tags + + ## If scope is 'tags', should we include tags that users on this pod follow? + ## These are added in addition to 'pod_tags', if set. + #include_user_tags: false + + ## If scope is 'tags', a comma separated list of tags here can be set. + ## For example "linux,diaspora", to receive posts related to these tags + #pod_tags: + ## Here you can override settings defined above if you need ## to have them different in different environments. production: ## Section environment: ## Section - #redis_url: 'redis://production.example.org:6379' + #redis: 'redis://production.example.org:6379' development: ## Section environment: ## Section - #redis_url: 'redis://production.example.org:6379' + #redis: 'redis://production.example.org:6379' diff --git a/config/eye.rb b/config/eye.rb index 52d25aea40c22fd3d928e6e46c4eae33497e690b..fdfbed198cf27df43edcf49964adb008479ea253 100644 --- a/config/eye.rb +++ b/config/eye.rb @@ -7,7 +7,7 @@ end Eye.application("diaspora") do working_dir Rails.root.to_s - env "DB" => ENV["DB"], "RAILS_ENV" => rails_env + env "RAILS_ENV" => rails_env stdout "log/eye_processes_stdout.log" unless rails_env == "development" stderr "log/eye_processes_stderr.log" @@ -40,7 +40,7 @@ Eye.application("diaspora") do with_condition(AppConfig.chat.enabled? && AppConfig.chat.server.enabled?) do process :xmpp do - start_command "bin/bundle exec vines start" + start_command "bin/bundle exec rails runner Prosody.start" daemonize true pid_file "tmp/pids/xmpp.pid" stop_signals [:TERM, 10.seconds, :KILL] diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 9f3f8cd923bbb88678725884ca913a1bcf8e59ad..686871f66f01f75d7f28a32f1208d6fc4497de26 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -2,6 +2,13 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. +# bootstrap-markdown plugin relies on rails-assets-bootstrap gem but we use +# bootstrap-sass this line makes sure we exclude every asset comming +# from rails-assets-bootstrap to prevent conflicts with bootstrap-sass +Rails.configuration.assets.paths.reject! do |path| + path.include?("rails-assets-bootstrap") && !path.include?("rails-assets-bootstrap-markdown") +end + Diaspora::Application.configure do config.serve_static_files = AppConfig.environment.assets.serve? # config.static_cache_control = "public, max-age=3600" if AppConfig[:serve_static_assets].to_s == 'true' diff --git a/config/initializers/color_themes.rb b/config/initializers/color_themes.rb new file mode 100644 index 0000000000000000000000000000000000000000..9c12af8a674f98406bd2420cd7f90ac11e5a0579 --- /dev/null +++ b/config/initializers/color_themes.rb @@ -0,0 +1,19 @@ +# Generate the path to the .yml file with the available color themes. +color_themes_file = Rails.root.join("config/color_themes.yml") +# Check in case config/color_themes.yml does not exist. +if color_themes_file.exist? + # Load the file specified by the generated path. + color_themes = YAML.load_file(color_themes_file) + # If the file contains one or more color themes, include them in AVAILABLE_COLOR_THEMES, + # else include the original theme. + AVAILABLE_COLOR_THEMES = + if color_themes["available"].length > 0 + color_themes["available"] + else + {"original" => "Original Dark"} + end +else + AVAILABLE_COLOR_THEMES = {"original" => "Original Dark"} +end +# Get all codes from available themes into a separate variable, so that they can be called easier. +AVAILABLE_COLOR_THEME_CODES = AVAILABLE_COLOR_THEMES.keys diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb index 68e071e7c37ecf2c1252dc3cca117e4c8d2227b0..a50aead3e98605d604fea252cde6825c78bf567b 100644 --- a/config/initializers/cors.rb +++ b/config/initializers/cors.rb @@ -1,7 +1,11 @@ Rails.application.config.middleware.insert 0, Rack::Cors do allow do - origins '*' - resource '/.well-known/host-meta' - resource '/webfinger' + origins "*" + resource "/api/openid_connect/user_info", methods: %i(get post) + resource "/api/v0/*", methods: %i(delete get post) + resource "/.well-known/host-meta" + resource "/.well-known/webfinger" + resource "/.well-known/openid-configuration" + resource "/webfinger" end end diff --git a/config/initializers/diaspora_federation.rb b/config/initializers/diaspora_federation.rb index 19a01937b802961ff2070b2ae5be6786b8b24f6e..05b105905ebf50e8e30410e38e187921488d4879 100644 --- a/config/initializers/diaspora_federation.rb +++ b/config/initializers/diaspora_federation.rb @@ -5,9 +5,12 @@ DiasporaFederation.configure do |config| config.certificate_authorities = AppConfig.environment.certificate_authorities.get + config.http_concurrency = AppConfig.settings.typhoeus_concurrency.to_i + config.http_verbose = AppConfig.settings.typhoeus_verbose? + config.define_callbacks do - on :fetch_person_for_webfinger do |handle| - person = Person.find_local_by_diaspora_handle(handle) + on :fetch_person_for_webfinger do |diaspora_id| + person = Person.where(diaspora_handle: diaspora_id, closed_account: false).where.not(owner: nil).first if person DiasporaFederation::Discovery::WebFinger.new( acct_uri: "acct:#{person.diaspora_handle}", @@ -25,7 +28,7 @@ DiasporaFederation.configure do |config| end on :fetch_person_for_hcard do |guid| - person = Person.find_local_by_guid(guid) + person = Person.where(guid: guid, closed_account: false).where.not(owner: nil).take if person DiasporaFederation::Discovery::HCard.new( guid: person.guid, @@ -47,7 +50,7 @@ DiasporaFederation.configure do |config| # find existing person or create a new one person_entity = Person.find_by(diaspora_handle: person.diaspora_id) || Person.new(diaspora_handle: person.diaspora_id, guid: person.guid, - serialized_public_key: person.exported_key, url: person.url) + serialized_public_key: person.exported_key, pod: Pod.find_or_create_by(url: person.url)) profile = person.profile profile_entity = person_entity.profile ||= Profile.new @@ -63,64 +66,69 @@ DiasporaFederation.configure do |config| person_entity.save! end - on :fetch_private_key_by_diaspora_id do |diaspora_id| + on :fetch_private_key do |diaspora_id| key = Person.where(diaspora_handle: diaspora_id).joins(:owner).pluck(:serialized_private_key).first - OpenSSL::PKey::RSA.new key unless key.nil? - end - - on :fetch_author_private_key_by_entity_guid do |entity_type, guid| - key = entity_type.constantize.where(guid: guid).joins(author: :owner).pluck(:serialized_private_key).first - OpenSSL::PKey::RSA.new key unless key.nil? - end - - on :fetch_public_key_by_diaspora_id do |diaspora_id| - key = Person.where(diaspora_handle: diaspora_id).pluck(:serialized_public_key).first - OpenSSL::PKey::RSA.new key unless key.nil? - end - - on :fetch_author_public_key_by_entity_guid do |entity_type, guid| - key = entity_type.constantize.where(guid: guid).joins(:author).pluck(:serialized_public_key).first - OpenSSL::PKey::RSA.new key unless key.nil? + OpenSSL::PKey::RSA.new(key) unless key.nil? end - on :entity_author_is_local? do |entity_type, guid| - entity_type.constantize.where(guid: guid).joins(author: :owner).exists? + on :fetch_public_key do |diaspora_id| + key = Person.find_or_fetch_by_identifier(diaspora_id).serialized_public_key + OpenSSL::PKey::RSA.new(key) unless key.nil? end - on :fetch_entity_author_id_by_guid do |entity_type, guid| - entity_type.constantize.where(guid: guid).joins(:author).pluck(:diaspora_handle).first + on :fetch_related_entity do |entity_type, guid| + entity = Diaspora::Federation::Mappings.model_class_for(entity_type).find_by(guid: guid) + Diaspora::Federation::Entities.related_entity(entity) if entity end - on :queue_public_receive do |xml| - Workers::ReceiveUnencryptedSalmon.perform_async(xml) + on :queue_public_receive do |xml, legacy=false| + Workers::ReceivePublic.perform_async(xml, legacy) end - on :queue_private_receive do |guid, xml| + on :queue_private_receive do |guid, xml, legacy=false| person = Person.find_by_guid(guid) - if person.nil? || person.owner_id.nil? - false - else - Workers::ReceiveEncryptedSalmon.perform_async(person.owner.id, xml) - true + (person.present? && person.owner_id.present?).tap do |user_found| + Workers::ReceivePrivate.perform_async(person.owner.id, xml, legacy) if user_found end end - on :receive_entity do - # TODO + on :receive_entity do |entity, recipient_id| + case entity + when DiasporaFederation::Entities::AccountDeletion + Diaspora::Federation::Receive.account_deletion(entity) + when DiasporaFederation::Entities::Retraction + Diaspora::Federation::Receive.retraction(entity, recipient_id) + else + persisted = Diaspora::Federation::Receive.perform(entity) + Workers::ReceiveLocal.perform_async(persisted.class.to_s, persisted.id, [recipient_id].compact) if persisted + end end on :fetch_public_entity do |entity_type, guid| - entity = entity_type.constantize.find_by(guid: guid, public: true) - Diaspora::Federation.post(entity) if entity.is_a? Post + entity = Diaspora::Federation::Mappings.model_class_for(entity_type).find_by(guid: guid, public: true) + Diaspora::Federation::Entities.post(entity) if entity.is_a? Post end on :fetch_person_url_to do |diaspora_id, path| - Person.find_by(diaspora_handle: diaspora_id).send(:url_to, path) + Person.find_or_fetch_by_identifier(diaspora_id).url_to(path) end - on :update_pod do - # TODO + on :update_pod do |url, status| + pod = Pod.find_or_create_by(url: url) + + if status.is_a? Symbol + pod.status = Pod::CURL_ERROR_MAP.fetch(status, :unknown_error) + pod.error = "FederationError: #{status}" + elsif status >= 200 && status < 300 + pod.status = :no_errors unless Pod.statuses[pod.status] == Pod.statuses[:version_failed] + else + pod.status = :http_failed + pod.error = "FederationError: HTTP status code was: #{status}" + end + pod.update_offline_since + + pod.save end end end diff --git a/config/initializers/entypo.rb b/config/initializers/entypo.rb new file mode 100644 index 0000000000000000000000000000000000000000..0c99a40ee2a073e26504fa4fe28e50a084818dbc --- /dev/null +++ b/config/initializers/entypo.rb @@ -0,0 +1 @@ +Entypo.css_prefix = "entypo" diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index cd871780d62ab40a5d9c400ed4a305f45e27fc82..d0825039061c7c793bb2df210bf08d5c85649bb3 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,4 +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, :xml,:message, :text, :bio] +Rails.application.config.filter_parameters += %i(password message text bio) diff --git a/config/initializers/haml.rb b/config/initializers/haml.rb index 83225bbd43c782f567b158e767e66e1e18d03dd9..0eacbe0d57d944a2484825a7a4528147ac4ac3f4 100644 --- a/config/initializers/haml.rb +++ b/config/initializers/haml.rb @@ -1,2 +1,2 @@ -Haml::Template.options[:format] = :html5 -Haml::Template.options[:escape_html] = true +Hamlit::Engine.options[:format] = :html +Hamlit::Engine.options[:escape_html] = true diff --git a/config/initializers/load_libraries.rb b/config/initializers/load_libraries.rb index 86d701d33d8827b6be113648b6469a92548e0113..315ac3dabcb7ac7bf68264ec6520488832137146 100644 --- a/config/initializers/load_libraries.rb +++ b/config/initializers/load_libraries.rb @@ -14,10 +14,7 @@ require 'diaspora' require 'direction_detector' require 'email_inviter' require 'evil_query' -require 'hydra_wrapper' -require 'postzord' require 'publisher' require 'pubsubhubbub' -require 'salmon' require 'stream' require 'account_deleter' diff --git a/config/initializers/mailer_config.rb b/config/initializers/mailer_config.rb index b09e2630459aa3aa932e409b98a8bd608d3f892d..8cfb5e9b347abcac033e9e13b71d67d16c483683 100644 --- a/config/initializers/mailer_config.rb +++ b/config/initializers/mailer_config.rb @@ -1,21 +1,12 @@ # Copyright (c) 2010-2011, Diaspora Inc. This file is # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require Rails.root.join('lib', 'messagebus', 'mailer') Diaspora::Application.configure do config.action_mailer.perform_deliveries = AppConfig.mail.enable? unless Rails.env == 'test' || !AppConfig.mail.enable? - if AppConfig.mail.method == 'messagebus' - - if AppConfig.mail.message_bus_api_key.present? - config.action_mailer.delivery_method = Messagebus::Mailer.new(AppConfig.mail.message_bus_api_key.get) - config.action_mailer.raise_delivery_errors = true - else - puts "You need to set your messagebus api key if you are going to use the message bus service. no mailer is now configured" - end - elsif AppConfig.mail.method == "sendmail" + if AppConfig.mail.method == "sendmail" config.action_mailer.delivery_method = :sendmail sendmail_settings = { location: AppConfig.mail.sendmail.location.get diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb index 855078373e1d13cdaa381a4d3d4671e174b49739..3321cf370c5f77527d0b93fd709142a09f8464e3 100644 --- a/config/initializers/omniauth.rb +++ b/config/initializers/omniauth.rb @@ -13,7 +13,6 @@ Rails.application.config.middleware.use OmniAuth::Builder do if AppConfig.services.facebook.enable? provider :facebook, AppConfig.services.facebook.app_id, AppConfig.services.facebook.secret, { - display: "popup", scope: "public_profile,publish_actions", client_options: { ssl: { diff --git a/config/initializers/prosody.rb b/config/initializers/prosody.rb new file mode 100644 index 0000000000000000000000000000000000000000..093dd49249106a2a58dd66783e5c5535e86ff0e6 --- /dev/null +++ b/config/initializers/prosody.rb @@ -0,0 +1,22 @@ +if AppConfig.chat.enabled? && AppConfig.chat.server.enabled? + db = Rails.application.config + .database_configuration[Rails.env] + + Prosody.update_configuration( + bosh_port: AppConfig.chat.server.bosh.port, bosh_path: AppConfig.chat.server.bosh.bind, + bosh_interface: AppConfig.chat.server.bosh.address, + + log_debug: (AppConfig.chat.server.log.debug? ? "debug" : "info"), + log_info: "#{Dir.pwd}/#{AppConfig.chat.server.log.info}", + log_error: "#{Dir.pwd}/#{AppConfig.chat.server.log.error}", + + certs: "#{Dir.pwd}/#{AppConfig.chat.server.certs}", + hostname: AppConfig.environment.url, + + virtualhost_driver: db["adapter"], + virtualhost_database: db["database"], + virtualhost_username: db["username"], + virtualhost_password: db["password"], + virtualhost_host: db["host"] + ) +end diff --git a/config/initializers/set_up_image_redirects.rb b/config/initializers/set_up_image_redirects.rb index 64126a620309f7af04d53e988282854db0a5d764..9da80f0094e0735239c5caeb873417e6b29b2a12 100644 --- a/config/initializers/set_up_image_redirects.rb +++ b/config/initializers/set_up_image_redirects.rb @@ -3,6 +3,5 @@ if AppConfig.environment.image_redirect_url.present? Rails.application.config.middleware.insert(0, Rack::Rewrite) do r301 %r{/uploads/images/(.*)}, "#{AppConfig.environment.image_redirect_url}/uploads/images/$1" - r301 %r{/landing/(.*)}, "#{AppConfig.environment.image_redirect_url}/landing/$1" end end diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 9709cc27a8c98d7a783cb5981cbe3e98599d0a87..fa5ed372d6378bbf07aadeb382439fd4407336a9 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -52,3 +52,9 @@ end Sidekiq.configure_client do |config| config.redis = AppConfig.get_redis_options end + +schedule_file = "config/schedule.yml" + +if File.exist?(schedule_file) && Sidekiq.server? + Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file) +end diff --git a/config/initializers/will_paginate.rb b/config/initializers/will_paginate.rb index 966b1da5c5776650d369fcb9a8ac59661552dd5a..8922b88b21731d053af8f97408c86f74089b9b25 100644 --- a/config/initializers/will_paginate.rb +++ b/config/initializers/will_paginate.rb @@ -15,9 +15,9 @@ module WillPaginate class BootstrapLinkRenderer < LinkRenderer protected - + def html_container(html) - tag :div, tag(:ul, html), container_attributes + tag :div, tag(:ul, html, class: "pagination"), container_attributes end def page_number(page) diff --git a/config/locales/devise/devise.ar.yml b/config/locales/devise/devise.ar.yml index 148cd8a6eb2eb9be528c92b9e604111ec0d40cd2..da3745647af9ec886d9f66c21c57ddd3a0a6b21b 100644 --- a/config/locales/devise/devise.ar.yml +++ b/config/locales/devise/devise.ar.yml @@ -7,80 +7,85 @@ ar: devise: confirmations: - confirmed: "تم تأكيد Øسابك، وتسجيل دخولك" + confirmed: "Ø£Ùكّد Øسابك بنجاØ. لقد ولجت." new: - resend_confirmation: "أعÙد إرسال تعليمات التأكيد" - send_instructions: "ستصلك ÙÙŠ بضع دقائق رسالة إلكترونية تØوي تعليمات تأكيد الØساب الخاص بك" + resend_confirmation: "أعد إرسال إرشادات التّأكيد" + send_instructions: "سيصلك بريد إلكترونيّ قريبًا Ùيه إرشادات تأكيد الØساب." failure: - inactive: "لم يتم تÙعيل Øسابك بعد" - invalid: "اسم المستخدم غير صØÙŠØ Ø£Ùˆ كلمة المرور غير صØÙŠØØ©." - invalid_token: "رمزالتعرÙØ© غير صØÙŠØ" - locked: "تم Ù‚ÙÙ„ Øسابك" - timeout: "إنقضت مدة جلستك، الرجاء تسجيل الدخول من جديد للمتابعة" - unauthenticated: "عليك تسجيل الدخول او التسجيل قبل المتابعة." - unconfirmed: "يجب تأكيد Øسابك قبل المتابعة." + inactive: "لم ÙŠÙÙعّل Øسابك بعد." + invalid: "اسم المستخدم أو كلمة مروره غير صالØØ©." + invalid_token: "رمز الاستيثاق غير صالØ." + locked: "Øسابك مقÙول." + not_found_in_database: "البريد الإلكترونيّ أو كلمة المرور غير صالØØ©." + timeout: "انتهت جلستك، Ùضلًا Ù„Ùج مجدّدًا للمتابعة." + unauthenticated: "عليك الولوج أو التسجيل للمتابعة." + unconfirmed: "عليك تأكيد Øسابك للمتابعة." invitations: - invitation_token_invalid: "نأسÙ! هذه الدعوة غير صالØØ©." - send_instructions: "تم إرسال دعوتك" - updated: "تم إنشاء كلمة المرور بنجاØØŒ أنت الآن متصل" + invitation_token_invalid: "نأسÙ! رمز الدّعوة غير صالØ." + send_instructions: "Ø£Ùرسلت الدّعوة." + updated: "ضÙبطت كلمة المرور بنجاØ. لقد ولجت." mailer: confirmation_instructions: - confirm: "أكÙد Øسابي" - subject: "تعليمات التأكيد" - you_can_confirm: "يمكنك تأكيد Øسابك عبر الرابط التالي" - hello: "مرØبا %{email}!" + confirm: "أكّد Øسابي" + subject: "إرشادات التّأكيد" + you_can_confirm: "يمكنك تأكيد Øسابك عبر الوصلة الآتية:" + hello: "أهلًا %{email}!" inviter: accept_at: ", %{url}, يمكنك قبولها عبر الرابط التالي" has_invited_you: "%{name} يدعوك للإنضمام إلى دياسبرا" - have_invited_you: "%{names} يدعونك للإنضمام إلى دياسبرا" + have_invited_you: "دعاك %{names} للانضمام إلى دياسبرا*" reset_password_instructions: - change: "غيÙر كلمة المرور" - ignore: "إذا لم تكن من طلب هذا، رجاء تجاهل هذا البريد" - someone_requested: "Ø£Øدهم طلب رابطا لتغيير كلمة مرورك, ويمكنك Ùعل هذا عبر الرابط الآتي" - subject: "تعليمات إعادة إدخال كلمة المرور" - wont_change: "كلمة مرورك لن تتغير قبل أن تنقر الرابط التالي وتدخل كلمة مرور جديدة" + change: "غيّر كلمة المرور" + ignore: "إن لم تكن أنت Ùتجاهل هذا البريد رجاءً." + someone_requested: "طلب Ø£Øدهم وصلة لتغيير كلمة المرور. إن كنت أنت ذاك Ùيمكنك اتّباع الوصلة أدناه." + subject: "إرشادات تصÙير كلمة المرور" + wont_change: "لن تتغيّر كلمة المرور Øتّى تدخل الوصلة أعلاه وتنشئ غيرها." unlock_instructions: - account_locked: "لقد تم Øظر Øسابك ظرÙيا بسبب العدد المÙرط من Ù…Øاولات الدخول الÙاشلة" - click_to_unlock: "انقر الرابط بأدناه لإعادة ÙØªØ Øسابك:" - subject: "تعليمات إعادة ÙØªØ Øسابك" - unlock: "أعد ÙØªØ Øسابي" - welcome: "مرØبا %{email} !" + account_locked: "لقد Ù‚ÙÙÙ„ Øسابك بسبب عدد Ù…Øاولات الولوج غير النّاجØ." + click_to_unlock: "انقر الوصلة أدناه Ù„Ùكّ الØساب:" + subject: "إرشادات Ùكّ القÙÙ„" + unlock: "Ùكّ Øسابي" + welcome: "مرØبًا %{email}!" passwords: edit: - change_password: "غيÙر كلمة المرور" + change_password: "غيّر كلمة المرور" + confirm_password: "أكّد كلمة المرور" + new_password: "كلمة المرور الجديدة" new: - forgot_password: "هل نسيت كلمة المرور؟" - no_account: "هذا البريد الإلكتروني غير مرتبط بأي Øساب. إذا كنت تنتظر دعوة, ÙÙ†ØÙ† نقوم بتوزيعها بأسرع وسيلة لتصل الجميع" - send_password_instructions: "أعÙد تعيين كلمة المرور" - send_instructions: "ستصلك رسالة إلكترونية ÙÙŠ بضع دقائق تØوي تعليمات إعادة تعيين كلمة المرور الخاصة بك" - updated: "تم تغيير كلمة السر خاصتك بنجاØ. أنت الآن متصل" + email: "البريد الإلكترونيّ" + forgot_password: "أنسيت كلمة المرور؟" + no_account: "ليس هناك Øساب بهذا البريد الإلكترونيّ" + reset_password: "صÙّر كلمة المرور" + send_password_instructions: "أرسل لي إرشادات تصÙير كلمة المرور" + send_instructions: "سيصلك بريد إلكترونيّ قريبًا Ùيه إرشادات تصÙير كلمة المرور." + updated: "تغيّرت كلمة المرور بنجاØ. لقد ولجت." registrations: - destroyed: ".وداعا! تم إلغاء Øسابك بنجاØ. ونأمل أن نراكم مرة أخرى قريبا" - signed_up: ".تمت عملية تسجيلك بنجاØ. ستصلك رسالة إلكترونية Øال تÙعيله" - updated: "قمت بتØديث Øسابك بنجاØ." + destroyed: "الوداع! ØÙØ°Ù Øسابك بنجاØ. نأمل أن نراك قريبًا." + signed_up: "لقد سجّلت بنجاØ. إن طلبت تأكيدًا Ùقد Ø£Ùرسل إلى بريدك." + updated: "لقد Øدّثت Øسابك بنجاØ." sessions: new: - login: "تسجيل الدخول" + login: "Ù„Ùج" modern_browsers: "تدعم المتصÙØات الØديثة Ùقط." password: "كلمة المرور" - remember_me: "تذكرني" - sign_in: "تسجيل الدخول" - username: "إسم المستخدم" - signed_in: "تم تسجيل الدخول بنجاØ." - signed_out: "تم تسجيل الخروج بنجاØ" + remember_me: "تذكّرني" + sign_in: "Ù„Ùج" + username: "اسم المستخدم" + signed_in: "ولجت بنجاØ." + signed_out: "خرجت بنجاØ." shared: links: - forgot_your_password: "نسيت كلمة المرور؟" - receive_confirmation: "لم تصلك تعليمات تأكيد Øسابك؟" - receive_unlock: "لم تصلك تعليمات إعادة ÙØªØ Øسابك؟" - sign_in: "تسجيل الدخول" - sign_up: "التسجيل" - sign_up_closed: "التسجيلات مغلقة Øاليا" + forgot_your_password: "أنسيت كلمة المرور؟" + receive_confirmation: "ألم تصلك إرشادات التّأكيد؟" + receive_unlock: "ألم تصلك إرشادات Ùكّ القÙل؟" + sign_in: "Ù„Ùج" + sign_up: "أنشئ Øسابًا" + sign_up_closed: "تسجيل الØسابات مقÙول Øاليًّا." unlocks: new: - resend_unlock: "أعÙد إرسال تعليمات إعادة ÙØªØ Øسابك" - send_instructions: "ستصلك رسالة إلكترونية خلال دقائق تØتوي على تعليمات إعادة ÙØªØ Øسابك" - unlocked: "تم إعادة ÙØªØ Øسابك بنجاØØŒ أنت الآن متصل" + resend_unlock: "أعد إرسال إرشادات Ùكّ القÙÙ„" + send_instructions: "سيصلك بريد إلكترونيّ قريبًا Ùيه إرشادات Ù„Ùكّ Ù‚ÙÙ„ الØساب." + unlocked: "ÙÙكّ Ù‚ÙÙ„ الØساب بنجاØ. لقد ولجت." errors: messages: already_confirmed: "تم التأكيد مسبقا" diff --git a/config/locales/devise/devise.da.yml b/config/locales/devise/devise.da.yml index f76aefb038cc0be28d282dd166df71e6d752361d..645d4169034984aec8018c48d8dbd302c8500f83 100644 --- a/config/locales/devise/devise.da.yml +++ b/config/locales/devise/devise.da.yml @@ -13,13 +13,13 @@ da: send_instructions: "Du vil modtage en e-mail med instruktioner om hvordan du bekræfter din konto om et par minutter." failure: inactive: "Din konto er endnu ikke aktiveret." - invalid: "Forkert brugernavn eller adgangskode." - invalid_token: "Ugyldig token." + invalid: "Forkert %{authentication_keys} eller adgangskode." + invalid_token: "Ugyldig autentifikation." locked: "Din konto er lÃ¥st." not_found_in_database: "Forkert e-mail eller adgangskode." timeout: "Du har været inaktiv for længe. Log ind for at fortsætte." unauthenticated: "Du skal logge ind eller oprette en konto for at fortsætte." - unconfirmed: "Du skal bekræfte din konto for at fortsætte." + unconfirmed: "Du skal bekræfte din e-mailkonto før du fortsætter." invitations: invitation_token_invalid: "Beklager! Invitationen er ikke gyldig." send_instructions: "Din invitation er blevet sendt." @@ -44,7 +44,7 @@ da: account_locked: "Din konto er blevet lÃ¥st pÃ¥ grund af en stor mængde mislykkede log ind forsøg." click_to_unlock: "Klik pÃ¥ linket nedenfor for at aktivere din konto:" subject: "Aktiver instruktioner" - unlock: "Aktivér min konto" + unlock: "Aktiver min konto" welcome: "Velkommen %{email}!" passwords: edit: @@ -88,6 +88,6 @@ da: unlocked: "Din konto er blevet lÃ¥st op. Du er nu logget ind." errors: messages: - already_confirmed: "var allerede bekræftet" + already_confirmed: "var allerede bekræftet - prøv at logge ind" not_found: "ikke fundet" not_locked: "blev ikke lÃ¥st" \ No newline at end of file diff --git a/config/locales/devise/devise.de.yml b/config/locales/devise/devise.de.yml index dc5854b78ac5c4d76a8579c528da105ecdf6af6d..41efcc1a2375773cd465fc1338edcbdeba8527f3 100644 --- a/config/locales/devise/devise.de.yml +++ b/config/locales/devise/devise.de.yml @@ -7,19 +7,22 @@ de: devise: confirmations: - confirmed: "Dein Konto wurde erfolgreich bestätigt. Du bist nun angemeldet." + confirmed: "Deine E-Mail-Adresse wurde erfolgreich bestätigt." new: resend_confirmation: "Anweisungen zum Bestätigen erneut senden" - send_instructions: "Du wirst in ein paar Minuten eine E-Mail erhalten, die beschreibt, wie du dein Konto bestätigst." + send_instructions: "Du wirst in ein paar Minuten eine E-Mail mit Anweisungen zum Bestätigen deiner E-Mail-Adresse erhalten." + send_paranoid_instructions: "Falls deine E-Mail-Adresse in unserer Datenbank existiert, erhälst du in ein paar Minuten eine E-Mail mit Anweisungen zur Bestätigung deiner E-Mail-Adresse." failure: + already_authenticated: "Du bist schon angemeldet." inactive: "Dein Konto wurde noch nicht aktiviert." - invalid: "Ungültiger Benutzername oder ungültiges Kennwort." + invalid: "Ungültiger %{authentication_keys} oder ungültiges Kennwort." invalid_token: "Ungültiger Authentifizierungstoken." + last_attempt: "Du hast einen weiteren Versuch, bevor dein Konto gesperrt wird." locked: "Dein Konto ist gesperrt." - not_found_in_database: "Passwort oder E-Mail-Adresse ungültig" + not_found_in_database: "%{authentication_keys} oder Passwort ungültig." timeout: "Deine Sitzung ist abgelaufen! Um fortzufahren, melde dich bitte erneut an." unauthenticated: "Du musst dich anmelden oder registrieren, um fortzufahren." - unconfirmed: "Du musst dein Konto bestätigen, um fortzufahren." + unconfirmed: "Du musst deine E-Mail-Adresse bestätigen, um fortzufahren." invitations: invitation_token_invalid: "Das Einladungstoken ist ungültig!" send_instructions: "Deine Einladung wurde versandt." @@ -34,10 +37,12 @@ de: accept_at: "unter %{url}, kannst du sie über den untenstehenden Link akzeptieren." has_invited_you: "" have_invited_you: "%{names} haben Dich eingeladen diaspora* beizutreten" + password_change: + subject: "Passwort geändert" reset_password_instructions: change: "Mein Kennwort ändern" ignore: "Wenn du dies nicht angefordert hast, ignoriere bitte diese E-Mail." - someone_requested: "Jemand hat einen Link angefordert, um dein Kennwort zu ändern. Falls du das warst, kannst das durch den unten aufgeführten Link tun." + someone_requested: "Jemand hat einen Link angefordert, um dein Kennwort zu ändern. Falls du das warst, kannst du das durch den unten aufgeführten Link tun." subject: "Setze dein Kenwort zurück" wont_change: "Dein Kennwort bleibt unverändert, bis du es über den Link änderst und ein neues erstellst." unlock_instructions: @@ -46,24 +51,35 @@ de: subject: "Anweisungen zum Entsperren" unlock: "Mein Konto entsperren" welcome: "Willkommen %{email}!" + omniauth_callbacks: + failure: "Konnte dich nicht mittels %{kind} authentifizieren, denn „%{reason}â€." + success: "Erfolgreich authentifiziert mittels %{kind}-Konto." passwords: edit: change_password: "Mein Kennwort ändern" - confirm_password: "Passwort bestätigen" - new_password: "Neues Passwort" + confirm_password: "Kennwort bestätigen" + new_password: "Neues Kennwort" new: email: "E-Mail-Adresse" forgot_password: "Kennwort vergessen?" no_account: "Es existiert kein Benutzerkonto mit dieser E-Mail-Adresse" - reset_password: "Passwort zurücksetzen" + reset_password: "Kennwort zurücksetzen" send_password_instructions: "Anleitung zum Zurücksetzen des Кennworts anfordern" + no_token: "Du kannst auf diese Seite nicht zugreifen, ohne von einer E-Mail zur Passwortrücksetzung zu kommen. Falls du von einer E-Mail zur Passwortrücksetzung kommst, vergewissere dich bitte, dass du die vollständige angegebene URL verwendet hast." send_instructions: "Du wirst in ein paar Minuten eine E-Mail erhalten, die beschreibt, wie du dein Kennwort zurücksetzt." - updated: "Dein Kennwort wurde erfolgreich geändert. Du bist nun angemeldet." + send_paranoid_instructions: "Falls deine E-Mail-Adresse in unserer Datenbank existiert, erhälst du in ein paar Minuten einen Link zum Zurücksetzen deines Passworts an deine E-Mail-Adresse." + updated: "Dein Passwort wurde erfolgreich geändert. Du bist nun angemeldet." + updated_not_active: "Dein Passwort wurde erfolgreich geändert." registrations: destroyed: "Tschüss! Dein Konto wurde erfolgreich geschlossen. Wir hoffen, dich bald wiederzusehen." signed_up: "Du hast dich erfolgreich registriert. Sofern aktiviert, wurde dir eine Bestätigung per E-Mail zugesandt." - updated: "Du hast dein Konto erfolgreich aktualisiert." + signed_up_but_inactive: "Du hast dich erfolgreich registriert. Wir konnten dich aber nicht anmelden, weil dein Konto noch nicht aktiviert ist." + signed_up_but_locked: "Du hast dich erfolgreich registriert. Wir konnten dich aber nicht anmelden, weil dein Konto gesperrt ist." + signed_up_but_unconfirmed: "Eine Nachricht mit einem Bestätigungslink wurde an deine E-Mail-Adresse gesendet. Bitte folge dem Link, um dein Konto zu aktivieren." + update_needs_confirmation: "Dein Konto hast du erfolgreich aktualisiert, aber deine neue E-Mail-Adresse müssen wir überprüfen. Bitte rufe deine E-Mails ab und folge dem Bestätigungslink, um deine neue E-Mail-Adresse zu bestätigen." + updated: "Dein Konto wurde erfolgreich aktualisiert." sessions: + already_signed_out: "Erfolgreich abgemeldet." new: login: "Anmelden" modern_browsers: "unterstützt nur moderne Browser." @@ -79,15 +95,21 @@ de: receive_confirmation: "Keine Bestätigungsanleitung erhalten?" receive_unlock: "Keine Entsperr-Anweisungen erhalten?" sign_in: "Anmelden" - sign_up: "Registrieren" + sign_up: "Konto erstellen" sign_up_closed: "Öffentliche Registrierungen sind momentan nicht möglich." unlocks: new: resend_unlock: "Entsperr-Anweisungen erneut senden" - send_instructions: "Du wirst in ein paar Minuten eine E-Mail erhalten, die beschreibt, wie du dein Konto entsperren kannst." - unlocked: "Dein Konto wurde erfolgreich entsperrt. Du bist nun angemeldet." + send_instructions: "Du wirst in ein paar Minuten eine E-Mail mit Anweisungen zum Entsperren deines Kontos erhalten." + send_paranoid_instructions: "Falls dein Konto existiert, erhälst du in ein paar Minuten eine E-Mail mit Anweisungen, um es zu entsperren." + unlocked: "Dein Konto wurde erfolgreich entsperrt. Bitte melde dich an, um fortzufahren." errors: messages: - already_confirmed: "wurde bereits bestätigt" + already_confirmed: "wurde bereits bestätigt, bitte versuche dich anzumelden" + confirmation_period_expired: "muss innerhalb von %{period} bestätigt werden, bitte erneut anfordern" + expired: "abgelaufen, bitte neu anfordern" not_found: "nicht gefunden" - not_locked: "war nicht gesperrt" \ No newline at end of file + not_locked: "war nicht gesperrt" + not_saved: + one: "%{resource} konnte wegen einem Fehler nicht gespeichert werden:" + other: "%{resource} konnte wegen %{count} Fehlern nicht gespeichert werden:" \ No newline at end of file diff --git a/config/locales/devise/devise.de_formal.yml b/config/locales/devise/devise.de_formal.yml index 2034ff57779d80373c85d0ab000bfc9c322feaa0..8639b38e352931a8f674596ae8458b43e35fdd44 100644 --- a/config/locales/devise/devise.de_formal.yml +++ b/config/locales/devise/devise.de_formal.yml @@ -7,23 +7,26 @@ de_formal: devise: confirmations: - confirmed: "Ihr Konto wurde erfolgreich bestätigt. Sie sind nun angemeldet." + confirmed: "Ihre E-Mail-Adresse wurde erfolgreich bestätigt." new: resend_confirmation: "Anweisungen zum Bestätigen erneut senden" - send_instructions: "Sie werden in ein paar Minuten eine E-Mail erhalten, die beschreibt, wie Sie Ihr Konto bestätigen." + send_instructions: "Sie werden in ein wenigen Minuten eine E-Mail mit Anweisungen zum Bestätigen Ihrer E-Mail-Adresse erhalten." + send_paranoid_instructions: "Falls Ihre E-Mail-Adresse in unserer Datenbank existiert, erhalten Sie in wenigen Minuten eine E-Mail mit Anweisungen zur Bestätigung Ihrer E-Mail-Adresse." failure: - inactive: "Ihr Konto wurde noch nicht aktiviert." - invalid: "Ungültiger Benutzername oder ungültiges Kennwort." + already_authenticated: "Sie sind bereits angemeldet." + inactive: "Ihr Konto ist noch nicht aktiviert." + invalid: "%{authentication_keys} oder Passwort ungültig." invalid_token: "Ungültiger Authentifizierungstoken." + last_attempt: "Sie haben einen weiteren Versuch, bevor Ihr Konto gesperrt wird." locked: "Ihr Konto ist gesperrt." - not_found_in_database: "Ungültige E-Mail-Adresse oder ungültiges Passwort." - timeout: "Ihre Sitzung ist abgelaufen! Um fortzufahren, melden Sie sich bitte erneut an." + not_found_in_database: "%{authentication_keys} oder Passwort ungültig." + timeout: "Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an, um fortzufahren." unauthenticated: "Sie müssen sich anmelden oder registrieren, um fortzufahren." - unconfirmed: "Sie müssen ihr Konto bestätigen, um fortzufahren." + unconfirmed: "Sie müssen Ihre E-Mail-Adresse bestätigen, um fortzufahren." invitations: invitation_token_invalid: "Das Einladungstoken ist ungültig!" send_instructions: "Ihre Einladung wurde versandt." - updated: "Ihr Kennwort wurde akzeptiert. Sie sind nun angemeldet." + updated: "Ihr Passwort wurde erfolgreich gesetzt. Sie sind nun angemeldet." mailer: confirmation_instructions: confirm: "Mein Konto bestätigen" @@ -34,60 +37,79 @@ de_formal: accept_at: "unter %{url}, können Sie sie über den untenstehenden Link akzeptieren." has_invited_you: "%{name}" have_invited_you: "%{names} hat Sie eingeladen, diaspora* beizutreten" + password_change: + subject: "Passwort geändert" reset_password_instructions: - change: "Mein Kennwort ändern" + change: "Mein Passwort ändern" ignore: "Wenn Sie dies nicht angefordert haben, ignorieren Sie bitte diese E-Mail." - someone_requested: "Jemand hat einen Link angefordert, um Ihr Kennwort zu ändern. Wenn Sie das waren, können Sie das durch den unten aufgeführten Link tun." + someone_requested: "Jemand hat einen Link angefordert, um Ihr Passwort zu ändern. Wenn Sie das waren, können Sie das durch den unten aufgeführten Link tun." subject: "Setzen Sie Ihr Passwort zurück" - wont_change: "Ihr Kennwort bleibt unverändert, bis Sie es über den Link ändern und ein neues erstellen." + wont_change: "Ihr Passwort bleibt unverändert, bis Sie es über den Link ändern und ein neues erstellen." unlock_instructions: account_locked: "Ihr Konto wurde aufgrund von zu vielen fehlgeschlagenen Anmeldeversuchen gesperrt." click_to_unlock: "Folgen Sie dem unten aufgeführten Link, um Ihr Konto zu entsperren:" subject: "Anweisungen zum Entsperren" unlock: "Mein Konto entsperren" welcome: "Willkommen %{email}!" + omniauth_callbacks: + failure: "Konnte Sie nicht mittels %{kind} authentifizieren, denn „%{reason}â€." + success: "Erfolgreich authentifiziert mittels %{kind}-Konto." passwords: edit: - change_password: "Mein Kennwort ändern" + change_password: "Mein Passwort ändern" confirm_password: "Passwort bestätigen" new_password: "Neues Passwort" new: email: "E-Mail-Adresse" - forgot_password: "Kennwort vergessen?" + forgot_password: "Passwort vergessen?" no_account: "Es existiert kein Benutzerkonto mit dieser E-Mail-Adresse" reset_password: "Passwort zurücksetzen" send_password_instructions: "Anleitung zum Zurücksetzen des Кennworts anfordern" - send_instructions: "Sie werden in ein paar Minuten eine E-Mail erhalten, die beschreibt, wie Sie Ihr Kennwort zurücksetzen." - updated: "Ihr Kennwort wurde erfolgreich geändert. Sie sind nun angemeldet." + no_token: "Sie können auf diese Seite nicht zugreifen, ohne von einer E-Mail zur Passwortrücksetzung zu kommen. Falls sie von einer E-Mail zur Passwortrücksetzung kommen, vergewissern Sie sich bitte, dass Sie die vollständige angegebene URL verwendet haben." + send_instructions: "Sie werden in wenigen Minuten eine E-Mail mit Anweisungen zum Zurücksetzen Ihres Passworts erhalten." + send_paranoid_instructions: "Falls Ihre E-Mail-Adresse in unserer Datenbank existiert, erhalten Sie in wenigen Minuten einen Link zum Zurücksetzen Ihres Passworts an Ihre E-Mail-Adresse." + updated: "Ihr Passwort wurde erfolgreich geändert. Sie sind nun angemeldet." + updated_not_active: "Ihr Passwort wurde erfolgreich geändert." registrations: - destroyed: "Tschüss! Ihr Konto wurde erfolgreich geschlossen. Wir hoffen, Sie bald wiederzusehen." + destroyed: "Tschüss! Ihr Konto wurde erfolgreich gelöscht. Wir hoffen, Sie bald wiederzusehen." signed_up: "Sie haben sich erfolgreich registriert. Sofern aktiviert, wurde Ihnen eine Bestätigung per E-Mail zugesandt." - updated: "Ihr Konto wurde aktualisiert." + signed_up_but_inactive: "Sie haben sich erfolgreich registriert. Wir konnten Sie jedoch nicht anmelden, da Ihr Konto noch nicht aktiviert ist." + signed_up_but_locked: "Sie haben sich erfolgreich registriert. Wir konnten Sie jedoch nicht anmelden, da Ihr Konto gesperrt ist." + signed_up_but_unconfirmed: "Eine Nachricht mit einem Bestätigungslink wurde an Ihre E-Mail-Adresse gesendet. Bitte folgen Sie dem Link, um Ihr Konto zu aktivieren." + update_needs_confirmation: "Ihr Konto haben Sie erfolgreich aktualisiert, aber Ihre neue E-Mail-Adresse müssen wir überprüfen. Bitte rufen Sie Ihre E-Mails ab und folgen Sie dem Bestätigungslink, um Ihre neue E-Mail-Adresse zu bestätigen." + updated: "Ihr Konto wurde erfolgreich aktualisiert." sessions: + already_signed_out: "Erfolgreich abgemeldet." new: login: "Einloggen" modern_browsers: "unterstützt nur moderne Browser." - password: "Kennwort" + password: "Passwort" remember_me: "Angemeldet bleiben" sign_in: "Anmelden" username: "Benutzername" signed_in: "Angemeldet." - signed_out: "Abgemeldet." + signed_out: "Erfolgreich abgemeldet." shared: links: - forgot_your_password: "Kennwort vergessen?" + forgot_your_password: "Passwort vergessen?" receive_confirmation: "Keine Bestätigungsanleitung erhalten?" receive_unlock: "Keine Entsperr-Anweisungen erhalten?" sign_in: "Anmelden" - sign_up: "Registrieren" + sign_up: "Konto erstellen" sign_up_closed: "Öffentliche Registrierungen sind momentan nicht möglich." unlocks: new: resend_unlock: "Entsperr-Anweisungen erneut senden" - send_instructions: "Sie werden in ein paar Minuten eine E-Mail erhalten, die beschreibt, wie Sie Ihr Konto entsperren können." - unlocked: "Ihr Konto wurde erfolgreich entsperrt. Sie sind nun angemeldet." + send_instructions: "Sie werden in ein wenigen Minuten eine E-Mail mit Anweisungen zum Entsperren Ihres Kontos erhalten." + send_paranoid_instructions: "Falls Ihr Konto existiert, erhalten Sie in wenigen Minuten eine E-Mail mit Anweisungen, um es zu entsperren." + unlocked: "Ihr Konto wurde erfolgreich entsperrt. Bitte melden Sie sich an, um fortzufahren." errors: messages: - already_confirmed: "wurde bereits bestätigt" + already_confirmed: "wurde bereits bestätigt, bitte versuchen Sie, sich anzumelden" + confirmation_period_expired: "muss innerhalb von %{period} bestätigt werden, bitte erneut anfordern" + expired: "abgelaufen, bitte neu anfordern" not_found: "nicht gefunden" - not_locked: "war nicht gesperrt" \ No newline at end of file + not_locked: "war nicht gesperrt" + not_saved: + one: "%{resource} konnte aufgrund eines Fehlers nicht gespeichert werden:" + other: "%{resource} konnte aufgrund von %{count} Fehlern nicht gespeichert werden:" \ No newline at end of file diff --git a/config/locales/devise/devise.en.yml b/config/locales/devise/devise.en.yml index e1269d7bcbecd8225701d7efbd120490aa3f50bc..45f35a2386f5dc0f68781a11914ae9d979760106 100644 --- a/config/locales/devise/devise.en.yml +++ b/config/locales/devise/devise.en.yml @@ -1,88 +1,129 @@ en: - errors: - messages: - not_found: "not found" - already_confirmed: "was already confirmed" - not_locked: "was not locked" - devise: - failure: - unauthenticated: 'You need to sign in or sign up before continuing.' - unconfirmed: 'You have to confirm your account before continuing.' - locked: 'Your account is locked.' - not_found_in_database: 'Invalid email or password.' - invalid: 'Invalid username or password.' - invalid_token: 'Invalid authentication token.' - timeout: 'Your session expired, please sign in again to continue.' - inactive: 'Your account was not activated yet.' - sessions: - new: - login: 'Log in' - username: 'Username' - password: 'Password' - sign_in: 'Sign in' - remember_me: "Remember me" - modern_browsers: 'only supports modern browsers.' - signed_in: 'Signed in successfully.' - signed_out: 'Signed out successfully.' - passwords: - send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.' - updated: 'Your password was changed successfully. You are now signed in.' - edit: - change_password: "Change my password" - new_password: "New password" - confirm_password: "Confirm password" - new: - forgot_password: "Forgot your password?" - no_account: 'No account with this email exists' - reset_password: "Reset password" - email: "Email address" - send_password_instructions: "Send me reset password instructions" confirmations: - send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' - confirmed: 'Your account was successfully confirmed. You are now signed in.' - new: - resend_confirmation: "Resend confirmation instructions" - registrations: - signed_up: 'You have signed up successfully. If enabled, a confirmation was sent to your e-mail.' - updated: 'You updated your account successfully.' - destroyed: 'Bye! Your account was successfully deleted. We hope to see you again soon.' - unlocks: - send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.' - unlocked: 'Your account was successfully unlocked. You are now signed in.' + confirmed: Your email address has been successfully confirmed. + send_instructions: You will receive an email with instructions for how to confirm + your email address in a few minutes. + send_paranoid_instructions: If your email address exists in our database, you + will receive an email with instructions for how to confirm your email address + in a few minutes. new: - resend_unlock: "Resend unlock instructions" - invitations: - send_instructions: 'Your invitation has been sent.' - invitation_token_invalid: 'Our apologies! That invitation token is not valid.' - updated: 'Your password was set successfully. You are now signed in.' + resend_confirmation: Resend confirmation instructions + failure: + already_authenticated: You are already signed in. + inactive: Your account is not activated yet. + invalid: Invalid %{authentication_keys} or password. + locked: Your account is locked. + last_attempt: You have one more attempt before your account is locked. + not_found_in_database: Invalid %{authentication_keys} or password. + timeout: Your session expired. Please sign in again to continue. + unauthenticated: You need to sign in or sign up before continuing. + unconfirmed: You have to confirm your email address before continuing. + invalid_token: Invalid authentication token. mailer: - welcome: "Welcome %{email}!" - hello: "Hello %{email}!" confirmation_instructions: - subject: 'Confirmation instructions' - you_can_confirm: "You can confirm your account through the link below:" - confirm: "Confirm my account" + subject: Confirmation instructions + you_can_confirm: 'You can confirm your account through the link below:' + confirm: Confirm my account reset_password_instructions: - subject: 'Reset password instructions' - someone_requested: "Someone has requested a link to change your password. If it was you, you can do this through the link below." - change: "Change my password" - wont_change: "Your password won't change until you access the link above and create a new one." - ignore: "If you didn't request this, please ignore this email." + subject: Reset password instructions + someone_requested: Someone has requested a link to change your password. If + it was you, you can do this through the link below. + change: Change my password + wont_change: Your password won't change until you access the link above and + create a new one. + ignore: If you didn't request this, please ignore this email. unlock_instructions: - subject: 'Unlock instructions' - account_locked: "Your account has been locked due to an excessive number of unsuccessful sign in attempts." - click_to_unlock: "Click the link below to unlock your account:" - unlock: "Unlock my account" + subject: Unlock instructions + account_locked: Your account has been locked due to an excessive number of + unsuccessful sign in attempts. + click_to_unlock: 'Click the link below to unlock your account:' + unlock: Unlock my account + password_change: + subject: Password Changed + welcome: Welcome %{email}! + hello: Hello %{email}! inviter: has_invited_you: "%{name}" have_invited_you: "%{names} have invited you to join diaspora*" - accept_at: "at %{url}, you can accept it through the link below." + accept_at: at %{url}, you can accept it through the link below. + omniauth_callbacks: + failure: Could not authenticate you from %{kind} because "%{reason}". + success: Successfully authenticated from %{kind} account. + passwords: + no_token: You can't access this page without coming from a password reset email. + If you do come from a password reset email, please make sure you used the + full URL provided. + send_instructions: You will receive an email with instructions on how to reset + your password in a few minutes. + send_paranoid_instructions: If your email address exists in our database, you + will receive a password recovery link at your email address in a few minutes. + updated: Your password has been changed successfully. You are now signed in. + updated_not_active: Your password has been changed successfully. + edit: + change_password: Change my password + new_password: New password + confirm_password: Confirm password + new: + forgot_password: Forgot your password? + no_account: No account with this email exists + reset_password: Reset password + email: Email address + send_password_instructions: Send me reset password instructions + registrations: + destroyed: Bye! Your account was successfully deleted. We hope to see you again + soon. + signed_up: You have signed up successfully. If enabled, a confirmation was sent + to your e-mail. + signed_up_but_inactive: You have signed up successfully. However, we could not + sign you in because your account is not yet activated. + signed_up_but_locked: You have signed up successfully. However, we could not + sign you in because your account is locked. + signed_up_but_unconfirmed: A message with a confirmation link has been sent + to your email address. Please follow the link to activate your account. + update_needs_confirmation: You updated your account successfully, but we need + to verify your new email address. Please check your email and follow the confirm + link to confirm your new email address. + updated: Your account has been updated successfully. + sessions: + signed_in: Signed in successfully. + signed_out: Signed out successfully. + already_signed_out: Signed out successfully. + new: + login: Log in + username: Username + password: Password + sign_in: Sign in + remember_me: Remember me + modern_browsers: only supports modern browsers. + unlocks: + send_instructions: You will receive an email with instructions for how to unlock + your account in a few minutes. + send_paranoid_instructions: If your account exists, you will receive an email + with instructions for how to unlock it in a few minutes. + unlocked: Your account has been unlocked successfully. Please sign in to continue. + new: + resend_unlock: Resend unlock instructions + invitations: + send_instructions: Your invitation has been sent. + invitation_token_invalid: Our apologies! That invitation token is not valid. + updated: Your password was set successfully. You are now signed in. shared: links: - sign_in: 'Sign in' - sign_up: 'Sign up' - sign_up_closed: 'Open signups are closed at this time.' - forgot_your_password: 'Forgot your password?' - receive_confirmation: "Didn't receive confirmation instructions?" - receive_unlock: "Didn't receive unlock instructions?" + sign_in: Sign in + sign_up: Create account + sign_up_closed: Open signups are closed at this time. + forgot_your_password: Forgot your password? + receive_confirmation: Didn't receive confirmation instructions? + receive_unlock: Didn't receive unlock instructions? + errors: + messages: + already_confirmed: was already confirmed, please try signing in + confirmation_period_expired: needs to be confirmed within %{period}, please + request a new one + expired: has expired, please request a new one + not_found: not found + not_locked: was not locked + not_saved: + one: '1 error prohibited this %{resource} from being saved:' + other: "%{count} errors prohibited this %{resource} from being saved:" diff --git a/config/locales/devise/devise.es-AR.yml b/config/locales/devise/devise.es-AR.yml index 3cd26390b670a264f900d30c33703d15cda1e55f..3b39eecf168f31a087b5f640e93f5cbc6674e962 100644 --- a/config/locales/devise/devise.es-AR.yml +++ b/config/locales/devise/devise.es-AR.yml @@ -7,19 +7,22 @@ es-AR: devise: confirmations: - confirmed: "Tu cuenta se confirmó sin problemas. Ya estás conectado." + confirmed: "Tu dirección de correo electrónico se confirmó con éxito." new: resend_confirmation: "Reenviarme instrucciones para confirmar mi cuenta" - send_instructions: "En unos minutos vas a recibir un correo electrónico con instrucciones para confirmar tu cuenta." + send_instructions: "En unos minutos vas a recibir un e-mail con instrucciones para confirmar tu dirección de correo electrónico." + send_paranoid_instructions: "Si tu dirección de correo electrónico existe en nuestra base de datos, en pocos minutos recibirás un e-mail con instrucciones de cómo confirmar tu dirección de correo electrónico." failure: + already_authenticated: "Ya estás conectado." inactive: "Tu cuenta todavÃa no fue activada." - invalid: "La contraseña o el nombre de usuario introducidos son incorrectos" + invalid: "%{authentication_keys} o contraseña incorrecta." invalid_token: "El identificador de autenticación no es válido." + last_attempt: "Tienes un intento más antes de que tu cuenta sea bloqueada." locked: "Tu cuenta está bloqueada" - not_found_in_database: "Contraseña o e-mail incorrecto." - timeout: "Tu sesión expiró, por favor conectate de nuevo." + not_found_in_database: "%{authentication_keys} o contraseña incorrecta." + timeout: "Tu sesión expiró, por favor conéctate de nuevo." unauthenticated: "Necesitás conectarte a tu cuenta, o registrarse, para continuar." - unconfirmed: "Necesitas confirmar tu cuenta antes de continuar." + unconfirmed: "Necesitas confirmar tu dirección de correo electrónico antes de continuar." invitations: invitation_token_invalid: "¡Perdón! ¡El identificador de la invitación no es válido!" send_instructions: "Ya se envió tu invitacÃon." @@ -34,6 +37,8 @@ es-AR: accept_at: "en %{url}, podes aceptarlo desde el link de abajo " has_invited_you: "%{name} te ha invitado a unirte a Diaspora" have_invited_you: "%{names} te han invitado a unirte a diaspora*" + password_change: + subject: "Contraseña cambiada" reset_password_instructions: change: "Cambiar mi contraseña" ignore: "Si vos no hiciste la solicitud, por favor ignorá este correo." @@ -46,6 +51,9 @@ es-AR: subject: "Instrucciones para desbloquear la cuenta" unlock: "Desbloquear mi cuenta" welcome: "¡Bienvenid@ %{email}!" + omniauth_callbacks: + failure: "PodrÃas no ser autenticado desde %{kind} porque \"%{reason}\"." + success: "Autenticado correctamente desde la cuenta %{kind}." passwords: edit: change_password: "Cambiar mi contraseña" @@ -57,13 +65,21 @@ es-AR: no_account: "No hay ninguna cuenta con esta dirección de correo electrónico. Si estás esperando una invitación, te la enviaremos tan pronto como sea posible." reset_password: "Resetear contraseña" send_password_instructions: "Enviame instrucciones para cambiar mi contraseña." + no_token: "No puedes acceder a esta página si no vienes de un mensaje de restablecimiento de contraseña. Si vienes de un mensaje de restablecimiento de contraseña, por favor asegúrate de que has utilizado la URL completa proporcionada en el mensaje." send_instructions: "En unos minutos vas a recibir un correo electrónico con instrucciones para cambiar tu contraseña." - updated: "Tu contraseña se cambió sin problemas. Ya estás conectado." + send_paranoid_instructions: "Si tu dirección de e-mail existe en nuestra base de datos, en pocos minutos recibirás un correo electrónico con un enlace para recuperar la contraseña." + updated: "Tu contraseña se cambió con éxito. Ya estás conectado." + updated_not_active: "Tu contraseña ha sido cambiada con éxito." registrations: destroyed: "¡Chau! Tu cuenta se canceló sin problemas. Esperamos volver a verte pronto." signed_up: "Fuiste registrado sin problemas. Si está habilitado, te enviamos un correo electrónico con instrucciones para confirmar tu cuenta." - updated: "Tu cuenta fue actualizada sin problemas." + signed_up_but_inactive: "Te has registrado exitosamente. Sin embargo, no puedes iniciar sesión porque tu cuenta todavÃa no ha sido activada." + signed_up_but_locked: "Te has registrado exitosamente. Sin embargo, no puedes iniciar sesión porque tu cuenta está bloqueada." + signed_up_but_unconfirmed: "Un mensaje con un enlace de confirmación ha sido enviado a tu dirección de e-mail. Por favor abre el enlace para activar tu cuenta." + update_needs_confirmation: "Has actualizado tu cuenta correctamente, pero necesitamos verificar tu nueva dirección de e-mail. Por favor revisa tu correo electrónico y haz clic en el enlace de confirmación para finalizar con la verificación de tu nueva dirección de e-mail." + updated: "Tu cuenta fue actualizada con éxito." sessions: + already_signed_out: "Te has desconectado con éxito." new: login: "Iniciar sesión" modern_browsers: "Sólo es compatible con navegadores modernos." @@ -85,9 +101,15 @@ es-AR: new: resend_unlock: "Reenviarme instrucciones para desbloquear mi cuenta" send_instructions: "En unos minutos vas a recibir un correo electrónico con instrucciones para desbloquear tu cuenta." - unlocked: "Tu cuenta fue desbloqueado sin problemas. Ya estás conectado." + send_paranoid_instructions: "Si tu cuenta existe, en pocos minutos recibirás un e-mail con instrucciones para desbloquearla." + unlocked: "Tu cuenta fue desbloqueada con éxito. Por favor conéctate para continuar." errors: messages: - already_confirmed: "ya habÃa sido confirmada" + already_confirmed: "ya ha sido confirmada, por favor intenta conectarte" + confirmation_period_expired: "necesitas ser confirmado dentro de %{period}, por favor solicita uno nuevo" + expired: "ha caducado, por favor solicite uno nuevo" not_found: "no fue encontrada" - not_locked: "no estaba bloqueada" \ No newline at end of file + not_locked: "no estaba bloqueada" + not_saved: + one: "1 error prohÃbe que este %{resource} sea guardado:" + other: "%{count} errores prohÃben que este %{resource} sea guardado:" \ No newline at end of file diff --git a/config/locales/devise/devise.es-CL.yml b/config/locales/devise/devise.es-CL.yml index 52b6dea1e3db9a62d26b68c6b1b44f27aa134b20..a0c900776fa6add62bd4aa3dac159af6cde2cdb6 100644 --- a/config/locales/devise/devise.es-CL.yml +++ b/config/locales/devise/devise.es-CL.yml @@ -11,10 +11,13 @@ es-CL: new: resend_confirmation: "Reenviar las instrucciones de confirmación" send_instructions: "Recibirás un correo con instrucciones acerca de como confirmar tu cuenta en pocos minutos." + send_paranoid_instructions: "Si tu dirección de correo electrónico ya existe en nuestra base de datos, recibirás un correo electrónico con instrucciones sobre cómo confirmar tu dirección de correo electrónico en unos pocos minutos." failure: + already_authenticated: "Ya iniciaste sesión." inactive: "Tu cuenta aún no ha sido activada." invalid: "Nombre de usuario o contraseña incorrecta." invalid_token: "Identificador de autenticación inválido." + last_attempt: "Tiene un intento más antes de que tu cuenta sea bloqueada." locked: "Tu cuenta está bloqueada." timeout: "Tu sesión caducó, debes acceder de nuevo para continuar." unauthenticated: "Necesitas iniciar sesión o registrarte antes de continuar." @@ -33,6 +36,8 @@ es-CL: accept_at: "en %{url}, puedes aceptar en el enlace inferior." has_invited_you: "%{name}" have_invited_you: "%{names} te ha invitado a unirte a Diaspora*" + password_change: + subject: "Contraseña cambiada" reset_password_instructions: change: "Cambiar mi contraseña" ignore: "Si no has solicitado esto, por favor, ignora este correo." @@ -45,6 +50,9 @@ es-CL: subject: "Instrucciones para desbloquear tu cuenta" unlock: "Desbloquear mi cuenta" welcome: "Bienvenid@ %{email}!" + omniauth_callbacks: + failure: "No se pudo autenticar desde %{kind} porque \"%{reason}\"." + success: "Autenticado correctamente desde %{kind} cuenta." passwords: edit: change_password: "Cambiar mi contraseña" @@ -52,11 +60,15 @@ es-CL: forgot_password: "¿Olvidaste tu contraseña?" no_account: "No existe una cuenta asociada con ese email. Si estas esperando una invitación, la enviaremos a la brevedad" send_password_instructions: "EnvÃame instrucciones para restablecer la contraseña" + no_token: "No puedes acceder a esta página sino viene de un correo electrónico de restablecimiento de contraseña. Si viene de un correo electrónico de restablecimiento de contraseña, por favor asegúrese de que utilizó la URL completa proporcionada." send_instructions: "Recibirás un correo con instrucciones para restablecer tu contraseña en pocos minutos." + send_paranoid_instructions: "Si su dirección de email existe en nuestra base de datos, usted recibirá un correo electrónico con un enlace para la recuperación de la contraseña." updated: "Tu contraseña ha sido modificada. Ya has entrado a tu cuenta." + updated_not_active: "Tu contraseña ha sido cambiada exitosamente." registrations: destroyed: "¡Adiós! Tu cuenta ha sido cancelada. Esperamos volver a verte pronto." signed_up: "Te has registrado correctamente. Te hemos enviado un correo de confirmación." + signed_up_but_inactive: "Te has registrado con éxito. Sin embargo, no podemos dejarte ingresar porque tu cuenta todavÃa no está activada." updated: "Tu cuenta ha sido actualizada." sessions: new: diff --git a/config/locales/devise/devise.es.yml b/config/locales/devise/devise.es.yml index 8a3c05b97943018ef58a25909a119e5ee4a9fb41..cbf73e3a9760fcfe1986682de8f8e45f39806ab3 100644 --- a/config/locales/devise/devise.es.yml +++ b/config/locales/devise/devise.es.yml @@ -11,10 +11,13 @@ es: new: resend_confirmation: "Reenviar las instrucciones de confirmación" send_instructions: "Recibirás un correo con instrucciones para confirmar tu cuenta en unos minutos." + send_paranoid_instructions: "Si tu email existe en nuestra base de datos, recibirás un correo con instrucciones para confirmar tu dirección en unos pocos minutos." failure: + already_authenticated: "Ya estás identificado." inactive: "Tu cuenta no se ha activado todavÃa." invalid: "Nombre de usuario o contraseña incorrectos." invalid_token: "Identificador de autenticación incorrecto." + last_attempt: "Tienes un intento más antes de que se bloquee tu cuenta." locked: "Tu cuenta está bloqueada." not_found_in_database: "Contraseña o Email incorrecto." timeout: "Tu sesión ha expirado, por favor accede de nuevo para continuar." @@ -34,6 +37,8 @@ es: accept_at: "en %{url}, puedes aceptar en el enlace inferior." has_invited_you: "%{name} te ha invitado a unirte a Diaspora" have_invited_you: "%{names} te ha invitado a unirte a Diaspora*" + password_change: + subject: "La contraseña ha sido cambiada." reset_password_instructions: change: "Cambiar mi contraseña" ignore: "Si no has solicitado esto, por favor ignora este mensaje." @@ -46,6 +51,9 @@ es: subject: "Instrucciones para desbloquear la cuenta" unlock: "Desbloquear mi cuenta" welcome: "¡Bienvenid@ %{email}!" + omniauth_callbacks: + failure: "No pudimos identificarte desde %{kind} por \"%{reason}\"." + success: "Identificado correctamente desde la cuenta %{kind}." passwords: edit: change_password: "Cambiar mi contraseña" @@ -57,13 +65,21 @@ es: no_account: "No existe una cuenta con ese correo" reset_password: "Resetear contraseña" send_password_instructions: "EnvÃame instrucciones para restablecer la contraseña" + no_token: "No puedes acceder a esta página sin venir un correo de reseteo de contraseña. Si vienes de uno de estos correos, por favor asegúrate de utilizar la URL proporcionada." send_instructions: "Recibirás un correo con instrucciones para cambiar tu contraseña en unos minutos." + send_paranoid_instructions: "Si tu correo existe en nuestra base de datos, recibirás un enlace para recuperar la contraseña en unos minutos." updated: "Has modificado tu contraseña. ¡Ya estás dentro!" + updated_not_active: "Tu contraseña se ha cambiado correctamente." registrations: destroyed: "¡Adiós! Hemos cancelado tu cuenta. Esperamos volver a verte pronto." signed_up: "Te has registrado con éxito. Si tu registro está activado, recibirás un mensaje de confirmación en tu correo electrónico." + signed_up_but_inactive: "Te has identificado correctamente. Sin embargo, no podemos permitirte entrar ya que tu cuenta todavÃa no se ha activado." + signed_up_but_locked: "Te has identificado correctamente. Sin embargo, no podemos permitirte entrar porque tu cuenta está bloqueada." + signed_up_but_unconfirmed: "Se ha enviado a tu email un mensaje con el link de confirmación. Por favor, pulsa sobre el link para activar tu cuenta." + update_needs_confirmation: "Has actualizado tu cuenta correctamente, pero necesitamos verificar tu nuevo email. Por favor, entra en tu correo y pulsa el enlace de confirmación que encontrarás en él." updated: "Has actualizado tu cuenta con éxito." sessions: + already_signed_out: "Has desconectado correctamente." new: login: "Acceder" modern_browsers: "Sólo es compatible con navegadores modernos." @@ -85,9 +101,15 @@ es: new: resend_unlock: "Volver a enviar las instrucciones de desbloqueo." send_instructions: "Recibirás un correo con instrucciones para desbloquear tu cuenta en pocos minutos." + send_paranoid_instructions: "Si tu cuenta existe, recibirás un email con instrucciones sobre cómo desbloquear la cuenta en unos minutos." unlocked: "Tu cuenta se ha desbloqueado. ¡Ya estás dentro!" errors: messages: already_confirmed: "ya fue confirmada" + confirmation_period_expired: "necesitas ser confirmado en %{period}, por favor solicita una nueva" + expired: "ha caducado, por favor pide uno nuevo" not_found: "no se ha encontrado" - not_locked: "no estaba bloqueada" \ No newline at end of file + not_locked: "no estaba bloqueada" + not_saved: + one: "1 error impidió guardar %{resource}:" + other: "%{count} errores impidieron guardar a %{resource}:" \ No newline at end of file diff --git a/config/locales/devise/devise.fr.yml b/config/locales/devise/devise.fr.yml index a8c646e8b4f188947947fd23bca9c341d2735ada..a6dd4277fb7ac16c8d8246ddebd6d4131f29091d 100644 --- a/config/locales/devise/devise.fr.yml +++ b/config/locales/devise/devise.fr.yml @@ -11,10 +11,13 @@ fr: new: resend_confirmation: "Renvoyer les instructions de confirmation" send_instructions: "Vous allez recevoir dans quelques minutes un courriel contenant les instructions pour confirmer votre compte." + send_paranoid_instructions: "Si votre e-mail existe dans notre base de données, vous recevrez un e-mail avec les instructions pour confirmer votre adresse e-mail dans quelques minutes." failure: + already_authenticated: "Vous êtes déjà connecté-e" inactive: "Votre compte n’a pas encore été activé." invalid: "Pseudo ou mot de passe invalide." invalid_token: "Jeton d’authentification invalide." + last_attempt: "Vous avez encore une tentative avant que votre compte ne soit verrouillé." locked: "Votre compte est verrouillé." not_found_in_database: "Courriel ou mot de passe invalide." timeout: "Votre session a expiré. Veuillez vous connecter de nouveau pour continuer." @@ -34,6 +37,8 @@ fr: accept_at: "à %{url}, vous pouvez l'accepter à travers le lien ci-dessous." has_invited_you: "%{name}" have_invited_you: "%{names} vous a invité à rejoindre diaspora*" + password_change: + subject: "Mot de passe changé" reset_password_instructions: change: "Changer mon mot de passe" ignore: "Si vous n'avez pas demandé cela, merci d'ignorer ce courriel." @@ -46,6 +51,9 @@ fr: subject: "Instructions de déverrouillage" unlock: "Débloquer mon compte" welcome: "Bienvenue %{email} !" + omniauth_callbacks: + failure: "Impossible de vous authentifier depuis %{kind} car \"%{reason}\"." + success: "Authentification réussie depuis le compte %{kind}." passwords: edit: change_password: "Changer mon mot de passe" @@ -57,13 +65,21 @@ fr: no_account: "Aucun compte n'est associé à cette adresse de courrier électronique." reset_password: "Réinitialiser le mot de passe" send_password_instructions: "Envoyer les instructions de réinitialisation de mot de passe" + no_token: "Vous ne pouvez accéder à cette page sans venir d'un e-mail de réinitialisation du mot de passe. Veuillez vérifier que vous avez utiliser l'URL en entier." send_instructions: "Vous allez recevoir dans quelques minutes un courriel contenant les instructions pour réinitialiser votre mot de passe." + send_paranoid_instructions: "Si votre adresse email est dans notre base de données, vous allez recevoir un lien pour remettre votre mot de passe dans quelques minutes." updated: "Votre mot de passe a été modifié. Vous êtes à présent connecté-e." + updated_not_active: "Votre mot de passe a été changé avec succès." registrations: destroyed: "Votre compte a été supprimé avec succès. Nous espérons vous revoir très bientôt. Au revoir !" signed_up: "Votre inscription a été effectuée. Si cette dernière est activée, une confirmation a été envoyée à votre adresse de courrier électronique." + signed_up_but_inactive: "Vous vous êtes inscrit·e avec succès. Cependant, vous ne pouvez pas vous connecter parce que votre compte n'est pas encore activé." + signed_up_but_locked: "Vous vous êtes inscrit·e avec succès. Cependant, vous ne pouvez pas vous connecter parce que votre compte est verrouillé." + signed_up_but_unconfirmed: "Un courriel avec un lien de confirmation vous a été envoyé. Veuillez suivre ce lien pour activer votre compte." + update_needs_confirmation: "Vous avez mis à jour votre compte correctement mais nous devons vérifier votre nouvelle adresse e-mail. Veuillez consulter votre boite aux lettres et cliquer sur le lien de confirmation." updated: "Vous avez mis à jour votre compte." sessions: + already_signed_out: "Déconnexion réussie." new: login: "Se connecter" modern_browsers: "supporte seulement des navigateurs modernes." @@ -85,9 +101,15 @@ fr: new: resend_unlock: "Renvoyer les instructions de déblocage" send_instructions: "Vous allez recevoir dans quelques minutes un courriel avec les instructions pour déverrouiller votre compte." + send_paranoid_instructions: "Si votre compte existe, vous recevrez un courriel avec des instructions pour le déverrouiller d’ici quelques minutes." unlocked: "Votre compte a été déverrouillé. Vous êtes à présent connecté-e." errors: messages: already_confirmed: "a déjà été confirmé" + confirmation_period_expired: "aurait dû être confirmé dans les %{period}, veuillez en demander un nouveau" + expired: "a expiré, veuillez faire une nouvelle demande" not_found: "introuvable" - not_locked: "n’a pas été verrouillé" \ No newline at end of file + not_locked: "n’a pas été verrouillé" + not_saved: + one: "1 erreur a empêché ce %{resource} d’être utilisé" + other: "%{count} erreurs ont empêché ce %{resource} d’être utilisé" \ No newline at end of file diff --git a/config/locales/devise/devise.hy.yml b/config/locales/devise/devise.hy.yml index 83b11bd59cd6c2f3a65a372d95257d9771e3e0b2..f3213a5d3a8bd4cb6e551f6f29c6e6e207da236d 100644 --- a/config/locales/devise/devise.hy.yml +++ b/config/locales/devise/devise.hy.yml @@ -7,19 +7,21 @@ hy: devise: confirmations: - confirmed: "Õ€Õ¡Õ·Õ«Õ¾Õ¤ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¾Õ¥ÖÖ‰ Ô±ÕµÕªÕ´ Õ¡Ö€Õ¤Õ¥Õ¶ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¸Ö‚Õ´ Õ¥Õ½Ö‰" + confirmed: "Էլ․հասÖÕ¥Õ¤ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¾Õ¥ÖÖ‰" new: resend_confirmation: "Ô¿Ö€Õ¯Õ«Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨" - send_instructions: "ÕÕ¸ÕºÕ¥Õ¶Õ¥Ö€Õ« Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¯Õ½Õ¿Õ¡Õ¶Õ¡Õ½Õ Õ°Õ¡Õ·Õ«Õ¾Õ¤ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬Õ¸Ö‚ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Õ¾Ö‰" + send_instructions: "ÕÕ¸ÕºÕ¥Õ¶Õ¥Ö€Õ« Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¯Õ½Õ¿Õ¡Õ¶Õ¡Õ½Õ Õ§Õ¬â€¤Õ°Õ¡Õ½ÖÕ¥Õ¤ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬Õ¸Ö‚ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Õ¾Ö‰" + send_paranoid_instructions: "ÔµÕ©Õ¥ Ö„Õ¸ էլ․հասÖÕ¥Õ¶ Õ¯Õ¡ Õ´Õ¥Ö€ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¢Õ¡Õ¦Õ¡ÕµÕ¸Ö‚Õ´, Ö€Õ¸ÕºÕ¥Õ¶Õ¥Ö€Õ« Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¯Õ½Õ¿Õ¡Õ¶Õ¡Õ½Õ Õ§Õ¬â€¤Õ°Õ¡Õ½ÖÕ¥Õ¤ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬Õ¸Ö‚ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Õ¾Ö‰" failure: inactive: "Õ”Õ¸ Õ°Õ¡Õ·Õ«Õ¾Õ¨ Õ¤Õ¥Õ¼ Õ¡Õ¯Õ¿Õ«Õ¾Õ¡ÖÕ¾Õ¡Õ® Õ¹Õ§Ö‰" - invalid: "ÕÕÕ¡Õ¬ Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶ Õ¯Õ¡Õ´ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Ö‰" + invalid: "ÕÕÕ¡Õ¬ %{authentication_keys} Õ¯Õ¡Õ´ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Ö‰" invalid_token: "Õ†Õ¸Ö‚ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ´Õ¡Õ¶ Õ½ÕÕ¡Õ¬Ö‰" + last_attempt: "ÔµÖ‚Õ½ Õ´Õ¥Õ¯ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¸Ö‚Õ¶Õ¥Õ½ Õ¶Õ¡ÕÖ„Õ¡Õ¶ Õ°Õ¡Õ·Õ«Õ¾Õ¤ Õ¯Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ«Ö‰" locked: "Õ”Õ¸ Õ°Õ¡Õ·Õ«Õ¾Õ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ§Ö‰" - not_found_in_database: "Ô±Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ էլ․հասÖÕ¥ Õ¯Õ¡Õ´ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Ö‰" + not_found_in_database: "ÕÕÕ¡Õ¬ %{authentication_keys} Õ¯Õ¡Õ´ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Ö‰" timeout: "Ô±Õ·ÕÕ¡Õ¿Õ¡Õ·Ö€Õ»Õ¡Õ¶Õ«Õ¤ ÕªÕ¡Õ´Õ¯Õ¥Õ¿Õ¶ Õ¡Õ¶ÖÕ¥Õ¬ Õ§, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¯Ö€Õ¯Õ«Õ¶ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ«Ö€, Õ¸Ö€ Õ·Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ½Ö‰" unauthenticated: "Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬Õ¸Ö‚Ö Õ¡Õ¼Õ¡Õ» ÕºÕ¥Õ¿Ö„ Õ§ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ½ Õ¯Õ¡Õ´ Õ£Ö€Õ¡Õ¶ÖÕ¾Õ¥Õ½Ö‰" - unconfirmed: "Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬Õ¸Ö‚Ö Õ¡Õ¼Õ¡Õ» ÕºÕ¥Õ¿Ö„ Õ§ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ½ Õ°Õ¡Õ·Õ«Õ¾Õ¤Ö‰" + unconfirmed: "Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬Õ¸Ö‚Ö Õ¡Õ¼Õ¡Õ» ÕºÕ¥Õ¿Ö„ Õ§ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ½ էլ․հասÖÕ¥Õ¤Ö‰" invitations: invitation_token_invalid: "Õ€Õ¡Õ¦Õ¡Ö€ Õ¶Õ¥Ö€Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶, Õ¢Õ¡ÕµÖ Õ¡ÕµÕ½ Õ°Ö€Õ¡Õ¾Õ¥Ö€Õ¨ Õ¾Õ¡Õ¾Õ¥Ö€ Õ¹Õ§Ö‰" send_instructions: "Õ€Ö€Õ¡Õ¾Õ¥Ö€Õ¤ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¡Õ® Õ§Ö‰" @@ -57,11 +59,18 @@ hy: no_account: "Ô±ÕµÕ½ Õ§Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ¸Õ¾ Õ°Õ¡Õ·Õ«Õ¾ Õ¹Õ¯Õ¡Ö‰" reset_password: "ÕŽÕ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨" send_password_instructions: "ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥Ö„ Õ«Õ¶Õ± Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ ÖƒÕ¸ÕÕ¥Õ¬Õ¸Ö‚ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨" + no_token: "Ô±ÕµÕ½ Õ§Õ»Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§ Õ´Õ«Õ¡ÕµÕ¶ Õ£Õ¡Õ²Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ²Õ¸Ö‚Õ´Õ¸Õ¾ Õ¶Õ¡Õ´Õ¡Õ¯Õ«Ö Õ£Õ¡Õ¬Õ¸Ö‚ Õ¤Õ¥ÕºÖ„Õ¸Ö‚Õ´Ö‰ ÔµÕ©Õ¥ Õ°Õ¥Õ¶Ö Õ¡ÕµÕ¤Õ¿Õ¥Õ²Õ«Ö Õ§, Õ¸Ö€ Õ¥Õ¯Õ¥Õ¬ Õ¥Õ½, Õ°Õ¡Õ¾Õ¡Õ½Õ¿Õ«Õ¡ÖÕ«Ö€, Õ¸Ö€ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¡Õ¯Õ¡Õ¶ Õ°Õ²Õ¸Ö‚Õ´Õ¶ Õ¥Õ½ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬Ö‰" send_instructions: "ÕÕ¸ÕºÕ¥Õ¶Õ¥Ö€Õ« Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¯Õ½Õ¿Õ¡Õ¶Õ¡Õ½Õ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¤ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬Õ¸Ö‚ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Õ¾Ö‰" + send_paranoid_instructions: "ÔµÕ©Õ¥ Ö„Õ¸ էլ․հասÖÕ¥Õ¶ Õ¯Õ¡ Õ´Õ¥Ö€ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¢Õ¡Õ¦Õ¡ÕµÕ¸Ö‚Õ´, Ö€Õ¸ÕºÕ¥Õ¶Õ¥Ö€Õ« Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¯Õ½Õ¿Õ¡Õ¶Õ¡Õ½Õ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¤ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ²Õ¸Ö‚Õ´Õ¸Õ¾Ö‰" updated: "Ô³Õ¡Õ²Õ¿Õ¡Õ¢Õ¡Õ¼Õ¤ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ ÖƒÕ¸ÕÕ¾Õ¥ÖÖ‰ Õ€Õ«Õ´Õ¡ Õ¡Ö€Õ¤Õ¥Õ¶ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¸Ö‚Õ´ Õ¥Õ½Ö‰" + updated_not_active: "Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¤ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ ÖƒÕ¸ÕÕ¾Õ¥ÖÖ‰" registrations: destroyed: "Ցը՜։ Õ”Õ¸ Õ°Õ¡Õ·Õ«Õ¾Õ¨ Õ¢Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² ÖƒÕ¡Õ¯Õ¾Õ¥ÖÖ‰ Õ€Õ¸Ö‚Õ½Õ¸Õ¾ Õ¥Õ¶Ö„ Õ·Õ¸Ö‚Õ¿Õ¸Õ¾ Õ¯Ö€Õ¯Õ«Õ¶ Õ¯Õ°Õ¡Õ¶Õ¤Õ«ÕºÕ¥Õ¶Ö„Ö‰" signed_up: "Ô²Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² Õ£Ö€Õ¡Õ¶ÖÕ¾Õ¥ÖÕ«Ö€Ö‰ Õ„Õ«Õ¡ÖÕ¾Õ¡Õ® Õ¬Õ«Õ¶Õ¥Õ¬Õ¸Ö‚ Õ¤Õ¥ÕºÖ„Õ¸Ö‚Õ´, Ö„Õ¸ Õ§Õ¬.ÖƒÕ¸Õ½Õ¿Õ«Õ¶ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¯Õ½Õ¿Õ¡Õ¶Õ¡Õ½Ö‰" + signed_up_but_inactive: "Ô²Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² Õ£Ö€Õ¡Õ¶ÖÕ¾Õ¥ÖÕ«Ö€Ö‰ Ô±ÕµÕ¶Õ¸Ö‚Õ°Õ¡Õ¶Õ¤Õ¥Ö€Õ±, Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¨ Õ¹Õ½Õ¿Õ¡ÖÕ¾Õ¥ÖÕ Õ°Õ¡Õ·Õ¾Õ«Õ¤ Õ¤Õ¥Õ¼ Õ¡Õ¯Õ¿Õ«Õ¾Õ¡ÖÕ¾Õ¡Õ® Õ¹Õ¬Õ«Õ¶Õ¥Õ¬Õ¸Ö‚ ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾Ö‰" + signed_up_but_locked: "Ô²Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² Õ£Ö€Õ¡Õ¶ÖÕ¾Õ¥ÖÕ«Ö€Ö‰ Ô±ÕµÕ¶Õ¸Ö‚Õ°Õ¡Õ¶Õ¤Õ¥Ö€Õ±, Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¨ Õ¹Õ½Õ¿Õ¡ÖÕ¾Õ¥ÖÕ Õ°Õ¡Õ·Õ¾Õ«Õ¤ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ¬Õ«Õ¶Õ¥Õ¬Õ¸Ö‚ ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾Ö‰" + signed_up_but_unconfirmed: "Õ”Õ¸ էլ․հասÖÕ¥Õ«Õ¶ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¥Õ¶Ö„ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ Õ°Õ²Õ¸Ö‚Õ´Õ¸Õ¾Ö‰ Ô±Õ¶ÖÕ«Ö€ Õ¡ÕµÕ¤ Õ°Õ²Õ¸Ö‚Õ´Õ¸Õ¾ Õ°Õ¡Õ·Õ«Õ¾Õ¤ Õ¡Õ¯Õ¿Õ«Õ¾Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰" + update_needs_confirmation: "Õ€Õ¡Õ·Õ«Õ¾Õ¤ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ©Õ¡Ö€Õ´Õ¡ÖÖ€Õ¥ÖÕ«Ö€, Õ¢Õ¡ÕµÖ Õ¤Õ¥Õ¼ ÕºÕ¥Õ¿Ö„ Õ§ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ½ Õ¶Õ¸Ö€ էլ․հասÖÕ¥Õ¤Ö‰ ÕÕ¿Õ¸Ö‚Õ£Õ«Ö€ էլ․փոստդ Õ¸Ö‚ Õ¡Õ¶ÖÕ«Ö€ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ Õ°Õ²Õ¸Ö‚Õ´Õ¸Õ¾, Õ¸Ö€ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ½ Õ¡ÕµÕ¶Ö‰" updated: "Õ€Õ¡Õ·Õ«Õ¾Õ¤ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¾Õ¥ÖÖ‰" sessions: new: @@ -79,15 +88,16 @@ hy: receive_confirmation: "Õ‰Õ¥ÕžÕ½ Õ½Õ¿Õ¡ÖÕ¥Õ¬ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰" receive_unlock: "Õ‰Õ¥ÕžÕ½ Õ½Õ¿Õ¡ÖÕ¥Õ¬ Õ¡ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ´Õ¡Õ¶ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰" sign_in: "Õ„Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬" - sign_up: "Ô³Ö€Õ¡Õ¶ÖÕ¾Õ¥Õ¬" + sign_up: "Õ€Õ¡Õ·Õ«Õ¾ Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬" sign_up_closed: "Ô±ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ Õ¢Õ¡Ö Õ£Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ¥Õ¶Ö‰" unlocks: new: resend_unlock: "Ô¿Ö€Õ¯Õ«Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¡ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ´Õ¡Õ¶ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨" send_instructions: "ÕÕ¸ÕºÕ¥Õ¶Õ¥Ö€Õ« Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¯Õ½Õ¿Õ¡Õ¶Õ¡Õ½Õ Õ°Õ¡Õ·Õ«Õ¾Õ¤ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ«Ö Õ°Õ¡Õ¶Õ¥Õ¬Õ¸Ö‚ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Õ¾Ö‰" - unlocked: "Õ€Õ¡Õ·Õ«Õ¾Õ¤ Õ¢Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² Õ¡ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¥ÖÖ‰ Ô±ÕµÕªÕ´ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¸Ö‚Õ´ Õ¥Õ½Ö‰" + send_paranoid_instructions: "ÔµÕ©Õ¥ Õ°Õ¡Õ·Õ«Õ¾Õ¤ Õ£Õ¸ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¸Ö‚Õ¶Õ«, Ö€Õ¸ÕºÕ¥Õ¶Õ¥Ö€Õ« Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´ Õ¶Õ¡Õ´Õ¡Õ¯ Õ¯Õ½Õ¿Õ¡Õ¶Õ¡Õ½Õ Õ¡ÕµÕ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¸Ö‚Õ´Õ«Ö Õ°Õ¡Õ¶Õ¥Õ¬Õ¸Ö‚ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Õ¾Ö‰" + unlocked: "Õ€Õ¡Õ·Õ«Õ¾Õ¤ Õ¢Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² Õ¡ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¥ÖÖ‰ Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬Ö‰" errors: messages: - already_confirmed: "Õ¡Ö€Õ¤Õ¥Õ¶ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¾Õ¥Õ¬ Õ§" + already_confirmed: "Õ¡Ö€Õ¤Õ¥Õ¶ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¾Õ¥Õ¬ Õ§, ÖƒÕ¸Ö€Õ±Õ«Ö€ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬" not_found: "Õ¹Õ« Õ£Õ¿Õ¶Õ¾Õ¥Õ¬" not_locked: "Õ¯Õ¸Õ²ÕºÕ¾Õ¡Õ® Õ¹Õ§" \ No newline at end of file diff --git a/config/locales/devise/devise.is.yml b/config/locales/devise/devise.is.yml index 00ec3e5d29a7f0386bac1fca9a8db99b3b499c58..5e3b06edbdf266a4f73f2c1d0f55d2b21b6209d3 100644 --- a/config/locales/devise/devise.is.yml +++ b/config/locales/devise/devise.is.yml @@ -54,13 +54,13 @@ is: new: email: "Netfang" forgot_password: "Gleymdirðu lykilorðinu þÃnu?" - no_account: "Enginn notandi með þetta netfang ert til. Ef þú ert að bÃða eftir boði, þá erum við að senda þau út eins fljótt og auðið er" + no_account: "Enginn notandi með þetta netfang ert til" reset_password: "Endurstilla lykilorð" send_password_instructions: "Senda mér leiðbeiningar um hvernig ég get endurstillt lykilorðið mitt" send_instructions: "Þú munt fá tölvupóst innan fárra mÃnútna, með leiðbeiningum um hvernig þú getur endurstillt lykilorð þitt." updated: "Lykilorði þÃnu hefur hér með verið breytt. Þú ert nú skráð/ur inn." registrations: - destroyed: "Bæ! Aðgangur þinn hefur hér með verið afturkallaður. Við vonumst til þess að sjá þig brátt aftur." + destroyed: "Bæ! Aðgangi þÃnum hefur verið eytt. Við vonumst samt til þess að sjá þig bráðum aftur." signed_up: "Þú hefur hér með stofnað aðgang. Staðfesting var send á tölvupóstfang þitt, ef kveikt er á þeim möguleika." updated: "Þú hefur nú uppfært aðgang þinn." sessions: diff --git a/config/locales/devise/devise.ja.yml b/config/locales/devise/devise.ja.yml index de4236ad745a903b9cb19cc2fdd0b7b9cbc4c542..7cfff0e10736d899f39cd447c6a69327638e18b0 100644 --- a/config/locales/devise/devise.ja.yml +++ b/config/locales/devise/devise.ja.yml @@ -11,19 +11,22 @@ ja: new: resend_confirmation: "èªè¨¼ãƒ¡ãƒ¼ãƒ«ã‚’å†é€ã™ã‚‹" send_instructions: "数分後ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆèªè¨¼ã®æ‰‹ç¶šãメールãŒå±Šãã¾ã™ã€‚" + send_paranoid_instructions: "ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒç§ãŸã¡ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«å˜åœ¨ã™ã‚‹å ´åˆã€æ•°åˆ†ã§ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’確èªã™ã‚‹æ–¹æ³•ã«ã¤ã„ã¦ã®æ‰‹é †ã‚’記載ã—ãŸãƒ¡ãƒ¼ãƒ«ãŒå±Šãã¾ã™ã€‚" failure: - inactive: "アカウントã¯ã¾ã 承èªã•ã‚Œã¦ã„ã¾ã›ã‚“。" + already_authenticated: "æ—¢ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³æ¸ˆã¿ã§ã™ã€‚" + inactive: "アカウントã¯ã¾ã 有効ã«ãªã£ã¦ã„ã¾ã›ã‚“。" invalid: "ユーザåã¾ãŸã¯ãƒ‘スワードãŒä¸æ£ã§ã™ã€‚" invalid_token: "無効ãªèªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³ã§ã™ã€‚" + last_attempt: "アカウントãŒãƒãƒƒã‚¯ã•ã‚Œã‚‹ã¾ã§ã«ã€ã¾ã 複数回試ã™ã“ã¨ãŒã§ãã¾ã™ã€‚" locked: "アカウントãŒãƒãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚" not_found_in_database: "メールアドレスã¾ãŸã¯ãƒ‘スワードãŒç„¡åŠ¹ã§ã™ã€‚" - timeout: "セッション切れã«ãªã‚Šã¾ã—ãŸã€‚続ãã«ã¯ã‚‚ã†ä¸€åº¦ãƒã‚°ã‚¤ãƒ³ã—ã¦ãã ã•ã„。" - unauthenticated: "進むã«ã¯ãƒã‚°ã‚¤ãƒ³ã¾ãŸã¯æ–°è¦ç™»éŒ²ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚" + timeout: "セッション切れã«ãªã‚Šã¾ã—ãŸã€‚続ãã«ã¯ã‚‚ã†ä¸€åº¦ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¦ãã ã•ã„。" + unauthenticated: "進むã«ã¯ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã¾ãŸã¯æ–°è¦ç™»éŒ²ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚" unconfirmed: "進ã«ã¯ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’確èªã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚" invitations: invitation_token_invalid: "ã”使用ã®æ‹›å¾…トークンã¯ç„¡åŠ¹ã§ã™ï¼" send_instructions: "招待メールをé€ä¿¡ã—ã¾ã—ãŸã€‚" - updated: "パスワードã®è¨å®šã«æˆåŠŸã—ã¾ã—ãŸã€‚æ—¢ã«ãƒã‚°ã‚¤ãƒ³æ¸ˆã¿ã§ã™ã€‚" + updated: "パスワードã®è¨å®šã«æˆåŠŸã—ã¾ã—ãŸã€‚æ—¢ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³æ¸ˆã¿ã§ã™ã€‚" mailer: confirmation_instructions: confirm: "アカウントをèªè¨¼ã™ã‚‹" @@ -31,8 +34,11 @@ ja: you_can_confirm: "次ã®ãƒªãƒ³ã‚¯ã‹ã‚‰ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒèªè¨¼ã§ãã¾ã™ã€‚" hello: "%{email}ã•ã‚“ã€ã“ã‚“ã«ã¡ã¯ï¼" inviter: + accept_at: "%{url} ã§ã€ä¸‹ã®ãƒªãƒ³ã‚¯ã‹ã‚‰å—ã‘入れるã“ã¨ãŒã§ãã¾ã™ã€‚" has_invited_you: "%{name}ã•ã‚“" have_invited_you: "%{names}ã•ã‚“ãŒãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©ã«æ‹›å¾…ã—ã¦ã„ã¾ã™" + password_change: + subject: "パスワードを変更ã—ã¾ã—ãŸ" reset_password_instructions: change: "パスワードを変更ã™ã‚‹" ignore: "å†è¨å®šã‚’申請ã—ãŸè¦šãˆãŒãªã„å ´åˆã¯ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚’無視ã—ã¦ãã ã•ã„。" @@ -40,11 +46,14 @@ ja: subject: "パスワードå†è¨å®šæ‰‹ç¶šã" wont_change: "上ã®ãƒªãƒ³ã‚¯ã‚’アクセスã—ã¦æ–°ã—ã„パスワードを登録ã™ã‚‹ã¾ã§ã¯ãƒ‘スワードãŒå¤‰æ›´ã•ã‚Œã¾ã›ã‚“。" unlock_instructions: - account_locked: "ãƒã‚°ã‚¤ãƒ³å¤±æ•—ãŒå¤šã™ãŽãŸãŸã‚ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒãƒãƒƒã‚¯ã•ã‚Œã¾ã—ãŸã€‚" + account_locked: "サインイン失敗回数ãŒå¤šã™ãŽãŸãŸã‚ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒãƒãƒƒã‚¯ã•ã‚Œã¾ã—ãŸã€‚" click_to_unlock: "アカウントã®ãƒãƒƒã‚¯ã‚’解除ã™ã‚‹ã®ã«ä¸‹è¨˜ã®ãƒªãƒ³ã‚¯ã«ã‚¯ãƒªãƒƒã‚¯ã—ã¦ãã ã•ã„。" subject: "ãƒãƒƒã‚¯è§£é™¤èª¬æ˜Ž" unlock: "アカウントã®ãƒãƒƒã‚¯ã‚’解除ã™ã‚‹" welcome: "%{email}ã•ã‚“ã€ã‚ˆã†ã“ãï¼" + omniauth_callbacks: + failure: "\"%{reason}\" ã®ãŸã‚ã€%{kind} ã‹ã‚‰èªè¨¼ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" + success: "%{kind} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‹ã‚‰æ£å¸¸ã«èªè¨¼ã—ã¾ã—ãŸã€‚" passwords: edit: change_password: "パスワードを変更ã™ã‚‹" @@ -56,37 +65,50 @@ ja: no_account: "ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«ä¸€è‡´ã™ã‚‹ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯å˜åœ¨ã—ã¾ã›ã‚“。招待待ã¡ã®æ–¹ã¯ã€ãªã‚‹ã¹ãæ—©ã出ã›ã‚‹ã‚ˆã†ã«åŠªåŠ›ã—ã¦ã„ã¾ã™ã®ã§ã€ã‚‚ã†å°‘々ãŠå¾…ã¡ãã ã•ã„。" reset_password: "パスワードã®å†è¨å®š" send_password_instructions: "パスワードå†ç™ºè¡Œã®æ‰‹ç¶šãメールをé€ã£ã¦ãã ã•ã„。" + no_token: "パスワードリセットã®ãƒ¡ãƒ¼ãƒ«ã‹ã‚‰ã§ã¯ãªã„ã¨ã€ã“ã®ãƒšãƒ¼ã‚¸ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。パスワードリセットã®ãƒ¡ãƒ¼ãƒ«ã‹ã‚‰æ¥ãŸå ´åˆã¯ã€æä¾›ã•ã‚ŒãŸå®Œå…¨ãªURLを使用ã—ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。" send_instructions: "数分後ã«ãƒ‘スワードå†ç™ºè¡Œã®æ‰‹ç¶šãメールãŒå±Šãã¾ã™ã€‚" - updated: "パスワードã®å¤‰æ›´ã«æˆåŠŸã—ã¾ã—ãŸã€‚æ—¢ã«ãƒã‚°ã‚¤ãƒ³æ¸ˆã¿ã§ã™ã€‚" + send_paranoid_instructions: "ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒç§ãŸã¡ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«å˜åœ¨ã™ã‚‹å ´åˆã€æ•°åˆ†ã§ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãƒ‘スワード回復リンクをå—ä¿¡ã—ã¾ã™ã€‚" + updated: "パスワードã®å¤‰æ›´ã«æˆåŠŸã—ã¾ã—ãŸã€‚æ—¢ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³æ¸ˆã¿ã§ã™ã€‚" + updated_not_active: "パスワードãŒæ£å¸¸ã«å¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚" registrations: destroyed: "ã•ã‚ˆã†ãªã‚‰ï¼ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®å–消ã—ã«æˆåŠŸã—ã¾ã—ãŸã€‚ã¾ãŸã®ã”å‚åŠ ã‚’ãŠå¾…ã¡ã—ã¦ã„ã¾ã™ã€‚" signed_up: "æ–°è¦ç™»éŒ²ã«æˆåŠŸã—ã¾ã—ãŸã€‚è¨å®šãŒæœ‰åŠ¹ãªå ´åˆã€ç¢ºèªãƒ¡ãƒ¼ãƒ«ã‚‚é€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚" + signed_up_but_inactive: "ã”登録手続ããŒå®Œäº†ã—ã¦ã„ã¾ã™ã€‚ã—ã‹ã—ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒã¾ã 有効ã«ãªã£ã¦ãŠã‚Šã¾ã›ã‚“ã®ã§ã€ã‚µã‚¤ãƒ³ã‚¤ãƒ³ãŒå‡ºæ¥ã¾ã›ã‚“ã§ã—ãŸã€‚" + signed_up_but_locked: "ã”登録手続ããŒå®Œäº†ã—ã¦ã„ã¾ã™ã€‚ã—ã‹ã—ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒãƒãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€ã‚µã‚¤ãƒ³ã‚¤ãƒ³ãŒå‡ºæ¥ã¾ã›ã‚“ã§ã—ãŸã€‚" + signed_up_but_unconfirmed: "ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«èªè¨¼ãƒªãƒ³ã‚¯ã®è¨˜è¼‰ã•ã‚ŒãŸãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒé€ä¿¡ã•ã‚Œã¦ã„ã¾ã™ã€‚ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’有効ã«ã™ã‚‹ãƒªãƒ³ã‚¯ã‚’é–‹ã„ã¦ãã ã•ã„。" + update_needs_confirmation: "アカウントをæ£å¸¸ã«æ›´æ–°ã—ã¾ã—ãŸãŒã€ç§ãŸã¡ã¯æ–°ã—ã„メールアドレスを確èªã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚メールを確èªã—ã¦ã€æ–°ã—ã„メールアドレスを確èªã™ã‚‹ãŸã‚ã«ã€ç¢ºèªã®ãƒªãƒ³ã‚¯ã‚’クリックã—ã¦ãã ã•ã„。" updated: "アカウントã®æ›´æ–°ã«æˆåŠŸã—ã¾ã—ãŸã€‚" sessions: + already_signed_out: "サインアウトã«æˆåŠŸã—ã¾ã—ãŸã€‚" new: login: "ãƒã‚°ã‚¤ãƒ³" modern_browsers: "最新型ã®ãƒ–ラウザã«ã—ã‹å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。" password: "パスワード" remember_me: "ãƒã‚°ã‚¤ãƒ³ã—ãŸã¾ã¾ã«ã™ã‚‹" - sign_in: "ãƒã‚°ã‚¤ãƒ³" + sign_in: "サインイン" username: "ユーザå" - signed_in: "ãƒã‚°ã‚¤ãƒ³ã«æˆåŠŸã—ã¾ã—ãŸã€‚" - signed_out: "ãƒã‚°ã‚¢ã‚¦ãƒˆã«æˆåŠŸã—ã¾ã—ãŸã€‚" + signed_in: "サインインã«æˆåŠŸã—ã¾ã—ãŸã€‚" + signed_out: "サインアウトã«æˆåŠŸã—ã¾ã—ãŸã€‚" shared: links: forgot_your_password: "パスワードを忘れã¾ã—ãŸã‹ã€‚" receive_confirmation: "èªè¨¼æ‰‹ç¶šãメールãŒå±Šãã¾ã›ã‚“ã§ã—ãŸã‹ã€‚" receive_unlock: "ãƒãƒƒã‚¯è§£é™¤ã®èª¬æ˜ŽãŒå±Šãã¾ã›ã‚“ã§ã—ãŸã‹ã€‚" - sign_in: "ãƒã‚°ã‚¤ãƒ³" + sign_in: "サインイン" sign_up: "æ–°è¦ç™»éŒ²" sign_up_closed: "一般ã®æ–°è¦ç™»éŒ²ã¯ç¾åœ¨å—ã‘付ã‘ã¦ã„ã¾ã›ã‚“。" unlocks: new: resend_unlock: "ãƒãƒƒã‚¯è§£é™¤æ‰‹ç¶šãメールをå†é€ã™ã‚‹" send_instructions: "数分後ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒãƒƒã‚¯è§£é™¤ã®æ‰‹ç¶šãメールãŒå±Šãã¾ã™ã€‚" - unlocked: "アカウントã®ãƒãƒƒã‚¯è§£é™¤ã«æˆåŠŸã—ã¾ã—ãŸã€‚æ—¢ã«ãƒã‚°ã‚¤ãƒ³æ¸ˆã¿ã§ã™ã€‚" + send_paranoid_instructions: "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒå˜åœ¨ã™ã‚‹å ´åˆã¯ã€æ•°åˆ†ã§ãƒãƒƒã‚¯ã‚’解除ã™ã‚‹æ–¹æ³•ã«ã¤ã„ã¦ã®æ‰‹é †ã‚’記載ã—ãŸãƒ¡ãƒ¼ãƒ«ãŒå±Šãã¾ã™ã€‚" + unlocked: "アカウントã®ãƒãƒƒã‚¯è§£é™¤ã«æˆåŠŸã—ã¾ã—ãŸã€‚æ—¢ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³æ¸ˆã¿ã§ã™ã€‚" errors: messages: - already_confirmed: "æ—¢ã«èªè¨¼æ¸ˆã¿ã§ã™ã€‚" + already_confirmed: "æ—¢ã«èªè¨¼æ¸ˆã¿ã§ã™ã€‚サインインã—ã¦ã¿ã¦ãã ã•ã„。" + confirmation_period_expired: "%{period} 以内ã«ç¢ºèªã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚æ–°ã—ãリクエストã—ã¦ãã ã•ã„" + expired: "有効期é™åˆ‡ã‚Œã§ã™ã€‚æ–°ã—ãリクエストã—ã¦ãã ã•ã„" not_found: "見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" - not_locked: "ãƒãƒƒã‚¯ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚" \ No newline at end of file + not_locked: "ãƒãƒƒã‚¯ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚" + not_saved: + other: "%{count} エラーã®ãŸã‚ã€ã“ã® %{resource} ã®ä¿å˜ã‚’ç¦æ¢ã—ã¾ã—ãŸ:" \ No newline at end of file diff --git a/config/locales/devise/devise.nl.yml b/config/locales/devise/devise.nl.yml index 39c04fdad57ec7f22fa40196988ffe3adaaafbc4..5737adb5727e248507a00ffb984f11ccfd00ed32 100644 --- a/config/locales/devise/devise.nl.yml +++ b/config/locales/devise/devise.nl.yml @@ -79,7 +79,7 @@ nl: receive_confirmation: "Geen bevestigingsinstructies ontvangen?" receive_unlock: "Geen ontgrendelinstructies ontvangen?" sign_in: "Inloggen" - sign_up: "Registreer" + sign_up: "Creëer een account" sign_up_closed: "Vrij registreren is momenteel niet mogelijk." unlocks: new: diff --git a/config/locales/devise/devise.pt-BR.yml b/config/locales/devise/devise.pt-BR.yml index ebbcbf061f978465c0210c70e372150b8a86b9bb..a030aa10762a4f26ffe467842493433688b5b9a2 100644 --- a/config/locales/devise/devise.pt-BR.yml +++ b/config/locales/devise/devise.pt-BR.yml @@ -7,19 +7,22 @@ pt-BR: devise: confirmations: - confirmed: "Sua conta foi confirmada com sucesso. Seja bem-vindo(a)!" + confirmed: "Seu endereço de e-mail foi confirmado com sucesso." new: resend_confirmation: "Reenviar as instruções de confirmação." - send_instructions: "Em poucos minutos, você receberá um email com as instruções sobre como confirmar a sua conta." + send_instructions: "Você receberá em breve um e-mail com instruções para confirmar seu endereço de e-mail." + send_paranoid_instructions: "Se o seu endereço de e-mail estiver no banco de dados, você receberá, em alguns minutos, uma mensagem com instruções para confirmá-lo." failure: + already_authenticated: "Você já entrou." inactive: "Sua conta ainda não foi ativada." - invalid: "Nome de usuário ou senha inválidos." + invalid: "Senha ou %{authentication_keys} inválidos." invalid_token: "Token de autenticação inválido." + last_attempt: "Você só pode fazer mais uma tentativa antes que sua conta seja bloqueada." locked: "Sua conta está bloqueada." - not_found_in_database: "Email ou senha inválido(a)." - timeout: "Sua sessão expirou; por favor, entre novamente para continuar." + not_found_in_database: "Senha ou %{authentication_keys} inválidos." + timeout: "Sua sessão expirou. Por favor, entre novamente para continuar." unauthenticated: "Você precisa entrar ou se cadastrar antes de continuar." - unconfirmed: "Você deve confirmar a sua conta antes de continuar." + unconfirmed: "Você deve confirmar seu endereço de e-mail antes de continuar." invitations: invitation_token_invalid: "Seu convite é inválido!" send_instructions: "Seu convite foi enviado." @@ -34,6 +37,8 @@ pt-BR: accept_at: "em %{url}, você pode aceitar através do link abaixo." has_invited_you: "%{name}" have_invited_you: "%{names} convidou você para participar de diaspora*" + password_change: + subject: "Senha Alterada" reset_password_instructions: change: "Alterar minha senha" ignore: "Se você não fez esta solicitação, por favor ignore este email." @@ -46,6 +51,9 @@ pt-BR: subject: "Instruções para desbloqueio" unlock: "Desbloquear minha conta" welcome: "Bem-vindo(a) %{email}!" + omniauth_callbacks: + failure: "Não foi possÃvel autenticar você pelo %{kind} porque \"%{reason}\"." + success: "Autenticação com conta do %{kind} bem-sucedida." passwords: edit: change_password: "Mudar minha senha" @@ -57,13 +65,21 @@ pt-BR: no_account: "Não há nenhuma conta com este email" reset_password: "Resetar senha" send_password_instructions: "Envie-me instruções para redefinir minha senha." - send_instructions: "Você receberá em breve um email com instruções sobre como redefinir sua senha." - updated: "Sua senha foi alterada com sucesso." + no_token: "Você só pode acessar esta página a partir de um e-mail de recuperação de senha. Se esse é o caso, certifique-se que usou o URL fornecido completo." + send_instructions: "Você receberá em breve um e-mail com instruções para redefinir sua senha." + send_paranoid_instructions: "Se o seu endereço de e-mail estiver no banco de dados, você receberá, em alguns minutos, uma mensagem com um link de recuperação de senha." + updated: "Sua senha foi alterada com sucesso. Você está em sessão." + updated_not_active: "Sua senha foi alterada com sucesso." registrations: destroyed: "Tchau! Sua conta foi cancelada com sucesso. Esperamos vê-lo novamente em breve." signed_up: "Você se inscreveu com êxito. Se habilitado, a confirmação foi enviada para seu e-mail." - updated: "Você atualizou a sua conta com sucesso." + signed_up_but_inactive: "Você se cadastrou com êxito. Porém não pode entrar porque sua conta ainda não foi ativada." + signed_up_but_locked: "Você se cadastrou com êxito. Porém não pode entrar porque sua conta está bloqueada." + signed_up_but_unconfirmed: "Uma mensagem de confirmação foi enviada para seu endereço de e-mail. Clique no link para ativar sua conta." + update_needs_confirmation: "Você atualizou sua conta, mas precisamos verificar seu novo endereço de e-mail. Por favor, cheque seu e-mail e clique no link fornecido para confirmá-lo." + updated: "Sua conta foi atualizada com sucesso." sessions: + already_signed_out: "A sessão foi terminada com sucesso." new: login: "Entrar" modern_browsers: "somente suporta navegadores modernos." @@ -79,15 +95,21 @@ pt-BR: receive_confirmation: "Não recebeu instruções de confirmação?" receive_unlock: "Não recebeu instruções de desbloqueio?" sign_in: "Entrar" - sign_up: "Cadastre-se" + sign_up: "Criar conta" sign_up_closed: "Registros abertos estão encerrados no momento." unlocks: new: resend_unlock: "Reenviar instruções de desbloqueio" - send_instructions: "Você receberá em breve um email com as instruções sobre como desbloquear a sua conta." - unlocked: "Sua conta foi desbloqueada com sucesso. Seja bem-vindo!" + send_instructions: "Você receberá em breve um e-mail com instruções para desbloquear sua conta." + send_paranoid_instructions: "Se sua conta existir, você receberá, em alguns minutos, um e-mail com instruções para desbloqueá-la." + unlocked: "Sua conta foi desbloqueada com sucesso. Entre para continuar." errors: messages: - already_confirmed: "já foi confirmado" + already_confirmed: "já foi confirmado, por favor, tente fazer login" + confirmation_period_expired: "deve ser confirmado dentro de %{period}, por favor, solicite uma nova" + expired: "expirou, por favor, solicite uma nova" not_found: "não encontrado" - not_locked: "não foi bloqueado" \ No newline at end of file + not_locked: "não foi bloqueado" + not_saved: + one: "1 erro impediu-nos de salvar %{resource}:" + other: "%{count} erros impediram-nos de salvar %{resource}:" \ No newline at end of file diff --git a/config/locales/devise/devise.sv.yml b/config/locales/devise/devise.sv.yml index f4501970f77f75a735bde2fdb1c4b6f2008735b7..37360dc31ba7e80983ba493b9ca84b51880b174e 100644 --- a/config/locales/devise/devise.sv.yml +++ b/config/locales/devise/devise.sv.yml @@ -79,7 +79,7 @@ sv: receive_confirmation: "Fick du inget bekräftelsemail?" receive_unlock: "Fick du inga upplÃ¥sningsinstruktioner?" sign_in: "Logga in" - sign_up: "Registrera dig" + sign_up: "Skapa konto" sign_up_closed: "Formuläret för att bli medlem är tyvärr stängt." unlocks: new: diff --git a/config/locales/devise/devise.zh-TW.yml b/config/locales/devise/devise.zh-TW.yml index 811f882c02547d07b4309362d582392efcbd8444..b34378975503cf5530bec4ad32d6f197c0343cf2 100644 --- a/config/locales/devise/devise.zh-TW.yml +++ b/config/locales/devise/devise.zh-TW.yml @@ -7,19 +7,22 @@ zh-TW: devise: confirmations: - confirmed: "帳號確èªæˆåŠŸã€‚ä½ å·²ç¶“ç™»å…¥äº†ã€‚" + confirmed: "é›»å信箱已經æˆåŠŸç¢ºèªäº†ã€‚" new: resend_confirmation: "é‡é€ç¢ºèªæ¥é©Ÿ" - send_instructions: "幾分é˜ä¹‹å…§ï¼Œä½ 會收到一å°ä¿¡ä»¶ï¼Œèªªæ˜Žå¦‚何確èªå¸³è™Ÿã€‚" + send_instructions: "幾分é˜ä¹‹å…§ä½ 就會收到一å°é›»å郵件,說明如何確èªä¿¡ç®±ã€‚" + send_paranoid_instructions: "如果資料庫裡é¢æœ‰ä½ çš„é›»å信箱的話,幾分é˜ä¹‹å…§ä½ 就會收到一å°é›»å郵件,說明如何確èªä¿¡ç®±ã€‚" failure: - inactive: "ä½ çš„å¸³è™Ÿå°šæœªé–‹é€šã€‚" - invalid: "使用者å稱或密碼無效。" + already_authenticated: "已經登入了。" + inactive: "ä½ çš„å¸³è™Ÿé‚„æ²’æœ‰é–‹é€šã€‚" + invalid: "%{authentication_keys}或是密碼無效。" invalid_token: "èªè‰ä¿¡ç‰©ç„¡æ•ˆã€‚" - locked: "ä½ çš„å¸³è™Ÿå·²éŽ–å®šã€‚" - not_found_in_database: "無效的電å郵件或密碼。" - timeout: "工作階段已逾時,è¦ç¹¼çºŒçš„話請é‡æ–°ç™»å…¥ã€‚" + last_attempt: "ä½ é‚„å¯ä»¥å†è©¦ä¸€æ¬¡ï¼Œå¤±æ•—的話帳號就會鎖定了。" + locked: "ä½ çš„å¸³è™Ÿè¢«éŽ–å®šäº†ã€‚" + not_found_in_database: "%{authentication_keys}或密碼無效。" + timeout: "工作階段éŽæœŸäº†ï¼Œè¦ç¹¼çºŒä½¿ç”¨çš„話請é‡æ–°ç™»å…¥ã€‚" unauthenticated: "繼續之å‰ä½ å¿…é ˆå…ˆç™»å…¥æˆ–è¨»å†Šã€‚" - unconfirmed: "ä½ å¿…é ˆå…ˆç¢ºèªå¸³è™Ÿæ‰èƒ½ç¹¼çºŒã€‚" + unconfirmed: "è¦ç¹¼çºŒä½¿ç”¨å¿…é ˆè¦å…ˆç¢ºèªé›»å信箱。" invitations: invitation_token_invalid: "很抱æ‰ï¼æ¤é‚€è«‹ä¿¡ç‰©ç„¡æ•ˆã€‚" send_instructions: "邀請å¡å¯„出去了。" @@ -34,6 +37,8 @@ zh-TW: accept_at: "æ–¼ %{url}ï¼Œä½ å¯ä»¥é€éŽä»¥ä¸‹é€£çµä¾†æŽ¥å—。" has_invited_you: "%{name}" have_invited_you: "%{names} é‚€è«‹ä½ åŠ å…¥ diaspora* " + password_change: + subject: "密碼改了" reset_password_instructions: change: "更改密碼" ignore: "å¦‚æžœä½ æ²’æœ‰è¦æ±‚éŽï¼Œè«‹ä¸ç”¨ç®¡é€™å°ä¿¡ã€‚" @@ -46,6 +51,9 @@ zh-TW: subject: "解鎖æ¥é©Ÿ" unlock: "帳號解鎖" welcome: "æ¡è¿Žä½ ,%{email}ï¼" + omniauth_callbacks: + failure: "è·Ÿ %{kind} èªè‰å¤±æ•—ï¼ŒåŽŸå› æ˜¯ï¼š%{reason}。" + success: "%{kind} 帳號èªè‰æˆåŠŸã€‚" passwords: edit: change_password: "更改密碼" @@ -57,13 +65,21 @@ zh-TW: no_account: "沒有和這個電å信箱關è¯çš„帳號" reset_password: "é‡è¨å¯†ç¢¼" send_password_instructions: "傳é€å¯†ç¢¼é‡è¨çš„æ¥é©Ÿçµ¦æˆ‘" - send_instructions: "幾分é˜ä¹‹å…§ï¼Œä½ 會收到一å°èªªæ˜Žå¦‚何é‡è¨å¯†ç¢¼çš„信件。" + no_token: "這個é é¢åªçµ¦é‡è¨å¯†ç¢¼çš„é›»åéƒµä»¶ä½¿ç”¨ã€‚å¦‚æžœä½ çœŸçš„æ˜¯é»žå¯†ç¢¼é‡è¨ä¿¡ä»¶éŽä¾†çš„,請確定用的是信件ä¸å®Œæ•´çš„網å€ã€‚" + send_instructions: "幾分é˜ä¹‹å…§ä½ 就會收到一å°é›»å郵件,說明如何é‡è¨å¯†ç¢¼ã€‚" + send_paranoid_instructions: "如果資料庫裡é¢æœ‰ä½ çš„é›»å信箱的話,幾分é˜ä¹‹å…§ä½ 就會收到一å°é›»å郵件,裡é¢æœ‰é‡è¨å¯†ç¢¼çš„連çµã€‚" updated: "密碼更改æˆåŠŸï¼Œä½ 已經登入了。" + updated_not_active: "密碼修改æˆåŠŸã€‚" registrations: destroyed: "掰掰ï¼ä½ 的帳號已經å–消了。希望ä¸ä¹…後å†è¦‹ã€‚" signed_up: "ä½ å·²ç¶“ç™»è¨˜æˆåŠŸäº†ã€‚如果有è¨å®šçš„話,確èªä¿¡æœƒé€åˆ°ä½ 的信箱。" + signed_up_but_inactive: "帳號註冊æˆåŠŸäº†ã€‚ä¸éŽå› 為帳號還沒有開通,所以ä¸èƒ½ç™»å…¥ã€‚" + signed_up_but_locked: "帳號註冊æˆåŠŸäº†ã€‚ä¸éŽå› 為帳號在鎖定的狀態,所以還ä¸èƒ½ç™»å…¥ã€‚" + signed_up_but_unconfirmed: "已經寄一å°é›»åéƒµä»¶åˆ°ä½ çš„ä¿¡ç®±äº†ï¼Œè£¡é¢æœ‰å¸³è™Ÿç¢ºèªçš„連çµã€‚請點那個連çµä¾†é–‹é€šä½ 的帳號。" + update_needs_confirmation: "帳號更改æˆåŠŸï¼Œä¸éŽæˆ‘å€‘å¿…é ˆé©—è‰ä½ æ–°çš„é›»åä¿¡ç®±ã€‚è«‹æª¢æŸ¥ä½ çš„ä¿¡ç®±çœ‹æœ‰æ²’æœ‰æˆ‘å€‘å¯„çµ¦ä½ çš„ä¿¡ä»¶ï¼Œä¸¦ä¸”é»žä¿¡ä»¶ä¸çš„連çµä¾†é€²è¡Œç¢ºèªã€‚" updated: "帳號更新æˆåŠŸäº†ã€‚" sessions: + already_signed_out: "登出æˆåŠŸã€‚" new: login: "登入" modern_browsers: "僅支æ´æ–°æ½®çš„ç€è¦½å™¨ã€‚" @@ -80,14 +96,19 @@ zh-TW: receive_unlock: "沒收到解鎖æ¥é©Ÿå—Žï¼Ÿ" sign_in: "登入" sign_up: "註冊" - sign_up_closed: "ç›®å‰ä¸é–‹æ”¾å…¬é–‹ç™»è¨˜ã€‚" + sign_up_closed: "ç›®å‰ä¸å°å¤–開放註冊。" unlocks: new: resend_unlock: "é‡é€è§£éŽ–æ¥é©Ÿ" - send_instructions: "幾分é˜ä¹‹å…§ï¼Œä½ 會收到一å°ä¿¡ä»¶ï¼Œèªªæ˜Žå¦‚ä½•å°‡ä½ çš„å¸³è™Ÿè§£éŽ–ã€‚" - unlocked: "帳號解鎖æˆåŠŸã€‚ä½ å·²ç¶“ç™»å…¥äº†ã€‚" + send_instructions: "幾分é˜ä¹‹å…§ä½ 就會收到一å°é›»åéƒµä»¶ï¼Œèªªæ˜Žå¦‚ä½•å°‡ä½ çš„å¸³è™Ÿè§£éŽ–ã€‚" + send_paranoid_instructions: "如果帳號å˜åœ¨çš„話,幾分é˜ä¹‹å…§ä½ 就會收到一å°é›»å郵件,說明如何解鎖。" + unlocked: "帳號解鎖æˆåŠŸäº†ã€‚è¦ç¹¼çºŒä½¿ç”¨è«‹å…ˆç™»å…¥ã€‚" errors: messages: - already_confirmed: "被確èªéŽäº†" + already_confirmed: "已經確èªéŽäº†ï¼Œè«‹ç™»å…¥çœ‹çœ‹" + confirmation_period_expired: "å¿…é ˆåœ¨%{period}內完æˆç¢ºèªï¼Œè«‹å†é‡è©¦ä¸€æ¬¡ã€‚" + expired: "已經éŽæœŸäº†ï¼Œè«‹å†é‡è©¦ä¸€æ¬¡ã€‚" not_found: "找ä¸åˆ°" - not_locked: "沒被鎖定" \ No newline at end of file + not_locked: "沒被鎖定" + not_saved: + other: "這ç†%{resource}è³‡æ–™å› ç‚ºç™¼ç”Ÿäº†%{count}次錯誤而無法儲å˜ï¼š" \ No newline at end of file diff --git a/config/locales/diaspora/af.yml b/config/locales/diaspora/af.yml index 1706e005ea5f41dee7922753a899c33cb550e888..5f323019ffa592be10d05cb526700fd5332157ad 100644 --- a/config/locales/diaspora/af.yml +++ b/config/locales/diaspora/af.yml @@ -14,7 +14,4 @@ af: aspects: index: help: - tutorial_link_text: "Tutoriale" - people: - profile_sidebar: - photos: "Fotos" \ No newline at end of file + tutorial_link_text: "Tutoriale" \ No newline at end of file diff --git a/config/locales/diaspora/ar.yml b/config/locales/diaspora/ar.yml index e82d7a05becab2e1878ce8421917c023b5bb1a6f..fea24a3d7c687f3adfc8bdc64336326114ffddda 100644 --- a/config/locales/diaspora/ar.yml +++ b/config/locales/diaspora/ar.yml @@ -5,11 +5,8 @@ ar: - _applications: "التطبيقات" - _comments: "تعليقات" + _applications: "التّطبيقات" _contacts: "المتراسلون" - _home: "الرئيسية" - _photos: "صور" _services: "الخدمات" _statistics: "Ø¥Øصائيّات" account: "الØساب" @@ -65,13 +62,7 @@ ar: two: "عدد المستخدمين الجدد لهذا الأسبوع: اثنان" zero: "عدد المستخدمين الجدد لهذا الأسبوع: صÙر" current_server: "تاريخ الخادوم الØاليّ هو ‎%{date}‎" - ago: "منذ %{time}" all_aspects: "كل الÙئات" - application: - helper: - unknown_person: "شخص مجهول" - video_title: - unknown: "عنوان Ùيديو مجهول" are_you_sure: "أمتأكّد؟" are_you_sure_delete_account: "أمتأكّد من ØØ°Ù Øسابك؟ هذا إجراء لا عودة Ùيه!" aspect_memberships: @@ -85,17 +76,9 @@ ar: success: "إضاÙØ© صديق إلى الÙئة بنجاØ" aspect_listings: add_an_aspect: "+ أض٠Ùئة جديدة" - deselect_all: "الغاء اختيار الكل" - edit_aspect: "تعديل %{name}" - select_all: "اختر الكل" aspect_stream: stay_updated: "إبقَ على اطلاع" stay_updated_explanation: "تيّارك الرئيس مَمْلÙوءٌ بجميع جهات إتصالك Ùˆ الوسوم التي تتابع Ùˆ منشورات من بعض أعضاء المجتمع المبدعين." - contacts_not_visible: "رؤية عضو لآخر ÙÙŠ هاته الÙئة غير متاØØ©" - contacts_visible: "رؤية عضو لآخر ÙÙŠ هاته الÙئة متاØØ©" - create: - failure: "Ùشل إنشاء الÙئة" - success: "تم إنشاء الÙئة الجديدة %{name}" destroy: failure: "%{name} ليس خاليا ولا يمكن ØØ°ÙÙ‡" success: ".Ø¨Ù†Ø¬Ø§Ø %{name} تم إزالة" @@ -103,21 +86,13 @@ ar: aspect_list_is_not_visible: "قائمة الÙئة مخÙية عن الأعضاء الأخرين ÙÙŠ الÙئة" aspect_list_is_visible: "قائمة الÙئة مرئية للأعضاء الآخرين ÙÙŠ الÙئة" confirm_remove_aspect: "تأكيد Øذ٠هذه الÙئة؟" - make_aspect_list_visible: "Ùئة مرئية" - remove_aspect: "Øذ٠هذه الÙئة" - rename: "إعادة تسمية" - update: "تØديث" - updating: "جارى التØديث" + rename: "أعد التّسمية" + update: "Øدّث" + updating: "ÙŠØدّث" index: - diaspora_id: - content_1: "معر٠دياسبرا الخاص بك هو:" - content_2: "أعطه لأي شخص وسيتمكن من إيجادك على دياسبرا." - heading: "معر٠دياسبورا" donate: "تبرّع" - handle_explanation: "هذا وسيط دياسبرا. مثل البريد الالكتروني، يمكنك منØÙ‡ للأصدقاء Øتى تستطيع التواصل معهم." help: do_you: "هل:" - email_feedback: "أرسل لنا ملاØظاتك إذا أردت %{link}" feature_suggestion: "... تملك %{link} اقتراØا؟" find_a_bug: "... وجدت %{link}?" have_a_question: "... تملك %{link}?" @@ -127,30 +102,19 @@ ar: tag_feature: "ميزة" tag_question: "سؤال" introduce_yourself: "هذه هى ساØØ© مشاركاتك.  هيا قدم Ù†Ùسك." - keep_diaspora_running: "ØاÙظ على التطور السريع Ù„ ديسبرا بتبرعاتك الشهرية" new_here: follow: "تابÙع %{link} ورØب بالمÙستخدمين الجدد لدياسبرا !" learn_more: "تعلم المزيد" title: "مرØبا بالمستخدمين الجدد" - no_contacts: "لا أعضاء" - no_tags: "+ جÙـد وسما لمتابعته" - people_sharing_with_you: "أعضاء يتشاركون معك" - post_a_message: "انشر رسالة >>" services: content: "يمكنك توصيل Øساب ديسبورا الخاص بك بالخدمات الآتية:" heading: "صل Øسابك بالخدمات" - unfollow_tag: "أَوقÙ٠متابعة #%{tag}" welcome_to_diaspora: "مرØبا بك ÙÙŠ دياسبرا , %{name} !" - new: - create: "أنشئ" - name: "إسم" no_contacts_message: community_spotlight: "أضواء المجتمع" or_spotlight: "أو يمكنك المشاركة مع %{link}" - try_adding_some_more_contacts: "تستطيع أن تبØØ« عن أو تدعو جهات إتصال أكثر." - you_should_add_some_more_contacts: "ÙŠÙستØسن إضاÙØ© مزيد من الأعضاء" - no_posts_message: - start_talking: "لم يتØدث Ø£Øد بعد!" + try_adding_some_more_contacts: "يمكنك البØØ« عن متراسلين آخرين أو لربّما ‎%{invite_link}." + you_should_add_some_more_contacts: "عليك إضاÙØ© متراسلين آخرين!" seed: acquaintances: "معارÙÙÙŠ" family: "العائلة" @@ -159,7 +123,6 @@ ar: update: failure: "Ùئتك, %{name}, اسمها طويل ولا يمكن ØÙظها." success: ".Ø¨Ù†Ø¬Ø§Ø %{name} تم تعديل" - back: "ارجع" blocks: create: failure: "لم استطع تجاهل هذا المستخدم. evasion#" @@ -170,21 +133,14 @@ ar: explanation: "%{link} انشر ÙÙŠ دياسبرا من أي مكان بØÙظ الرابط ÙÙŠ Ù…Ùضلتك/علاماتك" heading: "زر المÙضلة" post_something: "انشر شيئا على دياسبرا" - post_success: "تم النشر, إغلاق!" cancel: "ألغÙ" comments: new_comment: comment: "علّÙÙ‚" commenting: "جارى التعليق..." - one: "تعليقٌ واØد" - other: "%{count} تعليق" - zero: "لا تعليقات" contacts: - create: - failure: "Ùشل ÙÙŠ إنشاء الإتصال" index: add_a_new_aspect: "أض٠Ùئة جديدة" - add_to_aspect: "Add contacts to %{name}" all_contacts: "كل جهات الاتصال" community_spotlight: "ضوء المجتمع" my_contacts: "جهات الاتصال الخاصة بي" @@ -193,29 +149,16 @@ ar: only_sharing_with_me: "Ùقط يتشاركون معي" start_a_conversation: "ابدأ Ù…Øادثة" title: "جهات الاتصال" - your_contacts: "جهات الاتصال" - sharing: - people_sharing: "أعضاء يتشاركون معك:" spotlight: community_spotlight: "ضوء المجتمع" conversations: create: fail: "رسالة غير صالØØ©" sent: "Ø£ÙرْسÙلَت الرسالة" - helper: - new_messages: - few: "%{count} رسائل جديدة" - many: "%{count} رسالةً جديدة" - one: "رسالةٌ واØدةٌ جديدة" - other: "%{count} رسالة جديدة" - two: "%{count} رسالتان جديدتان" - zero: "لا توجد رسائل جديدة" index: inbox: "الوارد" - no_conversation_selected: "لم تØدد أية Ù…Øادثة" no_messages: "لا توجد رسائل" new: - abandon_changes: "أأتجاهل التغييرات؟" send: "أَرْسÙÙ„" sending: "ÙŠÙرسـَل..." subject: "موضوع" @@ -234,10 +177,8 @@ ar: error_messages: helper: correct_the_following_errors_and_try_again: "صØÙ‘Ø Ø§Ù„Ø£Ø®Ø·Ø§Ø¡ الآتية ÙˆØاول مجدّدًا." - invalid_fields: "Øقول غير صالØØ©" - login_try_again: "Ùضلًا <a href='%{login_link}'>Ù„Ùج</a> وجرّب مجدّدًا." fill_me_out: "املأني" - find_people: "اعثر على أشخاص أو #وسوم" + find_people: "ابØØ« عن أشخاص أو #وسوم" help: keyboard_shortcuts: keyboard_shortcuts_li5: "r - أعد مشاركة التدوينة الØاليّة" @@ -245,33 +186,18 @@ ar: keyboard_shortcuts_li7: "o - اÙØªØ Ø£ÙˆÙ‘Ù„ وصلة ÙÙŠ التدوينة الØاليّة" posts_and_posting: character_limit_a: "65535 Ù…ØرÙًا. هذا أكبر بÙÙ€ 65395 Ù…ØرÙًا الذي تØصل عليها ÙÙŠ تويتر! Ø›)" - hide: "أخÙÙ" invitations: a_facebook_user: "مستخدم Ùايسبوك" check_token: not_found: "الدعوة الرمزية غير موجودة" create: - already_contacts: "لقد قمت بإنشاء اتصال مع هذا العضو مسبقا" - already_sent: "لقد قمت بدعوة هذا الشخص مسبقا" no_more: "لم يتبقى لك أية دعوات" - own_address: "لا تستطيع إرسال دعوة لعنوانك الخاص" rejected: "واجه هذا البريد الإلكتروني مشاكلا: " sent: "تم إرسال دعوتك" - edit: - accept_your_invitation: "قبÙÙ„ دعوتك" - your_account_awaits: "Øسابك ينتظر." new: - already_invited: "لم يقبل هؤلاء الأشخاص دعوتك:" - aspect: "Ùئة" - check_out_diaspora: "تØقق من دياسبورا" - if_they_accept_info: "إذا قبلوا دعوتك ØŒ سيتم إضاÙتهم إلى الÙئة التي دعوتهم إليها" invite_someone_to_join: "دعوة صديق للإنضمام إلى دياسبرا" language: "اللغة" - personal_message: "رسالة شخصية" - resend: "إعادة إرسال" send_an_invitation: "إرسال دعوة" - send_invitation: "إرسال الدعوة" - to: "إلى" layouts: application: back_to_top: "الذهاب إلى الاعلى" @@ -280,44 +206,14 @@ ar: source_package: "نزّل Øزمة الشّÙÙرة المصدريّة" toggle: "ØَوّÙÙ„ لموقع الهوات٠المØمولة" whats_new: "ما الجديد؟" - your_aspects: "Ùئاتك" header: - admin: "المشرÙ" - blog: "مدونة" code: "شيÙرة" - login: "تسجيل الدخول" logout: "خروج" profile: "المل٠الشخصى" - recent_notifications: "آخر التنبيهات" settings: "إعدادات" - view_all: "عرض الكل" - likes: - likes: - people_dislike_this: - few: "%{count} كرهوا هذا" - many: "%{count} كرهوا هذا" - one: "كره هذا شخص٠واØد" - other: "%{count} كرهو هذا" - two: "%{count} كرها" - zero: "لا Ø£Øد يكره هذا" - people_like_this: - few: "%{count} إعجابات" - many: "%{count} إعجابًا" - one: "إعجابٌ واØد" - other: "%{count} إعجابًا" - two: "%{count} إعجابان" - zero: "لا إعجابات" - people_like_this_comment: - few: "%{count} إعجابات" - many: "%{count} إعجابًا" - one: "إعجابٌ واØد" - other: "%{count} إعجاب" - two: "%{count} أعجبهما" - zero: "لا إعجابات" - limited: "Ù…Øدود" + limited: "Ù…Øدّد" more: "أكثر" - next: "التالي" - no_results: "لم ÙŠÙعثر على نتائج" + no_results: "لا نتائج" notifications: also_commented: few: "%{actors} علق أيضا على %{post_link} %{post_author}." @@ -340,14 +236,6 @@ ar: other: "%{actors} علقوا على %{post_link}." two: "%{actors} علقا على %{post_link}." zero: "%{actors} علق على %{post_link}." - helper: - new_notifications: - few: "%{count} تنبيهات جديدة" - many: "%{count} تنبيهات جديدة" - one: "1 تنبيه جديد" - other: "%{count} تنبيهات جديدة" - two: "%{count} تنبيهان" - zero: "لا تنبيهات جديدة" index: and: "Ùˆ" and_others: @@ -463,7 +351,6 @@ ar: liked: "%{name} أعجبته مشاركتك." view_post: "عرض المشاركة >" mentioned: - mentioned: "قام بذكرك ÙÙŠ مشاركة:" subject: "%{name} قام بذكرك ÙÙŠ دياسبرا" private_message: reply_to_or_view: "رÙد أو اعرض هذه المØادثة >" @@ -481,103 +368,45 @@ ar: to_change_your_notification_settings: "لتعديل إعدادات التنبيهات خاصتك" nsfw: "غير مناسب لمكان العمل" ok: "Øسنًا" - or: "أو" - password: "كلمة المرور" - password_confirmation: "أكّد كلمة المرور" people: add_contact: invited_by: "تمت دعوتك بواسطة" - add_contact_small: - add_contact_from_tag: "إضاÙØ© مراسل من tag" - aspect_list: - edit_membership: "تعديل العضويات بالÙئات" - helper: - results_for: " نتائج من أجل %{params}" index: looking_for: "تبØØ« عن مشاركات موسومة بـ %{tag_link}ØŸ" no_one_found: "...ولم يعثر على Ø£Øد" no_results: "يجب تØديد شيء للبØØ« عنه" results_for: "نتائج البØØ« عن" searching: "جارى البØØ«ØŒ كن صبوراً من Ùضلك..." - one: "1شخص" - other: "%{count} عضو" person: - add_contact: "إضاÙØ© عضو" - already_connected: "أضي٠مسبقا" - pending_request: "طلبات معلقة" thats_you: "هذا أنت" profile_sidebar: bio: "سيرة" born: "تاريخ الميلاد" - edit_my_profile: "تØرير ملÙÙ‰ الشخصى" gender: "الجنس" - in_aspects: "ÙÙŠ الÙئة" location: "مكان" - remove_contact: "Ø¥Øذ٠العضو" - remove_from: "ØØ°Ù %{name} من %{aspect}?" show: closed_account: "لقد تم إغلاق هذا الØساب." does_not_exist: "هذا العضو غير موجود" has_not_shared_with_you_yet: "%{name} لمْ يشارك أي مشاركة معك بعد" - ignoring: "أنت تتجاهل جميع المشاركات من %{name}." - incoming_request: "%{name} يريد المشاركة معك" - mention: "إشارة" - message: "رسالة" - not_connected: "أنت لا تتشارك مع هذا العضو" - recent_posts: "مشاركات Øديثة" - recent_public_posts: "مشاركات عامة Øديثة" - return_to_aspects: "العودة إلى صÙØØ© الÙئات" - see_all: "مشاهدة الكل" - start_sharing: "بدء المشاركة" - to_accept_or_ignore: "للقبول أو التجاهل" - sub_header: - add_some: "أض٠بعض" - edit: "عدّÙÙ„" - you_have_no_tags: "لا تتوÙر على وسوم" - webfinger: - fail: "للأسÙØŒ لم نجد %{handle}." - zero: "لا Ø£Øد" photos: - comment_email_subject: "صور %{name}" create: integrity_error: "Ùشل رÙع الصورة، أواثقٌ أن هذا المل٠صورة؟" runtime_error: "Ùشل رÙع الصورة، هل قمت بربطها مع نص؟" type_error: "Ùشل رÙع الصورة، أواثقٌ أن صورة ما قد Ø£ÙضيÙَت؟" destroy: notice: "ØÙØ°ÙÙَت الصورة." - edit: - editing: "تØرير" - new: - back_to_list: "عÙد إلى القائمة" - new_photo: "صورة جديدة" - post_it: "شاركها!" new_photo: empty: "{file} Ùارغ، رجاءًا أَعÙد تØديد الملÙات دونه." invalid_ext: "{file} له صيغة غير صالØØ©. {extensions} هي الصيغ الوØيدة Ø§Ù„Ù…Ø³Ù…ÙˆØ Ø¨Ù‡Ø§." size_error: "{file} ذو Øجم كبير جدا, {sizeLimit} هو الØجم الأقصى Ø§Ù„Ù…Ø³Ù…ÙˆØ Ø¨Ù‡." new_profile_photo: - or_select_one_existing: "او اختار صور من %{photos}" upload: "ارْÙَع صورةً شخصيةً جديدة" - photo: - view_all: "عرض كل صور %{name}" show: - collection_permalink: "رابط دائم للمجموعة" - delete_photo: "اØْذÙ٠الصورة" - edit: "عَدّÙÙ„" - edit_delete_photo: "عَدّÙÙ„ وص٠الصورة / اØْذÙ٠الصورة" - make_profile_photo: "اجعلها صورة المل٠الشخصى" show_original_post: "Ø¥ÙعرÙضْ المشاركة الأصلية" - update_photo: "ØَدّÙØ« الصورة" - update: - error: "Ùشل تØرير الصورة." - notice: "ØÙدّÙثَت الصورة بنجاØ." posts: presenter: title: "مشاركة من %{name}" show: - destroy: "اØØ°Ù" - not_found: "عÙوًا، لم نجد هذه المشاركة." - permalink: "رابط دائم" photos_by: few: "%{count} photos by %{author}" many: "%{count} photos by %{author}" @@ -586,14 +415,11 @@ ar: two: "Two photos by %{author}" zero: "No photos by %{author}" reshare_by: "أعيد مشاركتها بواسطة %{author}" - previous: "السابق" - privacy: "الخصوصية" - privacy_policy: "سياسة الخصوصية" - profile: "المل٠الشخصي" + privacy: "الخصوصيّة" + profile: "الملÙÙ‘ الشخصيّ" profiles: edit: allow_search: "Ø§Ø³Ù…ÙŽØ Ù„Ù„Ø¬Ù…ÙŠØ¹ بالبØØ« عنك من خلال دياسبرا" - edit_profile: "ØَرّÙر المل٠الشخصى" first_name: "اسمÙÙƒ" last_name: "لقبÙÙƒ" update_profile: "ØَدّÙØ« المل٠الشخصى" @@ -603,14 +429,12 @@ ar: your_location: "مكانÙÙƒ" your_name: "اسمك" your_photo: "صورتÙÙƒ" - your_private_profile: "ملÙÙƒ الشخصى الخاص" - your_public_profile: "ملÙÙƒ الشخصى العام" your_tags: "صÙÙ Ù†Ùسك ÙÙŠ 5 كلمات" your_tags_placeholder: "مثال: #دياسبرا #إسلام #عرب #موسيقى #ÙÙ†" update: failed: "Ùشل ÙÙ‰ تØديث ملÙÙƒ الشخصى" updated: "تم تØديث ملÙÙƒ الشخصى" - public: "عام" + public: "عامّ" reactions: few: "%{count} reactions" many: "%{count} reactions" @@ -622,63 +446,21 @@ ar: closed: "التسجيلات مغلقة على هذه المنصة" create: success: "سجل ÙÙŠ دياسبرا" - edit: - cancel_my_account: "إلغاء Øسابي" - edit: "تعديل %{name}" - leave_blank: "(اتركها Ùارغة ÙÙŠ Øال أردت عدم تغييرها)" - password_to_confirm: "(Ù†Øتاج لكلمة مرورك الØالية لتأكيد التغييرات)" - unhappy: "غير راض?" - update: "تØديث" new: - create_my_account: "أًنشÙئ Øسابي" email: "الإيميـــل" enter_email: "أدخل عنوان بريد إلكتروني" enter_password: "أدخل كلمة مرور" enter_password_again: "أعد إدخال كلمة المرور" enter_username: "اختر معر٠(Ùقط ØروÙ, أرقام, Ùˆ الإشارات الخطية)" - join_the_movement: "إنضم للرّكب" password: "كلمة السر" sign_up: "سجّل" - sign_up_message: "Social Networking with a <3" username: "إسم المستخدم" - requests: - create: - sending: "ÙŠÙرسÙÙ„ ..." - sent: "قمت بعرض المشاركة مع %{name}. سيصلهم طلبك Ùورا Øال تسجيل دخولهم ÙÙŠ دياسبرا" - destroy: - error: "رجاءًا ØَدّÙد Ùئة" - ignore: "طلب اتصال Ù…Ùتَجاهَل." - success: "أنتما تتشاركان معًا الآن." - helper: - new_requests: - few: "%{count} طلبات تشارك جديدة!" - many: "%{count} طلب تشارك جديد!" - one: "طلب تشارك جديد!" - other: "%{count} طلب تشارك جديد!" - two: "%{count} طلبان جديدان!" - zero: "لا يوجد طلبات مشاركة جديدة" - manage_aspect_contacts: - existing: "جهات الإتصال الموجودة مسبقًا" - manage_within: "أَدÙر جهات الإتصال ÙÙŠ" - new_request_to_person: - sent: "Ø£ÙرْسÙلَت!" reshares: comment_email_subject: "نشر %{resharer} المÙعاد لمشاركة %{author}" - create: - failure: "هناك خطأ ما ÙÙŠ إعادة نشر هذه المشاركة." reshare: deleted: "لقد تم Øذ٠المشاركة الأصلية بواسطة المسؤل ." - reshare: - few: "%{count} إعادة النشر" - many: "%{count} إعادة النشر" - one: "إعادة نشرها مرات عديدة" - other: "%{count} إعادة النشر" - two: "%{count} إعادة النشر مرة واØدة " - zero: "إعادة النشر" reshare_confirmation: "هل Ø£ÙعÙيد نشرالمشاركة %{author} ØŸ" - reshare_original: "أعد نشر المشاركة الأصلية" reshared_via: "أعيد مشاركتها عبر" - show_original: "اعرض الأصلية" search: "ابØØ«" services: create: @@ -688,36 +470,14 @@ ar: success: "تم Ù…Ø³Ø Ø§Ù„Ù…ØµØ§Ø¯Ù‚Ø© بنجاØ" failure: error: "خطأ خلال Ù…Øاولة الإتصال بالخدمة" - finder: - no_friends: "لم ÙŠÙعثَر على أصدقاء Ùايسبوك." - service_friends: "%{service} الأصدقاء" index: disconnect: "قطع الإتصال" edit_services: "تعديل الخدمات" logged_in_as: "متصل بØساب" really_disconnect: "قطع إتصال %{service}?" - inviter: - click_link_to_accept_invitation: "إتبع هذا الرابط لقبول دعوتك" - join_me_on_diaspora: "انضم معى إلي DIASPORA*" - remote_friend: - invite: "دعوة" - not_on_diaspora: "ليس بعد على دياسبرا" - resend: "إعادة إرسال" settings: "إعدادات" - share_visibilites: - update: - post_hidden_and_muted: "مشاركة %{name} تم إخÙائها والتنبيهات أوقÙÙت" - see_it_on_their_profile: "إن أردت مشاهدة تØديثات هذه المشاركة، زÙر صÙØØ© ملÙÙ‘ ‎%{name}‎ الشخصيّ." shared: - add_contact: - add_new_contact: "أض٠متصل جديد" - create_request: "ابØØ« باستخدام معر٠دياسبرا" - diaspora_handle: "ديسبورا@Ùرع.org" - enter_a_diaspora_username: "أدخل معر٠دياسبرا:" - know_email: "أتَعرÙ٠عناوين بريدهم الإلكترونية ØŸ يَجدر بك دعوتهم" - your_diaspora_username_is: "وسيط دياسبورا خاصتك هو: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "أض٠إلى Ùئة" toggle: few: "ÙÙŠ %{count} Ùئات" many: "ÙÙŠ %{count} Ùئات" @@ -725,23 +485,11 @@ ar: other: "ÙÙŠ %{count} Ùئة" two: "ÙÙŠ %{count} Ùئتين" zero: "أش٠إلى Ùئة" - contact_list: - all_contacts: "جميع الأعضاء" - footer: - logged_in_as: "ولوج بـ %{name}" - your_aspects: "ÙئاتÙÙƒ" invitations: by_email: "عبر البريد الإلكتروني" - dont_have_now: "لا تملك دعوات Øاليا، لكنها قادمة قريبا" - from_facebook: "عبر Ùسبوك" - invitations_left: "%{count} متبقية" - invite_someone: "دعوة شخص ما" invite_your_friends: "ادع٠أصدقاءك" invites: "دعوات" - invites_closed: "الدعوات غير متاØØ© على هذه المنصة Øاليا" share_this: "شارك هذه الوصلة عبر البريد الإلكترونيّ، أو المدوّنات أو الشّبكات الاجتماعيّة!" - notification: - new: "%{type} جديد من %{from}" public_explain: atom_feed: "إمداد" control_your_audience: "التØكم ÙÙŠ من يتابعونك" @@ -753,38 +501,19 @@ ar: title: "اضبÙØ· الخدمات المتصلة" visibility_dropdown: "استخدم القائمة المنسدلة لتغير رؤية مشالركاتك (Ù†Ù‚ØªØ±Ø Ø£Ù„Ø¥Ø®ØªØ§Ø± الأول )" publisher: - all: "الجميع" - all_contacts: "جميع الÙئات" discard_post: "تجاهل المشاركة" - make_public: "انشرها للجميع" new_user_prefill: hello: "مرØبًا جميعًا، أنا #%{new_user_tag}. " i_like: "I'm interested in %{tags}." invited_by: "شكراً على الدعوة، " newhere: "جديد هنا" - post_a_message_to: "انشر رسالة إلى %{aspect}" posting: "يَنشÙر ..." - publishing_to: "نشر إلى: " share: "شَارÙÙƒ" - share_with: "شارÙÙƒ مع %{aspect}" upload_photos: "Øمل الصور" whats_on_your_mind: "ماذا يجول ÙÙŠ خاطرك؟" - reshare: - reshare: "أَعÙد النشر" stream_element: - connect_to_comment: "اتصل بهذا المستخدم لتعلق على مشاركاته" - currently_unavailable: "التعليق غير Ù…ØªØ§Ø Øالياً" - dislike: "لم يعجبني" - hide_and_mute: "أخـÙ٠وأسكـتْ" - ignore_user: "تجاهل %{name}" - ignore_user_description: "تجاهل Ùˆ Øذ٠المستخدم من كل المجموعات؟" - like: "أعجبني" - shared_with: "Ù…Ùشَارك مع: %{aspect_names}" - show: "إظهر" - unlike: "إلغاء إعجابى" via: "بواسطة %{link}" via_mobile: "عبر المØمول" - viewable_to_anyone: "يستطيع أي شخص على الشبكة رؤية هذه المشاركة." statistics: name: "الاسم" network: "الشبكة" @@ -793,22 +522,9 @@ ar: status_messages: create: success: "ذَكَرْتَ بنجاØ: %{names}" - destroy: - failure: "Ùشل ØØ°Ù٠المشاركة" - helper: - no_message_to_display: "ï»» توجد رسائل لعرضها." new: mentioning: "ذكر %{person}" too_long: "{\"few\"=>\"المرجو ان تكون رسالتك أقل من %{count} ØرÙ\", \"many\"=>\"المرجو ان تكون رسالتك أقل من %{count} ØرÙ\", \"one\"=>\"المرجو ان تكون رسالتك أقل من %{count} ØروÙ\", \"other\"=>\"المرجو ان تكون رسالتك أقل من %{count} ØروÙ\", \"two\"=>\"المرجو ان تكون رسالتك أقل من %{count} ØرÙ\", \"zero\"=>\"المرجو ان تكون رسالتك أقل من %{count} ØروÙ\"}" - stream_helper: - hide_comments: "أخْÙ٠كل التعليقات" - show_comments: - few: "اعرض %{count} تعليقات أخرى " - many: "اعرض تعليقين أخرين " - one: "اعرض %{count} تعليقات أخرى " - other: "لا توجد تعليقات أخرى " - two: "اعرض تعليقا أخر" - zero: "اعرض %{count} تعليقات أخرى " streams: activity: title: "نشاطى" @@ -830,22 +546,11 @@ ar: title: "ساØØ© المشاركات" public: title: "النشاط العام" - tag_followings: - create: - failure: "Ùشل ÙÙŠ متابعة: #%{name}" - none: "لا تستطيع متابعة وسم Ùارغ!" - success: "بدأت Ø¨Ù†Ø¬Ø§Ø Ù…ØªØ§Ø¨Ø¹Ø©: #%{name}" - destroy: - failure: "Ùشل ÙÙŠ إيقا٠متابعة: #%{name}" - success: "Ø£ÙˆÙ‚Ù Ø¨Ù†Ø¬Ø§Ø Ù…ØªØ§Ø¨Ø¹Ø©: #%{name}" tags: show: follow: "تابع #%{tag}" - following: "أنت تتابع #%{tag}" none: "الوسم الÙارغ غير موجود!" stop_following: "أوق٠متابعة #%{tag}" - terms_and_conditions: "الشروط والأØكام" - undo: "أأتراجع؟" username: "اسم المستخدم" users: confirm_email: @@ -868,7 +573,6 @@ ar: comment_on_post: "...علق Ø£Øدهم على مشاركتك" current_password: "كلمة المرور الØالية" download_export: "نزّل ملÙÙŠ الشخصيّ" - download_photos: "تØميل صوري" edit_account: "تعديل الØساب" email_awaiting_confirmation: "لقد أرسلنا إليك رابط تÙعيل إلى %{unconfirmed_email}. ÙˆØتى تتبع هذا الرابط وتÙعل العنوان الجديد، سنستمر ÙÙŠ استخدام بريدك الأساسي %{email}." export_data: "تصدير البيانات" @@ -891,7 +595,6 @@ ar: awesome_take_me_to_diaspora: "مدهش! خذنى إلى دياسبرا*" hashtag_explanation: "الوسوم ØªØ³Ù…Ø Ù„Ùƒ بالØديث عن اهتماماتك ومتابعتها. وهي أيضا طريقة عبقرية للعثور على أناس جدد بدياسبرا." hashtag_suggestions: "جرب الوسوم التالية اØب #Ùن، #Ø£Ùلام، #صور، إلخ." - saved: "تم الØÙظ!" who_are_you: "من أنت؟" privacy_settings: ignored_users: "المستخدمين الذين تم تجاهلهم" @@ -910,13 +613,6 @@ ar: settings_updated: "تم تØديث اﻹعدادات" unconfirmed_email_changed: "عÙدَÙÙ„ البريد الإلكتروني. بØاجة إلى التÙعيل." unconfirmed_email_not_changed: "Ùشل تعديل البريد الإلكتروني" - webfinger: - fetch_failed: "Ùشل تØميل webfinger المل٠الشخصى لـ %{profile_url}" - hcard_fetch_failed: "خطأ خلال تØميل hcard الخاص بـ #{@account}" - no_person_constructed: "هذا الـ hcard غير صالØ." - not_enabled: "webfinger غير Ù…Ùعل للمضي٠%{account}" - xrd_fetch_failed: "خطأ خلال استرجاع xrd من الØساب %{account}" - welcome: "مرØبا!" will_paginate: next_label: "التالى >>" previous_label: "<< السابق" \ No newline at end of file diff --git a/config/locales/diaspora/art-nvi.yml b/config/locales/diaspora/art-nvi.yml index 84d1e13e96e9114a263dcf094f6c69e7f741d307..ada1adab7880e6ce129f4f763e1046bf62bd6adf 100644 --- a/config/locales/diaspora/art-nvi.yml +++ b/config/locales/diaspora/art-nvi.yml @@ -6,10 +6,7 @@ art-nvi: _applications: "Lapo aydiaspora" - _comments: "Aysäplltxevi" _contacts: "Eylan" - _home: "Kelutral" - _photos: "ayrel" _services: "Hìte'e" account: "Ngeyä Diaspora" activerecord: @@ -22,21 +19,13 @@ art-nvi: admins: stats: go: "salew" - ago: "%{time} kam" all_aspects: "Nìwotx Aypongu" - application: - helper: - unknown_person: "tute astxong" are_you_sure: "Nga lu law srak?" are_you_sure_delete_account: "Nga lu law tsnì new tspivang ngeyä Diasporati srak? fìkem ke laytem mawkrr!" aspects: destroy: success: "%{name}l 'ìlmaku fìtsengeta." index: - diaspora_id: - content_1: "Ngeyä Diaspora Tstxo lu:" - content_2: "Fpe' fì'u" - heading: "Diaspora Tstxo" donate: "Tìng" help: feature_suggestion: "... %{link} tìmok srak?" @@ -51,22 +40,12 @@ art-nvi: follow: "Sutx %{link}it ulte zola'u nìprrte' sute amip ne Diaspora*!" learn_more: "nume nì'ul" title: "Zola'u nìprrte' ma sute amip" - no_contacts: "Kea 'eylan" - post_a_message: "plltxe 'upxareit >>" - unfollow_tag: "Ke serutx #%{tag}" welcome_to_diaspora: "Zola'u nìprrte' ne Diaspora ma %{name}!" - new: - create: "Ngop" seed: family: "Soaia" friends: "Eylan" work: "Tìkangkem" - back: "ne'ìm" cancel: "Ftang" - comments: - one: "1 säplltxevi" - other: "%{count} aysäplltxevi" - zero: "Kea aysäplltxevi" contacts: index: add_a_new_aspect: "Ngop ponguti amip" @@ -74,14 +53,10 @@ art-nvi: my_contacts: "Oeyä Eylan" start_a_conversation: "Ngal sngä'i tìpängkxoti" title: "Eylan" - your_contacts: "Ngeyä Eylan" conversations: create: fail: "kxeyey 'upxare" sent: "'Upxare fpìme'" - helper: - new_messages: - zero: "kea 'upxare amip" index: inbox: "'Upxare tsenge" no_messages: "Kea upxare" @@ -95,19 +70,15 @@ art-nvi: email: "Ikran lì'u" fill_me_out: "Pamrel si mì oe" find_people: "Run suteti fu #säsulìnit" - hide: "Wan" invitations: new: language: "Lì'fya" layouts: header: - blog: "pìlok" logout: "Hum" profile: "Txin" - recent_notifications: "Upxare asop" settings: "Sìfkeytok" more: "nì'ul" - next: "hay" no_results: "Ke rìmun." notifications: index: @@ -116,13 +87,7 @@ art-nvi: single_admin: subject: "'Upxare teri ngeyä Diaspora:" ok: "Tam" - or: "fu" - password: "Ftemlì'u" - password_confirmation: "Ftemlì'u latem" people: - helper: - results_for: " u %{params}ir" - one: "Tute" person: thats_you: "Fì'u nga lu!" profile_sidebar: @@ -130,32 +95,10 @@ art-nvi: born: "ftxozä" gender: "fnepe tokx" location: "Kelku" - remove_from: "'aku %{name}it ta %{aspect} srak?" - show: - message: "'upxare" - recent_posts: "Upxare asop" - see_all: "Tse'a nìwotx" - sub_header: - edit: "latem" - zero: "Kea sute" photos: - comment_email_subject: "%{name}yä rel" destroy: notice: "Relìl 'aìmku" - edit: - editing: "leratem" - new: - new_photo: "Rel amip" - show: - delete_photo: "'aku relit" - edit: "latem" - edit_delete_photo: "latem relit tìsla'tsuti fu 'aku relit" - posts: - show: - destroy: "'aku" - previous: "ham" privacy: "Le'aw 'awpoä Sìfkeytok" - privacy_policy: "Le'aw 'awpoä sìfkeytok aysänume" profile: "Txin" profiles: edit: @@ -166,29 +109,15 @@ art-nvi: your_name: "ngeyä tstxo" your_photo: "ngeyä rel" public: "Frapo tsun tsive'a fì'u" - registrations: - edit: - edit: "Latem %{name}it" - unhappy: "Nga lu keftxo srak?" - new: - sign_up_message: "Tsenge eylanìri tsnì zamunge ♥" - requests: - create: - sending: "fpere'" - new_request_to_person: - sent: "fpìme'!" search: "Fwew" settings: "Sìfkeytok" shared: invitations: by_email: "ìlä email" - from_facebook: "Ta Facebook" invite_your_friends: "pawm ngeyä eylanti fìtseng" publisher: upload_photos: "Fpe' relit" stream_element: - like: "Sunu" - unlike: "Ke Sunu" via: "ìlä %{link}" streams: activity: @@ -204,8 +133,6 @@ art-nvi: title: "@plltxole" multi: title: "Payfya" - terms_and_conditions: "Horen" - undo: "Tätxaw srefxiset?" username: "Tstxo" users: edit: @@ -226,5 +153,4 @@ art-nvi: privacy_settings: title: "Le'aw 'awpoä Sìfkeytok" update: - language_changed: "lì'fyal lìmatem" - welcome: "Zola'u nìprrte'!" \ No newline at end of file + language_changed: "lì'fyal lìmatem" \ No newline at end of file diff --git a/config/locales/diaspora/ast.yml b/config/locales/diaspora/ast.yml index 3181c2260e006fac2941a67be3ef6a107989e81a..8c6ade701b0a21f328e484479a0087b642313539 100644 --- a/config/locales/diaspora/ast.yml +++ b/config/locales/diaspora/ast.yml @@ -6,9 +6,7 @@ ast: _applications: "Aplicaciones" - _comments: "Comentarios" _contacts: "Contactos" - _photos: "fotos" _services: "Servicios" account: "Cuenta" activerecord: @@ -39,13 +37,7 @@ ast: username: invalid: "ye inválidu. Sólo se permiten lletres, númberos y guiones baxos." taken: "yá ta ocupáu." - ago: "hai %{time}" all_aspects: "Tolos aspeutos" - application: - helper: - unknown_person: "persona desconocida" - video_title: - unknown: "TÃtulu de videu desconocÃu" are_you_sure: "¿Tas seguru?" are_you_sure_delete_account: "¿Tas seguru de que quies zarrar la cuenta? ¡Esto nun pue desfacese!" aspect_memberships: @@ -59,17 +51,9 @@ ast: success: "Amestóse'l contautu al aspeutu correutamente." aspect_listings: add_an_aspect: "+ Amestar un aspeutu" - deselect_all: "Nun seleicionar nada" - edit_aspect: "Editar %{name}" - select_all: "Seleicionar too" aspect_stream: stay_updated: "Sigui al dÃa" stay_updated_explanation: "Na to canal principal apaecen los tos contautos, etiquetes que sigues, y publicaciones d'algunos miembros creativos de la comunidá." - contacts_not_visible: "Los contactos d'esti aspeutu nun podrán vese unos a otros." - contacts_visible: "Los contactos d'esti aspeutu podrán vese unos a otros." - create: - failure: "Falló la creación del aspeutu." - success: "Creóse'l nuevu aspeutu %{name}" destroy: failure: "%{name} nun ta baleru nun pudo desaniciase." success: "%{name} desanicióse correutamente." @@ -77,21 +61,13 @@ ast: aspect_list_is_not_visible: "Los contactos d'esti aspeutu nun puen vese unos a otros." aspect_list_is_visible: "Los contactos d'esti aspeutu puen vese unos a otros." confirm_remove_aspect: "¿Tas seguru de que quies desaniciar esti aspeutu?" - make_aspect_list_visible: "¿facer los contactos d'esti aspeutu visibles ente ellos?" - remove_aspect: "Desaniciar esti aspeutu" rename: "renomar" update: "anovar" updating: "anovando" index: - diaspora_id: - content_1: "La to ID de diaspora* ye:" - content_2: "Compártila per uquiera y podrán alcontrate'n Diaspora*." - heading: "ID de diaspora*" donate: "Donar" - handle_explanation: "Esta ye la to ID de diaspora*. Como una direición de corréu, pues dala pa que la xente t'alcuentre." help: do_you: "¿Seique:" - email_feedback: "Si lo prefieres, manda la to opinión %{link}" feature_suggestion: "... tienes %{link} que suxerir?" find_a_bug: "... alcuentres %{link}?" have_a_question: "... tienes %{link}?" @@ -105,25 +81,15 @@ ast: follow: "¡Sigui %{link} y da la bienvenida a diaspora* a los usuarios nuevos!" learn_more: "Más información" title: "Da la bienvenida a los usuarios nuevos" - no_contacts: "Nun hai contautos" - no_tags: "+ Alcontrar una etiqueta pa siguila" - people_sharing_with_you: "Persones que comparten contigo" - post_a_message: "publica un mensaxe >>" services: content: "Pues coneutar los servicios siguientes a diaspora*:" heading: "Coneutar servicios" - unfollow_tag: "Dexar de siguir #%{tag}" welcome_to_diaspora: "¡Afáyati en diaspora*, %{name}!" - new: - create: "Crear" - name: "Nome (visible pa ti namái)" no_contacts_message: community_spotlight: "destacao de la comunidá" or_spotlight: "O pues compartir con %{link}" try_adding_some_more_contacts: "Pues guetar o convidar a más contautos." you_should_add_some_more_contacts: "¡TendrÃes d'amestar más contautos!" - no_posts_message: - start_talking: "¡Inda naide dixo nada!" seed: acquaintances: "ConocÃos" family: "Familia" @@ -132,44 +98,28 @@ ast: update: failure: "El to aspeutu, %{name}, tenÃa un nome llargu enforma pa poder guardalu." success: "Editóse correutamente'l to aspeutu, %{name}." - back: "Anterior" bookmarklet: explanation: "Publicar en diaspora* dende uquiera poniendo esti enllaz nos marcadores => %{link}." heading: "Bookmarklet" post_something: "Publicar en diaspora*" - post_success: "¡Publicao! Zarrando." cancel: "Encaboxar" comments: new_comment: comment: "Comentariu" commenting: "Comentando..." - one: "1 comentariu" - other: "%{count} comentarios" - zero: "nun hai comentarios" - contacts: - create: - failure: "Nun pudo crease'l contautu" delete: "Desaniciar" email: "Corréu electrónicu" error_messages: helper: correct_the_following_errors_and_try_again: "Corrixi los errores siguientes y vuelvi a intentalo." - invalid_fields: "Campos inválidos" fill_me_out: "Escribir equÃ" find_people: "Alcontrar persones o #etiquetes" - hide: "Tapecer" limited: "Llendáu" more: "Más" - next: "siguiente" no_results: "Nun s'alcontraron resultaos" nsfw: "Inseguro nel trabayu (NSFW)" ok: "Aceutar" - or: "o" - password: "Contraseña" - password_confirmation: "Confirmación de contraseña" - previous: "anterior" privacy: "Intimidá" - privacy_policy: "PolÃtica d'intimidá" profile: "Perfil" public: "Públicu" reactions: @@ -178,7 +128,4 @@ ast: zero: "0 reacciones" search: "Guetar" settings: "Preferencies" - terms_and_conditions: "Términos y condiciones" - undo: "¿Desfacer?" - username: "Nome d'usuariu" - welcome: "¡Afáyati!" \ No newline at end of file + username: "Nome d'usuariu" \ No newline at end of file diff --git a/config/locales/diaspora/az.yml b/config/locales/diaspora/az.yml index d9b80b1d7a35faa02e4a531f7a20a3128827afdd..f3584d8791537d312a3f2da59ddbe8ea378ca6e4 100644 --- a/config/locales/diaspora/az.yml +++ b/config/locales/diaspora/az.yml @@ -6,10 +6,7 @@ az: _applications: "Applikasiya" - _comments: "" _contacts: "" - _home: "" - _photos: "ŞəkillÉ™r" _services: "Servis" account: "Akkaunt" activerecord: @@ -32,13 +29,7 @@ az: username: invalid: "" taken: "" - ago: "%{time}%{time}" all_aspects: "Bütün tÉ™rÉ™flÉ™r" - application: - helper: - unknown_person: "bilinmÉ™yÉ™n sÉ™xs" - video_title: - unknown: "bilinmeyen video basligi" are_you_sure: "" are_you_sure_delete_account: "Ä°stifadəçiliyini baÄŸlamaq isteyindÉ™ É™minsÉ™n? bu tamamlanmayıb" aspect_memberships: @@ -50,36 +41,22 @@ az: success: "" aspect_listings: add_an_aspect: "" - deselect_all: "" - edit_aspect: "" - select_all: "" aspect_stream: stay_updated: "SÉ™yfÉ™dÉ™ qal" stay_updated_explanation: "" - contacts_not_visible: "" - contacts_visible: "" - create: - failure: "" - success: "" destroy: success: "" edit: aspect_list_is_not_visible: "" aspect_list_is_visible: "" confirm_remove_aspect: "" - remove_aspect: "" rename: "yenidÉ™n adlandırmaq" update: "yenilÉ™mÉ™k" updating: "yenilÉ™nir" index: - diaspora_id: - content_1: "" - heading: "" donate: "" - handle_explanation: "" help: do_you: "" - email_feedback: "" feature_suggestion: "" find_a_bug: "" have_a_question: "" @@ -93,26 +70,16 @@ az: follow: "" learn_more: "" title: "XoÅŸ gÉ™lmisiniz,yeni istifadəçilÉ™rmiz" - no_contacts: "" - no_tags: "" - people_sharing_with_you: "" - post_a_message: "Divarda mesaj yerləşdir!" services: content: "" heading: "VericiyÉ™ BaÄŸlan" - unfollow_tag: "" welcome_to_diaspora: "" - new: - create: "" - name: "" no_contacts_message: community_spotlight: |- Bank icma xidmÉ™ti. Bank icmaya xidmÉ™t etmir. or_spotlight: "" you_should_add_some_more_contacts: "" - no_posts_message: - start_talking: "" seed: acquaintances: "" family: "" @@ -121,28 +88,18 @@ az: update: failure: "" success: "" - back: "" bookmarklet: explanation: "" heading: "ьфпр" post_something: "" - post_success: "лPostedClosing" cancel: "Dala" comments: new_comment: comment: "" commenting: "" - one: "" - other: "" - zero: "Heç ÅŸÉ™rh yoxdu" contacts: - create: - failure: "" index: - add_to_aspect: "ÅŸÉ™xs É™lavÉ™ edin %{name}" start_a_conversation: "" - sharing: - people_sharing: "" delete: "Poz" email: "" error_messages: @@ -150,26 +107,14 @@ az: correct_the_following_errors_and_try_again: "" fill_me_out: "" find_people: "" - hide: "MÉ™tni gizlÉ™t." limited: "" more: "" - next: "sonraki" no_results: "Heç bir nÉ™ticÉ™ tapılmadı" nsfw: "" ok: "OK" - or: "vÉ™" - password: "" - password_confirmation: "" - people: - zero: "VerilmiÅŸ parametrlÉ™rÉ™ uyÄŸun nÉ™fÉ™r tapılmadı. <br/> XahiÅŸ olunur axtarış parametirlÉ™rini dÉ™yiÅŸdirÉ™siniz." - previous: "É™vvÉ™lki" privacy: "Gaga" - privacy_policy: "gAG" profile: "Profil" public: "" search: "" settings: "Set" - terms_and_conditions: "Terms and Conditions" - undo: "Undo?" - username: "" - welcome: "" \ No newline at end of file + username: "" \ No newline at end of file diff --git a/config/locales/diaspora/be.yml b/config/locales/diaspora/be.yml index e65714872768c7fdbafe69e8e9e8214add6522df..78c4506d4f4e4844e9af002541bd734e96cef3b0 100644 --- a/config/locales/diaspora/be.yml +++ b/config/locales/diaspora/be.yml @@ -6,10 +6,7 @@ be: _applications: "праграмы" - _comments: "каментары" _contacts: "кантакты" - _home: "home" - _photos: "Фатаграфіі" _services: "паÑлугі" account: "Ðккаунт" activerecord: @@ -41,11 +38,6 @@ be: invalid: "Памылка. ДазвалÑюцца літары, лічбы Ñ– падкрÑÑліванні." taken: "ужо Ñ–Ñнуе." all_aspects: "уÑе катыгорыі" - application: - helper: - unknown_person: "невÑÐ´Ð¾Ð¼Ð°Ñ Ð°Ñоба" - video_title: - unknown: "невÑдомае відÑа" are_you_sure: "Ñапраўды?" are_you_sure_delete_account: "Ð’Ñ‹ Ñапраўды хочаце выдаліць Ваш акаўнт? ГÑта не магчыма будзе адмÑніць!" aspects: @@ -54,14 +46,6 @@ be: success: "Кантакты паÑпÑхова дададзены Ñž аÑпект." aspect_listings: add_an_aspect: "+ дадаць катыгорыю" - deselect_all: "ÐчыÑціць выбранае" - edit_aspect: "змÑніць %{name}" - select_all: "Ðдзначыць уÑÑ‘" - contacts_not_visible: "у гÑтай катыгорыі катакты не могуць бачыць адзін аднаго." - contacts_visible: "у гÑтай катыгорыі катакты могуць бачыць адзін аднаго." - create: - failure: "Памылка пры ÑтварÑнні аÑпекта." - success: "Твой новы аÑпект %{name} Ñтворан." destroy: failure: "%{name} не пуÑÑ‚Ð°Ñ Ñ– не можа быць выдалена." success: "%{name} паÑпÑхова выдалена" @@ -69,17 +53,11 @@ be: aspect_list_is_not_visible: "ÑÐ¿Ñ–Ñ ÐºÐ°Ñ‚Ñ‹Ð³Ð¾Ñ€Ñ‹Ð¹ не бачны Ð´Ð»Ñ ÑžÑÑ–Ñ…" aspect_list_is_visible: "ÑÐ¿Ñ–Ñ ÐºÐ°Ñ‚Ñ‹Ð³Ð¾Ñ€Ñ‹Ð¹ бачны Ð´Ð»Ñ ÑžÑÑ–Ñ…" confirm_remove_aspect: "Ñ‚Ñ‹ Ñапраўды жадаешь выдаліць гÑтую катыгорыю?" - make_aspect_list_visible: "зрабіць катакты Ñž гÑтай катыгорыі адкрытымі?" - remove_aspect: "выдаліць катыгорыю" rename: "перайменаваць" update: "абнавіць" updating: "абнаўлÑÑŽ ..." index: - diaspora_id: - content_1: "твой Diaspora ID:" - heading: "Diaspora ID" donate: "падзÑка" - handle_explanation: "ГÑта твой Diaspora ID. Як Ñ– Ð°Ð´Ñ€Ð°Ñ Ñлектроннай пошты, Ñ‚Ñ‹ можаш даць Ñго людзÑм, каб Ñны маглі з табой звÑзацца." help: do_you: "ГÑта тычыцца:" here_to_help: "СупольнаÑці Diaspora тут!" @@ -90,20 +68,12 @@ be: follow: "Сачы за %{link} Ñ– вітай новых карыÑтальнікаў diaspora*!" learn_more: "паказаць больш" title: "Прывітанне, Ðовы Ўдзельнік!(чалавек)" - no_contacts: "Ð½Ð°Ð¼Ñ ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð°Ñž" - post_a_message: "напіÑаць паведамленне >>" - unfollow_tag: "больш не Ñачыць за #%{tag}" welcome_to_diaspora: "Вітаем Ñž Diaspora, %{name}!" - new: - create: "Стварыць" - name: "Ñ–Ð¼Ñ (бачна толькі табе)" no_contacts_message: community_spotlight: "Ñупольны праглÑд" or_spotlight: "Ñ‚Ñ‹ можаш такÑама падзÑліцца %{link}" try_adding_some_more_contacts: "Ñ‚Ñ‹ можаш знайÑці ці дадаць Ð½Ð¾Ð²Ñ‹Ñ ÐºÐ°Ñ‚Ñ€Ð°ÐºÑ‚Ñ‹" you_should_add_some_more_contacts: "Ñпачатку дадай пару кантактаў" - no_posts_message: - start_talking: "пакуль ніхто нічога не казаў" seed: acquaintances: "знаёмыÑ" family: "ÑÑм'Ñ" @@ -112,18 +82,12 @@ be: update: failure: "не магчыма захаваць катыгорыю %{name}, занадта Ð´Ð»Ñ–Ð½Ð°Ñ Ð½Ð°Ð·Ð²Ð°." success: "ÐºÐ°Ñ‚Ñ‹Ð³Ð¾Ñ€Ñ‹Ñ %{name} была паÑпÑхова выдалена" - back: "назад" cancel: "адмÑніць" - comments: - one: "1 каментар" - zero: "каментароў нÑма" contacts: index: all_contacts: "уÑе кантакты" - your_contacts: "твае кантакты" conversations: new: - abandon_changes: "ÑкаÑаваць змены" send: "даÑлаць" sending: "адÑылаю ..." delete: "выдаліць" @@ -131,10 +95,8 @@ be: error_messages: helper: correct_the_following_errors_and_try_again: "ÑпраўлÑй памылкі Ñ– паÑпрабуй зноў." - invalid_fields: "Ð½ÐµÐ´Ð°Ð¿ÑƒÑˆÑ‡Ð°Ð»ÑŒÐ½Ñ‹Ñ Ñ€Ð°Ð´ÐºÑ–" fill_me_out: "запоўні мÑне" find_people: "Пошук людзей ці #Ñ‚Ñгаў" - hide: "Схаваць" invitations: new: invite_someone_to_join: "запраÑÑ– каго-небудзь да Diaspora!" @@ -144,21 +106,12 @@ be: settings: "налады" limited: "абмежавана" more: "больш" - next: "далей" no_results: "нічога не знайшлоÑÑŒ" nsfw: "не Ð´Ð·ÐµÐ»Ñ ÑžÑÑ–Ñ… вачÑй" ok: "ok" - or: "ці" - password: "пароль" - password_confirmation: "падцвердзіць пароль" - previous: "назад" privacy: "ПрыватнаÑць" - privacy_policy: "ВыкараÑтанне аÑабіÑÑ‚Ñ‹Ñ… дадзенных" profile: "Прафіль" public: "адкрыта" search: "Пошук" settings: "Ðалады" - terms_and_conditions: "Умовы выкараÑтоўваннÑ" - undo: "назад" - username: "Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка" - welcome: "Прывітанне!" \ No newline at end of file + username: "Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка" \ No newline at end of file diff --git a/config/locales/diaspora/bg.yml b/config/locales/diaspora/bg.yml index f5f7d9196433a90e7d66a391a631627d9b118352..5b049ed1448f4c141151984e6f674493515a6762 100644 --- a/config/locales/diaspora/bg.yml +++ b/config/locales/diaspora/bg.yml @@ -6,10 +6,7 @@ bg: _applications: "ПриложениÑ" - _comments: "Коментари" _contacts: "Контакти" - _home: "Ðачална Ñтраница" - _photos: "Ñнимки" _services: "УÑлуги" account: "Ðкаунт" activerecord: @@ -36,13 +33,7 @@ bg: username: invalid: "не е валидно. Разрешени Ñа Ñамо букви, цифри и долна черта." taken: "е вече заето." - ago: "преди %{time}" all_aspects: "Ð’Ñички аÑпекти" - application: - helper: - unknown_person: "непознато лице" - video_title: - unknown: "Видеото е Ñ Ð½ÐµÐ¸Ð·Ð²ÐµÑтно заглавие" are_you_sure: "Сигурни ли Ñте?" are_you_sure_delete_account: "ÐаиÑтина ли желаете да затворите акаунта Ñи? ÐÑма връщане назад!" aspect_memberships: @@ -56,17 +47,9 @@ bg: success: "Контактът е добавен към аÑпекта." aspect_listings: add_an_aspect: "+ Създаване на аÑпект" - deselect_all: "Ðикой" - edit_aspect: "Редактиране на \"%{name}\"" - select_all: "Ð’Ñички" aspect_stream: stay_updated: "ОÑтанете информирани" stay_updated_explanation: "ВашиÑÑ‚ поток Ñе ÑÑŠÑтои от вÑичките Ви контакти, марки (които Ñледите) и публикации на изÑвени членове на общноÑтта." - contacts_not_visible: "Контактите в аÑпекта нÑма да бъдат видими един за друг." - contacts_visible: "Контактите в аÑпекта ще бъдат видими един за друг." - create: - failure: "ÐÑпектът не бе Ñъздаден." - success: "ÐовиÑÑ‚ аÑпект \"%{name}\" бе Ñъздаден" destroy: failure: "%{name} не е празен, затова не може да бъде изтрит." success: "%{name} бе изтрит." @@ -74,21 +57,13 @@ bg: aspect_list_is_not_visible: "ÑпиÑъкът на аÑпекта не е видим за оÑтаналите в аÑпекта" aspect_list_is_visible: "ÑпиÑъкът на аÑпекта е видим за оÑтаналите в аÑпекта" confirm_remove_aspect: "ÐаиÑтина ли желаете аÑпектът да бъде премахнат?" - make_aspect_list_visible: "нека контактите в аÑпекта Ñе виждат един друг" - remove_aspect: "Изтриване на аÑпекта" rename: "преименуване" update: "обнови" updating: "обновÑване" index: - diaspora_id: - content_1: "ВашиÑÑ‚ Ð°Ð´Ñ€ÐµÑ Ð² Diaspora е:" - content_2: "Споделете го Ñ ÐºÐ¾Ð¹Ñ‚Ð¾ и да е и той ще Ви намери в Diaspora." - heading: "ÐÐ´Ñ€ÐµÑ Ð² Diaspora" donate: "Дарете" - handle_explanation: "Това е вашиÑÑ‚ Ð°Ð´Ñ€ÐµÑ Ð² Diaspora. ÐаподобÑва Ð°Ð´Ñ€ÐµÑ Ð½Ð° ел. поща - давате го на хора, за да Ñе Ñвържат Ñ Ð²Ð°Ñ." help: do_you: "Вие:" - email_feedback: "Ðко предпочитате изпратете отзив по %{link}." feature_suggestion: "... имате Ð¸Ð´ÐµÑ Ð·Ð° нова %{link}?" find_a_bug: "... Ñте открили грешка (%{link})?" have_a_question: "... имате %{link}?" @@ -102,25 +77,15 @@ bg: follow: "Следете %{link} и приветÑтвайте новите потребители на Diaspora*!" learn_more: "Ðаучете повече" title: "Поздравете новодошлите" - no_contacts: "ÐÑма контакти" - no_tags: "+ Ðамиране на марки" - people_sharing_with_you: "Хора ÑподелÑщи Ñ Ð²Ð°Ñ" - post_a_message: "публикуване на Ñъобщение >>" services: content: "Можете да Ñвържете Ñледните уÑлуги към Diaspora:" heading: "Свързване към уÑлуги" - unfollow_tag: "ПрекратÑване Ñледенето на #%{tag}" welcome_to_diaspora: "Добре дошли в Diaspora, %{name}!" - new: - create: "Създаване" - name: "Име (видимо е Ñамо за ваÑ)" no_contacts_message: community_spotlight: "в центъра на вниманието" or_spotlight: "Или Ñподелете Ñ %{link}" try_adding_some_more_contacts: "Можете да Ñ‚ÑŠÑ€Ñите (в кутиÑта отгоре) или да поканите хора (отдÑÑно)." you_should_add_some_more_contacts: "Добавете нÑколко контакта!" - no_posts_message: - start_talking: "ÐÑма публикации." seed: acquaintances: "Познати" family: "СемейÑтво" @@ -129,7 +94,6 @@ bg: update: failure: "ÐÑпектът \"%{name}\" има твърде дълго име. Ðе може да бъде запаметен." success: "ÐÑпектът \"%{name}\" е уÑпешно редактиран." - back: "Ðазад" blocks: create: failure: "ПотребителÑÑ‚ не може да бъде игнориран. #evasion" @@ -140,21 +104,14 @@ bg: bookmarklet: explanation: "Публикувайте в Diaspora от където и да е, запаметÑвайки %{link} като отметка." post_something: "Публикуване в Diaspora" - post_success: "Публикувано!" cancel: "Отказ" comments: new_comment: comment: "Коментар" commenting: "Коментиране..." - one: "1 коментар" - other: "%{count} коментара" - zero: "нÑма коментари" contacts: - create: - failure: "Контактът не бе Ñъздаден" index: add_a_new_aspect: "Създаване на аÑпект" - add_to_aspect: "добавете нÑкой от контактите Ñи към \"%{name}\"" all_contacts: "Ð’Ñички контакти" my_contacts: "Моите контакти" no_contacts: "Изглежда Ñ‚Ñ€Ñбва да добавите контакти!" @@ -162,29 +119,16 @@ bg: only_sharing_with_me: "Само ÑподелÑщите Ñ Ð¼ÐµÐ½" start_a_conversation: "Ðачало на разговор" title: "Контакти" - your_contacts: "Вашите контакти" - sharing: - people_sharing: "Хора ÑподелÑщи Ñ Ð²Ð°Ñ:" spotlight: community_spotlight: "Ð’ центъра на вниманието" conversations: create: fail: "Ðевалидно Ñъобщение" sent: "Съобщението е изпратено" - helper: - new_messages: - few: "%{count} нови ÑъобщениÑ" - many: "%{count} нови ÑъобщениÑ" - one: "1 ново Ñъобщение" - other: "%{count} нови ÑъобщениÑ" - two: "%{count} нови ÑъобщениÑ" - zero: "ÐÑма нови ÑъобщениÑ" index: inbox: "ВходÑщи" - no_conversation_selected: "нÑма избран разговор" no_messages: "нÑма ÑъобщениÑ" new: - abandon_changes: "Отказвате Ñе от промените?" send: "Изпращане" sending: "Изпращане..." subject: "тема" @@ -203,34 +147,20 @@ bg: error_messages: helper: correct_the_following_errors_and_try_again: "Поправете Ñледните грешки и опитайте отново." - invalid_fields: "Ðевалидни полета" fill_me_out: "Попълнете ме" find_people: "Ðамерете хора или #марки" - hide: "Скриване" invitations: a_facebook_user: "Потребител на Facebook" check_token: not_found: "Данните за поканата не Ñа намерени" create: - already_contacts: "Вече Ñте Ñвързани Ñ Ñ‚Ð°Ð²Ð° лице" - already_sent: "Вече Ñте Ñвързани Ñ Ñ‚Ð°Ð²Ð° лице." no_more: "Ðе разполагате Ñ Ð¿Ð¾Ð²ÐµÑ‡Ðµ покани." - own_address: "Ðе можете да пращате покана до ÑобÑÑ‚Ð²ÐµÐ½Ð¸Ñ Ñи адреÑ." rejected: "Възникна проблем ÑÑŠÑ Ñледната ел. поща: " sent: "Покани Ñа изпратени до: " - edit: - your_account_awaits: "ВашиÑÑ‚ акаунт ви очаква!" new: - already_invited: "Следните хора не Ñа потвърдили поканата ви:" - aspect: "ÐÑпект" - if_they_accept_info: "ако приемат поканата ще бъдат добавени към аÑпекта в който Ñте ги поканили." invite_someone_to_join: "Поканете нÑкой в Diaspora!" language: "Език за поканата" - personal_message: "Лично Ñъобщение" - resend: "Повторно изпращане" send_an_invitation: "Изпращане на поканата" - send_invitation: "Изпрати покана" - to: "До" layouts: application: back_to_top: "Ðагоре" @@ -238,43 +168,13 @@ bg: public_feed: "Публична емиÑÐ¸Ñ Ð¾Ñ‚ Diaspora за %{name}" toggle: "вкл./изкл. на Ð¼Ð¾Ð±Ð¸Ð»Ð½Ð¸Ñ Ð¸Ð·Ð³Ð»ÐµÐ´" whats_new: "какво ново?" - your_aspects: "вашите аÑпекти" header: - admin: "ÐдминиÑтриране" - blog: "блог" code: "код" - login: "впиÑване" logout: "ОтпиÑване" profile: "Профил" - recent_notifications: "Скорошни извеÑтиÑ" settings: "ÐаÑтройки" - view_all: "Показване на вÑички" - likes: - likes: - people_dislike_this: - few: "не е хареÑана %{count} пъти" - many: "не е хареÑана %{count} пъти" - one: "не е хареÑана %{count} път" - other: "не е хареÑана %{count} пъти" - two: "не е хареÑана %{count} пъти" - zero: "вÑички Ñа Ñ Ñ…Ð°Ñ€ÐµÑали" - people_like_this: - few: "хареÑана %{count} пъти" - many: "хареÑана %{count} пъти" - one: "хареÑана %{count} път" - other: "хареÑана %{count} пъти" - two: "хареÑана %{count} пъти" - zero: "не е хареÑана" - people_like_this_comment: - few: "хареÑан %{count} пъти" - many: "хареÑан %{count} пъти" - one: "хареÑан %{count} път" - other: "хареÑан %{count} пъти" - two: "хареÑан %{count} пъти" - zero: "не е хареÑан" limited: "Ограничена" more: "Още" - next: "Ñледваща" no_results: "ÐÑма намерени резултати" notifications: also_commented: @@ -295,14 +195,6 @@ bg: other: "%{actors} коментираха ваша %{post_link}." two: "%{actors} коментираха ваша %{post_link}." zero: "%{actors} коментира ваша %{post_link}." - helper: - new_notifications: - few: "%{count} нови извеÑтиÑ" - many: "%{count} нови извеÑтиÑ" - one: "1 ново извеÑтие" - other: "%{count} нови извеÑтиÑ" - two: "%{count} нови извеÑтиÑ" - zero: "ÐÑма нови извеÑтиÑ" index: and: "и" and_others: @@ -361,7 +253,6 @@ bg: liked: "%{name} хареÑа вашата публикациÑ" view_post: "Преглед на публикациÑта >" mentioned: - mentioned: "Ви Ñпомена в публикациÑ:" subject: "%{name} Ви Ñпомена в Diaspora*" private_message: reply_to_or_view: "Отговорете или прегледайте разговора >" @@ -378,96 +269,40 @@ bg: thanks: "БлагодарÑ," to_change_your_notification_settings: "за да промените наÑтройките за извеÑÑ‚Ñване" ok: "Добре" - or: "или" - password: "Парола" - password_confirmation: "Потвърждаване на паролата" people: - add_contact_small: - add_contact_from_tag: "добавÑне на контакт от марка" - aspect_list: - edit_membership: "принадлежноÑÑ‚ към аÑпекти" - helper: - results_for: " резултата за %{params}" index: looking_for: "ТърÑите публикации Ñ Ð¼Ð°Ñ€ÐºÐ° %{tag_link}?" no_one_found: "...и никой не е намерен." no_results: "Хей! Въведете нещо за Ñ‚ÑŠÑ€Ñене." results_for: "резултат от Ñ‚ÑŠÑ€Ñенето за" - one: "1 човек" - other: "%{count} човека" person: - add_contact: "добавÑне на контакт" - already_connected: "Вече Ñте Ñвързани" - pending_request: "Ðеразгледана покана" thats_you: "Това Ñте Вие!" profile_sidebar: bio: "биографични данни" born: "рожден ден" - edit_my_profile: "Редактирайте профила Ñи" gender: "пол" location: "меÑтоположение" - remove_contact: "премахване на контакта" - remove_from: "Премахване на %{name} от %{aspect}?" show: closed_account: "Ðкаунтът е затворен." does_not_exist: "Лицето не ÑъщеÑтвува!" has_not_shared_with_you_yet: "%{name} вÑе още не е Ñподелил нито една Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ñ Ñ Ð’Ð°Ñ!" - ignoring: "Ð’Ñички публикации на %{name} биват игнорирани." - incoming_request: "%{name} желае да ÑÐ¿Ð¾Ð´ÐµÐ»Ñ Ñ Ð’Ð°Ñ" - mention: "Споменете" - message: "Съобщение" - not_connected: "Вие не ÑподелÑте Ñ Ð»Ð¸Ñ†ÐµÑ‚Ð¾" - recent_posts: "Скорошни публикации" - recent_public_posts: "Скорошни публични публикации" - return_to_aspects: "Ðазад към Ñтраницата Ñ Ð°Ñпекти" - see_all: "Показване на вÑички" - start_sharing: "започнете да ÑподелÑте" - sub_header: - add_some: "добавете нÑколко" - edit: "редактиране" - you_have_no_tags: "не Ñте добавили марки към профила Ñи!" - webfinger: - fail: "За Ñъжаление %{handle} не може да бъде намерен." - zero: "0 човека" photos: - comment_email_subject: "Снимка на %{name}" create: integrity_error: "Снимката не бе качена. Сигурни ли Ñте, че Ñте избрали изображение?" runtime_error: "Снимката не бе качена. Сигурни ли Ñте, че Ñте закопчали колана Ñи?" type_error: "Снимката не бе качена. Сигурни ли Ñте, че е добавено изображение?" destroy: notice: "Снимката е изтрита." - edit: - editing: "Редактиране" - new: - back_to_list: "Ðазад към ÑпиÑъка" - new_photo: "Ðова Ñнимка" - post_it: "публикуване!" new_photo: empty: "{file} е празен. МолÑ, изберете наново файловете без празниÑ." invalid_ext: "{file} е Ñ Ð½ÐµÐ²Ð°Ð»Ð¸Ð´Ð½Ð¾ разширение. Позволени Ñа Ñамо: {extensions}." size_error: "{file} е твърде голÑм. МакÑималниÑÑ‚ разрешен размер е {sizeLimit}." new_profile_photo: - or_select_one_existing: "или изберете от вече качените %{photos}" upload: "Качете нова Ñнимка за профила!" - photo: - view_all: "вÑички Ñнимки на %{name}" show: - collection_permalink: "поÑтоÑнен Ð°Ð´Ñ€ÐµÑ Ð½Ð° колекциÑта" - delete_photo: "Изтриване на изображението" - edit: "редактиране" - edit_delete_photo: "Редактиране на опиÑанието / изтриване" - make_profile_photo: "ползване като профилна Ñнимка" show_original_post: "Оригиналната публикациÑ" - update_photo: "Ðктуализиране на Ñнимката" - update: - error: "Снимката не бе изтрита." - notice: "Снимката е обновена." posts: show: - destroy: "Изтриване" - not_found: "За Ñъжаление публикациÑта не може да бъде намерена." - permalink: "поÑтоÑнен адреÑ" photos_by: few: "%{count} Ñнимки от %{author}" many: "%{count} Ñнимки от %{author}" @@ -475,14 +310,11 @@ bg: other: "%{count} Ñнимки от %{author}" two: "2 Ñнимки от %{author}" zero: "ÐÑма Ñнимки от %{author}" - previous: "предишна" privacy: "ПоверителноÑÑ‚" - privacy_policy: "Ð”ÐµÐºÐ»Ð°Ñ€Ð°Ñ†Ð¸Ñ Ð·Ð° поверителноÑÑ‚" profile: "Профил" profiles: edit: allow_search: "Разрешете Ñ‚ÑŠÑ€Ñенето в Diaspora за ВаÑ" - edit_profile: "ÐаÑтройки на профила" first_name: "СобÑтвено име" last_name: "Фамилно име" update_profile: "ОбновÑване на профила" @@ -492,8 +324,6 @@ bg: your_location: "МеÑтоположение" your_name: "Вашето име" your_photo: "Снимка" - your_private_profile: "ВашиÑÑ‚ личен профил" - your_public_profile: "ВашиÑÑ‚ публичен профил" your_tags: "Опишете Ñе Ñ Ð´Ð¾ 5 #думи (марки)" your_tags_placeholder: "например: #Ð‘ÑŠÐ»Ð³Ð°Ñ€Ð¸Ñ #diaspora #Ñ„Ð¸Ñ‚Ð½ÐµÑ #музика #котки" update: @@ -511,55 +341,17 @@ bg: closed: "Ðови региÑтрации не Ñа възможни на този pod на Diaspora." create: success: "Вие Ñе приÑъединихте към Diaspora!" - edit: - leave_blank: "(оÑтавете празно ако не желаете да го променÑте)" - password_to_confirm: "(за да бъдат потвърдени промените е необходима текущата Ви парола)" - unhappy: "Ðе Ñте доволни?" - update: "ОбновÑване" new: - create_my_account: "Създаване на акаунт!" enter_email: "Въведете ел. поща" enter_password: "Въведете парола" enter_password_again: "Въведете отново Ñъщата парола" enter_username: "Изберете Ñи потребителÑко име (Ñамо букви, цифри и долна черта)" - join_the_movement: "ПриÑъединете Ñе към движението!" - sign_up_message: "Ñоциалната мрежа ÑÑŠÑ â™¥" - requests: - create: - sending: "Изпращане" - sent: "Изпратили Ñте покана до %{name} за да започнете да ÑподелÑте - щом Ñе впишат в Diaspora ще видÑÑ‚ поканата." - destroy: - error: "МолÑ, изберете аÑпект!" - success: "Сега ÑподелÑте." - helper: - new_requests: - few: "%{count} нови покани!" - many: "%{count} нови покани!" - one: "нова покана!" - other: "%{count} нови покани!" - two: "%{count} нови покани!" - zero: "нÑма нови покани" - manage_aspect_contacts: - existing: "СъщеÑтвуващи контакти" - new_request_to_person: - sent: "изпратена!" reshares: comment_email_subject: "Споделена Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¾Ñ‚ %{resharer} Ñ Ð°Ð²Ñ‚Ð¾Ñ€ %{author}'" - create: - failure: "Възникна грешка при ÑподелÑнето на публикациÑта." reshare: deleted: "Оригиналната Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ñ Ðµ изтрита от автора." - reshare: - few: "%{count} ÑподелÑниÑ" - many: "%{count} ÑподелÑниÑ" - one: "1 ÑподелÑне" - other: "%{count} ÑподелÑниÑ" - two: "%{count} ÑподелÑниÑ" - zero: "СподелÑне" reshare_confirmation: "СподелÑне публикациÑта на %{author}?" - reshare_original: "СподелÑне на оригинала" reshared_via: "Ñподелено чрез" - show_original: "Оригиналът" search: "ТърÑене" services: create: @@ -570,36 +362,14 @@ bg: success: "УдоÑтоверението е изтрито уÑпешно." failure: error: "възникна грешка при Ñвързването Ñ ÑƒÑлугата" - finder: - fetching_contacts: "Diaspora копира приÑтелите ви от %{service}. МолÑ, пробвайте отново Ñлед нÑколко минути." - no_friends: "ÐÑма намерени приÑтели от Facebook." - service_friends: "ПриÑтели от %{service}" index: disconnect: "изключване" edit_services: "ÐаÑтройки на уÑлугите" logged_in_as: "впиÑани Ñте като" really_disconnect: "ÐаиÑтина ли желаете ÑвързаноÑтта Ñ %{service} да бъде изключена?" - inviter: - click_link_to_accept_invitation: "Кликнете върху връзката, за да приемете поканата" - join_me_on_diaspora: "ПриÑъединете Ñе към мен в DIASPORA*" - remote_friend: - invite: "покани" - not_on_diaspora: "Ð’Ñе още не е в Diaspora" - resend: "повторно изпращане" settings: "ÐаÑтройки" - share_visibilites: - update: - post_hidden_and_muted: "ПубликациÑта на %{name} е Ñкрита, а получаването на извеÑÑ‚Ð¸Ñ Ð·Ð° Ð½ÐµÑ - прекратено." - see_it_on_their_profile: "Ðко желаете да прегледате новините отноÑно публикациÑта на %{name} можете да поÑетите профила му." shared: - add_contact: - add_new_contact: "ДобавÑне на контакт" - create_request: "ТърÑи по Ð°Ð´Ñ€ÐµÑ Ð² Diaspora" - enter_a_diaspora_username: "Въведете потребителÑко име от Diaspora:" - know_email: "Знаете адреÑите на ел. им поща? ТрÑбва да ги поканите" - your_diaspora_username_is: "Вашето потребителÑко име в Diaspora е %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "ДобавÑне в аÑпект" toggle: few: "Ð’ %{count} аÑпекта" many: "Ð’ %{count} аÑпекта" @@ -607,22 +377,10 @@ bg: other: "Ð’ %{count} аÑпекта" two: "Ð’ %{count} аÑпекта" zero: "Добавете контакт" - contact_list: - all_contacts: "Ð’Ñички контакти" - footer: - logged_in_as: "впиÑани Ñте като %{name}" - your_aspects: "вашите аÑпекти" invitations: by_email: "по ел. поща" - dont_have_now: "За момента не разполагате Ñ Ð¿Ð¾ÐºÐ°Ð½Ð¸, но Ñкоро ще имате!" - from_facebook: "от Facebook" - invitations_left: "(имате %{count} покани)" - invite_someone: "Поканете нÑкого" invite_your_friends: "Поканете приÑтелите Ñи" invites: "Покани" - invites_closed: "Издаването на покани за този pod на Diaspora за момента е прекратено" - notification: - new: "Ðово %{type} от %{from}" public_explain: control_your_audience: "Определете публиката" logged_in: "впиÑани Ñте в %{service}" @@ -633,56 +391,24 @@ bg: title: "ÐаÑтройване на Ñвързаните уÑлуги" visibility_dropdown: "Ползвайте падащото меню, за да промените видимоÑтта на публикациÑта. (Препоръчително е да направите първата Ñи Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿ÑƒÐ±Ð»Ð¸Ñ‡Ð½Ð°.)" publisher: - all: "вÑички" - all_contacts: "вÑички контакти" discard_post: "ОтхвърлÑне на публикациÑта" - make_public: "направете публично" new_user_prefill: hello: "Привет на вÑички, аз Ñъм #%{new_user_tag}. " i_like: "ИнтереÑува ме %{tags}." invited_by: "Ð‘Ð»Ð°Ð³Ð¾Ð´Ð°Ñ€Ñ Ð·Ð° поканата, " newhere: "ÐовТук" - post_a_message_to: "Публикувайте публично Ñъобщение в %{aspect}" posting: "Публикуване..." - publishing_to: "публикуване в: " share: "Споделете" - share_with: "ÑподелÑне Ñ" upload_photos: "Качете Ñнимки" whats_on_your_mind: "За какво миÑлите?" - reshare: - reshare: "ÑподелÑне Ñ" stream_element: - connect_to_comment: "Свържете Ñе Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ, за да коментирате публикациÑта му" - currently_unavailable: "временно не е възможно да коментирате" - dislike: "Ðе ми хареÑва" - hide_and_mute: "Скриване и прекратÑване на извеÑÑ‚Ñването за публикациÑта" - ignore_user: "Игнориране на %{name}" - ignore_user_description: "Игнориране и премахване на Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ Ð¾Ñ‚ вÑички аÑпекти?" - like: "ХареÑва ми" - nsfw: "ПубликациÑта Ðе е ПодходÑща за Работното ÐœÑÑто (NSFW), Ñпоред автора. %{link}" - shared_with: "Споделена Ñ: %{aspect_names}" - unlike: "Ðе ми хареÑва" via: "чрез %{link}" - viewable_to_anyone: "ПубликациÑта е видима за вÑеки" status_messages: create: success: "Споменахте уÑпешно: %{names}" - destroy: - failure: "ПубликациÑта не бе изтрита" - helper: - no_message_to_display: "ÐÑма Ñъобщение за изобразÑване." new: mentioning: "Споменаване на %{person}" too_long: "{\"few\"=>\", Ð¼Ð¾Ð»Ñ Ñъкратете Ñъобщението Ñи до %{count} знака\", \"many\"=>\", Ð¼Ð¾Ð»Ñ Ñъкратете Ñъобщението Ñи до %{count} знака\", \"one\"=>\", Ð¼Ð¾Ð»Ñ Ñъкратете Ñъобщението Ñи до %{count} знака\", \"other\"=>\", Ð¼Ð¾Ð»Ñ Ñъкратете Ñъобщението Ñи до %{count} знака\", \"two\"=>\", Ð¼Ð¾Ð»Ñ Ñъкратете Ñъобщението Ñи до %{count} знака\", \"zero\"=>\", Ð¼Ð¾Ð»Ñ Ñъкратете Ñъобщението Ñи до %{count} знака\"}" - stream_helper: - hide_comments: "Скриване на коментарите" - show_comments: - few: "Показване на оÑтаналите %{count} коментара" - many: "Показване на оÑтаналите %{count} коментара" - one: "Показване на още 1 коментар" - other: "Показване на оÑтаналите %{count} коментара" - two: "Показване на още 2 коментара" - zero: "ÐÑма други коментари" streams: aspects: title: "Вашите аÑпекти" @@ -706,22 +432,11 @@ bg: title: "Публична активноÑÑ‚" tags: title: "Публикации маркирани Ñ \"%{tags}\"" - tag_followings: - create: - failure: "Ðе започнахте да Ñледите \"#%{name}\". Да не би вече да Ñледите марката?" - none: "Ðе може да Ñледите празна марка!" - success: "Ура! Започнахте да Ñледите \"#%{name}\"." - destroy: - failure: "Следенето на \"#%{name}\" не е прекратено." - success: "Следенето на \"#%{name}\" е прекратено." tags: show: follow: "Следете #%{tag}" - following: "Следите #%{tag}" none: "Ðе ÑъщеÑтвува празна марка!" stop_following: "ПрекратÑване Ñледването на #%{tag}" - terms_and_conditions: "Общи уÑÐ»Ð¾Ð²Ð¸Ñ Ð¸ правила" - undo: "ОтмÑна?" username: "ПотребителÑко име" users: confirm_email: @@ -739,7 +454,6 @@ bg: change_password: "ПромÑна на паролата" close_account: dont_go: "МолÑ, не Ñи отивайте!" - if_you_want_this: "Ðко наиÑтина го желаете въведете паролата Ñи, по-долу и натиÑнете \"ЗатварÑне на акаунта\"" lock_username: "потребителÑко ви име Ñе \"заключва\" - ако пожелаете да Ñе върнете отново" locked_out: "автоматично ще бъдете отпиÑани, а акаунтът - \"заключен\"" make_diaspora_better: "ÐадÑваме Ñе да ни помогнете в уÑилиÑта ни да направим уÑлугата Diaspora по-добра. Ðко наиÑтина желаете да напуÑнете ето какво Ñе Ñлучва при напуÑкане:" @@ -749,7 +463,6 @@ bg: close_account_text: "ЗатварÑне на акаунта" comment_on_post: "...нÑкой коментира Ваша публикациÑ?" current_password: "Текуща парола" - download_photos: "Ñнимките ви" edit_account: "ÐаÑтройки на акаунта" email_awaiting_confirmation: "Изпратена е връзка за активиране до %{unconfirmed_email}. Докато не Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¸Ñ€Ð°Ñ‚Ðµ ще бъде ползвана Ñтарата ел. поща (%{email})." export_data: "СвалÑне на..." @@ -771,7 +484,6 @@ bg: community_welcome: "ОбщноÑтта около Diaspora Ñ Ñ€Ð°Ð´Ð¾ÑÑ‚ Ви приветÑтва на борда!" hashtag_explanation: "Диез марките (#име–на-марката) ви позволÑват да коментирате и Ñледите интереÑни за Ð²Ð°Ñ Ñ‚ÐµÐ¼Ð¸. УлеÑнÑват и откриване на хора ÑÑŠÑ Ñходни интереÑи в Diaspora." hashtag_suggestions: "Пробвайте да Ñледвате нÑколко марки като #Ð‘ÑŠÐ»Ð³Ð°Ñ€Ð¸Ñ #diaspora #Ñ„Ð¸Ñ‚Ð½ÐµÑ Ð¸ др." - saved: "ЗапиÑано!" well_hello_there: "Здравейте!" what_are_you_in_to: "От какво Ñе интереÑувате?" who_are_you: "Кой Ñте Вие?" @@ -791,7 +503,6 @@ bg: settings_updated: "ÐаÑтройките Ñа обновени" unconfirmed_email_changed: "Ел. поща е променена. Ðеобходимо е да Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¸Ñ€Ð°Ñ‚Ðµ." unconfirmed_email_not_changed: "Ел. поща не бе променена" - welcome: "Привет от Diaspora," will_paginate: next_label: "Ñледваща »" previous_label: "« предишна" \ No newline at end of file diff --git a/config/locales/diaspora/br.yml b/config/locales/diaspora/br.yml index 5fc75ce7ced396afb3818dad02d257ba6e4b3dcb..2b515ef6e36d56f6bdf5efd4c39fb2682d79d813 100644 --- a/config/locales/diaspora/br.yml +++ b/config/locales/diaspora/br.yml @@ -6,11 +6,8 @@ br: _applications: "Arloadoù" - _comments: "Evezhiadennoù" _contacts: "Darempredoù" _help: "Skoazell" - _home: "Degemer" - _photos: "luc'hskeudennoù" _services: "Servijoù" account: "Kont" activerecord: @@ -82,6 +79,8 @@ br: other: "%{count} implijer" zero: "%{count} implijer" week: "Sizhun" + user_entry: + invite_token: "Bilhed-pediñ" user_search: add_invites: "Ouzhpennañ pedadennoù" email_to: "Postel evit pediñ" @@ -101,13 +100,7 @@ br: other: "Niver a implijerien nevez er sizhun-mañ: %{count}" zero: "Niver a implijerien nevez er sizhun-mañ: hini ebet" current_server: "Deiziad red ar servijer zo %{date}" - ago: "%{time} zo" all_aspects: "An holl strolladoù" - application: - helper: - unknown_person: "den dianav" - video_title: - unknown: "Titl video dianav" are_you_sure: "Ha sur oc'h ?" are_you_sure_delete_account: "Ha sur oc'h e fell deoc'h klozañ ho kont ? Ne c'hallo ket bezañ disc'hraet !" aspect_memberships: @@ -121,18 +114,10 @@ br: success: "Ouzhpennet eo bet an darempred d'ar strollad ervat" aspect_listings: add_an_aspect: "+ Ouzhpennañ ur strollad" - deselect_all: "Diziuzañ pep tra" - edit_aspect: "Aozañ %{name}" - select_all: "Diuzañ pep tra" aspect_stream: make_something: "Grit un dra bennak" stay_updated: "Heuliañ an nevezenti" stay_updated_explanation: "O red pennañ a zo peurleugniet gant o darempredoù, o tagoù heuliet, ha dre mesajoù izili zo ar rouedad." - contacts_not_visible: "Ne vo ket gouest an darempredoù er strollad-mañ d'en em welet an eil d'egile." - contacts_visible: "Gouest e vo an darempredoù er strollad-mañ d'en em welet an eil d'egile." - create: - failure: "C'hwitet eo krouidigezh ar strollad." - success: "Krouet eo bet ho strollad nevez, %{name}" destroy: failure: "%{name} n'eo ket goullo ha ne c'hall ket bezañ diverket" success: "Diverket eo bet %{name} ervat." @@ -140,24 +125,15 @@ br: aspect_list_is_not_visible: "N'hall ket darempredoù ar strollad-mañ en em welet" aspect_list_is_visible: "Gallout a ra darempredoù ar strollad-mañ en em welet" confirm_remove_aspect: "Ha sur oc'h e fell deoc'h diverkañ ar strollad-mañ ?" - make_aspect_list_visible: "lakaat an holl darempredoù er strollad-mañ d'en em welet ?" - remove_aspect: "Diverkañ ar strollad-mañ" rename: "cheñch an anv" update: "hizivaat" updating: "oc'h hizivaat" index: - diaspora_id: - content_1: "Setu ho kod anaout evit Diaspora:" - content_2: "Roit anezhañ d'an dud, dezho da c'hallout mont e darempred ganeoc'h war Diaspora." - heading: "Kod anaout Diaspora" donate: "Reiñ arc'hant" - handle_explanation: "Setu aze ho kod anaout evit diaspora. Evel ur chomlec'h postel e c'hellit skignañ anezhañ, d'an dud da vont e darempred ganeoc'h." help: any_problem: "Ur gudenn bennak?" contact_podmin: "Kit e darempred gant merour ho pod!" do_you: "Hag:" - email_feedback: "Kasit ur roudenn dre %{link}, ma'z e fell gwelloc'h deoc'h." - email_link: "Postel" feature_suggestion: "... ul %{link} ?" find_a_bug: "... kavet ur %{link} ?" have_a_question: "... ul %{link} ?" @@ -175,25 +151,15 @@ br: follow: "Heuilhit %{link} ha roit an degemer mat d'an implijerien nevez war Diapora*!" learn_more: "Gouzout hiroc'h" title: "Degemer an implijerien nevez" - no_contacts: "Darempred ebet" - no_tags: "+ Kavout un dikedenn da heuliañ" - people_sharing_with_you: "Tud a rann keleier ganeoc'h" - post_a_message: "embann ur gemennadenn" services: content: "Gallout a rit kennaskañ ar servijoù-mañ ouzh Diaspora" heading: "Servijoù kennaskañ" - unfollow_tag: "Paouez a heuliañ #%{tag}" welcome_to_diaspora: "Donemat deoc'h e Diaspora, %{name} !" - new: - create: "Krouiñ" - name: "Anv (gwelet ganeoc'h hepken)" no_contacts_message: community_spotlight: "Emañ ar gouloù warne" or_spotlight: "pe gallout a rit rannañ dre %{link}" try_adding_some_more_contacts: "Gallout a rit klask darempredoù pe pediñ re all" you_should_add_some_more_contacts: "Dleout a rafec'h ouzhpennañ darempredoù all !" - no_posts_message: - start_talking: "N'eus bet lavaret grik gant den evit poent !" seed: acquaintances: "Tud anavezet" family: "Familh" @@ -202,7 +168,6 @@ br: update: failure: "Re hir eo anv ho strollad, %{name}, evit gallout bezañ enrollet" success: "Kemmet eo bet ho strollad, %{name}, ervat." - back: "Distreiñ" blocks: create: failure: "N'hallan ket ober van eus an implijer-mañ" @@ -214,21 +179,14 @@ br: explanation: "Postit traoù war diaspora* adalek forzh pelec'h dre lakaat ur sined d'al liamm-mañ => %{link}." heading: "Sinedoù Diaspora" post_something: "Embann un dra bennak e Diaspora" - post_success: "Embannet ! O serriñ !" cancel: "Nullañ" comments: new_comment: comment: "Evezhiadenn" commenting: "Oc'h embann..." - one: "1 evezhiadenn" - other: "%{count} evezhiadenn" - zero: "evezhiadenn ebet" contacts: - create: - failure: "Dibosupl krouiñ an darempred" index: add_a_new_aspect: "Ouzhpennañ ur strollad nevez" - add_to_aspect: "Ouzhpennañ darempredoù da %{name}" all_contacts: "An holl zarempredoù" community_spotlight: "Nevezenti ar rouedad" my_contacts: "Ma darempredoù" @@ -237,33 +195,20 @@ br: only_sharing_with_me: "O rannañ keleier ganin hepken" start_a_conversation: "Boulc'hañ ur gaoz" title: "Darempredoù" - your_contacts: "Ho tarempredoù" - sharing: - people_sharing: "Tud a rann keleier ganeoc'h:" spotlight: community_spotlight: "Nevezenti ar rouedad" suggest_member: "Kinnig anv un ezel" conversations: - conversation: - participants: "Perzhidi" create: fail: "kemennadenn direizh" no_contact: "Alato, ezhomm ho peus ouzhpennañ an darempred da gentañ !" sent: "Kemennadenn bet kaset" - helper: - new_messages: - one: "1 gemennadenn nevez" - other: "%{count} a gemennadennoù nevez" - zero: "kemennadenn nevez ebet" index: conversations_inbox: "Kaozeadennoù – Boest degemer" - create_a_new_conversation: "boulc'hañ gant ur gaoz nevez" inbox: "Boest-lizheroù" new_conversation: "Kaoz nevez" - no_conversation_selected: "n'eus bet diuzet kaoz ebet" no_messages: "kemennadenn ebet" new: - abandon_changes: "Dilezel ar c'hemmoù ?" send: "Kaset" sending: "O kas..." subject: "danvez" @@ -284,10 +229,6 @@ br: error_messages: helper: correct_the_following_errors_and_try_again: "Divankit ar fazioù da heul ha klaskit en-dro." - invalid_fields: "Maeziennoù direizh" - login_try_again: "'%{login_link}'>Kevreit</a> ha klaskit en-dro." - post_not_public: "N'eo ket foran an destenn emaoc'h o klask lenn!" - post_not_public_or_not_exist: "An embannadenn emaoc'h o klask lenn n'eo ket foran he statud pe n'eus ket anezhi !" fill_me_out: "Disilañ ac'hanon" find_people: "Kavout tud pe #tikedennoù" help: @@ -372,45 +313,27 @@ br: tutorial: "kelennskrid" tutorials: "kelennskridoù" wiki: "wiki" - hide: "Kuzhat" - ignore: "Na ober van" - invitation_codes: - excited: "%{name} a zo laouen da welet ac'hanoc'h amañ" invitations: a_facebook_user: "Un implijer eus Facebook" check_token: not_found: "N'eo ket bet kaset ar bilhed-pediñ" create: - already_contacts: "Liammet oc'h ouzh an den-mañ c'hoazh" - already_sent: "Kouviet eo bet an den-mañ ganeoc'h c'hoazh." empty: "Merkit da nebeutañ ur chomlec'h postel." no_more: "N'ho 'peus pedadenn ebet ken." note_already_sent: "Pedadennoù a zo dija bet kaset da : %{emails}" - own_address: "Ne c'hallit ket kas ur gouviadenn deoc'h-c'hwi hoc'h-unan." rejected: "Kudennoù zo gant ar chomlec'hioù postel-mañ: " sent: "Pedadennoù zo bet kaset da: %{emails}" - edit: - accept_your_invitation: "Asantiñ d'ar bedadenn" - your_account_awaits: "Ho kont a zo o c'hortoz !" new: - already_invited: "N'eo ket bet asantet d'ho pedadenn gant an dud-mañ:" - aspect: "Strollad" - check_out_diaspora: "Sell 'ta ouzh diaspora* !" codes_left: one: "Chom 'ra %{count} pedadenn war ar c'hod-mañ." other: "Chom 'ra %{count} pedadenn war ar c'hod-mañ." zero: "Ne chom pedadenn ebet ar ar c'hod-mañ ken." comma_separated_plz: "Gallout a rit merkañ meur a chomlec'h postel dispartiet gant skejoù." - if_they_accept_info: "ma vez asantet ganto e vint ouzhpennet d'ar strollad lec'h m'ho peus pedet anezho." invite_someone_to_join: "Kouviit unan bennak da zont e Diaspora !" language: "Yezh" paste_link: "Ken-rannit al liamm-se gant ho mignoned evit pediñ aneho war disapora*, pe kasit al liamm dre bostel war-eeun." - personal_message: "Kemennadenn brevez" - resend: "Adkas" send_an_invitation: "Kas ur bedadenn" - send_invitation: "Kas ar bedadenn" sending_invitation: "O kas ar bedadenn" - to: "Da" layouts: application: back_to_top: "Distreiñ e krec'h" @@ -419,35 +342,13 @@ br: source_package: "Pellgargañ pakad ar boneg tarzh" toggle: "gweredekaat/diweredekaat ar stumm evit an hezougoù" whats_new: "petra nevez ?" - your_aspects: "ho strolladoù" header: - admin: "Merañ" - blog: "blog" code: "kod" - help: "Skoazell" - login: "kevreañ" logout: "Digevreañ" profile: "Aelad" - recent_notifications: "Kemennoù nevez" settings: "Arventennoù" - view_all: "Gwelet pep tra" - likes: - likes: - people_dislike_this: - one: "1 den displijet zo bet" - other: "Displijet ez eus bet %{count} den" - zero: "Den n'eo bet displijet" - people_like_this: - one: "1 den plijet zo bet" - other: "%{count} den plijet zo bet" - zero: "Den ebet n'eo bet plijet" - people_like_this_comment: - one: "%{count} plijus" - other: "%{count} plijus" - zero: "den ebet plijet" limited: "Bevennet" more: "Muioc'h" - next: "war-lerc'h" no_results: "Disoc'h ebet kavet" notifications: also_commented: @@ -462,11 +363,6 @@ br: one: "Un evezhiadenn da %{post_link} zo bet savet gant.%{actors}." other: "Un evezhiadenn da %{post_link} zo bet savet gant.%{actors}." zero: "Un evezhiadenn da %{post_link} zo bet savet gant.%{actors}." - helper: - new_notifications: - one: "ur gemennadenn nevez" - other: "%{count} kemennadenn nevez" - zero: "kemennadenn nevez ebet" index: all_notifications: "An holl gemennoù" also_commented: "Evezhiadennoù lakaet all" @@ -521,7 +417,6 @@ br: zero: "N'eus den ebet %{actors} o rannañ udb. ganeoc'h." notifier: a_post_you_shared: "ur post" - accept_invite: "Asantiñ ho pedadenn diaspora*" click_here: "klikañ amañ" comment_on_post: reply: "Varienn: %{name}" @@ -551,7 +446,6 @@ br: liked: "plijet eo bet %{name} gant ar pezh zo bet skrivet ganeoc'h" view_post: "Sellet ouzh an embannadenn >" mentioned: - mentioned: "en/he deus meneget ac'hanoc'h en ur post :" subject: "%{name} en/he deus meneget ac'hanoc'h war diaspora*" private_message: reply_to_or_view: "Respont pe sellet ouzh ar gaoz-mañ >" @@ -569,20 +463,9 @@ br: to_change_your_notification_settings: "evit cheñch an arventennoù kemenn" nsfw: "NSFW" ok: "Mat eo" - or: "pe" - password: "Ger-tremen" - password_confirmation: "Kadarnaat ar ger-tremen" people: add_contact: invited_by: "kouviet oc'h bet gant" - add_contact_small: - add_contact_from_tag: "ouzhpennañ un darempred adalek un tag" - aspect_list: - edit_membership: "kemmañ koumanant ar strollad" - helper: - is_not_sharing: "N'emañ ket %{name} o rannañ ganeoc'h" - is_sharing: "%{name} a zo o rannañ ganeoc'h" - results_for: " disoc'hoù evit %{params}" index: couldnt_find_them: "N'eus ket bet gallet kavout anezho ?" looking_for: "O klask war-lec'h embannadennoù taget gant %{tag_link} emaoc'h ?" @@ -592,99 +475,46 @@ br: search_handle: "Ober gant ho kod anaout diaspora* (username@pod.tld) evit bezañ sur da gavout ho mignoned." searching: "O klask, gortozit ur pennadig..." send_invite: "Netra c'hoazh ? Kas ur bedadenn !" - one: "1 den" - other: "%{count} den" person: - add_contact: "Ouzhpennañ an darempred" - already_connected: "Kennasket c'hoazh" - pending_request: "Rekedoù e-skourr" thats_you: "C'hwi eo !" profile_sidebar: bio: "Buhez" born: "Deiziad ganedigezh" - edit_my_profile: "Kemmañ ma aelad" gender: "Reizh" - in_aspects: "er strolladoù" location: "Lec'hiadur" - photos: "Skeudennoù" - remove_contact: "dilemel an darempred" - remove_from: "Dilemel %{name} a-ziwar %{aspect}?" show: closed_account: "Ar c'hont-mañ a zo bet prenet." does_not_exist: "An den-mañ n'eus ket anezhañ !" has_not_shared_with_you_yet: "N'eo bet rannet embannadenn ebet ganeoc'h a-berzh %{name}" - ignoring: "Ne daolit ket evezh eus holl postoù %{name}" - incoming_request: "%{name} n'efe c'hoant eskemm diganit" - mention: "Meneg" - message: "Kemmenadenn" - not_connected: "Ne rannit ket keleier gant an den-mañ" - recent_posts: "Embannadennoù diwezhañ" - recent_public_posts: "Embannadennoù Foran Nevez" - return_to_aspects: "Distreiñ da bajenn ho strolladoù" - see_all: "Gwelet pep tra" - start_sharing: "Kregiñ da rannañ keleier gant unan bennak." - to_accept_or_ignore: "evit asantiñ pe chom hep teurel evezh." - sub_header: - add_some: "ouzhpennañ" - edit: "kemmañ" - you_have_no_tags: "N'ho peus tag ebet!" - webfinger: - fail: "Siwazh, n'omp ket bet evit kavout %{handle}." - zero: "den ebet" photos: - comment_email_subject: "Skeudenn %{name}" create: integrity_error: "C'hwitet war kargadenn ar skeudenn. Sur oc'h eo ur skeudenn ?" runtime_error: "C'hwitet war kargadenn ar skeudenn. Sur oc'h eo staget ho kouriz surentez ?" type_error: "C'hwitet war kargadenn ar skeudenn. Sur oc'h bezañ bet ouzhpennet ur skeudenn ?" destroy: notice: "Dilamet eo bet ar skeudenn" - edit: - editing: "O kemmañ" - new: - back_to_list: "Distreiñ d'ar roll" - new_photo: "Skeudenn nevez" - post_it: "embann !" new_photo: empty: "{file} a zo goulo, diuzit ar restroù en-dro heptañ mar plij." invalid_ext: "Ar restr {file} en deus ur astenn direizh. N'eus nemet {extensions} hag a zo asantet." size_error: "Re vras eo {file}, {sizeLimit} eo ar ar vrasañ posupl." new_profile_photo: - or_select_one_existing: "pe diuzit unan a zo diouti %{photos}" upload: "Kargit ur poltred nevez evit ho aelad !" - photo: - view_all: "sellet ouzh holl skeudennoù %{name}" show: - collection_permalink: "peurliamm an dastumad" - delete_photo: "Lemel ar skeudenn kuit" - edit: "kemmañ" - edit_delete_photo: "Kemmañ deskrivadenn ar skeudenn/ dilemel ar skeudenn" - make_profile_photo: "Sevel ur skeudenn aelad" show_original_post: "Diskouez an embannadenn orin" - update_photo: "Hizivaat ar skeudenn" - update: - error: "C'hwitet war kemmadur ar skeudenn." - notice: "Skeudenn bet hizivaet ervat." posts: presenter: title: "Un embannadenn a-berzh %{name}" show: - destroy: "Diverkañ" - not_found: "Digarezit, n'eo ket bet kavet an embannadenn." - permalink: "peurliamm" photos_by: one: "Ur skeudenn gant %{author}" other: "%{count} skeudenn gant %{author}" zero: "Skeudenn ebet gant %{author}" reshare_by: "Adrannet gant %{author}" - previous: "kent" privacy: "Prevezded" - privacy_policy: "Reolennoù prevezded" profile: "Aelad" profiles: edit: allow_search: "Aotren tud da glask ac'hanoc'h war diaspora*" - edit_profile: "Kemmañ an aelad" first_name: "Anv-bihan" last_name: "Anv-familh" nsfw_check: "Merkañ kement tra rannet ganin evel NSFW" @@ -695,8 +525,6 @@ br: your_location: "Lec'h annez" your_name: "Hoc'h anv" your_photo: "Ho poltred" - your_private_profile: "Ho aelad prevez" - your_public_profile: "Ho aelad foran" your_tags: "Deskrivit ac'hanoc'h gant 5 ger" your_tags_placeholder: "evel #sinema #farsus #loened #Breizh #dudioù" update: @@ -711,60 +539,24 @@ br: closed: "Stanket eo an enskrivadur war ar pod diaspora*-mañ" create: success: "Enskrivet oc'h war diaspora* !" - edit: - cancel_my_account: "Nullañ ma c'hont" - edit: "Kemmañ %{name}" - leave_blank: "(laoskit goullo mar ne fell ket deoc'h cheñch an dra-se)" - password_to_confirm: "(rekis eo ho ker-tremen evit kadarnaat ar cheñchamantoù)" - unhappy: "Displijet ?" - update: "Hizivaat" invalid_invite: "Al liamm pedadenn roet ganeoc'h n'eo ket mat ken" new: - create_my_account: "Krouiñ ma c'hont !" email: "POSTEL" enter_email: "Skrivit ur postel" enter_password: "Merkit ur ger-tremen (c'hwec'h arouezenn da nebeutañ)" enter_password_again: "Skrivit an hevelep ger-tremen hag a-raok" enter_username: "Dibabit un anv-implijer (lizherennoù, niverennoù hag isvarrennoù nemetken)" - join_the_movement: "Kemerit perzh !" password: "GER-TREMEN" password_confirmation: "KADARNAAT AR GER-TREMEN" sign_up: "LAKAAT E ANV" - sign_up_message: "Er rouedadoù sokial gant ur ♥" submitting: "O kas..." username: "ANV-IMPLIJER" - requests: - create: - sending: "O kas" - sent: "Goulennet ho peus rannan traoù gant %{name}. Gwelet a raio-se ar wech o tont ma kennasko da diaspora*." - destroy: - error: "Diuzit ur strollad mar plij !" - ignore: "Chom hep ober van eus ar goulenn darempred" - success: "Mignoned oc'h bremañ." - helper: - new_requests: - one: "Reked nevez !" - other: "%{count} reked nevez !" - zero: "Reked nevez ebet" - manage_aspect_contacts: - existing: "Darempredoù a zo diouto" - manage_within: "Merañ an darempredoù e" - new_request_to_person: - sent: "kaset !" reshares: comment_email_subject: "Adrannadenn %{resharer} eus embannadenn %{author}" - create: - failure: "Ur gudenn a zo bet en ur adrannañ an embannadenn." reshare: deleted: "Embannadenn orin diverket gant an aozer." - reshare: - one: "1 Adrannadenn" - other: "%{count} Adrannadenn" - zero: "Adrannadenn" reshare_confirmation: "Rannañ pelloc'h testenn %{author} ?" - reshare_original: "Rannañ ar stumm orin pelloc'h" reshared_via: "rannet pelloc'h dre" - show_original: "Diskouez ar stumm orin" search: "Klask" services: create: @@ -776,10 +568,6 @@ br: success: "Diverket ar c'hennask gant berzh." failure: error: "Ur gudenn a zo bet en ur c'hennaskañ ar servij" - finder: - fetching_contacts: "diaspora* a zo o poblekat ho mignoned %{service}, deuit en-dro en un nebeud munutennoù mar plij" - no_friends: "Mignoned Facebook ebet kavet" - service_friends: "Mignoned %{service}" index: connect: "Kennaskañ" disconnect: "digennaskañ" @@ -787,49 +575,18 @@ br: logged_in_as: "kevreet evel" really_disconnect: "digennaskañ diouzh %{service} ?" services_explanation: "Embann ho postoù dre servijoù all a c'hallit en ur gennaskañ ouzh servijoù all." - inviter: - click_link_to_accept_invitation: "Klikañ war al liamm-mañ evit asantiñ d'ar bedadenn" - join_me_on_diaspora: "Deus ganin war diaspora*" - remote_friend: - invite: "kouviañ" - not_on_diaspora: "N'eo ket c'hoazh war diaspora*" - resend: "adkas" settings: "Arventennoù" - share_visibilites: - update: - post_hidden_and_muted: "Embannadenn %{name} az o bet kuzhet, hag ar c'hemennoù a zo bet mutet." - see_it_on_their_profile: "M'ho 'peus c'hoant gwelet hizivadennoù war ar bajenn-mañ, kit da weladenniñ aelad %{name}" shared: - add_contact: - add_new_contact: "Ouzhpennañ un darempred nevez" - create_request: "Kavout dre kod anaout Diaspora" - diaspora_handle: "diaspora@handle.org" - enter_a_diaspora_username: "Enlakait ul lesanv diaspora*:" - know_email: "Anavezout a rit o chomlec'h postel ? Ret vefe deoc'h pedin anezhe" - your_diaspora_username_is: "Setu hoc'h anv-implijer war Diaspora: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Ouzhpennañ an darempred" toggle: one: "en %{count} strollad" other: "e %{count} strollad" zero: "Ouzhpennañ d'ar strollad" - contact_list: - all_contacts: "An holl zarempredoù" - footer: - logged_in_as: "kevreet evel %{name}" - your_aspects: "ho strolladoù" invitations: by_email: "Dre bostel" - dont_have_now: "N'ho 'peus hini ebet er mare-mañ, met bez ez eus muioc'h a bedadennoù o tont !" - from_facebook: "Diwar Facebook" - invitations_left: "(%{count} a chom deoc'h)" - invite_someone: "Pediñ unan bennak" invite_your_friends: "Pediñ mignoned" invites: "Pedadennoù" - invites_closed: "Ar pedadennoù a zo prenet evit ar mare war ar pod diaspora*-mañ" share_this: "Rannañ an ere dre bostel, blog, pe rouedadoù kevredadel !" - notification: - new: "%{type} nevez a-berzh %{from}" public_explain: atom_feed: "Gwazh atom" control_your_audience: "Mestroniit ho heklev" @@ -841,11 +598,8 @@ br: title: "Arventennañ ar servijoù kennasket" visibility_dropdown: "Implijit ar roll disachañ evit kemmañ gwelusted ho embannadenn. (Aliañ a reomp deoc'h da lakaat an hini kentañ-mañ foran.)" publisher: - all: "an holl" - all_contacts: "an holl zarempredoù" discard_post: "Nullan an embannadenn" get_location: "Kaout ho lec'hiadur" - make_public: "diskouez d'an holl" new_user_prefill: hello: "Demat d'an holl, me zo %{new_user_tag}. " i_like: "Dedennet on gant %{tags}. " @@ -853,36 +607,14 @@ br: newhere: "NevezAmañ" poll: add_a_poll: "Ouzhpennañ ur votadeg" - add_poll_answer: "Ouzhpennañ an dibarzh" - option: "Dibarzh 1" - question: "Goulenn" - remove_poll_answer: "Dilemel an dibarzh" - post_a_message_to: "Skrivañ ur gemennadenn da %{aspect}" posting: "Oc'h embann..." - preview: "Rakwel" - publishing_to: "embann da : " remove_location: "Lemel kuit al lec'hiadur" share: "Kenrannañ" - share_with: "rannañ gant" upload_photos: "Pellgargañ skeudennoù" whats_on_your_mind: "E petra emaoc'h o soñjal ?" - reshare: - reshare: "Rannañ pelloc'h" stream_element: - connect_to_comment: "Kennaskit gant an implijer-mañ evit lakaat evezhiadennoù war e embannadennoù" - currently_unavailable: "n'eus ket tu lakaat evezhiadennoù evit ar mare" - dislike: "Displijus" - hide_and_mute: "Kuzhat ha lakaat da devel" - ignore_user: "Ober van eus %{name}" - ignore_user_description: "Ober van ha dilemel an implijer eus an holl strolladoù ?" - like: "Plijus" - nsfw: "An embannadenn-mañ a zo bet merket NSFW gant e aozer. %{link}" - shared_with: "Rannet gant: %{aspect_names}" - show: "diskouez" - unlike: "Displijus" via: "dre %{link}" via_mobile: "dre pellgomzer" - viewable_to_anyone: "An embannadenn-mañ a c'hell bezañ gwelet gant an holl dud war ar web" simple_captcha: label: "Merkañ ar c'hod er voest:" message: @@ -893,19 +625,9 @@ br: status_messages: create: success: "Meneget gant berzh : %{names}" - destroy: - failure: "C'hwitet en ur diverkañ an embannadenn" - helper: - no_message_to_display: "Kemennadenn ebet da ziskouez." new: mentioning: "Menegiñ : %{person}" too_long: "{\"one\"=>\"Lezit ho kemennadennoù statud dindan %{count}\", \"other\"=>\"Lezit ho kemennadennoù statud dindan %{count}\", \"zero\"=>\"Lezit ho kemennadennoù statud dindan %{count}\"}" - stream_helper: - hide_comments: "Kuzhat an holl evezhiadennoù" - show_comments: - one: "Diskouez un evezhiadenn ouzhpenn" - other: "Diskouez %{count} evezhiadenn ouzhpenn" - zero: "evezhiadenn all ebet" streams: activity: title: "Ma obererezh" @@ -931,22 +653,11 @@ br: title: "Obererezh Foran" tags: title: "Embannadennoù merket : %{tags}" - tag_followings: - create: - failure: "C'hwitet eo bet heuliañ: #%{name}... Heuliañ a rit anezhañ c'hoazh ?" - none: "N'eus ket tu deoc'h heuliañ un tag goulo !" - success: "Brav, emaoc'h oc'h heuliañ: #%{name}" - destroy: - failure: "C'hwitet eo bet paouez da heuliañ: #%{name}. Ha n'ho poa ket paouezet d'e heuliañ c'hoazh ?" - success: "Siwazh, n'emaoc'h ket oc'h heuliañ #%{name} ken." tags: show: follow: "Heuliañ #%{tag}" - following: "Oc'h heuliañ #%{tag}" none: "An tag goulo n'eus ket dioutañ !" stop_following: "Paouez da heuliañ #%{tag}" - terms_and_conditions: "Termenoù ha diferadoù" - undo: "Dizober ?" username: "Anv-implijer" users: confirm_email: @@ -967,7 +678,6 @@ br: character_minimum_expl: "a rank bezañ ennañ c'hwec'h arouezenn da vihanañ" close_account: dont_go: "Hep, n'it ket kuit mar plij !" - if_you_want_this: "M'ho 'peus c'hoant e c'hoarvezfe da vat, enlakait ho ger-kuzh dindan ha klikit war \"Prenañ ar gont\"" lock_username: "Ho anv implijer a vo stanket. Ne vo ket tu deoc'h krouiñ ur gont nevez war ar pod-mañ gant an hevelep anv." locked_out: "Digennasket ha stanket e vo ho gont betek ma vo diverket" make_diaspora_better: "C'hoant hon eus diadpora* da vezañ gwelloc'h, neuze vefe ret deoc'h sikour ac'hanomp e plas mont kuit. M'ho 'peus c'hoant mont kuit, c'hoant hon eus ouifec'h petra c'hoarvezo goude" @@ -979,12 +689,10 @@ br: current_password: "Ho ker-tremen" current_password_expl: "an hini a zo implijet ganeoc'h evit kennaskañ" download_export: "Pellgargañ ma aelad" - download_photos: "pellgargañ ma skeudennoù" edit_account: "Kemmañ ar gont" email_awaiting_confirmation: "Kaset ez eus bet deoc'h ul liamm gweredekaat %{unconfirmed_email}. E-keit ha na vo ket heuliet al liamm-se ha gweredekaet ar chomlec'h nevez ganeoc'h e kendalc'himp da ober gant ho chomlec'h kozh %{email}." export_data: "Ezporzhiañ roadennoù" following: "Arventennoù ar rannadennoù" - getting_started: "Arventennoù an implijerien nevez" liked: "unan bennak a zo plijet gant o embannadenn" mentioned: "meneget oc'h en un embannadenn" new_password: "Ger-tremen nevez" @@ -1003,7 +711,6 @@ br: connect_to_facebook_link: "O kennaskañ d'ho kont Facebook" hashtag_explanation: "Gant an hashtags ez eus tu deoc'h eskemm hag heuliañ ar pezh a zedenn ac'hanoc'h. Un doare dreist da gavout tud nevez war diaspora* eo ivez." hashtag_suggestions: "Klaskit heuliañ klavioù evel #arz, #filmoù, #gif, h.a." - saved: "Enrollet !" well_hello_there: "Hey, demat deoc'h !" what_are_you_in_to: "Petra blij deoc'h ?" who_are_you: "Piv oc'h-c'hwi ?" @@ -1023,13 +730,6 @@ br: settings_updated: "Nevesaet an arventennoù" unconfirmed_email_changed: "Cheñchet eo ar chomlec'h postel. Rekis eo gweredekaat." unconfirmed_email_not_changed: "C'hwitet eo bet ar cheñchamant chomlec'h postel" - webfinger: - fetch_failed: "N'haller ket resevout an aelad webfinger evit %{profile_url}" - hcard_fetch_failed: "Ur gudenn a zo bet en ur resevout an hcard evit %{account}" - no_person_constructed: "N'eus ket bet tu da sevel un den adalek an hcard-mañ" - not_enabled: "war a-seblant n'eo ket gweredekaet webfinger evit ostiz %{account}" - xrd_fetch_failed: "Ur gudenn a zo bet en ur resevout an xrd evir ar gont %{account}" - welcome: "Donemat deoc'h !" will_paginate: next_label: "war-lerc'h «" previous_label: "« kent" \ No newline at end of file diff --git a/config/locales/diaspora/bs.yml b/config/locales/diaspora/bs.yml index acca4cf4c69b07808986f855aa98b4d44337d089..b61e05996f9879f8e77511cb1e25e4bc2629897f 100644 --- a/config/locales/diaspora/bs.yml +++ b/config/locales/diaspora/bs.yml @@ -6,11 +6,8 @@ bs: _applications: "Aplikacije" - _comments: "Komentari" _contacts: "Kontakti" _help: "Pomoć" - _home: "PoÄetna" - _photos: "fotografije" _services: "Servisi" account: "RaÄun" activerecord: @@ -103,13 +100,7 @@ bs: other: "koliÄina novih korisnika ove sedmice: %{count}" zero: "koliÄina novih korisnika ove sedmice: %{count}" current_server: "Trenutni datum servera je %{date}" - ago: "prije %{time}" all_aspects: "Svi Aspekti" - application: - helper: - unknown_person: "nepoznata osoba" - video_title: - unknown: "Nepoznat Video Naziv" are_you_sure: "Jeste sigurni?" are_you_sure_delete_account: "Jeste sigurni da želite zatvoriti raÄun? Ovo se ne može poniÅ¡titi!" aspect_memberships: @@ -123,18 +114,10 @@ bs: success: "UspjeÅ¡no dodavanje kontakta u aspekt." aspect_listings: add_an_aspect: "+ Dodaj jedan aspekt" - deselect_all: "OdznaÄi sve" - edit_aspect: "Uredu %{name}" - select_all: "OznaÄi sve" aspect_stream: make_something: "Napravi neÅ¡to" stay_updated: "Budite Ažurni" stay_updated_explanation: "VaÅ¡ glavni tok je popunjen sa svim vaÅ¡im kontaktima, oznakama koje pratite, i objavama od nekih kreativnih Älanova zajednice." - contacts_not_visible: "Kontakti u ovom aspektu neće moći vidjeti jedan drugog." - contacts_visible: "Kontakti u ovom aspektu će moći vidjeti jedan drugog." - create: - failure: "Kreiranje aspekta neuspjeÅ¡no." - success: "VaÅ¡ novi aspekt %{name} je kreran" destroy: failure: "%{name} nije prazno i ne može biti uklonjeno." success: "%{name} je uspjeÅ¡no uklonjeno." @@ -142,24 +125,15 @@ bs: aspect_list_is_not_visible: "lista aspekata je sakrivena od drugih u aspektu" aspect_list_is_visible: "lista aspekata je vidljiva od drugih u aspektu" confirm_remove_aspect: "Jeste li sigurni da želite izbrisati ovaj aspekt?" - make_aspect_list_visible: "uÄini kontakte u ovom aspektu vidljive jedan drugome?" - remove_aspect: "IzbriÅ¡i ovaj aspekt" rename: "preimenuj" update: "ažuriraj" updating: "ažuriram" index: - diaspora_id: - content_1: "VaÅ¡ Diaspora ID je:" - content_2: "Dajte bilo kome i oni će vas moći naći na Diaspori." - heading: "Diaspora ID" donate: "Doniraj" - handle_explanation: "Ovo je vaÅ¡ Diaspora ID. Kao i email adresu, možete ovo dati ljudima kako bi vas kontaktirali." help: any_problem: "Ikakav Problem?" contact_podmin: "Kontaktirajte administratora vaÅ¡eg poda!" do_you: "Da li:" - email_feedback: "%{link} vaÅ¡e povratne informacije, ako preferirate" - email_link: "Email" feature_suggestion: "... imate sugestiju za %{link}?" find_a_bug: "... ste pronaÅ¡li %{link}?" have_a_question: "... imate %{link}?" @@ -172,31 +146,20 @@ bs: tutorial_link_text: "Tutorijali" tutorials_and_wiki: "%{tutorial} i %{wiki}: Pomoć za prve korake." introduce_yourself: "Ovo je vaÅ¡ tok. PoÄnite i predstavite se." - keep_diaspora_running: "ÄŒuvajte razvoj Diaspore brz sa mjeseÄnom donacijom!" keep_pod_running: "ÄŒuvajte %{pod} uvijek brz i kupite serverima dozu sa mjeseÄnom donacijom!" new_here: follow: "Slijedi %{link} i pozovi nove korisnike na Diasporu*!" learn_more: "NauÄi viÅ¡e" title: "DobrodoÅ¡li Novi Korisnici" - no_contacts: "Nema kontakata" - no_tags: "+ PronaÄ‘i oznaku za slijeÄ‘enje" - people_sharing_with_you: "Ljudi dijele s tobom" - post_a_message: "objavi poruku >>" services: content: "Možete povezati sljedeće servise na Diasporu:" heading: "Servisi Povezivanja" - unfollow_tag: "Prestani slijediti #%{tag}" welcome_to_diaspora: "DobrodoÅ¡li na Diasporu, %{name}!" - new: - create: "Kreiraj" - name: "Ime (vidljivo samo vama)" no_contacts_message: community_spotlight: "u centru pažnje" or_spotlight: "Ili možete podijeliti sa %{link}" try_adding_some_more_contacts: "Možete tražiti ili pozvati viÅ¡e kontakata." you_should_add_some_more_contacts: "Trebali bi dodati joÅ¡ viÅ¡e kontakata!" - no_posts_message: - start_talking: "Niko joÅ¡ niÅ¡ta nije rekao!" seed: acquaintances: "Poznanici" family: "Porodica" @@ -205,7 +168,6 @@ bs: update: failure: "VaÅ¡ aspekt, %{name}, ima predugo ime da bi se snimilo." success: "VaÅ¡ aspekt, %{name}, je uspjeÅ¡no ureÄ‘en." - back: "Nazad" blocks: create: failure: "Nisam mogao/la ignorisati tog korisnika. #evasion" @@ -217,21 +179,14 @@ bs: explanation: "Objavite na Diasporu od bilo kuda bilježenjem ovog linka ==> %{link}" heading: "Bilježnik" post_something: "Objavi na Diasporu" - post_success: "Objavljeno! Zatvaram!" cancel: "Otkaži" comments: new_comment: comment: "Komentar" commenting: "KomentariÅ¡em..." - one: "1 komentar" - other: "%{count} komentari" - zero: "nema komentara" contacts: - create: - failure: "NeuspjeÅ¡no kreiranje kontakta" index: add_a_new_aspect: "Dodaj novi aspekt" - add_to_aspect: "dodaj kontakte za %{name}" all_contacts: "Svi Kontakti" community_spotlight: "U Centru Pažnje" my_contacts: "Moji Kontakti" @@ -240,32 +195,18 @@ bs: only_sharing_with_me: "Samo dijele sa mnom" start_a_conversation: "ZapoÄni razgovor" title: "Kontakti" - your_contacts: "VaÅ¡i Kontakti" - sharing: - people_sharing: "Ljudi koji dijele s vama:" spotlight: community_spotlight: "U Centru Pažnje" suggest_member: "PreporuÄi Älana" conversations: - conversation: - participants: "UÄesnici" create: fail: "Nevažeća poruka" no_contact: "Hej, morate prvo dodati kontakt!" sent: "Poruka poslata" - helper: - new_messages: - few: "%{count} novih poruka" - many: "%{count} novih poruka" - one: "%{count} nova poruka" - other: "%{count} novih poruka" - zero: "Nema novih poruka" index: inbox: "PoÅ¡ta" - no_conversation_selected: "ni jedan razgovor nije odabran" no_messages: "nema poruka" new: - abandon_changes: "Odbaciti izmjene?" send: "PoÅ¡alji" sending: "Slanje..." subject: "predmet" @@ -284,9 +225,6 @@ bs: error_messages: helper: correct_the_following_errors_and_try_again: "Popravite sljedeće greÅ¡ke i pokuÅ¡ajte ponovo." - invalid_fields: "Nevažeća Polja" - login_try_again: "Molimo <a href='%{login_link}'>prijavite se</a> i pokuÅ¡ajte ponovo." - post_not_public: "Objava koji pokuÅ¡avate pregledati nije javna!" fill_me_out: "Ispuni" find_people: "PronaÄ‘i ljude ili #oznake" help: @@ -346,29 +284,17 @@ bs: tutorial: "tutorijal" tutorials: "tutorijali" wiki: "wiki" - hide: "Sakrij" - invitation_codes: - excited: "%{name} je uzbuÄ‘en/a Å¡to vas vidi ovdje." invitations: a_facebook_user: "Facebook korisnik" check_token: not_found: "Znakovi pozivnice nisu pronaÄ‘eni" create: - already_contacts: "Već ste povezani sa ovom osobom." - already_sent: "Već ste pozvali ovu osobu." empty: "Molimo unesite najmanje jednu email adresu." no_more: "Nemate viÅ¡e pozivnica." note_already_sent: "Pozivnice su već poslate za: %{emails}" - own_address: "Ne možete poslati pozivnicu na svoju liÄnu adresu." rejected: "Sljedeće email adrese su imale probleme: " sent: "Pozivnice su poslate za: %{emails}" - edit: - accept_your_invitation: "Potvrdite vaÅ¡u pozivnicu" - your_account_awaits: "VaÅ¡ raÄun Äeka!" new: - already_invited: "Sljedeći ljudi nisu prihvatili vaÅ¡u pozivnicu:" - aspect: "Aspekt" - check_out_diaspora: "Probajte Diasporu!" codes_left: few: "%{count} pozivnice preostale na ovom kodu" many: "%{count} pozivnica preostalo na ovom kodu" @@ -376,16 +302,11 @@ bs: other: "%{count} pozivnice preostale na ovom kodu" zero: "Nije preostalo pozivnica na ovom kodu" comma_separated_plz: "Možete unijeti mnogobrojne email adrese odvojene sa zarezima." - if_they_accept_info: "ako prihvate, biće dodani na aspekt u koji ste ih pozvali." invite_someone_to_join: "Pozovite nekoga da se pridruži Diaspori!" language: "Jezik" paste_link: "Dijeli ovu vezu sa svojim prijateljima da bi ih pozvao na Diasporu*, ili poÅ¡alji im vezu direktnom emailom." - personal_message: "Osobna poruka" - resend: "Ponovo poÅ¡alji" send_an_invitation: "PoÅ¡alji jednu pozivnicu" - send_invitation: "PoÅ¡alji pozivnicu" sending_invitation: "Slanje pozivnice..." - to: "Za" layouts: application: back_to_top: "Nazad na vrh" @@ -394,40 +315,13 @@ bs: source_package: "preuzmi paket izvornog koda" toggle: "Å¡timanje mobilno" whats_new: "Å¡ta je novo?" - your_aspects: "vaÅ¡i aspekti" header: - admin: "administrator" - blog: "blog" code: "kod" - login: "prijava" logout: "Odjavi se" profile: "Profil" - recent_notifications: "SkoraÅ¡nje obavijesti" settings: "Postavke" - view_all: "Pogledaj sve" - likes: - likes: - people_dislike_this: - few: "%{count} nesviÄ‘anja" - many: "%{count} nesviÄ‘anja" - one: "%{count} nesviÄ‘anje" - other: "%{count} nesviÄ‘anja" - zero: "nema nesviÄ‘anja" - people_like_this: - few: "%{count} sviÄ‘anja" - many: "%{count} sviÄ‘anja" - one: "%{count} sviÄ‘anje" - other: "%{count} sviÄ‘anja" - zero: "nema sviÄ‘anja" - people_like_this_comment: - few: "%{count} sviÄ‘anja" - many: "%{count} sviÄ‘anja" - one: "%{count} sviÄ‘anje" - other: "%{count} sviÄ‘anja" - zero: "nema sviÄ‘anja" limited: "OgraniÄeno" more: "ViÅ¡e" - next: "sljedeće" no_results: "Rezultati Nisu PronaÄ‘eni" notifications: also_commented: @@ -448,13 +342,6 @@ bs: one: "%{actors} je komentarisalo na vaÅ¡u %{post_link}." other: "%{actors} su komentarisali na vaÅ¡u %{post_link}." zero: "%{actors} je komentarisalo na vaÅ¡u %{post_link}." - helper: - new_notifications: - few: "%{count} novih obavijesti" - many: "%{count} novih obavijesti" - one: "%{count} novih obavijesti" - other: "%{count} novih obavijesti" - zero: "Nema novih obavijesti" index: and: "i" and_others: @@ -517,7 +404,6 @@ bs: zero: "%{actors} je zapoÄelo dijeliti s vama." notifier: a_post_you_shared: "objava." - accept_invite: "Prihvatite VaÅ¡u Diaspora* pozivnicu!" click_here: "klikni ovdje" comment_on_post: reply: "Odgovori ili pogledaj objavu od %{name} >" @@ -547,7 +433,6 @@ bs: liked: "%{name} se sviÄ‘a vaÅ¡a objava" view_post: "Pogledaj objavu >" mentioned: - mentioned: "spomenuo/la vas u objavi:" subject: "%{name} vas je spomenuo/la na Diaspori*" private_message: reply_to_or_view: "Odgovori na ili pogledaj razgovor >" @@ -565,106 +450,45 @@ bs: to_change_your_notification_settings: "da bi izmijenili vaÅ¡e postavke obavijesti" nsfw: "Nije pogodno" ok: "Uredu" - or: "ili" - password: "Å ifra" - password_confirmation: "Potvrda Å¡ifre" people: add_contact: invited_by: "pozvani ste od" - add_contact_small: - add_contact_from_tag: "dodaj kontakt sa oznake" - aspect_list: - edit_membership: "uredi Älanstvo aspekta" - helper: - is_not_sharing: "%{name} ne dijeli s vama" - is_sharing: "%{name} dijeli s vama" - results_for: " rezultati za %{params}" index: looking_for: "Tražite objave oznaÄene sa %{tag_link}?" no_one_found: "...i niko nije pronaÄ‘en." no_results: "Hej! Trebate tražiti neÅ¡to." results_for: "rezultati pretrage za" searching: "pretraživanje, molimo budite strpljivi" - one: "1 osoba" - other: "%{count} ljudi" person: - add_contact: "dodaj kontakt" - already_connected: "Već povezani" - pending_request: "Zahtjev na Äekanju" thats_you: "To ste vi!" profile_sidebar: bio: "Biografija" born: "RoÄ‘endan" - edit_my_profile: "Uredi moj profil" gender: "Spol" - in_aspects: "u aspektima" location: "Lokacija" - photos: "Fotografije" - remove_contact: "ukloni kontakt" - remove_from: "Ukloni %{name} sa %{aspect}?" show: closed_account: "Ovaj raÄun je zatvoren." does_not_exist: "Osoba ne postoji!" has_not_shared_with_you_yet: "%{name} nije dijelio/la joÅ¡ ni jednu objavu s vama." - ignoring: "IgnoriÅ¡ete sve objave od %{name}." - incoming_request: "%{name} želiti dijeliti s vama" - mention: "Spominjanje" - message: "Poruka" - not_connected: "Ne dijelite sa ovom osobom." - recent_posts: "SkoraÅ¡nje Objave" - recent_public_posts: "SkoraÅ¡nje Javne Objave" - return_to_aspects: "Vratite se na vaÅ¡u stranicu aspekata" - see_all: "Vidi sve" - start_sharing: "poÄni dijeljenje" - to_accept_or_ignore: "prihvatiti ili ignorisati ga." - sub_header: - add_some: "dodajte neke" - edit: "uredi" - you_have_no_tags: "nemate oznaka!" - webfinger: - fail: "Izvinite, nisamo mogli pronaći %{handle}." - zero: "nema ljudi" photos: - comment_email_subject: "Fotografija od %{name}" create: integrity_error: "Objavljivanje fotografije neuspjeÅ¡no. Jeste li sigurni da je to bila slika?" runtime_error: "Objavljivanje fotografije neuspjeÅ¡no. Jeste sigurni da ste se dobro zavezali pojas?" type_error: "Objavljivanje fotografije neuspjeÅ¡no. Jeste li sigurni da je slika dodana?" destroy: notice: "Fotografija izbrisana." - edit: - editing: "UreÄ‘ivanje" - new: - back_to_list: "Nazad na Listu" - new_photo: "Nova Fotografija" - post_it: "objavi!" new_photo: empty: "{file} je prazno, molimo izaberite datoteke ponovo bez toga." invalid_ext: "{file} ima nevažeću ekstenziju. Samo {extensions} su dozvoljene." size_error: "{file} je preveliko, maksimalna veliÄina datoteke je {sizeLimit}." new_profile_photo: - or_select_one_existing: "ili odaberite jednu od vaÅ¡ih već postojećih %{photos}" upload: "Objavi novu fotografiju profila!" - photo: - view_all: "pogledaj sve fotografije od %{name}" show: - collection_permalink: "kolekcija premanentnih linkova" - delete_photo: "IzbriÅ¡i Fotografiju" - edit: "uredi" - edit_delete_photo: "Uredi opis fotografije / izbriÅ¡i fotografiju" - make_profile_photo: "napravi fotografiju profila" show_original_post: "Pokaži originalnu objavu" - update_photo: "Ažuriraj Fotografiju" - update: - error: "NeuspjeÅ¡no ureÄ‘ivanje fotografije." - notice: "Fotografija uspjeÅ¡no ažurirana." posts: presenter: title: "Objava od %{name}" show: - destroy: "IzbriÅ¡i" - not_found: "Izvinite, nismo mogli pronaći tu objavu." - permalink: "permanentni link" photos_by: few: "%{count} fotografije od %{author}." many: "%{count} fotografija od %{author}." @@ -672,14 +496,11 @@ bs: other: "%{count} fotografija od %{author}." zero: "Nema fotografija od %{author}" reshare_by: "Ponovo dijeli od %{author}" - previous: "prethodno" privacy: "Privatnost" - privacy_policy: "Pravila o Privatnosti" profile: "Profil" profiles: edit: allow_search: "Dozvoljeno ljudima da vas pretražuju unutar Diaspore" - edit_profile: "Uredi profil" first_name: "Ime" last_name: "Prezime" update_profile: "Ažuriraj Profil" @@ -689,8 +510,6 @@ bs: your_location: "VaÅ¡a lokacija" your_name: "VaÅ¡e ime" your_photo: "VaÅ¡a fotografija" - your_private_profile: "VaÅ¡ privatni profil" - your_public_profile: "VaÅ¡ javni profil" your_tags: "OpiÅ¡ite sebe u 5 rijeÄi" your_tags_placeholder: "kao #filmovi #maÄkice #putovanja #uÄitelj #sarajevo" update: @@ -707,63 +526,23 @@ bs: closed: "Prijave su zatvorene na ovom Diaspora podu." create: success: "Pridružili ste se Diaspori!" - edit: - cancel_my_account: "Otkaži moj raÄun" - edit: "Uredi %{name}" - leave_blank: "(ostaviti prazno ako ga ne želite mijenjati)" - password_to_confirm: "(trebamo vaÅ¡u trenutnu Å¡ifru da bi potvrdili vaÅ¡e izmjene)" - unhappy: "Nesretni?" - update: "Ažuriraj" invalid_invite: "Veza pozivnice koji ste obezbijedili viÅ¡e nije važeća!" new: - create_my_account: "Kreiraj moj raÄun!" email: "EMAIL" enter_email: "Unesite email" enter_password: "Unesite Å¡ifru (Å¡est karaktera minimalno)" enter_password_again: "Unesite istu Å¡ifru kao i maloprije" enter_username: "Izaberite korisniÄko ime (samo slova, brojevi i podcrte)" - join_the_movement: "Pridružite se pokretu!" password: "Å IFRA" password_confirmation: "POTVRDA Å IFRE" sign_up: "REGISTRACIJA" - sign_up_message: "DruÅ¡tveno Umrežavanje sa ♥" username: "KORISNIÄŒKO IME" - requests: - create: - sending: "Slanje" - sent: "Tražiti ste da dijelite sa %{name}. Trebali bi vidjeti sljedeći puta kada se prijave na Diasporu." - destroy: - error: "Molimo izaberite jedan aspekt!" - ignore: "Ignorisan zahtjev kontakta." - success: "Trenutno dijelite." - helper: - new_requests: - few: "%{count} nova zahtjeva!" - many: "%{count} novih zahtjeva!" - one: "%{count} novi zahtjev!" - other: "%{count} novih zahtjeva!" - zero: "nema novih zahtjeva" - manage_aspect_contacts: - existing: "Postojeći kontakti" - manage_within: "Upravljaj kontakte unutar" - new_request_to_person: - sent: "poslato!" reshares: comment_email_subject: "%{resharer} ponovno dijeljenje od %{author} objave" - create: - failure: "Dogodila se greÅ¡ka tokom ponovnog dijeljenja ove objave." reshare: deleted: "Originalna objava izbrisana od autora." - reshare: - few: "%{count} ponovna dijeljenja" - many: "%{count} ponovnih dijeljenja" - one: "%{count} ponovno dijeljenje" - other: "%{count} ponovnih dijeljenja" - zero: "Ponovo dijeli" reshare_confirmation: "Ponovo dijeli objavu od %{author}?" - reshare_original: "Ponovo dijeli original" reshared_via: "ponovo dijeljeno putem" - show_original: "Pokaži original" search: "Pretraga" services: create: @@ -775,61 +554,26 @@ bs: success: "UspjeÅ¡no izbrisana autentikacija." failure: error: "dogodila se greÅ¡ka tokom povezivanja servisa" - finder: - fetching_contacts: "Diaspora popunjava vaÅ¡e %{service} prijatelje, molimo provjerite ponovo za nekoliko minuta." - no_friends: "Ni jedan Facebook prijatelj nije pronaÄ‘en." - service_friends: "%{service} Prijatelji" index: disconnect: "iskljuÄi" edit_services: "Uredi servise" logged_in_as: "prijavljeni kao" really_disconnect: "iskljuÄiti %{service}?" services_explanation: "Povezivanje na servise daje vam mogućnost da objavljujete objave na njih kao Å¡to ih piÅ¡ete i na Diaspori." - inviter: - click_link_to_accept_invitation: "Pratite ovu vezu da bi prihvatili svoju pozivnicu" - join_me_on_diaspora: "Pridruži me na DIASPORU*" - remote_friend: - invite: "pozovi" - not_on_diaspora: "JoÅ¡ nije na Diaspori" - resend: "ponovo poÅ¡alji" settings: "Postavke" - share_visibilites: - update: - post_hidden_and_muted: "Objava od %{name} je sakrivena, i obavijesti su utiÅ¡ane." - see_it_on_their_profile: "Ako želite vidjeti ažuriranja na ovu objavu, posjetite stranicu profila od %{name}." shared: - add_contact: - add_new_contact: "Dodaj novi kontakt" - create_request: "Traži po Diaspora ID" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Unesite Diaspora korisniÄko ime:" - know_email: "Poznajete njihove email adrese? Trebali bi ih pozvati" - your_diaspora_username_is: "VaÅ¡e Diaspora korisniÄko ime je: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Dodaj kontakt" toggle: few: "U %{count} aspekta" many: "U %{count} aspekata" one: "U %{count} aspektu" other: "U %{count} aspektima" zero: "Dodaj kontakt" - contact_list: - all_contacts: "Svi kontakti" - footer: - logged_in_as: "prijavljen/a kao %{name}" - your_aspects: "vaÅ¡i aspekti" invitations: by_email: "Emailom" - dont_have_now: "Nemate ni jednu viÅ¡e trenutno, ali viÅ¡e pozivnica dolazi uskoro!" - from_facebook: "Sa Facebooka" - invitations_left: "%{count} ostalo" - invite_someone: "Pozovi nekoga" invite_your_friends: "Pozovi svoje prijatelje" invites: "Pozivi" - invites_closed: "Pozivi su trenutno zatvoreni na ovom Diaspora podu" share_this: "Dijeli ovu vezu putem emaila, bloga, ili omiljene druÅ¡tvene mreže!" - notification: - new: "Novi %{type} od %{from}" public_explain: atom_feed: "Atom feed" control_your_audience: "KontroliÅ¡ite svoju Publiku" @@ -841,59 +585,26 @@ bs: title: "Postavi povezane servise" visibility_dropdown: "Koristite ovu padajuću listu da bi izmjenili vidljivost vaÅ¡ih objava. (PreporuÄujemo da uÄinite ovu prvu objavu javnom.)" publisher: - all: "sve" - all_contacts: "svi kontakti" discard_post: "Odbaci objavu" get_location: "Dobijte lokaciju" - make_public: "uÄini javno" new_user_prefill: hello: "Zdravo svi, ja sam #%{new_user_tag}. " i_like: "Zainteresovan/a sam u %{tags}. " invited_by: "Hvala za poziv, " newhere: "NoviOvdje" - post_a_message_to: "Objavi poruku za %{aspect}" posting: "Objavljujem..." - preview: "Pregled" - publishing_to: "objavljujem za: " share: "Dijeli" - share_with: "podijeli sa" upload_photos: "Objavi fotografije" whats_on_your_mind: "Å ta vam je na umu?" - reshare: - reshare: "Ponovo dijeli" stream_element: - connect_to_comment: "Povežite se na ovog korisnika da bi komentarisali na njegovu objavu" - currently_unavailable: "komentarisanje trenutno nedostupno" - dislike: "Ne sviÄ‘a mi se" - hide_and_mute: "Sakrij i stiÅ¡aj objavu" - ignore_user: "IgnoriÅ¡i %{name}" - ignore_user_description: "Ignorisati i ukloniti korisnika sa svih aspekata?" - like: "SviÄ‘a mi se" - nsfw: "Ova objava je oznaÄena kao NSFW od njegog autora. %{link}" - shared_with: "Dijeljeno sa: %{aspect_names}" - show: "prikaži" - unlike: "Skini sviÄ‘anje" via: "putem %{link}" via_mobile: "putem mobitela" - viewable_to_anyone: "Ova objava je vidljiva svima na internetu" status_messages: create: success: "UspjeÅ¡no spomenuti: %{names}" - destroy: - failure: "NeuspjeÅ¡no brisanje objave" - helper: - no_message_to_display: "Nema poruka za prikaz." new: mentioning: "Spominje %{person}" too_long: "{\"few\"=>\"molimo da vaÅ¡e poruke statusa sadrže manje nego %{count} karaktera\", \"many\"=>\"molimo da vaÅ¡e poruke statusa sadrže manje nego %{count} karaktera\", \"one\"=>\"molimo da vaÅ¡e poruke statusa sadrže manje nego %{count} karakter\", \"other\"=>\"molimo da vaÅ¡e poruke statusa sadrže manje nego %{count} karaktera\", \"zero\"=>\"molimo da vaÅ¡e poruke statusa sadrže manje nego %{count} karaktera\"}" - stream_helper: - hide_comments: "Sakrij sve komentare" - show_comments: - few: "Pokaži %{count} viÅ¡e komentara" - many: "Pokaži %{count} viÅ¡e komentara" - one: "Pokaži %{count} viÅ¡e komentar" - other: "Pokaži %{count} viÅ¡e komentara" - zero: "Nema viÅ¡e komentara" streams: activity: title: "Moja Aktivnost" @@ -919,22 +630,11 @@ bs: title: "Javna Aktivnost" tags: title: "Objave oznaÄene: %{tags}" - tag_followings: - create: - failure: "NeuspjeÅ¡no praćenje #%{name}. Da li to već pratite?" - none: "Ne možete pratiti praznu oznaku!" - success: "Super! Sada pratite #%{name}." - destroy: - failure: "NeuspjeÅ¡no zaustavljanje praćenja #%{name}. Možda ste to već prestali pratiti?" - success: "Napokon! Ne pratite #%{name} viÅ¡e." tags: show: follow: "Prati #%{tag}" - following: "Pratim #%{tag}" none: "Prazna oznaka ne postoji!" stop_following: "Zaustavi Praćenje #%{tag}" - terms_and_conditions: "Uvjeti i Stanja" - undo: "PoniÅ¡ti?" username: "KorisniÄko ime" users: confirm_email: @@ -955,7 +655,6 @@ bs: character_minimum_expl: "mora biti najmanje Å¡est karaktera" close_account: dont_go: "Hej, molimo ne idi te!" - if_you_want_this: "Ako stvarno želite ovo, ukucajte vaÅ¡u svoju Å¡ifru ispod i kliknite \"Zatvori RaÄun\"" lock_username: "Ovo će zakljuÄati vaÅ¡e korisniÄko ime ako se odluÄite prijaviti ponovo poslije." locked_out: "Bit ćete odjavljeni i zakljuÄani od vaÅ¡eg raÄuna." make_diaspora_better: "Želimo da nam pomognete da uÄinimo Diasporu boljom, tako da bi nam trebali pomoći umjesto odlaženja. Ako ipak želite otići, želimo da znate Å¡ta se sljedeće deÅ¡ava." @@ -966,12 +665,10 @@ bs: comment_on_post: "...neko komentariÅ¡e na vaÅ¡u objavu?" current_password: "Trenutna Å¡ifra" current_password_expl: "ona s kojom se prijavljujete..." - download_photos: "preuzmi moje fotografije" edit_account: "Uredi raÄun" email_awaiting_confirmation: "Poslali smo aktivacijsku vezu na %{unconfirmed_email}. Dok ne budete pratili ovu objavu i aktivirali novu adresu, nastavit ćemo koristiti vaÅ¡u originalnu adresu %{email}." export_data: "Izvezi Podatke" following: "Postavke Praćenja" - getting_started: "Nove Postavke Korisnika" liked: "...se nekome sviÄ‘a vaÅ¡a objava?" mentioned: "...vas neko spomene u objavi?" new_password: "Nova Å¡ifra" @@ -991,7 +688,6 @@ bs: connect_to_facebook_link: "povezivanjem vaÅ¡eg Facebook raÄuna" hashtag_explanation: "Oznake vam omogućavaju da priÄate o i pratite vaÅ¡e interese. TakoÄ‘er su dobar naÄin da pronaÄ‘ete nove ljude na Diaspori." hashtag_suggestions: "PokuÅ¡ajte pratiti oznake kao Å¡to su #umjetnost, #filmovi, #gif, itd." - saved: "Snimljeno!" well_hello_there: "Dobro, zdravo!" what_are_you_in_to: "Å ta pratite?" who_are_you: "Ko ste vi?" @@ -1013,13 +709,6 @@ bs: settings_updated: "Postavke ažurirane" unconfirmed_email_changed: "Email izmijenjen. Potrebna aktivacija." unconfirmed_email_not_changed: "Izmjena emaila neuspjeÅ¡na" - webfinger: - fetch_failed: "neuspjeÅ¡no donoÅ¡enje webfinger profila za %{profile_url}" - hcard_fetch_failed: "dogodio se problem donoÅ¡enja hcard za %{account}" - no_person_constructed: "Ni jedna osoba nije uspjeÅ¡no izgraÄ‘ena sa ove hcard." - not_enabled: "webfinger se ne Äini omogućen za host od %{account}" - xrd_fetch_failed: "dogodila se greÅ¡ka dobijanja xrd sa raÄuna %{account}" - welcome: "DobrodoÅ¡li!" will_paginate: next_label: "sljedeće »" previous_label: "« prethodno" \ No newline at end of file diff --git a/config/locales/diaspora/cs.yml b/config/locales/diaspora/cs.yml index 2e50d48838c50451d49f930bbf51ae339cac6423..1447a20cc02cb13fff9da6600d3ea0886417ff57 100644 --- a/config/locales/diaspora/cs.yml +++ b/config/locales/diaspora/cs.yml @@ -6,11 +6,8 @@ cs: _applications: "Aplikace" - _comments: "Komentáře" _contacts: "Kontakty" _help: "NápovÄ›da" - _home: "Domů" - _photos: "Fotky" _services: "Služby" _statistics: "Statistiky" _terms: "pojmy" @@ -53,12 +50,19 @@ cs: taken: "je již obsazeno." admins: admin_bar: + dashboard: "PÅ™ehled" pages: "Stránky" + pod_network: "SÃÅ¥ pod" pod_stats: "Statistiky podu" report: "NahlášenÃ" sidekiq_monitor: "Monitor Sidekiq" user_search: "Hledat uživatele" weekly_user_stats: "Týdennà uživatelské statistiky" + dashboard: + fetching_diaspora_version: "Poslednà diaspora* v erze" + pod_status: "Statistiky podu" + pods: + pod_network: "SÃÅ¥ podu" stats: 2weeks: "DvoutýdennÃ" 50_most: "50 nejoblÃbenÄ›jÅ¡Ãch Å¡tÃtků" @@ -96,6 +100,7 @@ cs: email: "E-mail" guid: "GUID" id: "ID" + invite_token: "Token pozvánky" last_seen: "Naposledy navÅ¡tÃveno" ? "no" : ne @@ -113,7 +118,9 @@ cs: are_you_sure_unlock_account: "UrÄitÄ› chcete odemknout teto úÄet ?" close_account: "zruÅ¡it úÄet" email_to: "E-mailová adresa, kterou chcete pozvat" + lock_account: "Zamknout ÚÄet" under_13: "Zobrazit uživatele mladÅ¡Ã 13 let (COPPA)" + unlock_account: "Odemknout úÄet" users: few: "Nalezeni %{count} uživatelé" one: "Nalezen jeden uživatel" @@ -132,13 +139,23 @@ cs: other: "poÄet nových uživatelů tento týden: %{count}" zero: "žadný nový uživatel tento týden" current_server: "Aktuálnà datum na serveru je %{date}" - ago: "pÅ™ed %{time}" all_aspects: "VÅ¡echny aspekty" - application: - helper: - unknown_person: "Neznámá osoba" - video_title: - unknown: "Neznámý název videa" + api: + openid_connect: + authorizations: + destroy: + fail: "Pokus o odejmutà autorizace s ID %{id} selhalo" + new: + access: "%{name} potÅ™ebný pÅ™Ãstup do" + approve: "Schválit" + bad_request: "ChybÄ›jÃcà ID nebo URI" + deny: "zamÃtnout" + no_requirement: "%{name} Nevyžaduje oprávnÄ›nÃ" + redirection_message: "Opravdu chcete dát pÅ™Ãstup %{redirect_uri}" + user_applications: + index: + edit_applications: "Aplikace" + title: "Povolené aplikace" are_you_sure: "Jste si jisti?" are_you_sure_delete_account: "Opravdu chcete uzavÅ™Ãt svůj úÄet? Tuto operaci nelze vrátit!" aspect_memberships: @@ -154,48 +171,27 @@ cs: success: "Kontakt byl úspěšnÄ› pÅ™idán do aspektu." aspect_listings: add_an_aspect: "+ PÅ™idat aspekt" - deselect_all: "ZruÅ¡it výbÄ›r" - edit_aspect: "Upravit %{name}" - select_all: "Vybrat vÅ¡e" aspect_stream: make_something: "UdÄ›lejte nÄ›co" stay_updated: "Zůstaňte v kontaktu" stay_updated_explanation: "Proud je tvoÅ™en pÅ™ÃspÄ›vky vaÅ¡ich kontaktů, pÅ™ÃspÄ›vků se Å¡tÃtky, které sledujete, a pÅ™ÃspÄ›vků nÄ›kterých aktivnÃch Älenů komunity." - contacts_not_visible: "Kontakty v tomto aspektu se vzájemnÄ› neuvidÃ." - contacts_visible: "Kontakty v tomto aspektu se budou moci vzájemnÄ› vidÄ›t." - create: - failure: "VytvoÅ™enà aspektu selhalo." - success: "Váš nový aspekt %{name} byl vytvoÅ™en" destroy: failure: "%{name} nenà prázdný a nemůže být odstranÄ›n." success: "%{name} byl úspěšnÄ› odebrán." success_auto_follow_back: "%{name} byl úspěšnÄ› odstranÄ›n. Tento aspekt jste použÃval k automatickémy zaÅ™azenà uživatelů, které receiproÄnÄ› sledujete. Zkrontrolujte své uživatelské nastavenà a vyberte pro reciproÄnà sledovánà jiný aspekt." edit: - aspect_chat_is_enabled: "Kontakty v tomto aspektu s Vámi mohou chatovat." - aspect_chat_is_not_enabled: "Kontakty v tomto aspektu s Vámi nemohou chatovat." aspect_list_is_not_visible: "Sothereznam kontaktů je skryt ostatnÃm v aspektu" aspect_list_is_visible: "Seznam kontaktů je viditelný pro ostatnà v aspektu" confirm_remove_aspect: "Opravdu chcete odstranit tento aspekt?" - grant_contacts_chat_privilege: "dát kontaktům v tomto aspektu právo chatovat ?" - make_aspect_list_visible: "Umožnit kontaktům v tomto aspektu se vzájemnÄ› vidÄ›t?" - remove_aspect: "Odstranit tento aspekt" rename: "PÅ™ejmenovat" - set_visibility: "Nastavit viditelnost" update: "Aktualizovat" updating: "Aktualizuji" index: - diaspora_id: - content_1: "VaÅ¡e Diaspora ID je:" - content_2: "Dejte to nÄ›komu a bude vás moci najÃt na DiaspoÅ™e." - heading: "Diaspora ID" donate: "PÅ™ispÄ›jte" - handle_explanation: "Toto je vaÅ¡e Diaspora ID. PodobnÄ› jako e-mailovou adresu ho můžete dát lidem a budete na nÄ›m dostupnÃ." help: any_problem: "NÄ›jaký problém?" contact_podmin: "NapiÅ¡te správci vaÅ¡eho podu!" do_you: "PovÄ›zte:" - email_feedback: "Můžete také %{link} vaÅ¡i zpÄ›tnou vazbu, pokud tomu dáváte pÅ™ednost." - email_link: "E-mail" feature_suggestion: "… vymyslel jste novou %{link}?" find_a_bug: "… naÅ¡li jste %{link}?" have_a_question: "… máte nÄ›jakou %{link}?" @@ -208,31 +204,21 @@ cs: tutorial_link_text: "Tutoriály" tutorials_and_wiki: "%{faq}, %{tutorial} a %{wiki}: Pomoc pÅ™i prvnÃch krocÃch." introduce_yourself: "Tohle je váš proud. NaskoÄte a pÅ™edstavte se." - keep_diaspora_running: "Udržujte vývoj Diaspory rychlý mÄ›sÃÄnÃmi pÅ™ÃspÄ›vky!" keep_pod_running: "Pomozte %{pod} udržet rychlý, pÅ™ispÄ›jte naÅ¡im serverům na jejich mÄ›sÃÄnà dávku kávy!" new_here: follow: "Sleduj %{link} a pÅ™ivÃtej nové uživatele na diaspoÅ™e*!" learn_more: "Zjistit vÃce" title: "PÅ™ivÃtejte nové uživatele" - no_contacts: "Žádné kontakty" - no_tags: "+ NajÃt Å¡tÃtek k odbÄ›ru" - people_sharing_with_you: "Lidé, kteřà s vámi sdÃlÃ" - post_a_message: "Odeslat pÅ™ÃspÄ›vek »" services: content: "Můžete pÅ™ipojit následujÃcà služby na Diasporu:" heading: "PÅ™ipojit služby" - unfollow_tag: "PÅ™estat odebÃrat #%{tag}" welcome_to_diaspora: "VÃtejte na DiaspoÅ™e, %{name}!" - new: - create: "VytvoÅ™it" - name: "Název" no_contacts_message: community_spotlight: "Ve stÅ™edu pozornosti komunity" + invite_link_text: "Pozvánka" or_spotlight: "Můžete jej sdÃlet i pomocà %{link}" try_adding_some_more_contacts: "Nové kontakty můžete vyhledávat (nahoÅ™e) nebo nÄ›koho pozvat (vpravo)." you_should_add_some_more_contacts: "PÅ™idejte si vÃce kontaktů!" - no_posts_message: - start_talking: "Nikdo zatÃm jeÅ¡tÄ› nic nesdÄ›lil!" seed: acquaintances: "ZnámÃ" family: "Rodina" @@ -241,7 +227,6 @@ cs: update: failure: "Váš aspekt %{name} má pÅ™ÃliÅ¡ dlouhý název na to, aby mohl být uložen." success: "Váš aspekt %{name} byl úspěšnÄ› upraven." - back: "ZpÄ›t" blocks: create: failure: "Tohoto uživatele nedokáži ignorovat. #úhyb" @@ -253,22 +238,15 @@ cs: explanation: "PiÅ¡te na Diasporu odkudkoliv pomocà %{link}." heading: "Bookmarklet" post_something: "SdÃlet na DiaspoÅ™e" - post_success: "Odesláno! ZavÃrám!" cancel: "ZruÅ¡it" comments: new_comment: comment: "komentář" commenting: "KomentovánÃ..." - one: "1 komentář" - other: "%{count} komentářů" - zero: "Žádné komentáře" contacts: - create: - failure: "NepodaÅ™ilo se vytvoÅ™it kontakt" index: add_a_new_aspect: "PÅ™idat nový aspekt" add_contact: "PÅ™idej kontakt" - add_to_aspect: "PÅ™idat kontakty do %{name}" all_contacts: "VÅ¡echny kontakty" community_spotlight: "Aktuality z komunity" my_contacts: "Moje kontakty" @@ -276,19 +254,13 @@ cs: no_contacts_in_aspect: "V tomto aspektu jeÅ¡tÄ› nemáte žádné kontakty. Dále najdete seznam VaÅ¡ich existujÃcÃch kontaktů, které můžete do tohoto aspektu pÅ™idat." no_contacts_message: "ShlédnÄ›te %{community_spotlight}" only_sharing_with_me: "Pouze sdÃlejà se mnou" - remove_contact: "Odstraň kontakt" start_a_conversation: "Zahájit konverzaci" title: "Kontakty" user_search: "Hledat uživatele" - your_contacts: "VaÅ¡e kontakty" - sharing: - people_sharing: "Lidé, kteřà s vámi sdÃlÃ:" spotlight: community_spotlight: "Aktuality z komunity" suggest_member: "NavrhnÄ›te Älena" conversations: - conversation: - participants: "ÚÄastnÃci" create: fail: "Neplatná zpráva" no_contact: "Hej, musÃte kontakt nejdÅ™Ãv pÅ™idat!" @@ -296,23 +268,13 @@ cs: destroy: delete_success: "Konverzace byla úspěšnÄ› smazána" hide_success: "Konverzace byla úspěšnÄ› skryta" - helper: - new_messages: - few: "%{count} nové zprávy" - many: "%{count} nových zpráv" - one: "1 nová zpráva" - other: "%{count} nových zpráv" - two: "%{count} nové zprávy" - zero: "Žádné nové zprávy" index: conversations_inbox: "Konverzace - doruÄené" - create_a_new_conversation: "Zahájit novou konverzaci" inbox: "DoruÄená poÅ¡ta" new_conversation: "Nová konverzace" - no_conversation_selected: "nenà výbrána žádná konverzace" no_messages: "Žádné zprávy" new: - abandon_changes: "ZamÃtnout zmÄ›ny?" + message: "Zpráva" send: "Poslat" sending: "PosÃlám..." subject: "PÅ™edmÄ›t" @@ -323,6 +285,7 @@ cs: show: delete: "smazat a blokovat konverzaci" hide: "skrýt a ztlumit konverzaci" + last_message: "Zpráva obdržena%{timeago}" reply: "odpovÄ›Ä" replying: "OdpovÃdám…" date: @@ -335,10 +298,7 @@ cs: error_messages: helper: correct_the_following_errors_and_try_again: "Opravte následujÃcà chyby a zkuste to znovu." - invalid_fields: "Neplatná pole" - login_try_again: "ProsÃm <a href=%{login_link}>pÅ™ihlaÅ¡ se</a> a zkus to znovu." - post_not_public: "PÅ™ÃspÄ›vek, který se snažÃte zobrazit, nenà veÅ™ejný!" - post_not_public_or_not_exist: "PÅ™ÃspÄ›vek, který se snažÃte zobrazit, nenà veÅ™ejný, Äi neexistuje!" + need_javascript: "Tato stránka vyžaduje pro své plné fungovánà JavaScript. Pokud jste Javascript zakázali, povolte jej a obnovte stránku." fill_me_out: "Vyplňte" find_people: "NajÃt lidi nebo #Å¡tÃtky" help: @@ -560,47 +520,30 @@ cs: tutorial: "tutoriál" tutorials: "tutoriály" wiki: "wiki" - hide: "Skrýt" - ignore: "Ignorovat" invitation_codes: - excited: "%{name} tÄ› tu rád(a) vidÃ." not_valid: "Kód této pozvánky již nenà platný." invitations: a_facebook_user: "Uživatel Facebooku" check_token: not_found: "Pozvánka nebyla nalezena" create: - already_contacts: "Jste již propojeni s touto osobou" - already_sent: "Již jste pozvali tuto osobu." empty: "ProsÃme zadejte alespoň jednu emailovou adresu." no_more: "Nemáte žádné dalÅ¡Ã pozvánky." note_already_sent: "Pozvánky už byly odeslány adresám: %{emails}" - own_address: "Nemůžete poslat pozvánku na svou vlastnà adresu." rejected: "NásledujÃcà e-mailové adresy majà problémy: " sent: "Pozvánky byly poslány pro: %{emails}" - edit: - accept_your_invitation: "PÅ™ijmÄ›te pozvánÃ" - your_account_awaits: "Váš úÄet Äeká!" new: - already_invited: "NásledujÃcà lidé nepÅ™ijali vaÅ¡e pozvánÃ:" - aspect: "Aspekt" - check_out_diaspora: "VyzkouÅ¡ejte Diasporu!" codes_left: few: "%{count} pozvánky zbývájà pro tento kód" one: "Jedna pozvánka zbývá pro tento kód" other: "%{count} pozvánek zbývá pro tento kód" zero: "Nezbývá žádná pozvánka pro tento kód" comma_separated_plz: "Můžete zadat vÃce e-mailových adres oddÄ›lených Äárkami." - if_they_accept_info: "pokud pozvánà pÅ™ijme, bude pÅ™idán(a) do aspektu, do kterého byl(a) pozván(a)." invite_someone_to_join: "PozvÄ›te nÄ›koho na Diasporu!" language: "Jazyk" paste_link: "SdÃlejte tento odkaz s vaÅ¡imi přáteli abyste je pozvali do Diaspory*, nebo jim ho pÅ™Ãmo poÅ¡lete emailem." - personal_message: "Osobnà zpráva" - resend: "Znovu odeslat" send_an_invitation: "Odeslat pozvánku" - send_invitation: "Odeslat pozvánku" sending_invitation: "PosÃlám pozvánku..." - to: "Pro" layouts: application: back_to_top: "Nahoru" @@ -610,38 +553,14 @@ cs: statistics_link: "Statistiky podu" toggle: "PÅ™epnout mobilnà / plnou verzi" whats_new: "Co je nového?" - your_aspects: "VaÅ¡e aspekty" header: - admin: "Správce" - blog: "Blog" code: "Kód" - help: "NápovÄ›da" - login: "PÅ™ihlásit" logout: "Odhlásit se" profile: "Profil" - recent_notifications: "NejnovÄ›jÅ¡Ã oznámenÃ" settings: "NastavenÃ" - view_all: "Zobrazit vÅ¡echno" - likes: - likes: - people_dislike_this: - few: "%{count} uživatelům se to nelÃbÃ" - one: "jednomu uživateli se to nelÃbÃ" - other: "%{count} uživatelům se to nelÃbÃ" - zero: "žádná záporná hodnocenÃ" - people_like_this: - few: "%{count} uživatelům se to lÃbÃ" - one: "jednomu uživateli se to lÃbÃ" - other: "%{count} uživatelům se to lÃbÃ" - zero: "žádná kladná hodnocenÃ" - people_like_this_comment: - few: "%{count} uživatelům se to lÃbÃ" - one: "jednomu uživateli se to lÃbÃ" - other: "%{count} uživatelům se to lÃbÃ" - zero: "žádná kladná hodnocenÃ" + toggle_navigation: "Navigace" limited: "Omezený" more: "VÃce" - next: "DalÅ¡Ã" no_results: "Nebyly nalezeny žádné výsledky" notifications: also_commented: @@ -659,12 +578,6 @@ cs: one: "%{actors} komentoval(a) váš %{post_link}." other: "%{actors} komentovali váš %{post_link}." zero: "%{actors} komentovali váš %{post_link}." - helper: - new_notifications: - few: "%{count} nová upozornÄ›nÃ" - one: "Jedno nové upozornÄ›nÃ" - other: "%{count} nových upozornÄ›nÃ" - zero: "Žádná nová upozornÄ›nÃ" index: all_notifications: "VÅ¡echna upozornÄ›nÃ" also_commented: "Také okomentováno" @@ -732,7 +645,6 @@ cs: a_limited_post_comment: "Na soukromém pÅ™ÃspÄ›vku v diaspora* je k pÅ™eÄtenà nový komentář." a_post_you_shared: "pÅ™ÃspÄ›vek." a_private_message: "Máte v diaspora* novou soukromou zprávu." - accept_invite: "PÅ™ijmÄ›te vaÅ¡i pozvánku do Diaspory*!" also_commented: limited_subject: "Na pÅ™ÃspÄ›vku, který jste komentoval, byl pÅ™idán dalÅ¡Ã komentář." click_here: "KliknÄ›te zde" @@ -805,7 +717,6 @@ cs: view_post: "Zobrazit pÅ™ÃspÄ›vek »" mentioned: limited_post: "Byl jste zmÃnÄ›n v neveÅ™ejném pÅ™ÃspÄ›vku." - mentioned: "vás zmÃnil(a) v pÅ™ÃspÄ›vku:" subject: "%{name} vás zmÃnil(a) na DiaspoÅ™e*" private_message: reply_to_or_view: "Zobrazit konverzaci nebo na ni odpovÄ›dÄ›t »" @@ -860,20 +771,9 @@ cs: to_change_your_notification_settings: "upravte si nastavenà oznámenÃ." nsfw: "Citlivý obsah (erotika, násilà a podobnÄ›)" ok: "Budiž" - or: "nebo" - password: "Heslo" - password_confirmation: "Potvrzenà hesla" people: add_contact: invited_by: "Byl(a) jste pozván(a)" - add_contact_small: - add_contact_from_tag: "PÅ™idat kontakt ze Å¡tÃtku" - aspect_list: - edit_membership: "upravit Älena aspektu" - helper: - is_not_sharing: "%{name} s vámi nesdÃlÃ" - is_sharing: "%{name} s vámi sdÃlÃ" - results_for: " výsledky pro %{params}" index: couldnt_find_them: "Nemůžete je najÃt?" looking_for: "Hledáte pÅ™ÃspÄ›vky oznaÄené %{tag_link}?" @@ -883,101 +783,48 @@ cs: search_handle: "VaÅ¡e přátelé nejlépe najdete podle jejich diaspora* ID (uzivatel@pod.cz)." searching: "vyhledávám, prosÃm Äekejte…" send_invite: "Stále nic ? PoÅ¡lete pozvánku !" - one: "1 ÄlovÄ›k" - other: "%{count} lidÃ" person: - add_contact: "PÅ™idat kontakt" - already_connected: "Již pÅ™ipojen" - pending_request: "NevyÅ™Ãzená žádost" thats_you: "To jste vy!" profile_sidebar: bio: "NÄ›co o vás" born: "Datum narozenÃ" - edit_my_profile: "Upravit můj profil" gender: "PohlavÃ" - in_aspects: "v aspektech" location: "Poloha" - photos: "Fotky" - remove_contact: "Odstranit kontakt" - remove_from: "Odstranit %{name} z %{aspect}?" show: closed_account: "Tento úÄet byl uzavÅ™en." does_not_exist: "Osoba neexistuje!" has_not_shared_with_you_yet: "%{name} s vámi zatÃm žádný pÅ™ÃspÄ›vek nesdÃlÃ!" - ignoring: "Ignorujete vÅ¡echny pÅ™ÃspÄ›vky od %{name}." - incoming_request: "%{name} s vámi chce sdÃlet" - mention: "ZmÃnka" - message: "Zpráva" - not_connected: "NesdÃlÃte s touto osobou" - recent_posts: "Poslednà pÅ™ÃspÄ›vky" - recent_public_posts: "Poslednà veÅ™ejné pÅ™ÃspÄ›vky" - return_to_aspects: "Návrat na vaÅ¡i stránku s aspekty" - see_all: "Zobrazit vÅ¡echno" - start_sharing: "zaÄÃt sdÃlet" - to_accept_or_ignore: "pÅ™ijmout nebo ignorovat." - sub_header: - add_some: "pÅ™idat nÄ›jaké" - edit: "Upravit" - you_have_no_tags: "nemáte žádný Å¡tÃtek!" - webfinger: - fail: "Omlouváme se, ale %{handle} nebyl nalezen." - zero: "nikdo" photos: - comment_email_subject: "Fotky uživatele %{name}" create: integrity_error: "Nahránà fotky selhalo. Jste si jisti, že to byl obrázek?" runtime_error: "Nahránà fotky selhalo. Máte zapnutý bezpeÄnostà pás?" type_error: "Nahránà fotky selhalo. Jste si jist, že byl obrázek pÅ™idán?" destroy: notice: "Fotka smazána." - edit: - editing: "Upravit" - new: - back_to_list: "ZpÄ›t na seznam" - new_photo: "Nová fotka" - post_it: "poslat!" new_photo: empty: "{file} je prázdný, prosÃm vyberte soubory znovu bez nÄ›ho." invalid_ext: "{file} má chybnou pÅ™Ãponu. Jsou povoleny pouze {extensions}." size_error: "{file} je pÅ™iliÅ¡ veliký, maximálnà velikost je {sizeLimit}." new_profile_photo: - or_select_one_existing: "nebo vyberte ze svých již existujÃcÃch %{photos}" upload: "Nahrajte novou profilovou fotku!" - photo: - view_all: "zobrazit vÅ¡echny fotky uživatele %{name}" show: - collection_permalink: "trvalý odkaz kolekce" - delete_photo: "Smazat fotku" - edit: "upravit" - edit_delete_photo: "Upravit popis fotky / smazat fotku" - make_profile_photo: "vytvoÅ™it profilovou fotku" show_original_post: "Zobrazit původnà pÅ™ÃspÄ›vek" - update_photo: "Aktualizovat fotku" - update: - error: "NepodaÅ™ilo se upravit fotku." - notice: "Fotka úspěšnÄ› aktualizována." posts: presenter: title: "PÅ™ÃspÄ›vek uživatele %{name}" show: - destroy: "Smazat" forbidden: "Nemáte povolenà k této akci." - not_found: "Tento pÅ™ÃspÄ›vek nelze bohužel najÃt." - permalink: "trvalý odkaz" photos_by: few: "%{count} fotky uživatele %{author}" one: "Jedna fotka uživatele %{author}" other: "%{count} fotek uživatele %{author}" zero: "Žádné fotky uživatele %{author}" reshare_by: "SdÃlel %{author}" - previous: "PÅ™edchozÃ" privacy: "SoukromÃ" - privacy_policy: "Ochrana osobnÃch údajů" profile: "Profil" profiles: edit: allow_search: "Umožnit, aby vás lidé mohli najÃt na DiaspoÅ™e" - edit_profile: "Upravit profil" first_name: "Jméno" last_name: "PÅ™ÃjmenÃ" nsfw_check: "OznaÄit vÅ¡e, co sdÃlÃm, jako citlivý obsah" @@ -990,8 +837,6 @@ cs: your_location: "VaÅ¡e poloha" your_name: "VaÅ¡e jméno" your_photo: "VaÅ¡e fotografie" - your_private_profile: "Váš soukromý profil" - your_public_profile: "Váš veÅ™ejný profil" your_tags: "PopiÅ¡te se pÄ›ti slovy" your_tags_placeholder: "napÅ™. #filmy #koÅ¥ata #cestovánà #uÄitel #praha" update: @@ -1007,26 +852,16 @@ cs: closed: "PÅ™ihlášky nejsou otevÅ™eny na tomto podu Diaspory." create: success: "PÅ™ipojili jste se k DiaspoÅ™e!" - edit: - cancel_my_account: "ZruÅ¡it můj úÄet" - edit: "Upravit %{name}" - leave_blank: "(nechte prázdné, pokud nechcete provést zmÄ›nu)" - password_to_confirm: "(potÅ™ebujeme vaÅ¡e souÄasné heslo pro potvrzenà zmÄ›n)" - unhappy: "NeÅ¡Å¥astný?" - update: "Aktualizovat" invalid_invite: "Odkaz na pozvánku, který jste poskytli, již neplatÃ!" new: - create_my_account: "VytvoÅ™te mi úÄet!" email: "EMAIL" enter_email: "Zadejte e-mail" enter_password: "Zadejte heslo (alespoň 6 znaků)" enter_password_again: "Zadejte stejné heslo jako pÅ™edtÃm" enter_username: "Vyberte si uživatelské jméno (pouze pÃsmena, ÄÃslice a podtržÃtka)" - join_the_movement: "PÅ™ipojte se k nám!" password: "HESLO" password_confirmation: "POTVRZENà HESLA" sign_up: "ZAPSAT SE" - sign_up_message: "Sociálnà sÃÅ¥ se ♥" submitting: "OdesÃlánÃ..." terms: "VytvoÅ™enÃm úÄtu automaticky pÅ™ijÃmáte %{terms_link}." terms_link: "PodmÃnky použitÃ" @@ -1041,45 +876,15 @@ cs: reported_label: "<b>Oznámil/а</b> %{person}" review_link: "OznaÄit jako zkontrolované" status: - created: "Nahlášenà bylo vytvoÅ™eno" destroyed: "PÅ™ÃspÄ›vek byl zniÄen" failed: "Promiňte, nÄ›kde se stala chyba." - marked: "Zpráva byla oznaÄena jako schválená." title: "PÅ™ehled nahlášenÃ" - requests: - create: - sending: "OdesÃlánÃ" - sent: "Byl jste požádán ke sdÃlenà s uživatelem %{name}. MÄ›l(a) by to vidÄ›t po pÅ™ÃÅ¡tÃm pÅ™ihlášenà do Diaspory." - destroy: - error: "ProsÃm vyberte aspekt!" - ignore: "Ignorovat žádost kontaktu." - success: "Nynà jste přáteli." - helper: - new_requests: - few: "%{count} nové žádosti!" - one: "jedna nová žádost!" - other: "%{count} nových žádostÃ!" - zero: "žádné nové žádosti" - manage_aspect_contacts: - existing: "ExistujÃcà kontakty" - manage_within: "Spravovat kontakty uvnitÅ™" - new_request_to_person: - sent: "odesláno!" reshares: comment_email_subject: "%{resharer} sdÃlel pÅ™ÃspÄ›vek uživatele %{author}" - create: - failure: "PÅ™i sdÃlenà tohoto pÅ™ÃspÄ›vku doÅ¡lo k chybÄ›." reshare: deleted: "Původnà pÅ™ÃspÄ›vek byl autorem odstranÄ›n." - reshare: - few: "%{count}× sdÃleno" - one: "Jednou sdÃleno" - other: "%{count}× sdÃleno" - zero: "SdÃlet" reshare_confirmation: "SdÃlet pÅ™ÃspÄ›vek %{author}?" - reshare_original: "SdÃlet originál" reshared_via: "sdÃleno pomocÃ" - show_original: "Zobrazit originál" search: "Hledat" services: create: @@ -1091,10 +896,6 @@ cs: success: "Autorizace úspěšnÄ› odstranÄ›na." failure: error: "nastala chyba pÅ™i pÅ™ipojenà ke službÄ›" - finder: - fetching_contacts: "Diaspora právÄ› vyhledává vaÅ¡e přátele na %{service}, prosÃm vraÅ¥te se za pár minut" - no_friends: "Žádnà přátelé na Facebooku nenalezeni." - service_friends: "Přátelé na %{service}" index: connect: "PÅ™ipojit" disconnect: "odpojit" @@ -1104,33 +905,15 @@ cs: not_logged_in: "MomentálnÄ› nepÅ™ihlášen." really_disconnect: "odpojit %{service}?" services_explanation: "PÅ™ipojovánà se k službám vám dá možnost na nich publikovat své pÅ™ÃspÄ›vky hned co je napÃÅ¡ete na diaspoÅ™e*." - inviter: - click_link_to_accept_invitation: "KliknÄ›te na tento odkaz, pokud chcete pÅ™ijmout pozvánÃ" - join_me_on_diaspora: "PÅ™ipojte se ke mÄ› na DIASPORU*" + share_to: "NasdÃlet %{provider}" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "pozvat" - not_on_diaspora: "JeÅ¡tÄ› nenà na DiaspoÅ™e" - resend: "pÅ™eposlat" settings: "NastavenÃ" - share_visibilites: - update: - post_hidden_and_muted: "PÅ™ÃspÄ›vky uživatele %{name} byly skryty a upozornÄ›nà vypnuta." - see_it_on_their_profile: "Pokud chcete vidÄ›t zmÄ›ny tohoto pÅ™ÃspÄ›vku, navÅ¡tivte profil uživatele %{name}." shared: - add_contact: - add_new_contact: "PÅ™idat nový kontakt" - create_request: "Hledat podle Diaspora ID" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Zadejte uživatelské jméno na DiaspoÅ™e:" - know_email: "Znáte jejich e-mailové adresy? Můžete je pozvat" - your_diaspora_username_is: "VaÅ¡e uživatelské jméno na DiaspoÅ™e: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "PÅ™idat do aspektu" mobile_row_checked: "%{name} (odstranit)" mobile_row_unchecked: "%{name} (pÅ™idat)" toggle: @@ -1138,23 +921,11 @@ cs: one: "V jednom aspektu" other: "V %{count} aspektech" zero: "PÅ™idat kontakt" - contact_list: - all_contacts: "VÅ¡echny kontakty" - footer: - logged_in_as: "pÅ™ihlášen jako %{name}" - your_aspects: "vaÅ¡e aspekty" invitations: by_email: "e-mailem" - dont_have_now: "Již nemáte žádné, ale dalÅ¡Ã brzy pÅ™ibudou!" - from_facebook: "z Facebooku" - invitations_left: "%{count} zbývá" - invite_someone: "PozvÄ›te nÄ›koho" invite_your_friends: "PozvÄ›te vaÅ¡e přátele" invites: "Pozvánky" - invites_closed: "Pozvánky jsou aktuálnÄ› uzavÅ™eny na tomto Diaspora podu" share_this: "SdÃlejte tento odkaz pomocà emailu, blogu, nebo oblÃbené sociálnà sÃtÄ›!" - notification: - new: "Nový %{type} od %{from}" public_explain: atom_feed: "Proud Atom" control_your_audience: "UrÄete své obecenstvo" @@ -1166,12 +937,9 @@ cs: title: "Nastavit souvisejÃcà služby" visibility_dropdown: "Použijte toto menu pro zmÄ›nu viditelnosti svého pÅ™ÃspÄ›vku. (Váš prvnà pÅ™ÃspÄ›vek doporuÄujeme udÄ›lat veÅ™ejný.)" publisher: - all: "vÅ¡echny" - all_contacts: "vÅ¡echny kontakty" discard_post: "Zahodit pÅ™ÃspÄ›vek" formatWithMarkdown: "K formátovánà VaÅ¡eho pÅ™ÃspÄ›vku můžete použÃvat %{markdown_link}" get_location: "ZÃskat polohu" - make_public: "vytvoÅ™it veÅ™ejnou" new_user_prefill: hello: "Ahoj vÅ¡ichni, jsem #%{new_user_tag}." i_like: "Moje zájmy jsou %{tags}. " @@ -1179,36 +947,14 @@ cs: newhere: "NováÄek" poll: add_a_poll: "PÅ™idat anketu" - add_poll_answer: "PÅ™idat možnost" - option: "Prvnà možnost" - question: "Otázka" - remove_poll_answer: "Odebrat možnost" - post_a_message_to: "Poslat pÅ™ÃspÄ›vek do %{aspect}" posting: "OdesÃlám…" - preview: "Náhled" - publishing_to: "publikovánà na:" remove_location: "Odstranit pozici" share: "SdÃlet" - share_with: "sdÃlet s" upload_photos: "Nahrát fotky" whats_on_your_mind: "Co máte na mysli?" - reshare: - reshare: "SdÃlet jinam" stream_element: - connect_to_comment: "Spojte se s tÃmto uživatelem, abyste mohli komentovat jeho pÅ™ÃspÄ›vky." - currently_unavailable: "momentálnÄ› nelze pÅ™idávat komentáře" - dislike: "to se mi nelÃbÃ" - hide_and_mute: "Skrýt pÅ™ÃspÄ›vek" - ignore_user: "Ignorovat %{name}" - ignore_user_description: "Chcete ignorovat tohoto uživatele a odebrat jej ze vÅ¡ech aspektů?" - like: "to se mi lÃbÃ" - nsfw: "Tento pÅ™ÃspÄ›vek byl svým autorem oznaÄen jako citlivý obsah. %{link}" - shared_with: "SdÃleno s: %{aspect_names}" - show: "zobrazit" - unlike: "to se mi už nelÃbÃ" via: "skrz %{link}" via_mobile: "z mobilnÃho telefonu" - viewable_to_anyone: "Tento pÅ™ÃspÄ›vek je viditelný komukoli na webu" simple_captcha: label: "Zadejte kód do rámeÄku" message: @@ -1234,22 +980,12 @@ cs: status_messages: create: success: "ÚspěšnÄ› zmÃnÄ›no: %{names}" - destroy: - failure: "NepodaÅ™ilo se smazat pÅ™ÃspÄ›vek" - helper: - no_message_to_display: "Žádná zpráva k zobrazenÃ." new: mentioning: "ZmÃnka: %{person}" too_long: "{\"few\"=>\"prosÃm zkraÅ¥te svou zprávu na ménÄ› než %{count} znaky\", \"one\"=>\"prosÃm zkraÅ¥te svou zprávu na ménÄ› než %{count} znak\", \"other\"=>\"prosÃm zkraÅ¥te svou zprávu na ménÄ› než %{count} znaků\", \"zero\"=>\"prosÃm zkraÅ¥te svou zprávu na ménÄ› než %{count} znaků\"}" stream_helper: - hide_comments: "Skrýt vÅ¡echny komentáře" no_more_posts: "Dosáhl/a jste konce proudu." no_posts_yet: "ZatÃm zde nejsou žádné pÅ™ÃspÄ›vky." - show_comments: - few: "Zobrazit %{count} dalÅ¡Ãch komentářů" - one: "Zobrazit jeden dalÅ¡Ã komentář" - other: "Zobrazit %{count} dalÅ¡Ãch komentářů" - zero: "Žádné dalÅ¡Ã komentáře" streams: activity: title: "Moje aktivita" @@ -1276,13 +1012,6 @@ cs: tags: title: "PÅ™ÃspÄ›vky oznaÄené: %{tags}" tag_followings: - create: - failure: "NepodaÅ™ilo se odebÃrat #%{name}. NeodebÃráte už náhodou tento Å¡tÃtek?" - none: "Nemůžete odebÃrat prázdný Å¡tÃtek!" - success: "Hurá! ZaÄali jste odebÃrat #%{name}" - destroy: - failure: "NepodaÅ™ilo se ukonÄit odebÃránà #%{name}. Možná jste jej již pÅ™estali odebÃrát?" - success: "Jak chcete! Å tÃtek #%{name} již neodebÃráte." manage: no_tags: "Nesledujete žádné Å¡tÃtky" title: "Správa sledovaných Å¡tÃtků" @@ -1290,7 +1019,6 @@ cs: name_too_long: "UjistÄ›te se, že název tagu má ménÄ› než %{count} znaků. TeÄ jich má %{current_length}." show: follow: "OdebÃrat #%{tag}" - following: "OdebÃráte #%{tag}" none: "Prázdný Å¡tÃtek neexistuje!" stop_following: "PÅ™estat odebÃrat #%{tag}" tagged_people: @@ -1298,8 +1026,6 @@ cs: one: "1 osoba je oznaÄena Å¡tÃtkem %{tag}." other: "%{count} osob je oznaÄeno Å¡tÃtkem %{tag}" zero: "Nikdo nenà oznaÄen Å¡tÃtkem %{tag}" - terms_and_conditions: "PodmÃnky použÃvánÃ" - undo: "Vrátit zpÄ›t?" username: "Uživatelské jméno" users: confirm_email: @@ -1320,7 +1046,6 @@ cs: character_minimum_expl: "musà být alespoň Å¡est znaků dlouhé" close_account: dont_go: "ProsÃme, neodcházejte!" - if_you_want_this: "Pokud toto opravdu chcete, zadejte nÞe své heslo a stisknÄ›te „UzavÅ™Ãt úÄet“" lock_username: "TÃm pádem bude vaÅ¡e uživatelské jméno nedostupné, pokud se rozhodnete se vrátit." locked_out: "Budete odhlášeni a váš úÄet bude uzamÄen." make_diaspora_better: "ChtÄ›li bychom, abyste nám pomohli udÄ›lat Diasporu lepÅ¡Ã, tak nám prosÃm pomozte a neopouÅ¡tÄ›jte nás. Pokud vÅ¡ak opravdu chcete odejÃt, chceme vám sdÄ›lit, co bude následovat." @@ -1333,14 +1058,12 @@ cs: current_password_expl: "to, s kterým se pÅ™ihlaÅ¡ujeÅ¡..." download_export: "Stáhnout můj profil" download_export_photos: "Stáhnout moje fotky" - download_photos: "Stáhnout moje fotky" edit_account: "Upravit úÄet" email_awaiting_confirmation: "Na adresu %{unconfirmed_email} byl zaslán aktivaÄnà odkaz. Dokud tento odkaz neotevÅ™ete a svou novou adresu neaktivujete, budeme vás kontaktovat na vaÅ¡Ã staré adrese %{email}." export_data: "Exportovat data" export_in_progress: "MomentálnÄ› zpracováváme VaÅ¡e data. Dejte nám chvilku." export_photos_in_progress: "MomentálnÄ› zpracováváme VaÅ¡e fotky. Zkuste to prosÃm za chvilku." following: "Nastavenà sledovánÃ" - getting_started: "PÅ™edvolby nového uživatele" last_exported_at: "(Naposledy aktualizováno v %{timestamp})" liked: "…nÄ›komu se zalÃbà váš pÅ™ÃspÄ›vek?" mentioned: "…nÄ›kdo vás zmÃnà v pÅ™ÃspÄ›vku?" @@ -1367,7 +1090,6 @@ cs: connect_to_facebook_link: "napojenÃm vaÅ¡eho úÄtu na Facebooku" hashtag_explanation: "Å tÃtky vám dovolujà odebÃrat to, o co se zajÃmáte, a diskutovat o tom. Je to také skvÄ›lý způsob, jak na DiaspoÅ™e najÃt nové přátele." hashtag_suggestions: "Zkuste odebÃrat tÅ™eba Å¡tÃtky #umÄ›nÃ, #filmy, #gif a podobnÄ›." - saved: "Uloženo!" well_hello_there: "Jé, ahojte!" what_are_you_in_to: "Co vás zajÃmá?" who_are_you: "Kdo jste?" @@ -1391,13 +1113,6 @@ cs: settings_updated: "Nastavenà uloženo" unconfirmed_email_changed: "E-mail zmÄ›nÄ›n. Vyžaduje aktivaci." unconfirmed_email_not_changed: "ZmÄ›na e-mailu selhala" - webfinger: - fetch_failed: "Selhalo naÄtenà webfinger profilu pro %{profile_url}" - hcard_fetch_failed: "NepodaÅ™ilo se zÃskat hcard pro %{@account}" - no_person_constructed: "Z této hcard nemůže být vytvoÅ™ena žádná osoba." - not_enabled: "Vypadá to, že webfinger nemůže být povolen pro hosta úÄtu %{account}" - xrd_fetch_failed: "vyskytl se problém pÅ™i zÃskánà xrd z úÄtu %{account}" - welcome: "VÃtejte!" will_paginate: next_label: "dalšà »" previous_label: "« pÅ™edchozÃ" \ No newline at end of file diff --git a/config/locales/diaspora/cy.yml b/config/locales/diaspora/cy.yml index 8ed324f2d975c740adc342fee001e4cd688a6704..3f2cd3f82e404a764cf7de9c2b0bf2033b38fa10 100644 --- a/config/locales/diaspora/cy.yml +++ b/config/locales/diaspora/cy.yml @@ -6,7 +6,6 @@ cy: _contacts: "Cysylltiadau" - _photos: "Photos" activerecord: errors: models: @@ -25,19 +24,11 @@ cy: success: "Successfully added friend to aspect." aspect_listings: add_an_aspect: "+ Ychwanegu agwedd" - create: - failure: "Creu Agwedd wedi methu." - success: "Click on the plus on the left side to tell Diaspora who can see your new aspect." destroy: success: "%{name} cael ei dynnu yn llwyddiannol." edit: confirm_remove_aspect: "A ydych yn siŵr eich bod am ddileu yr agwedd hon?" - make_aspect_list_visible: "make aspect list visible?" - remove_aspect: "Dileu yr agwedd hwn" index: - diaspora_id: - heading: "ID Diaspora" - handle_explanation: "This is your diaspora handle. Like an email address, you can give this to people to reach you." help: do_you: "Ydych chi:" have_a_question: "... yn cael cwestion %{link}?" @@ -46,18 +37,11 @@ cy: tag_bug: "#bug" tag_feature: "#feature" tag_question: "#question" - no_contacts: "Dim cysylltiadau" - no_tags: "No tags" - new: - name: "Name" no_contacts_message: try_adding_some_more_contacts: "You can search (top) or invite (right) more contacts." you_should_add_some_more_contacts: "Dylech chi ychwanegu mwy o gysylltiadau!" - no_posts_message: - start_talking: "Nobody has said anything yet. Get the conversation started!" update: success: "Eich aspect, %{name}, wedi bod yn golygu yn llwyddiannus." - back: "Yn ôl" blocks: create: success: "Ôlreit, ni fyddwch yn gweld y defnyddiwr yn eich ffrwd yn y dyfodol. #silencio!" @@ -71,68 +55,27 @@ cy: contacts: index: add_a_new_aspect: "Ychwanegwch agwedd newydd" - add_to_aspect: "Add contacts to %{name}" all_contacts: "Cysylltiadau i gÅ·d" my_contacts: "Fy nghysylltiadau" no_contacts: "No contacts." title: "Cysylltiadau" - your_contacts: "Eich Cysylltiadau chi" conversations: create: sent: "Neges wedi anfon" - helper: - new_messages: - few: "%{count} new messages" - many: "%{count} new messages" - one: "1 new messages" - other: "%{count} new messages" - two: "%{count} new messages" - zero: "no new messages" delete: "Dileu" email: "E-bost" find_people: "Dod o hyd i bobl neu # tagiau" invitations: create: sent: "Your invitation has been sent." - new: - already_invited: "Already invited" - aspect: "Agwedd" - to: "I" layouts: application: toggle: "toggle mobile site" - your_aspects: "eich agweddau" header: - login: "login" logout: "Allgofnodi" profile: "profile" settings: "Gosodiadau" - view_all: "Gweld popeth" - likes: - likes: - people_dislike_this: - few: "%{count} people disliked this" - many: "%{count} o bobl ddim yn hoffi hwn" - one: "%{count} dislike" - other: "%{count} people disliked this" - two: "%{count} dislikes" - zero: "no people disliked this" - people_like_this: - few: "%{count} people liked this" - many: "%{count} people liked this" - one: "1 unigolyn yn hoffi hyn" - other: "%{count} pobl yn hoffi hyn" - two: "%{count} likes" - zero: "no people liked this" - people_like_this_comment: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" limited: "Cyfyngedig" - next: "nesaf" notifications: also_commented: few: "Mae %{actors} hefyd wedi sylwi ar %{post_link} %{post_author}." @@ -155,14 +98,6 @@ cy: other: "Mae %{actors} wedi sylwi ar eich %{post_link}." two: "Mae %{actors} wedi sylwi ar eich %{post_link}." zero: "Mae %{actors} wedi sylwi ar eich %{post_link}." - helper: - new_notifications: - few: "%{count} hysbysiadau newydd" - many: "%{count} hysbysiadau newydd" - one: "1 new notification" - other: "%{count} hysbysiadau newydd" - two: "%{count} new notifications" - zero: "no new notifications" index: and: "a" and_others: @@ -252,43 +187,18 @@ cy: sharing: "wedi dechrau rhannu gyda chi!" subject: "Mae %{name} wedi dechrau rhannu gyda chi i mewn Diaspora*" thanks: "Diolch," - or: "neu" - password: "Cyfrinair" - password_confirmation: "Cadarnhad Cyfrinair" people: - one: "1 unigolyn" - other: "%{count} pobl" person: - add_contact: "anadu cysylltiad" - pending_request: "pending request" thats_you: "chi sy hyn!" profile_sidebar: born: "born" - in_aspects: "i mewn agweddau" - remove_contact: "dileu cysylltiad" show: does_not_exist: "Dydy'r unigolyn ddim yn bodoli!" - incoming_request: "You have an incoming request from this person." - message: "Neges" - not_connected: "You are not connected with this person" - return_to_aspects: "Mynd yn ôl i dudalen agweddau" - see_all: "Gweld popeth" - start_sharing: "dechrau rhannu" - sub_header: - edit: "golygu" - zero: "no people" photos: - comment_email_subject: "ffoto %{name}" create: type_error: "Mae ffoto wedi methu llwytho i fyny. A ydych yn sicr delwedd ei ychwanegu?" destroy: notice: "Ffoto wedi dileu." - new: - back_to_list: "Nôl i'r Rhestr" - photo: - view_all: "gweld lluniau %{name} i gÅ·d" - show: - delete_photo: "Dileu'r Llun" posts: show: photos_by: @@ -298,11 +208,9 @@ cy: other: "%{count} photos by %{author}" two: "Two photos by %{author}" zero: "No photos by %{author}" - previous: "blaenorol" profile: "Proffil" profiles: edit: - edit_profile: "Golygu proffil" your_birthday: "Eich penblwydd" your_name: "Eich enw" your_photo: "Eich ffoto" @@ -319,64 +227,24 @@ cy: create: success: "Rydych chi wedi ymuno Diaspora!" new: - create_my_account: "Create my account" enter_email: "Enter an e-mail" - sign_up_message: "Social Networking with a <3" - requests: - create: - sending: "Sending..." - sent: "Rydych chi wedi gofyn i rannu gyda %{name}. Dylen nhw ei weld tro nesaf y byddant yn mewngofnodi i Diaspora." - destroy: - error: "Dewiswch agwedd!" - ignore: "Ignored friend request." - success: "Ffrindiau ydych chi!" - helper: - new_requests: - few: "%{count} new requests!" - many: "%{count} new requests!" - one: "new request!" - other: "%{count} new requests!" - two: "%{count} new requests!" - zero: "no new requests" reshares: - create: - failure: "Roedd camgymeriad yn rhannu y swydd hon." reshare: deleted: "Post gwreiddiol wedi cael ei ddileu gan yr awdur." - reshare: - few: "rhannwyd %{count} waith" - many: "rhannwyd %{count} waith" - one: "Rhannwyd unwaith" - other: "rhannwyd %{count} waith" - two: "rhannwyd %{count} waith" - zero: "Ailrhannu" reshare_confirmation: "Ailrhannu post %{author}?" - reshare_original: "Ailrhannu" reshared_via: "ailrhannwyd gan" - show_original: "Dangos yr wreiddiol" services: create: success: "Dilysu llwyddiannus." destroy: success: "Successfully destroyed authentication." - finder: - no_friends: "Dim ffrindiau Facebook wedi darganfod." - service_friends: "Ffrindiau %{service}" index: disconnect: "datgysylltu" logged_in_as: "mewngofnodi fel" really_disconnect: "datgysylltu %{service}?" - inviter: - click_link_to_accept_invitation: "Click this link to accept your invitation" - join_me_on_diaspora: "Cysylltu gyda fi mewn DIASPORA*" settings: "Gosodiadau" shared: - add_contact: - create_request: "Find by Diaspora handle" - diaspora_handle: "Diaspora handle" - your_diaspora_username_is: "%{diaspora_handle} ydy eich enw Diaspora" aspect_dropdown: - add_to_aspect: "Add to aspect" toggle: few: "Mewn %{count} agweddau" many: "Mewn %{count} agweddau" @@ -384,49 +252,16 @@ cy: other: "Mewn %{count} agweddau" two: "Mewn %{count} agweddau" zero: "Add to aspect" - contact_list: - all_contacts: "Cysylltiadau i gÅ·d" - footer: - your_aspects: "eich agweddau" invitations: by_email: "gan e-bost" - from_facebook: "O Facebook" - invitations_left: "(%{count} left)" - invites_closed: "Invites are currently closed on this Diaspora seed" - notification: - new: "%{type} newydd o %{from}" public_explain: title: "You are about to post a public message!" publisher: - all_contacts: "cysylltiadau i gÅ·d" - make_public: "gwneud yn gyhoeddus" new_user_prefill: i_like: "I'm interested in %{tags}." - post_a_message_to: "Post neges i %{aspect}" - share_with: "Share with %{aspect}" whats_on_your_mind: "Am be' dych chi'n meddwl?" - reshare: - reshare: "Rhannu eto" - stream_element: - connect_to_comment: "Cysylltu i ddefnyddiwr hwn i sylwi ar eu swydd" - dislike: "'Dwi ddim yn hoffi hyn" - hide_and_mute: "Hide and Mute" - like: "Dwi'n hoffi hyn" - unlike: "Dim hoffi" - viewable_to_anyone: "Mae'r post hon yn weladwy i unrhyw un ar y we" status_messages: - helper: - no_message_to_display: "Dim neges i arddangos." too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - hide_comments: "hide comments" - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: aspects: title: "Eich Agweddau" @@ -439,13 +274,6 @@ cy: title: "Your Mentions" multi: title: "Ffrwd" - tag_followings: - create: - failure: "Failed to follow: #%{name}" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" username: "Enw Defnyddiwr" users: confirm_email: @@ -476,7 +304,4 @@ cy: password_not_changed: "Password Change Failed" settings_not_updated: "Mae diweddaru gosodiadau wedi methu " unconfirmed_email_changed: "E-Mail Changed. Needs activation." - unconfirmed_email_not_changed: "E-Mail Change Failed" - webfinger: - hcard_fetch_failed: "there was a problem fetching the hcard for #{@account}" - no_person_constructed: "Ni allai unrhyw berson yn cael ei adeiladu o'r hcard hyn." \ No newline at end of file + unconfirmed_email_not_changed: "E-Mail Change Failed" \ No newline at end of file diff --git a/config/locales/diaspora/da.yml b/config/locales/diaspora/da.yml index 0d75ad1e50e47ef9916a679baa40b43dfbfc7677..229b78e9ed78acdba8845f4f8a6ad9334ecc5d05 100644 --- a/config/locales/diaspora/da.yml +++ b/config/locales/diaspora/da.yml @@ -5,12 +5,9 @@ da: - _applications: "Programmer" - _comments: "Kommentarer" + _applications: "Applikationer" _contacts: "Kontakter" _help: "Hjælp" - _home: "Hjem" - _photos: "Billeder" _services: "Tjenester" _statistics: "Statistik" _terms: "Betingelser" @@ -49,16 +46,23 @@ da: person: invalid: "er ugyldig." username: - invalid: "er ugyldig. Vi tillader kun bogstaver, tal og bundstreger." + invalid: "er ugyldig. Vi tillader kun bogstaver, tal og understreg." taken: "er allerede taget." admins: admin_bar: + dashboard: "Kontrolpanel" pages: "Sider" + pod_network: "Pod netværk" pod_stats: "Statistik for Pod" report: "Rapporter" sidekiq_monitor: "Sidekiq monitor" user_search: "Søg efter brugere" weekly_user_stats: "Ugentlig bruger-statistik" + dashboard: + fetching_diaspora_version: "Bestem seneste Diaspora version ..." + pod_status: "Pod status" + pods: + pod_network: "Pod netværk" stats: 2weeks: "2 uger" 50_most: "50 mest populære tags" @@ -92,6 +96,7 @@ da: email: "E-mail" guid: "GUID" id: "ID" + invite_token: "Invitationskort" last_seen: "Sidst set" ? "no" : Nej @@ -109,7 +114,10 @@ da: are_you_sure_unlock_account: "Er du sikker pÃ¥ at du vil genÃ¥bne denne konto?" close_account: "Luk konto" email_to: "Inviter pÃ¥ e-mail" + invite: "Inviter" + lock_account: "LÃ¥s konto" under_13: "Vis brugere der er under 13 (COPPA)" + unlock_account: "LÃ¥s konto op" users: one: "%{count} bruger fundet" other: "%{count} brugere fundet" @@ -125,13 +133,60 @@ da: other: "Nye brugere i denne uge: %{count}" zero: "Nye brugere i denne uge: ingen" current_server: "Serverens dato er %{date}" - ago: "%{time} siden" all_aspects: "Alle aspekter" - application: - helper: - unknown_person: "Ukendt person" - video_title: - unknown: "Ukendt videotitel" + api: + openid_connect: + authorizations: + destroy: + fail: "Forsøget pÃ¥ at tilbagekalde autoriseringen med ID %{id} lykkedes ikke" + new: + access: "%{name} kræver adgang til:" + approve: "Godkend" + bad_request: "Manglende klient ID eller omdirigeret URI" + client_id_not_found: "Der er ikke fundet nogen klient med client_id %{client_id} og omdirigerings URI %{redirect_uri}" + deny: "Afvis" + no_requirement: "%{name} kræver ingen tilladelser" + redirection_message: "Er du sikker pÃ¥ at du vil give adgang til %{redirect_uri}?" + error_page: + contact_developer: "Du bør kontakte applikationens udvikler og vedlægge følgende fejlmeddelelse:" + could_not_authorize: "Applikationen kan ikke autoriseres" + login_required: "Du skal logge ind for at kunne autorisere denne applikation" + title: "Ups! Noget gik galt :(" + scopes: + name: + description: "Dette giver applikationen adgang til dit navn" + name: "navn" + nickname: + description: "Dette giver applikationen adgang til dit kælenavn" + name: "kælenavn" + openid: + description: "Dette tillader applikationen at læse fra din basis profil" + name: "basis profil" + picture: + description: "Dette giver applikationen adgang til dine billeder" + name: "billede" + profile: + description: "Dette tillader applikationen at læse din udvidede profil" + name: "udvidet profil" + read: + description: "Dette tillader applikationen at læse fra din strøm, dine samtaler og hele din profil" + name: "læs profil, strøm og samtaler" + sub: + description: "Dette giver underprivilegier til applikationen" + name: "under" + write: + description: "Dette tillader applikationen at sende indlæg, skrive meddelelser og sende reaktioner" + name: "send indlæg, samtaler og reaktioner" + user_applications: + index: + access: "%{name} har adgang til:" + edit_applications: "Applikationer" + no_requirement: "%{name} kræver ingen tilladelser" + title: "Autoriserede applikationer" + no_applications: "Du har ingen autoriserede applikationer" + policy: "Se applikationens privatlivspolitik" + revoke_autorization: "Tilbagekald" + tos: "Se applikationens servicevilkÃ¥r" are_you_sure: "Er du sikker?" are_you_sure_delete_account: "Er du helt sikker pÃ¥ at du ønsker at lukke din konto? Det kan ikke fortrydes!" aspect_memberships: @@ -147,48 +202,27 @@ da: success: "Kontakt blev tilføjet aspektet." aspect_listings: add_an_aspect: "+ Tilføj et aspekt" - deselect_all: "Fravælg alle" - edit_aspect: "Redigér %{navn}" - select_all: "Vælg alle" aspect_stream: make_something: "Gør noget" stay_updated: "Hold dig opdateret" stay_updated_explanation: "Din hovedstrøm er befolket med dine kontakter, de tags du følger og indlæg fra kreative medlemmer af diaspora-samfundet. (Dette kan justeres i dine præferencer)" - contacts_not_visible: "Kontakter i dette aspekt vil ikke være i stand til at se hinanden." - contacts_visible: "Kontakter i dette aspekt vil være i stand til at se hinanden." - create: - failure: "Fejl under oprettelse af aspektet." - success: "Klik pÃ¥ plusset i venstre side for at fortælle diaspora, hvem der kan se dit nye aspekt." destroy: failure: "%{name} kunne ikke slettes." - success: "%{name} fjernet." + success: "%{name} er blevet slettet." success_auto_follow_back: "%{name} er blevet fjernet. Du havde sat dette aspekt til automatisk at tilføje brugere der var begyndt at dele med dig. GÃ¥ til dine brugerindstillinger for at vælge et nyt aspekt der automatisk tilføjer brugere der vælger at dele med dig." edit: - aspect_chat_is_enabled: "Kontakter i dette aspekt kan chatte med dig." - aspect_chat_is_not_enabled: "Kontakter i dette aspekt kan ikke chatte med dig." aspect_list_is_not_visible: "kontakter i dette aspekt er ikke i stand til at se hinanden." - aspect_list_is_visible: "kontakter i dette aspekt er synlige for hinanden." - confirm_remove_aspect: "Er du sikker pÃ¥ du vil slette dette aspekt?" - grant_contacts_chat_privilege: "Giv kontakter i dette aspekt chat-privilegier?" - make_aspect_list_visible: "Gør kontakter i dette aspekt synlige for hinanden?" - remove_aspect: "Slet dette aspekt" + aspect_list_is_visible: "Kontakter i dette aspekt er synlige for hinanden." + confirm_remove_aspect: "Er du sikker pÃ¥ at du vil slette dette aspekt?" rename: "Omdøb" - set_visibility: "Indstil synlighed" update: "Opdater" updating: "Opdaterer" index: - diaspora_id: - content_1: "Dit Diaspora-ID er:" - content_2: "Giv det til hvem som helst, og de vil kunne finde dig pÃ¥ Diaspora." - heading: "Diaspora-ID" - donate: "Donér" - handle_explanation: "Dette er dit Diaspora-ID. Som med en e-mail-adresse, kan du give det til folk, sÃ¥ de kan kontakte dig." + donate: "Doner" help: any_problem: "Problemer?" contact_podmin: "Kontakt din pods administrator!" do_you: "Har du:" - email_feedback: "%{link} din tilbagemelding, hvis du foretrækker det" - email_link: "E-mail" feature_suggestion: "... har du et %{link} forslag?" find_a_bug: "... har du fundet en %{link}?" have_a_question: "... har du et %{link}?" @@ -200,68 +234,50 @@ da: tag_question: "spørgsmÃ¥l" tutorial_link_text: "Guider" tutorials_and_wiki: "%{faq}, %{tutorial} og %{wiki}: Hjælp til at komme i gang." - introduce_yourself: "Dette er din strøm. Hop ud i den og introducér dig selv." - keep_diaspora_running: "Hjælp udviklingen af Diaspora med en mÃ¥nedlig donation!" + introduce_yourself: "Dette er din strøm. Hop ud i den og introducer dig selv." keep_pod_running: "Hjælp med at fÃ¥ %{pod} til at køre, og sørg for at administratoren kan fÃ¥ sig en kop kaffe i ny og næ med en mÃ¥nedlig donation." new_here: follow: "Følg %{link} og byd nye brugere velkommen til Diaspora!" learn_more: "Lær mere" title: "Byd nye brugere velkommen" - no_contacts: "Ingen kontakter" - no_tags: "+ Find et tag at følge" - people_sharing_with_you: "Personer der deler med dig" - post_a_message: "SlÃ¥ en besked op >>" services: content: "Du kan tilslutte følgende tjenester til Diaspora:" heading: "Tilslut tjenester" - unfollow_tag: "Hold op med at følge #%{tag}" - welcome_to_diaspora: "Velkommen til Diaspora %{name}!" - new: - create: "Opret" - name: "Navn (kun synligt for dig)" + welcome_to_diaspora: "Velkommen til Diaspora, %{name}!" no_contacts_message: community_spotlight: "Community Spotlight" + invite_link_text: "inviter" or_spotlight: "Eller du kan dele med %{link}" - try_adding_some_more_contacts: "Du kan søge efter eller invitere flere kontakter." - you_should_add_some_more_contacts: "Du kan tilføje nogle flere kontakter!" - no_posts_message: - start_talking: "Ingen har sagt noget endnu. Start samtalen!" + try_adding_some_more_contacts: "Du kan søge efter eller %{invite_link} flere kontakter." + you_should_add_some_more_contacts: "Du bør tilføje nogle flere kontakter!" seed: acquaintances: "Bekendte" family: "Familie" friends: "Venner" work: "Arbejde" update: - failure: "Dit aspekt, %{name}, var for langt til at blive gemt." + failure: "Dit aspekt, %{name}, havde for langt et navn til at blive gemt." success: "Dit aspekt, %{name}, er nu blevet redigeret." - back: "Tilbage" blocks: create: - failure: "Jeg kunne ikke ignorere denne bruger. #evasion" + failure: "Kunne ikke ignorere denne bruger. #evasion" success: "Du kommer ikke til at se denne bruger i din strøm igen. #silencio!" destroy: - failure: "Jeg kunne ikke stoppe med at ignorere denne bruger. #evasion" + failure: "Kunne ikke stoppe med at ignorere denne bruger. #evasion" success: "Lad os se hvad de har at sige! #sayhello" bookmarklet: explanation: "Skriv indlæg pÃ¥ Diaspora fra alle steder ved at bogmærke dette link => %{link}." heading: "Bogmærke" post_something: "Skriv indlæg til Diaspora" - post_success: "SlÃ¥et op! Lukker!" - cancel: "Annullér" + cancel: "Annuller" comments: new_comment: - comment: "Kommentér" + comment: "Kommenter" commenting: "Kommenterer ..." - one: "1 kommentar" - other: "%{count} kommentarer" - zero: "Ingen kommentarer" contacts: - create: - failure: "Kunne ikke oprette kontakten" index: add_a_new_aspect: "Tilføj nyt aspekt" add_contact: "Tilføj kontakt" - add_to_aspect: "Tilføj kontakter til %{name}" all_contacts: "Alle kontakter" community_spotlight: "Community Spotlight" my_contacts: "Mine kontakter" @@ -269,19 +285,14 @@ da: no_contacts_in_aspect: "Du har ikke nogen kontakter i dette aspekt endnu. Herunder er en liste over dine eksisterende kontakter som du kan føje til aspektet." no_contacts_message: "Se %{community_spotlight}" only_sharing_with_me: "Deler kun med mig" - remove_contact: "Fjern kontakt" start_a_conversation: "Start en samtale" title: "Kontakter" user_search: "Søg efter brugere" - your_contacts: "Dine kontakter" - sharing: - people_sharing: "Personer der deler med dig:" spotlight: community_spotlight: "Community Spotlight" + no_members: "Der er endnu ingen medlemmer." suggest_member: "ForeslÃ¥ et medlem" conversations: - conversation: - participants: "Deltagere" create: fail: "Ugyldig besked" no_contact: "Hej, du kan tilføje din første kontaktperson!" @@ -289,25 +300,15 @@ da: destroy: delete_success: "Konversationen er blevet slettet" hide_success: "Konversationen er blevet skjult" - helper: - new_messages: - few: "%{count} nye beskeder" - many: "%{count} nye beskeder" - one: "1 ny besked" - other: "%{count} nye beskeder" - two: "%{count} nye beskeder" - zero: "Ingen nye beskeder" index: conversations_inbox: "Samtaler - Indboks" - create_a_new_conversation: "Start en ny samtale" inbox: "Indbakke" new_conversation: "Nye samtaler" - no_conversation_selected: "Ingen samtale valgt" no_messages: "Ingen beskeder" new: - abandon_changes: "Opgiv ændringer?" + message: "Besked" send: "Send" - sending: "Sender..." + sending: "Sender ..." subject: "Emne" subject_default: "Intet emne" to: "Til" @@ -316,8 +317,9 @@ da: show: delete: "Slet samtalen" hide: "Skjul konversationen og gør den tavs" + last_message: "Sidste besked blev modtaget %{timeago}" reply: "Svar" - replying: "Svarer..." + replying: "Svarer ..." date: formats: birthday: "%d %B" @@ -327,20 +329,17 @@ da: email: "E-mail" error_messages: helper: - correct_the_following_errors_and_try_again: "Ret følgende fejl og prøv igen." - invalid_fields: "Ugyldige felter" - login_try_again: "<a href='%{login_link}'>Log ind</a> og prøv igen." - post_not_public: "Det indlæg du prøver at se er ikke offentligt!" - post_not_public_or_not_exist: "Det indlæg du prøver at se er enten ikke offentligt, eller ogsÃ¥ eksisterer det ikke!" + correct_the_following_errors_and_try_again: "Ret de følgende fejl og prøv igen." + need_javascript: "Denne hjemmeside kræver javascript for at fungere ordentligt. Hvis du har slÃ¥et javascript fra, slÃ¥ det venligst til igen og opdater hjemmesiden." fill_me_out: "Udfyld mig" - find_people: "Find venner eller #tags" + find_people: "Find mennesker eller #tags" help: account_and_data_management: close_account_a: "GÃ¥ til bunden af ​​dine indstillinger og tryk pÃ¥ knappen \"Luk konto\". Du vil blive bedt om at indtaste dit kodeord for at fuldende processen. Husk, hvis du lukker din konto vil du <strong>aldrig</strong> kunne genregistrere dit brugernavn pÃ¥ denne pod." close_account_q: "Hvordan sletter jeg min seed (konto)?" data_other_podmins_a: "SÃ¥ snart du deler med en person fra en anden pod vil de indlæg du deler med dem og en kopi af din profil blive lagret (cached) pÃ¥ deres pod, og være tilgængelige for denne pods database-administrator. NÃ¥r du sletter et indlæg eller profildata, bliver den slettet fra din pod og alle andre pods, hvor den tidligere har været gemt. Dine billeder bliver aldrig gemt pÃ¥ andre pods end den du selv bruger; det er kun links til billederne der bliver overført til andre pods." data_other_podmins_q: "Kan administratorer af andre pods se min information?" - data_visible_to_podmin_a: "Kommunikationen *mellem* pods er altid krypteret (ved hjælp af SSL og Diasporas egen transportkryptering), men lagring af data pÃ¥ pods er ikke krypteret. Hvis de ville, kunne database-administratoren for din pod (normalt den person der kører din pod) fÃ¥ adgang til alle dine profildata og alle dine indlæg (som det er tilfældet for de fleste hjemmesider der lagrer brugerdata). Kører du din egen pod giver det mere privatliv da du sÃ¥ styrer adgangen til databasen selv." + data_visible_to_podmin_a: "Kort sagt: alting. Kommunikationen mellem pods er altid krypteret (ved hjælp af SSL og Diasporas egen transportkryptering), men lagring af data pÃ¥ pods er ikke krypteret. Hvis de ville, kunne database-administratoren for din pod (normalt den person der kører din pod) fÃ¥ adgang til alle dine profildata og alle dine indlæg (som det er tilfældet for de fleste hjemmesider der lagrer brugerdata). Kører du din egen pod giver det mere privatliv da du sÃ¥ styrer adgangen til databasen selv." data_visible_to_podmin_q: "Hvor meget af min information kan min pod-administrator se?" download_data_a: "Ja. I bunden af din kontofane i Indstillinger er der to knapper. Den ene er til at downloade dine data, den andentil at downloade dine billeder." download_data_q: "Kan jeg downloade en kopi af alle de data der er indeholdt i min seed (konto)?" @@ -454,11 +453,11 @@ da: post_location_a: "Tryk pÃ¥ knappenÃ¥ls-ikonet ved siden af kameraet i feltet hvor du skriver dine indlæg. Det vil indsætte din placering fra OpenStreetMap. Du kan redigere din placering - mÃ¥ske ønsker du bare at vise hvilken by du er i og ikke hvilken gade." post_location_q: "Hvordan tilføjer jeg min placering til et indlæg?" post_notification_a: "Du kan finde et klokke ikon ved siden af X'et det øvre højre hjørne af indlægget. Tryk pÃ¥ det for at slÃ¥ notifikationer til og fra for dette indlæg." - post_notification_q: "Hvordan sørger jeg for at fÃ¥ notifikationer, eller at stoppe med at fÃ¥ notifikationer, om en post?" + post_notification_q: "Hvordan sørger jeg for at fÃ¥ notifikationer, eller at stoppe med at fÃ¥ notifikationer, om et indlæg?" post_poll_a: "Tryk pÃ¥ det ikon der ligner en graf for at lave en afstemning. Skriv et spørgsmÃ¥l og mindst to mulige svar. Husk at gøre dit indløg offentligt hvis du vil have at alle skal kunne deltage i din afstemning." post_poll_q: "Hvordan tilføjer jeg en afstemning til et indlæg?" post_report_a: "Tryk pÃ¥ advarselstrekanten i det øvre højre hjørne af indlægget for at anmelde det til din podmin. Skriv grunden til at du anmelder indlægget i dialog-boksen." - post_report_q: "Hvordan anmelder jeg et anstødeligt opslag?" + post_report_q: "Hvordan anmelder jeg et anstødeligt indlæg?" size_of_images_a: "Nej. Billederne skaleres automatisk til at passe til strømmen. Markdown har ikke en kode til angivelse af størrelsen af et billede." size_of_images_q: "Kan jeg tilpasse størrelsen pÃ¥ ​​billeder i indlæg eller kommentarer?" stream_full_of_posts_a1: "Din strøm bestÃ¥r af tre forskellige slags indlæg:" @@ -476,7 +475,7 @@ da: see_comment_q: "NÃ¥r jeg kommenterer eller synes om privat indlæg, hvem kan sÃ¥ se det" title: "Private indlæg" who_sees_post_a: "Kun Diaspora-brugere der er logget ind, og som du har placeret i dette aspekt inden du skrev dit begrænsede indlæg kan se det." - who_sees_post_q: "NÃ¥r jeg sender en besked til et aspekt (dvs. en privat post), hvem kan sÃ¥ se det?" + who_sees_post_q: "NÃ¥r jeg sender en besked til et aspekt (dvs. en privat indlæg), hvem kan sÃ¥ se det?" private_profiles: title: "Private profiler" whats_in_profile_a: "Din private profil indeholder biografi, placering, køn og fødselsdag. Det er de ting i den nederste del af profilredigeringssiden. Disse oplysninger er valgfri - det er op til dig om du vil udfylde dem. Indloggede brugere som du har føjet til dine aspekter er de eneste, der kan se din private profil. NÃ¥r de besøger din profilside kan de ogsÃ¥ se de indlæg du skrevet til de aspekt(er) de er i og dine offentlige indlæg." @@ -493,7 +492,7 @@ da: find_public_post_a: "Dine offentlige indlæg vises i strømmen hos alle der følger dig. Hvis du har inkluderet #tags i dine offentlige indlæg, vil enhver der følger disse tags kunne se dit indlæg i deres strøm. Hvert offentligt indlæg har ogsÃ¥ en specifik webadresse som alle kan se, ogsÃ¥ selvom de er ikke logget ind pÃ¥ Diaspora - dermed kan man linke til offentlige indlæg direkte fra Twitter, blogs osv. Offentlige indlæg kan ogsÃ¥ blive indekseret af søgemaskiner." find_public_post_q: "Hvordan kan folk finde mine offentlige indlæg?" see_comment_reshare_like_a: "Kommentarer, synes om og videredelinger af offentlige indlæg er ogsÃ¥ offentlige. Enhver der er logget pÃ¥ Diaspora og alle andre pÃ¥ internettet kan se hvad du skriver og kommenterer i et offentligt indlæg." - see_comment_reshare_like_q: "NÃ¥r jeg kommenterer, videredeler eller liker en offentlig post, Hvem kan sÃ¥ se det?" + see_comment_reshare_like_q: "NÃ¥r jeg kommenterer, videredeler eller liker et offentlig indlæg, Hvem kan sÃ¥ se det?" title: "Offentlige indlæg" who_sees_post_a: "Alle der bruger internettet vil kunne se dine offentlige indlæg, sÃ¥ vær sikker pÃ¥ at du virkelig ønsker at det skal være offentligt. Det er en fin mÃ¥de at række hÃ¥nden ud mod verden." who_sees_post_q: "NÃ¥r jeg laver et offentligt indlæg hvem kan sÃ¥ se det?" @@ -551,84 +550,77 @@ da: tutorial: "guide" tutorials: "guider" wiki: "wiki" - hide: "Skjul" - ignore: "Ignorer" + home: + default: + be_who_you_want_to_be: "Vær den du vil være" + be_who_you_want_to_be_info: "Mange sociale netværk insisterer pÃ¥, at du bruger din virkelige identitet. Ikke Diaspora. Her kan du vælge hvem du vil være og dele lige sÃ¥ meget, eller sÃ¥ lidt, om dig selv som du har lyst. Det er helt op til dig hvordan du vil interagere med andre folk." + byline: "Det sociale netværk hvor det er dig der har kontrollen" + choose_your_audience: "Vælg dit publikum" + choose_your_audience_info: "Ved hjælp af Diasporas aspekter kan du vælge de mennesker du vil dele med. Du kan privat eller offentlig som du har lyst til. Del et sjovt foto med hele verden, eller en dyb hemmelighed kun med dine nærmeste. Du bestemmer." + headline: "Velkommen til %{pod_name}" + own_your_data: "Vær i besiddelse af dine egne data" + own_your_data_info: "Mange sociale netværk tjener penge pÃ¥ dine data ved at analysere din opførsel og derefter bruge informationen til at sælge reklamer. Diaspora bruger ikke dine data til noget, men stÃ¥r til rÃ¥dighed sÃ¥ du kan kommunikere og dele med andre." + podmin: + admin_panel: "admin panel" + byline: "Du er i gang med at ændre internettet. Lad os komme i gang." + configuration_info: "Ã…ben %{database_path} og %{diaspora_path} i din favorit editor og gennemgÃ¥ dem omhyggeligt. De er udførligt kommenteret." + configure_your_pod: "Konfigurer din pod" + contact_irc: "kontakt os via IRC" + contribute: "Bidrag" + contribute_info: "Gør Diaspora endnu bedre! Hvis du finder en fejl sÃ¥ %{report_bugs}." + create_an_account: "Opret en konto" + create_an_account_info: "%{sign_up_link} til en ny konto." + faq_for_podmins: "FAQ for dem dervedligeholder en pod i vores wiki" + getting_help: "Hvordan fÃ¥r man hjælp" + getting_help_info: "Her er en liste af nogle %{faq} herunder nogle tips, tricks og løsninger pÃ¥ de mest almindelige problemer. Du er ogsÃ¥ velkommen til at %{irc}." + headline: "Velkommen, ven." + make_yourself_an_admin: "Gør dig selv til admin" + make_yourself_an_admin_info: "Du finder instruktioner i %{wiki}. Dette skulle tilføje et \"admin-link\" til din brugermenu i topbjælken nÃ¥r du er logget ind. Det giver dig adgang til ting som bruger-søgninger og stats for din pod. For de mere detaljerede aspekter af din pod, gÃ¥ til %{admin_panel}." + report_bugs: "indberet dem" + update_instructions: "opdater instruktioner i Diasporas wiki" + update_your_pod: "Opdater din pod" + update_your_pod_info: "Du kan finde %{update_instructions}" invitation_codes: - excited: "%{name} er glad for at se dig her." not_valid: "Invitationskoden er udløbet." invitations: a_facebook_user: "En Facebook-bruger" check_token: - not_found: "Invitationstoken ikke fundet" + not_found: "Invitation ikke fundet" create: - already_contacts: "Du er allerede forbundet med denne person" - already_sent: "Du har allerede inviteret denne person." empty: "Indsæt mindst en e-mailadresse." no_more: "Du har ikke flere invitationer." note_already_sent: "Der er allerede blevet sendt en invitation til %{emails}" - own_address: "Du kan ikke sende en invitation til din egen adresse." rejected: "Der var problemer med de følgende e-mail adresser: " sent: "Din invitation er blevet sendt til: %{emails}" - edit: - accept_your_invitation: "Acceptér din invitation" - your_account_awaits: "Din konto venter!" new: - already_invited: "Følgende personer har ikke accepteret din invitation:" - aspect: "Aspekt" - check_out_diaspora: "Check Diaspora ud!" codes_left: one: "En invitation tilbage pÃ¥ denne kode" other: "%{count} invitationer tilbage pÃ¥ denne kode" zero: "Ikke flere invitationer tilbage pÃ¥ denne kode" comma_separated_plz: "Du kan indsætte flere emailadresser ved at adskille dem med komma." - if_they_accept_info: "hvis de accepterer, vil de blive tilføjet til det aspekt du inviterede dem til." invite_someone_to_join: "Inviter en person til Diaspora!" language: "Sprog" paste_link: "Del dette link med sine venner for at invitere dem til Diaspora, eller email dem linket direkte." - personal_message: "Personlig besked" - resend: "Send igen" send_an_invitation: "Send en invitation" - send_invitation: "Send invitation" sending_invitation: "Sender invitation ..." - to: "Til" layouts: application: back_to_top: "Tilbage til toppen" + be_excellent: "Vær gode ved hinanden! ♥" powered_by: "Kører pÃ¥ Diaspora" public_feed: "Offentligt Diaspora-nyhedsfeed for %{name}" source_package: "Download kildekoden" statistics_link: "Pod statistik" toggle: "SlÃ¥ mobil side til/fra" whats_new: "Hvad er nyt?" - your_aspects: "Dine aspekter" header: - admin: "Admin" - blog: "Blog" code: "Kode" - help: "Hjælp" - login: "Log ind" logout: "Log ud" profile: "Profil" - recent_notifications: "Seneste meddelelser" settings: "Indstillinger" - view_all: "Se alle" - likes: - likes: - people_dislike_this: - one: "Én person synes ikke om" - other: "%{count} synes ikke om" - zero: "Ingen synes ikke om" - people_like_this: - one: "%{count} synes godt om dette" - other: "%{count} synes godt om dette" - zero: "Ingen synes godt om dette" - people_like_this_comment: - one: "%{count} synes om det" - other: "%{count} synes om det" - zero: "Ingen synes om det" + toggle_navigation: "SlÃ¥ navigation til/fra" limited: "Begrænset" more: "Mere" - next: "Næste" no_results: "Ingen resultater fundet" notifications: also_commented: @@ -646,14 +638,6 @@ da: one: "%{actors} kommenterede dit indlæg %{post_link}." other: "%{actors} kommenterede dit indlæg %{post_link}." zero: "%{actors} kommenterede dit indlæg %{post_link}." - helper: - new_notifications: - few: "%{count} nye notifikationer" - many: "%{count} ny notifikationer" - one: "1 ny notifikation" - other: "%{count} nye notifikationer" - two: "%{count} nye meddelelser" - zero: "Ingen nye notifikationer" index: all_notifications: "Alle notifikationer" also_commented: "kommenterede ogsÃ¥" @@ -690,9 +674,9 @@ da: two: "%{actors} syntes om dit slettede indlæg." zero: "%{actors} syntes om dit slettede indlæg." mentioned: - one: "%{actors} har nævnt dig i et indlæg %{post_link}." - other: "%{actors} har nævnt dig i et indlæg %{post_link}." - zero: "%{actors} har nævnt dig i et indlæg %{post_link}." + one: "%{actors} har nævnt dig i indlægget %{post_link}." + other: "%{actors} har nævnt dig i indlægget %{post_link}." + zero: "%{actors} har nævnt dig i indlægget %{post_link}." mentioned_deleted: few: "%{actors} har nævnt dig i et slettet indlæg." many: "%{actors} har nævnt dig i et slettet indlæg." @@ -730,9 +714,8 @@ da: a_limited_post_comment: "Der er en ny kommentar til dig i et lukket indlæg i Diaspora." a_post_you_shared: "et indlæg." a_private_message: "Der er en ny privat besked til dig i Diaspora." - accept_invite: "Accepter din Diaspora-invitation!" also_commented: - limited_subject: "Der er en ny kommentar til et opslag du har kommenteret" + limited_subject: "Der er en ny kommentar til et indlæg du har kommenteret" click_here: "Klik her" comment_on_post: limited_subject: "Der er en ny kommentar til et af dine indlæg" @@ -788,12 +771,13 @@ da: message: |- Hej! - Du er blevet inviteret til at deltage pÃ¥ Diaspora! + Du er blevet inviteret af %{diaspora_id} til at deltage pÃ¥ Diaspora! - Tryk pÃ¥ dette link for at starte + Tryk pÃ¥ dette link for at komme i gang: [%{invite_url}][1] + Eller tilføj %{diaspora_id} til dine kontakter hvis du allerede har en konto. Kærlig hilsen @@ -809,11 +793,11 @@ da: limited_post: "%{name} syntes om dit begrænsede indlæg" view_post: "Vis indlæg >" mentioned: - limited_post: "Du blev nævnt i et begrænset opslag." - mentioned: "omtalte dig i et indlæg:" + limited_post: "Du blev nævnt i et begrænset indlæg." subject: "%{name} har omtalt dig pÃ¥ Diaspora" private_message: reply_to_or_view: "Besvar eller se denne samtale >" + subject: "Der er en ny privat meddelelse til dig" remove_old_user: body: |- Hej, @@ -836,6 +820,8 @@ da: %{type} med ID %{id} er blevet markeret som stødende. + Begrundelse: "%{reason}" + [%{url}][1] Vær venlig at se pÃ¥ det sÃ¥ snart som muligt! @@ -863,111 +849,56 @@ da: thanks: "Tak," to_change_your_notification_settings: "for at ændre dine indstillinger for meddelelser" nsfw: "Uegnet til arbejdsvisning (NSFW)" - ok: "Ok." - or: "eller" - password: "Adgangskode" - password_confirmation: "Adgangskode bekræftelse" + ok: "OK" people: add_contact: invited_by: "Du er blevet inviteret af" - add_contact_small: - add_contact_from_tag: "Tilføj kontakt fra tag" - aspect_list: - edit_membership: "Redigér aspektsmedlemsskab" - helper: - is_not_sharing: "%{name} deler ikke med dig." - is_sharing: "%{name} deler med dig" - results_for: " resultat for %{params}" index: couldnt_find_them: "Kunne du ikke finde dem?" looking_for: "Leder du efter indlæg tagget med %{tag_link}?" - no_one_found: "... Og ingen blev fundet." + no_one_found: "... og ingen blev fundet." no_results: "Hey! Du er nødt til at søge efter noget." results_for: "Brugere der matcher %{search_term}" search_handle: "Vær sikker pÃ¥ at finde dine venner - brug deres Diaspora-id (brugernavn@pod.tld)." searching: "Søger, vent venligst..." send_invite: "Stadig ikke noget? Send en invitation!" - one: "1 person" - other: "%{count} personer" person: - add_contact: "Tilføj kontaktperson" - already_connected: "Allerede forbundet" - pending_request: "afventende anmodning" thats_you: "Det er dig!" profile_sidebar: bio: "Biografi" born: "Fødselsdag" - edit_my_profile: "Redigér min profil" gender: "Køn" - in_aspects: "I aspekter" location: "Placering" - photos: "Billeder" - remove_contact: "Fjern kontakt" - remove_from: "Fjern %{name} fra %{aspect}?" show: closed_account: "Denne konto er blevet lukket." does_not_exist: "Personen findes ikke!" has_not_shared_with_you_yet: "%{name} har ikke delt nogen indlæg med dig endnu!" - ignoring: "Du ignorerer alle indlæg fra %{name}." - incoming_request: "%{name} vil gerne dele med dig." - mention: "Nævn" - message: "Besked" - not_connected: "Du er ikke forbundet til denne person." - recent_posts: "Nylige indlæg" - recent_public_posts: "Seneste offentlige indlæg" - return_to_aspects: "Tilbage til aspektsoversigt" - see_all: "Se alle" - start_sharing: "Begynd at dele" - to_accept_or_ignore: "at godkende eller ignorere det." - sub_header: - add_some: "Tilføje nogle" - edit: "Redigér" - you_have_no_tags: "Du har ingen tags!" - webfinger: - fail: "Undskyld, vi kunne ikke finde %{handle}." - zero: "Ingen personer" photos: - comment_email_subject: "%{name}s billede" create: integrity_error: "Billed-upload fejlede. Er du sikker pÃ¥ det var et billede?" runtime_error: "Billed-upload fejlede. Er du sikker pÃ¥ at du har spændt sikkerhedsselen?" type_error: "Billed-upload fejlede. Er du sikker pÃ¥ at et billede var tilføjet?" destroy: notice: "Billede slettet." - edit: - editing: "Redigering" - new: - back_to_list: "GÃ¥ tilbage til liste" - new_photo: "Nyt billede" - post_it: "Del det!" new_photo: empty: "{file} er tom. Vælg venligst filer igen uden {file}." invalid_ext: "{file} har en ugyldig filtype. Kun {udvidelser} er tilladt." size_error: "{File} er for stor. Maksimal filstørrelse er {sizeLimit}." new_profile_photo: - or_select_one_existing: "eller vælg et fra dine eksisterende %{photos}" upload: "Upload et nyt profilbillede!" - photo: - view_all: "Se alle %{name}s billeder" show: - collection_permalink: "Samling permalink" - delete_photo: "Slet billede" - edit: "Redigér" - edit_delete_photo: "Redigér billedbeskrivelse / slet billede" - make_profile_photo: "Gør til profilbillede" show_original_post: "Vis oprindeligt indlæg" - update_photo: "Opdatér billede" - update: - error: "Kunne ikke redigere billede." - notice: "Billedet blev opdateret." + polls: + votes: + one: "%{count} stemme indtil videre" + other: "%{count} stemmer indtil videre" + zero: "Nul stemmer indtil videre" posts: presenter: - title: "Et opslag fra %{name}" + title: "Et indlæg fra %{name}" show: - destroy: "Slet" forbidden: "Denne handling er ikke tilladt." - not_found: "Vi kunne desværre ikke finde dette indlæg." - permalink: "Permalink" + location: "Sendt fra %{location}" photos_by: few: "%{count} billeder af %{author}" many: "%{count} billeder af %{author}" @@ -976,28 +907,31 @@ da: two: "To billeder af %{author}" zero: "Ingen billeder af %{author}" reshare_by: "Videredelt af %{author}" - previous: "Forrige" - privacy: "Privatindstillinger" - privacy_policy: "Privatlivspolitik" + privacy: "Privatliv" profile: "Profil" profiles: edit: allow_search: "Tillad folk at søge pÃ¥ dig i Diaspora" - edit_profile: "Rediger profil" + basic: "Min basis profil" + basic_hint: "Hvert element i din profil er valgfrit. Din basis profil vil altid være offentligt synlig." + extended: "Min udvidede profil" + extended_hint: "Tryk pÃ¥ kontakten for at indstille dine udvidede profildatas synlighed. Offentlig betyder, at alle pÃ¥ internettet kan se det. Begrænset betyder at kun mennesker som du deler med, vil se denne information." + extended_visibility_text: "Synlighed af din udvidede profil:" first_name: "Fornavn" last_name: "Efternavn" + limited: "Begrænset" nsfw_check: "Marker alt det jeg deler som NSFW" nsfw_explanation: "NSFW (not safe for work) er Diasporas selvregulerede fællesstandard for hvilket indhold der ikke vil være passende at se i en arbejdssituation. Hvis du ønsker at vise den slags indhold ofte, sÃ¥ husk at slÃ¥ denne valgmulighed til sÃ¥ det du deler vil være skjult fra folks strøm, med mindre de ønsker at se dem." nsfw_explanation2: "Hvis du vælger ikke at slÃ¥ denne valgmulighed til, husk at tilføje et #nsfw tag hver gang du deler denne slags materiale." + public: "Offentlig" + settings: "Profil indstillinger" update_profile: "Opdater profil" - your_bio: "Din bio" + your_bio: "Din biografi" your_birthday: "Din fødselsdag" your_gender: "Dit køn" your_location: "Din placering" your_name: "Dit navn" your_photo: "Dit foto" - your_private_profile: "Din private profil" - your_public_profile: "Din offentlige profil" your_tags: "Beskriv dig selv i fem ord" your_tags_placeholder: "SÃ¥som #diaspora #danmark #kattekillinger #musik #hacking" update: @@ -1012,26 +946,16 @@ da: closed: "Der er lukket for tilmeldinger pÃ¥ denne Diaspora server." create: success: "Du er nu en del af Diaspora!" - edit: - cancel_my_account: "Annullér min konto" - edit: "Redigér %{name}" - leave_blank: "(Lad det være tomt hvis du ikke ønsker at ændre det)" - password_to_confirm: "(Vi har brug for din nuværende adgangskode for at bekræfte dine ændringer)" - unhappy: "Ulykkelig?" - update: "Opdatér" - invalid_invite: "Det invitations link som du anvendte er ikke længere gyldigt!" + invalid_invite: "Det invitations-link som du anvendte er ikke længere gyldigt!" new: - create_my_account: "Opret min konto!" email: "E-mail" enter_email: "Indtast din e-mailadresse" enter_password: "Indtast en adgangskode (mindst seks tegn)" enter_password_again: "Indtast den samme adgangskode som før" enter_username: "Vælg et brugernavn (kun bogstaver, tal og understreg)" - join_the_movement: "Deltag i bevægelsen!" password: "Adgangskode" password_confirmation: "Bekræftelse af adgangskoden" - sign_up: "Tilmeld dig" - sign_up_message: "Socialt netværk med et <3" + sign_up: "Opret en profil" submitting: "Sender ..." terms: "Ved at oprette en konto accepterer du %{terms_link}." terms_link: "ServicevilkÃ¥r" @@ -1044,48 +968,18 @@ da: post_label: "<b>Indlæg</b>: %{title}" reason_label: "Begrundelse: %{text}" reported_label: "<b>Indrapporteret af</b> %{person}" + reported_user_details: "Detaljer om den indberettede bruger" review_link: "Marker som bedømt" status: - created: "Der er blevet lavet en rapport" destroyed: "Indlægget er blevet ødelagt" failed: "Noget gik galt" - marked: "Rapporten er blevet markeret som bedømt" title: "Rapport oversigt" - requests: - create: - sending: "Sender" - sent: "Du har bedt om at dele med %{name}. De vil se det næste gang de logger ind pÃ¥ Diaspora." - destroy: - error: "Vælg venligst et aspekt!" - ignore: "Ignorér kontaktanmodning." - success: "I deler nu." - helper: - new_requests: - one: "Ny anmodning!" - other: "%{count} nye anmodninger!" - zero: "Ingen nye anmodninger" - manage_aspect_contacts: - existing: "Eksisterende kontaktpersoner" - manage_within: "Administrér kontaktpersoner indenfor" - new_request_to_person: - sent: "Afsendt!" reshares: comment_email_subject: "%{resharer}s deling af %{author}s indlæg" - create: - failure: "Der opstod en fejl ved at dele dette indlæg." reshare: deleted: "Oprindeligt indlæg slettet af forfatter." - reshare: - few: "%{count} delinger" - many: "%{count} delinger" - one: "Én deling" - other: "%{count} delinger" - two: "%{count} delinger" - zero: "Del" reshare_confirmation: "Del %{author}s indlæg?" - reshare_original: "Del original" reshared_via: "Delt via" - show_original: "Vis original" search: "Søg" services: create: @@ -1097,89 +991,49 @@ da: success: "Godkendelsen er nu blevet slettet." failure: error: "Forbindelsen til denne service fejlede" - finder: - fetching_contacts: "Diaspora indsamler dine %{service}-venner. Vent venligst et øjeblik." - no_friends: "Ingen Facebook-venner fundet." - service_friends: "%{service} venner" index: connect: "Tilslut" disconnect: "Afbryd" - edit_services: "Redigér tjenester" + edit_services: "Rediger tjenester" logged_in_as: "Logget ind som %{nickname}." no_services_available: "Denne pod tilbyder for tiden ikke tilmelding." not_logged_in: "I øjeblikket ikke logget ind." really_disconnect: "Afbryd %{service}?" services_explanation: "Tilslutning til andre tjenester giver dig mulighed for at sende dine indlæg til dem, samtidig med at du skriver dem i Diaspora." - inviter: - click_link_to_accept_invitation: "Klik pÃ¥ dette link for at acceptere din invitation" - join_me_on_diaspora: "Deltag sammen med mig pÃ¥ Diaspora" + share_to: "Del til %{provider}" + title: "Administrer tilsluttede tjenester" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "Inviter" - not_on_diaspora: "Er endnu ikke pÃ¥ Diaspora" - resend: "Send igen" settings: "Indstillinger" - share_visibilites: - update: - post_hidden_and_muted: "%{name}s indlæg er nu skjult, og meddelelser er blevet gjort tavse." - see_it_on_their_profile: "Hvis du ønsker at se opdateringer til dette indlæg, besøg %{name}s profilside." shared: - add_contact: - add_new_contact: "Tilføj en ny kontakt" - create_request: "Find med Diaspora-ID" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Indsæt et Diaspora-brugernavn:" - know_email: "Kender du deres e-mail adresse? Du burde invitere dem" - your_diaspora_username_is: "Dit Diaspora-brugernavn er: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Tilføj kontakt" mobile_row_checked: "%{name} (fjern)" mobile_row_unchecked: "%{name} (tilføj)" toggle: - few: "I %{count} aspekter" - many: "I %{count} aspekter" one: "I %{count} aspekt" other: "I %{count} aspekter" - two: "I %{count} aspekter" - zero: "Tilføj kontakt" - contact_list: - all_contacts: "Alle kontaktpersoner" - footer: - logged_in_as: "logget ind som %{name}" - your_aspects: "Dine aspekter" invitations: by_email: "via e-mail" - dont_have_now: "Du har ikke nogen lige nu, men der kommer snart flere invitationer!" - from_facebook: "Fra Facebook" - invitations_left: "%{count} tilbage" - invite_someone: "Invitér en person" - invite_your_friends: "Invitér dine venner" + invite_your_friends: "Inviter dine venner" invites: "Invitationer" - invites_closed: "Invitationer er i øjeblikket lukkede pÃ¥ denne Diaspora server" share_this: "Del dette link via e-mail, blog eller dit yndlings-sociale netværk!" - notification: - new: "Ny %{type} fra %{from}" public_explain: atom_feed: "Atom feed" - control_your_audience: "Kontrollér dit publikum" + control_your_audience: "Kontroller dit publikum" logged_in: "Logget pÃ¥ %{service}" - manage: "Administrér tilsluttede tjenester" + manage: "Administrer tilsluttede tjenester" new_user_welcome_message: "Brug #tags til at klassificere dine indlæg og til at finde personer der deler dine interesser. Nævn folk ved at kalde dem ved @Navn" outside: "Offentlige meddelelser vil kunne ses af folk uden for Diaspora." share: "Del" title: "Opsæt tilsluttede tjenester" visibility_dropdown: "Brug denne dropdown til at ændre synligheden af ​​dit indlæg. (Vi foreslÃ¥r, at du gør dette første indlæg offentligt.)" publisher: - all: "Alle" - all_contacts: "Alle kontakter" - discard_post: "Kassér indlæg" + discard_post: "Kasser indlæg" formatWithMarkdown: "Du kan bruge %{markdown_link} til at formatere dine indlæg" get_location: "FÃ¥ din placering" - make_public: "Offentliggør" new_user_prefill: hello: "Hej allesammen, jeg er #%{new_user_tag}. " i_like: "Jeg interesserer mig for %{tags}." @@ -1187,36 +1041,14 @@ da: newhere: "newhere" poll: add_a_poll: "Tilføj en afstemning" - add_poll_answer: "Tilføj mulighed" - option: "Mulighed 1" - question: "SpørgsmÃ¥l" - remove_poll_answer: "Fjern mulighed" - post_a_message_to: "Send en besked til %{aspect}" - posting: "Sender..." - preview: "ForhÃ¥ndsvisning" - publishing_to: "Del med: " + posting: "Sender ..." remove_location: "Fjern placering" share: "Del" - share_with: "Del med" upload_photos: "Upload fotos" whats_on_your_mind: "Hvad har du pÃ¥ hjertet?" - reshare: - reshare: "Del igen" stream_element: - connect_to_comment: "Forbind til denne bruger for at kommentere pÃ¥ deres indlæg" - currently_unavailable: "Det er i øjeblikket ikke muligt at kommentere" - dislike: "Synes ikke om" - hide_and_mute: "Skjul indlægget og dets kommentarer" - ignore_user: "Ignorer %{name}" - ignore_user_description: "Ignorer og fjern bruger fra alle aspekter?" - like: "Synes om" - nsfw: "Dette indlæg er markeret af forfatteren som 'uegnet til arbejdsvisning'. %{link}" - shared_with: "Delt med: %{aspect_names}" - show: "Vis" - unlike: "Synes ikke om" via: "Via %{link}" via_mobile: "Via mobil" - viewable_to_anyone: "Dette indlæg er synlig for alle pÃ¥ internettet" simple_captcha: label: "Skriv koden i boksen:" message: @@ -1231,7 +1063,7 @@ da: disabled: "Ikke tilgængelig" enabled: "Tilgængelig" local_comments: "Lokale kommentarer" - local_posts: "Lokale opslag" + local_posts: "Lokale indlæg" name: "Navn" network: "Netværk" open: "Ã…ben" @@ -1242,24 +1074,12 @@ da: status_messages: create: success: "%{names} nævnt med succes" - destroy: - failure: "Kunne ikke slette post." - helper: - no_message_to_display: "Ingen beskeder at vise." new: mentioning: "Nævnt: %{person}" too_long: "Lav venligst en statusopdatering pÃ¥ under %{count} tegn. Lige nu er der %{current_length} tegn." stream_helper: - hide_comments: "Skjul alle kommentarer" no_more_posts: "Du har nÃ¥et bunden af denne strøm." no_posts_yet: "Der er endnu ingen indlæg." - show_comments: - few: "Vis %{count} flere kommentarer" - many: "Vis %{count} flere kommentarer" - one: "Vis én kommentar mere" - other: "Vis %{count} flere kommentarer" - two: "Vis to kommentarer til" - zero: "Ikke flere kommentarer" streams: activity: title: "Min aktivitet" @@ -1286,13 +1106,6 @@ da: tags: title: "Indlæg tagget med: %{tags}" tag_followings: - create: - failure: "Det lykkedes ikke at følge: #%{name}. Følger du allerede tag'et?" - none: "Du kan ikke følge et tomt tag!" - success: "Du følger nu #%{name}." - destroy: - failure: "Fejlede med at holde op med at følge #%{name}. MÃ¥ske har du allerede valgt ikke at følge tag'et?" - success: "Du følger ikke #%{name} længere." manage: no_tags: "Du følger ikke nogen tags." title: "HÃ¥ndter fulgte tags" @@ -1300,15 +1113,12 @@ da: name_too_long: "Lav venligst et tag-navn pÃ¥ under %{count} tegn. Lige nu er det pÃ¥ %{current_length} tegn." show: follow: "Følg #%{tag}" - following: "Følger #%{tag}" none: "Det tomme tag eksisterer ikke!" stop_following: "Hold op med at følge #%{tag}" tagged_people: one: "En person har brugt %{tag} tag" other: "%{count} personer har brugt %{tag} tag" zero: "Ingen har brugt %{tag} tag" - terms_and_conditions: "Regler og vilkÃ¥r" - undo: "Fortryd?" username: "Brugernavn" users: confirm_email: @@ -1323,33 +1133,31 @@ da: auto_follow_aspect: "Aspekt for automatisk tilføjede kontakter:" auto_follow_back: "Følg automatisk brugere der følger dig" change: "Skift" + change_color_theme: "Skift farvetema" change_email: "Skift e-mail" change_language: "Skift sprog" change_password: "Skift adgangskode" character_minimum_expl: "skal være mindst seks tegn" close_account: dont_go: "Hey, gÃ¥ ikke!" - if_you_want_this: "Hvis du virkelig ønsker dette, indtast da din adgangskode og klik pÃ¥ \"Luk konto\"" lock_username: "Dit brugernavn vil blive lÃ¥st. Du vil ikke kunne Ã¥bne en ny konto pÃ¥ denne pod med det samme ID." locked_out: "Du vil blive logget ud og derefter lÃ¥st ude af din konto indtil den er blevet slettet." make_diaspora_better: "Vi vlle ønske du blev og hjalp os med at gøre Diaspora til et bedre sted. Men hvis du virkelig ønsker at forlade os, foregÃ¥r det pÃ¥ denne mÃ¥de:" - mr_wiggles: "Hr. Wiggles bliver ked af det nÃ¥r du forlader os" + mr_wiggles: "Hr. Wiggles bliver ked af det hvis du forlader os" no_turning_back: "Du kan ikke fortryde dette! Hvis du er helt sikker, indtast din adgangskode herunder." what_we_delete: "Vi sletter alle dine indlæg og profildata sÃ¥ hurtigt som overhovedet muligt. Dine kommentarer til andre folks indlæg vil forblive, men vil vise dit Diaspora-ID og ikke dit navn." close_account_text: "Luk konto" comment_on_post: "... nogen har kommenteret dit indlæg." current_password: "Nuværende adgangskode" - current_password_expl: "det du loggede ind med..." + current_password_expl: "det du logger ind med ..." download_export: "Download min profil" download_export_photos: "Hent mine billeder" - download_photos: "Download mine billeder" edit_account: "Rediger konto" email_awaiting_confirmation: "Vi har sendt dig et aktiveringslink til %{unconfirmed_email}. Indtil du følger dette link og aktiverer den nye adresse, vil vi fortsætte med at bruge din oprindelige adresse %{email}." - export_data: "Eksportér data" + export_data: "Eksporter data" export_in_progress: "Vi er ved at behandle dine data. Vend venligst tilbage om et øjeblik." export_photos_in_progress: "Vi behandler dine billeder. Vend tilbage om et øjeblik." following: "Delingsindstillinger" - getting_started: "Ny bruger opsætning" last_exported_at: "(sidst opdateret %{timestamp})" liked: "... nogen synes om dit indlæg." mentioned: "... du er nævnt i et indlæg." @@ -1362,7 +1170,7 @@ da: request_export_update: "Genopfrisk mine profildata" reshared: "... nogen deler dit indlæg." show_community_spotlight: "Vis Community Spotlight i din strøm?" - show_getting_started: "Genaktivér 'Kom godt i gang'" + show_getting_started: "Genaktiver 'Kom godt i gang'" someone_reported: "Der er en der har sendt en rapport" started_sharing: "... nogen er begyndt at dele med dig." stream_preferences: "Opsætning af din Strøm" @@ -1376,19 +1184,20 @@ da: connect_to_facebook_link: "Forbinde din Facebook-konto" hashtag_explanation: "Hashtags giver dig mulighed for at tale om og følge dine interesser. De er ogsÃ¥ en fantastisk mÃ¥de at finde nye folk pÃ¥ Diaspora." hashtag_suggestions: "Prøv med følgende tags som #kunst, #film, #gif, osv." - saved: "Gemt!" well_hello_there: "Hejsa!" what_are_you_in_to: "Hvad er dine interesser?" who_are_you: "Hvem er du?" privacy_settings: ignored_users: "Ignorerede brugere" no_user_ignored_message: "Du ignorerer for tiden ikke andre brugere" - stop_ignoring: "hold op med at ignorere" + stop_ignoring: "Hold op med at ignorere" strip_exif: "Fjern metadata sÃ¥som: sted, fotografens navn og kameramodel fra mine uploadede billeder (anbefalet)" title: "Privatlivs indstillinger" public: does_not_exist: "Brugeren %{username} findes ikke!" update: + color_theme_changed: "Dit farvetema er blevet skiftet." + color_theme_not_changed: "Der opstod en fejl med at skifte farvetema." email_notifications_changed: "E-mail notifikation ændret" follow_settings_changed: "Følgeskabsindstillinger ændret" follow_settings_not_changed: "Ændring af følgeskabsindstillinger mislykkedes." @@ -1400,13 +1209,6 @@ da: settings_updated: "Indstillingerne blev opdateret" unconfirmed_email_changed: "E-mail ændret. Kræver aktivering." unconfirmed_email_not_changed: "E-mail ændring mislykkedes" - webfinger: - fetch_failed: "Kunne ikke hente webfinger profil for %{profile_url}" - hcard_fetch_failed: "Der opstod et problem i forbindelse med hentning af hcard for %{account}" - no_person_constructed: "Ingen person kunne konstrueres fra dette hcard." - not_enabled: "Det ser ikke ud til at webfinger er aktiveret pÃ¥ %{account}s domæne" - xrd_fetch_failed: "Der opstod en fejl i forbindelse med hentning af xrd fra kontoen %{account}" - welcome: "Velkommen!" will_paginate: next_label: "næste »" previous_label: "« forrige" \ No newline at end of file diff --git a/config/locales/diaspora/de.yml b/config/locales/diaspora/de.yml index 833865a4488435a9483423d5c2519be9c81d094b..41ec1a54a3d3dede17cef1476b65ba89171bb572 100644 --- a/config/locales/diaspora/de.yml +++ b/config/locales/diaspora/de.yml @@ -6,11 +6,8 @@ de: _applications: "Anwendungen" - _comments: "Kommentare" _contacts: "Kontakte" _help: "Hilfe" - _home: "Startseite" - _photos: "Fotos" _services: "Dienste" _statistics: "Statistiken" _terms: "Bedingungen" @@ -53,12 +50,19 @@ de: taken: "ist schon vergeben." admins: admin_bar: + dashboard: "Ãœbersicht" pages: "Seiten" + pod_network: "Pod-Netzwerk" pod_stats: "Pod Statistik" report: "Meldungen" sidekiq_monitor: "Sidekiq-Monitor" user_search: "Benutzersuche" weekly_user_stats: "Wöchentliche Benutzerstatistik" + dashboard: + fetching_diaspora_version: "Ermittle neueste diaspora*-Version" + pod_status: "Pod-Status" + pods: + pod_network: "Pod-Netzwerk" stats: 2weeks: "2 Wochen" 50_most: "Die 50 populärsten Tags" @@ -92,6 +96,7 @@ de: email: "E-Mail" guid: "GUID" id: "ID" + invite_token: "Einladungstoken" last_seen: "Zuletzt gesehen" ? "no" : Nein @@ -109,7 +114,10 @@ de: are_you_sure_unlock_account: "Bist du dir sicher, dass du dieses Konto entsperren möchtest?" close_account: "Konto schließen" email_to: "per E-Mail einladen" + invite: "einladen" + lock_account: "Konto sperren" under_13: "Zeige Benutzer, die unter 13 Jahre alt sind (COPPA)" + unlock_account: "Konto entsperren" users: one: "%{count} Benutzer gefunden" other: "%{count} Benutzer gefunden" @@ -125,70 +133,99 @@ de: other: "Anzahl neuer Benutzer diese Woche: %{count}" zero: "Anzahl neuer Benutzer diese Woche: Keiner" current_server: "Das aktuelle Serverdatum ist %{date}" - ago: "Vor %{time}" all_aspects: "Alle Aspekte" - application: - helper: - unknown_person: "Unbekannte Person" - video_title: - unknown: "Unbekannter Videotitel" + api: + openid_connect: + authorizations: + destroy: + fail: "Der Versuch, die Zulassung mit der ID %{id} zu widerrufen, ist fehlgeschlagen" + new: + access: "%{name} benötigt Zugriff auf:" + approve: "Zulassen" + bad_request: "Fehlende Client-ID oder Weiterleitungs-URI" + client_id_not_found: "Kein Client mit client_id %{client_id} und Weiterleitungs-URI %{redirect_uri} gefunden" + deny: "Ablehnen" + no_requirement: "%{name} benötigt keine Berechtigungen" + redirection_message: "Bist du dir sicher, dass du Zugriff von %{redirect_uri} zulassen möchtest?" + error_page: + contact_developer: "Du solltest den Entwickler der Anwendung kontaktieren und die folgende ausführliche Fehlermeldung beifügen:" + could_not_authorize: "Die Anwendung konnte nicht zugelassen werden" + login_required: "Du musst dich erst anmelden, bevor du diese Anwendung zulassen kannst" + title: "Oh! Etwas ist schiefgegangen :(" + scopes: + aud: + description: "Dies gewährt der Anwendung aud-Berechtigungen" + name: "aud" + name: + description: "Dies gewährt der Anwendung Name-Berechtigungen" + name: "Name" + nickname: + description: "Dies gewährt der Anwendung Benutzername-Berechtigungen" + name: "Benutzername" + openid: + description: "Das ermöglicht der Anwendung, dein grundlegendes Profil auszulesen" + name: "grundlegendes Profil" + picture: + description: "Dies gewährt der Anwendung Bild-Berechtigungen" + name: "Bild" + profile: + description: "Dies ermöglicht der Anwendung, Ihr erweitertes Profil auszulesen" + name: "erweitertes Profil" + read: + description: "Das ermöglicht der Anwendung, deinen Stream, deine Konversationen und dein vollständiges Profil auszulesen" + name: "Profil, Stream und Konversationen lesen" + sub: + description: "Dies gewährt der Anwendung sub-Berechtigungen" + name: "sub" + write: + description: "Das ermöglicht der Anwendung, neue Beiträge zu senden, Konversationen zu schreiben und Reaktionen zu senden" + name: "Beiträge, Konversationen und Reaktionen senden" + user_applications: + index: + access: "%{name} hat Zugriff auf:" + edit_applications: "Anwendungen" + no_requirement: "%{name} benötigt keine Berechtigungen" + title: "Zugelassene Anwendungen" + no_applications: "Du hast keine Anwendungen zugelassen" + policy: "Die Datenschutzerklärung der Anwendung ansehen" + revoke_autorization: "Widerrufen" + tos: "Die Nutzungsbedingungen der Anwendung ansehen" are_you_sure: "Bist du dir sicher?" are_you_sure_delete_account: "Möchtest du dein Konto wirklich schließen? Dieser Schritt kann nicht rückgängig gemacht werden!" aspect_memberships: destroy: - failure: "Die Person konnte nicht aus dem Aspekt entfernt werden" + failure: "Die Person konnte nicht aus dem Aspekt entfernt werden." forbidden: "Du bist nicht berechtigt, das zu tun." invalid_statement: "Doppelter Eintrag abgelehnt." - no_membership: "Konnte die ausgewählte Person in diesem Aspekt leider nicht finden" - success: "Die Person wurde erfolgreich aus dem Aspekt entfernt" + no_membership: "Die ausgewählte Person konnte in diesem Aspekt leider nicht gefunden werden." + success: "Die Person wurde aus dem Aspekt entfernt." aspects: add_to_aspect: failure: "Fehler beim Hinzufügen des Kontakts zum Aspekt." success: "Kontakt erfolgreich zum Aspekt hinzugefügt." aspect_listings: add_an_aspect: "+ Aspekt hinzufügen" - deselect_all: "Auswahl aufheben" - edit_aspect: "Bearbeite %{name}" - select_all: "Alle auswählen" aspect_stream: make_something: "Mache etwas" stay_updated: "Bleibe auf dem Laufenden" stay_updated_explanation: "Dein Stream ist gefüllt mit all deinen Kontakten, Tags, denen du folgst, sowie Beiträgen einiger kreativer Mitglieder der Gemeinschaft." - contacts_not_visible: "Kontakte in diesem Aspekt können einander nicht sehen." - contacts_visible: "Kontakte in diesem Aspekt können sich untereinander sehen." - create: - failure: "Fehler beim Erstellen des Aspekts." - success: "Dein neuer Aspekt %{name} wurde erstellt." destroy: failure: "%{name} konnte nicht entfernt werden." success: "%{name} wurde erfolgreich entfernt." success_auto_follow_back: "%{name} wurde erfolgreich entfernt. Du hast diesen Aspekt benutzt um Nutzern automatisch zu folgen. Ãœberprüfe deine Einstellungen um einen neuen Aspekt hierfür festzulegen." edit: - aspect_chat_is_enabled: "Kontakte in diesem Aspekt können mit dir chatten." - aspect_chat_is_not_enabled: "Kontakte in diesem Aspekt können nicht mit dir chatten." aspect_list_is_not_visible: "Kontakte in diesem Aspekt können einander nicht sehen." aspect_list_is_visible: "Kontakte in diesem Aspekt können einander sehen." confirm_remove_aspect: "Bist du dir sicher, dass du diesen Aspekt löschen möchtest?" - grant_contacts_chat_privilege: "Kontakten im Aspekt das Chatrecht gewähren?" - make_aspect_list_visible: "Kontakte aus diesem Aspekt öffentlich machen?" - remove_aspect: "Diesen Aspekt löschen" rename: "Umbenennen" - set_visibility: "Sichtbarkeit festlegen" update: "Ändern" - updating: "Ändere…" + updating: "Wird geändert …" index: - diaspora_id: - content_1: "Deine diaspora* ID ist:" - content_2: "Gib diese an andere weiter und sie werden dich leicht auf diaspora* finden können." - heading: "diaspora* ID" donate: "Spenden" - handle_explanation: "Das ist deine diaspora* ID. Du kannst sie wie eine E-Mail-Adresse weitergeben, damit andere Nutzer mit dir Kontakt aufnehmen können." help: any_problem: "Gibt's ein Problem?" contact_podmin: "Kontaktiere den Administrator deines Pods!" do_you: "Hast du:" - email_feedback: "Dein Feedback für diaspora* per %{link}" - email_link: "Email" feature_suggestion: "… eine Idee für eine %{link}?" find_a_bug: "… ein %{link}?" have_a_question: "… eine %{link}?" @@ -201,31 +238,21 @@ de: tutorial_link_text: "Anleitungen" tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki} helfen dir bei deinen ersten Schritten." introduce_yourself: "Das ist dein Stream. Leg los und stell dich vor." - keep_diaspora_running: "Die Entwicklung von diaspora* geht schneller voran, wenn Du monatlich spendest!" keep_pod_running: "Hilf %{pod} schnell zu arbeiten und kauf unseren Servern ihren monatlichen Schuss Kaffee!" new_here: follow: "Folge %{link} und begrüße neue Benutzer bei diaspora*!" learn_more: "mehr erfahren" title: "Begrüße neue Benutzer" - no_contacts: "Keine Kontakte" - no_tags: "+ Finde einen #Tag zum folgen" - people_sharing_with_you: "Leute, die mit dir teilen" - post_a_message: "Schreibe eine Nachricht >>" services: content: "Du kannst die folgenden Dienste mit diaspora* verbinden:" heading: "Verbinde Dienste" - unfollow_tag: "#%{tag} nicht mehr folgen" welcome_to_diaspora: "Willkommen bei diaspora*, %{name}!" - new: - create: "Erstellen" - name: "Name (nur für dich sichtbar)" no_contacts_message: community_spotlight: "Gemeinschafts-Schaukasten" + invite_link_text: "einladen" or_spotlight: "Du kannst auch mit %{link} teilen" try_adding_some_more_contacts: "Du kannst weitere Kontakte suchen oder welche %{invite_link}." you_should_add_some_more_contacts: "Du solltest ein paar neue Kontakte hinzufügen!" - no_posts_message: - start_talking: "Niemand hat bisher etwas gesagt!" seed: acquaintances: "Bekannte" family: "Familie" @@ -234,54 +261,41 @@ de: update: failure: "%{name} ist ein zu langer Name, um gespeichert zu werden." success: "Aspekt %{name} erfolgreich bearbeitet." - back: "Zurück" blocks: create: failure: "Ich konnte diesen Benutzer nicht ignorieren. #evasion" success: "Alles klar, Du wirst diesen Benutzer nicht mehr in deinem Stream sehen. #silencio!" destroy: - failure: "Ich konnte das Ignorieren dieses Benutzers nicht beenden. #evasion" + failure: "Ich konnte das Ignorieren dieses Benutzers nicht beenden. #evasion" success: "Mal sehen was sie zu sagen haben! #sayhello" bookmarklet: explanation: "Erstelle von überall einen Beitrag in diaspora*, indem du %{link} als Lesezeichen speicherst." heading: "Lesezeichen" post_something: "Erstelle einen Beitrag in diaspora*" - post_success: "Erstellt! Schließen …" cancel: "Abbrechen" comments: new_comment: comment: "Kommentieren" commenting: "Kommentieren …" - one: "Ein Kommentar" - other: "%{count} Kommentare" - zero: "Keine Kommentare" contacts: - create: - failure: "Fehler beim Erstellen des Kontakts" index: add_a_new_aspect: "Einen neuen Aspekt hinzufügen" add_contact: "Kontakt hinzufügen" - add_to_aspect: "Füge Kontakte zu %{name} hinzu" all_contacts: "Alle Kontakte" - community_spotlight: "Gemeinschafts-Fokus" + community_spotlight: "Gemeinschafts-Schaukasten" my_contacts: "Meine Kontakte" no_contacts: "Sieht so aus, als müsstest du einige Kontakte hinzufügen!" no_contacts_in_aspect: "Du hast noch keine Kontakte in diesem Aspekt. Unten ist eine Liste mit deinen bestehenden Kontakten, die du zu diesem Aspekt hinzufügen kannst." no_contacts_message: "Guck’ in den %{community_spotlight}" only_sharing_with_me: "Nur mit dir Teilende" - remove_contact: "Kontakt entfernen" start_a_conversation: "Beginne eine Unterhaltung" title: "Kontakte" user_search: "Nutzersuche" - your_contacts: "Deine Kontakte" - sharing: - people_sharing: "Leute, die mit dir teilen:" spotlight: community_spotlight: "Gemeinschafts-Schaukasten" + no_members: "Es gibt noch keine Mitglieder." suggest_member: "Ein Mitglied vorschlagen" conversations: - conversation: - participants: "Teilnehmer" create: fail: "Ungültige Nachricht" no_contact: "Hoppla, du musst den Kontakt erst hinzufügen!" @@ -289,23 +303,13 @@ de: destroy: delete_success: "Das Gespräch wurde erfolgreich gelöscht." hide_success: "Das Gespräch wurde erfolgreich ausgeblendet." - helper: - new_messages: - few: "%{count} neue Nachrichten" - many: "%{count} neue Nachrichten" - one: "Eine neue Nachricht" - other: "%{count} neue Nachrichten" - two: "%{count} neue Nachrichten" - zero: "Keine neuen Nachrichten" index: conversations_inbox: "Konversationen – Posteingang" - create_a_new_conversation: "beginne eine neue Konversation" inbox: "Eingang" new_conversation: "Neue Konversation" - no_conversation_selected: "Keine Konversation ausgewählt" no_messages: "Keine Nachrichten" new: - abandon_changes: "Änderungen verwerfen?" + message: "Nachricht" send: "Senden" sending: "Senden …" subject: "Betreff" @@ -314,8 +318,9 @@ de: new_conversation: fail: "Ungültige Nachricht" show: - delete: "Dieses Gespräch löschen." + delete: "Gespräch löschen" hide: "Gespräch ausblenden und stumm schalten." + last_message: "Letzte Nachricht empfangen %{timeago}" reply: "Antworten" replying: "Antworten …" date: @@ -328,15 +333,12 @@ de: error_messages: helper: correct_the_following_errors_and_try_again: "Korrigiere die folgenden Fehler und versuche es erneut." - invalid_fields: "Ungültige Felder" - login_try_again: "Bitte <a href='%{login_link}'>melde dich neu an</a> und versuche es erneut." - post_not_public: "Dieser Beitrag ist nicht öffentlich!" - post_not_public_or_not_exist: "Der Beitrag, den du anzusehen versuchst, ist nicht öffentlich oder existiert nicht!" + need_javascript: "Diese Website benötigt Javascript, um richtig zu funktionieren. Falls du Javascript deaktiviert haben solltest, bitte aktiviere es und aktualisiere diese Seite." fill_me_out: "Füll mich aus" find_people: "Leute oder #Tags finden" help: account_and_data_management: - close_account_a: "Gehe an das Ende deiner Kontoeinstellungen und drücke auf die Schaltfläche „Konto schließen“. Um den Vorgang abzuschließen wirst du dann aufgefordert, dein Passwort einzugeben. Denk dran, wenn du dein Konto schließt, kannst du dich <strong>nie wieder</strong> mit dem gleichen Benutzernamen auf dem gleichen Pod registrieren." + close_account_a: "Gehe an das Ende deiner Konto-Einstellungen und drücke auf die Schaltfläche „Konto schließen“. Um den Vorgang abzuschließen, wirst du dann aufgefordert, dein Kennwort einzugeben. Denk dran: Wenn du dein Konto schließt, kannst du dich auf diesem Pod <strong>nie wieder</strong> mit dem gleichen Benutzernamen registrieren." close_account_q: "Wie kann ich mein Konto löschen?" data_other_podmins_a: "Wenn du mit jemandem auf einem anderen Pod teilst, werden alle Beiträge, die du teilst, und eine Kopie deiner Profildaten auf dessen Pod gespeichert (\"gecached\") und sind dem Datenbankadministrator des Pods zugänglich. Wenn du einen Beitrag oder deine Profildaten löschst, geschieht dies auch auf allen anderen Pods, auf denen die Daten bisher gespeichert waren. Deine Bilder werden nur auf deinen eigenen Pod gespeichert; nur Links, die zu ihnen führen, werden anderen Pods übermittelt." data_other_podmins_q: "Können die Administratoren anderer Pods meine Informationen sehen?" @@ -365,7 +367,7 @@ de: rename_aspect_a: "Klick in der Stream-Ansicht in der Seitenleiste auf „Meine Aspekte†und dann auf das Stiftsymbol bei dem Aspekt, den du umbenennen möchtest, oder geh zu deiner „Kontakteâ€-Seite und wähl den entsprechenden Aspekt aus. Klick dann auf das Bearbeitungssymbol neben dem Aspektnamen oben auf der Seite, änder den Namen und klick auf „Ändernâ€." rename_aspect_q: "Wie benenne ich einen Aspekt um?" restrict_posts_i_see_a: "Ja. Klicke dazu in der Seitenleiste erst auf „Meine Aspekte“ und anschließend auf einzelne Aspekte, um diese aus- oder abzuwählen. Anschließend werden nur noch Beiträge von Personen aus den ausgewählten Aspekten im Stream angezeigt werden." - restrict_posts_i_see_q: "Kann ich die Beiträge, die ich sehe, auf bestimmte Aspekte beschränken?" + restrict_posts_i_see_q: "Kann ich angezeigte Beiträge in meinem Stream auf bestimmte Aspekte beschränken?" title: "Aspekte" what_is_an_aspect_a: "Um deine Kontakte in diaspora* in Gruppen einzuteilen, kannst du Aspekte anlegen. Zum Beispiel kannst du einen Aspekt für die Leute aus deiner Arbeit, einen für die Leute aus deiner Familie und einen für deine Freunde verwenden." what_is_an_aspect_q: "Was sind Aspekte?" @@ -475,7 +477,7 @@ de: see_comment_a: "Nur Leute, mit denen der Beitrag geteilt wurde (die Personen welche sich in den ausgewählten Aspekten des Orginalautors befinden), können Kommentare und Klicks auf „Gefällt mir“ sehen. " see_comment_q: "Wer sieht, dass mir ein privater Beitrag gefällt oder dass ich ihn kommentiert habe?" title: "Private Beiträge" - who_sees_post_a: "Nur eingeloggte diaspora*-Nutzer, welche sich in diesem Aspekt befinden, können deinen privaten Beitrag sehen." + who_sees_post_a: "Nur eingeloggte diaspora*-Nutzer, welche du vorher diesem privaten Aspekt zugeordnet hast, können den Beitrag sehen." who_sees_post_q: "Wenn ich einen Beitrag in einen Aspekt schreibe (privat), wer kann ihn sehen?" private_profiles: title: "Private Profile" @@ -551,93 +553,77 @@ de: tutorial: "Anleitung" tutorials: "Anleitungen" wiki: "Wiki" - hide: "Ausblenden" - ignore: "Ignorieren" + home: + default: + be_who_you_want_to_be: "Sei, wer du sein willst" + be_who_you_want_to_be_info: "Viele Netzwerke bestehen darauf, dass du deine wahre Identität verwendest. diaspora* nicht. Hier kannst du entscheiden, wer du sein willst und so viel oder wenig teilen, wie du möchtest. Es liegt ganz an dir, wie du mit anderen Personen interagieren möchtest." + byline: "Die soziale Onlinewelt, in der du deine Daten in der Hand hast." + choose_your_audience: "Wähle dein Publikum" + choose_your_audience_info: "diaspora*s Aspekte ermöglichen dir, nur mit den Menschen zu teilen, mit denen du möchtest. Du kannst so öffentlich oder privat sein, wie du willst. Teile ein witziges Foto mit der ganzen Welt oder ein tiefes Geheimnis nur mit deinen engsten Freunden. Du hast es in der Hand." + headline: "Willkommen auf %{pod_name}" + own_your_data: "Deine Daten, dein Eigentum" + own_your_data_info: "Viele Netzwerke nutzen deine Daten, um Geld zu verdienen, indem Sie deine Interaktionen auswerten und diese Informationen verwenden, um dir Werbung zu zeigen. diaspora* nutzt deine Daten zu keinem anderen Zweck, als es dir zu ermöglichen, dich mit anderen zu verbinden und mit ihnen zu teilen." + podmin: + admin_panel: "Administrationsbereich" + byline: "Du bist drauf und dran, das Internet zu ändern. Lass uns gleich alles einrichten, okay?" + configuration_info: "Öffne %{database_path} und %{diaspora_path} in deinem Lieblingstexteditor und sieh sie gründlich durch, sie sind ausführlich kommentiert." + configure_your_pod: "Richte deinen Pod ein" + contact_irc: "im IRC" + contribute: "Wirke mit" + contribute_info: "Mach diaspora* noch besser! Falls du Fehler findest, bitte %{report_bugs}." + create_an_account: "Erstelle ein Konto" + create_an_account_info: "Jetzt ein %{sign_up_link}." + faq_for_podmins: "häufig gestellte Fragen für Pod-Verwalter in unserem Wiki" + getting_help: "Erhalte Hilfe" + getting_help_info: "Wir haben einige %{faq} aufgelistet, einschließlich einiger zusätzlicher Tipps und Tricks und Lösungen für die häufigsten Probleme. Kontaktiere uns gerne auch %{irc}." + headline: "Willkommen, Freund." + make_yourself_an_admin: "Mach dich zum Admin" + make_yourself_an_admin_info: "Du kannst Anweisungen im %{wiki} finden. Das sollte deinem Benutzermenü in der Kopfleiste einen Link „Admin“ hinzufügen, wenn du angemeldet bist. Er stellt dir Dinge wie Benutzersuche und Statistiken für deinen Pod zur Verfügung. Für ausführliche Angaben über die betriebsbezogenen Aspekte deines Pods, besuche den %{admin_panel}." + report_bugs: "melde sie" + update_instructions: "Aktualisierungsanweisungen im diaspora*-Wiki" + update_your_pod: "Aktualisiere deinen Pod" + update_your_pod_info: "Du kannst %{update_instructions} finden." invitation_codes: - excited: "%{name} freut sich dich hier zu sehen." not_valid: "Dieser Einladungscode ist nicht mehr gültig" invitations: a_facebook_user: "Ein Facebook-Nutzer" check_token: not_found: "Einladungstoken nicht gefunden" create: - already_contacts: "Du bist bereits mit dieser Person verbunden" - already_sent: "Du hast diese Person bereits eingeladen." empty: "Bitte mindestens eine E-Mail-Adresse eingeben." no_more: "Du hast keine Einladungen mehr." note_already_sent: "Es wurde bereits eine Einladung an %{emails} gesendet" - own_address: "Du kannst keine Einladung an deine eigene Adresse senden." rejected: "Mit diesen E-Mail-Adressen gab es Probleme:" sent: "Einladungen wurden an %{emails} verschickt." - edit: - accept_your_invitation: "Deine Einladung akzeptieren" - your_account_awaits: "Dein Konto wartet!" new: - already_invited: "Die folgenden Personen haben deine Einladung nicht angenommen:" - aspect: "Aspekt" - check_out_diaspora: "Erkunde diaspora*!" codes_left: one: "%{count} Einladung auf diesem Code übrig." other: "%{count} Einladungen auf diesem Code übrig." zero: "Keine Einladung mehr auf diesem Code übrig." comma_separated_plz: "Du kannst mehrere Emailadressen, getrennt durch Kommas, eingeben." - if_they_accept_info: "Wenn sie deine Einladung annehmen, werden sie zu dem Aspekt hinzugefügt, in den du sie eingeladen hast." invite_someone_to_join: "Lade jemanden zu diaspora* ein!" language: "Sprache" paste_link: "Teile diesen Link mit deinen Freunden, um sie zu diaspora* einzuladen oder schick ihnen den Link direkt per Email." - personal_message: "Persönliche Nachricht" - resend: "Erneut senden" send_an_invitation: "Eine Einladung senden" - send_invitation: "Einladung senden" sending_invitation: "Sende Einladung..." - to: "An" layouts: application: back_to_top: "Zurück zum Anfang" + be_excellent: "Seid nett zueinander! ♥" powered_by: "Betrieben mit diaspora*" public_feed: "Öffentlicher diaspora* Feed von %{name}" source_package: "Quelltextpaket runterladen" statistics_link: "Pod-Statistiken" toggle: "Mobile Ansicht umschalten" - whats_new: "Was gibt's Neues?" - your_aspects: "Deine Aspekte" + whats_new: "Was gibt’s Neues?" header: - admin: "Administrator" - blog: "Blog" code: "Code" - help: "Hilfe" - login: "Anmelden" logout: "Abmelden" profile: "Profil" - recent_notifications: "Letzte Benachrichtigungen" settings: "Einstellungen" - view_all: "Alle anzeigen" - likes: - likes: - people_dislike_this: - few: "%{count} Personen gefällt das nicht" - many: "%{count} Personen gefällt das nicht" - one: "Einer Person gefällt das nicht" - other: "%{count} Personen gefällt das nicht" - two: "%{count} Personen gefällt das nicht" - zero: "Keinem gefällt das nicht" - people_like_this: - few: "%{count} Personen gefällt das" - many: "%{count} Personen gefällt das" - one: "Einer Person gefällt das" - other: "%{count} Personen gefällt das" - two: "%{count} Personen gefällt das" - zero: "Keinem gefällt das" - people_like_this_comment: - few: "Gefällt %{count}" - many: "Gefällt %{count}" - one: "Gefällt %{count}" - other: "Gefällt %{count}" - two: "Gefällt %{count}" - zero: "Gefällt niemandem" + toggle_navigation: "Navigation umschalten" limited: "Begrenzt" more: "Mehr" - next: "Nächste" no_results: "Keine Ergebnisse gefunden" notifications: also_commented: @@ -655,14 +641,6 @@ de: one: "%{actors} hat deinen Beitrag %{post_link} kommentiert." other: "%{actors} haben deinen Beitrag %{post_link} kommentiert." zero: "Niemand hat deinen Beitrag %{post_link} kommentiert." - helper: - new_notifications: - few: "%{count} neue Benachrichtigungen" - many: "%{count} neue Benachrichtigungen" - one: "Eine neue Benachrichtigung" - other: "%{count} neue Benachrichtigungen" - two: "%{count} neue Benachrichtigungen" - zero: "Keine neuen Benachrichtigungen" index: all_notifications: "Alle Benachrichtigungen" also_commented: "Auch kommentiert" @@ -699,12 +677,9 @@ de: two: "%{actors} gefällt dein gelöschter Beitrag." zero: "Niemandem gefällt dein gelöschter Beitrag." mentioned: - few: "%{actors} haben dich in einem %{post_link} erwähnt." - many: "%{actors} haben dich in einem %{post_link} erwähnt." - one: "%{actors} hat dich in einem %{post_link} erwähnt." - other: "%{actors} haben dich in einem %{post_link} erwähnt." - two: "%{actors} hat dich in einem %{post_link} erwähnt." - zero: "Niemand hat dich in einem %{post_link} erwähnt." + one: "%{actors} hat dich in dem Beitrag %{post_link} erwähnt." + other: "%{actors} haben dich in dem Beitrag %{post_link} erwähnt." + zero: "%{actors} hat dich in dem Beitrag %{post_link} erwähnt." mentioned_deleted: few: "%{actors} haben dich in einem gelöschten Beitrag erwähnt." many: "%{actors} haben dich in einem gelöschten Beitrag erwähnt." @@ -742,7 +717,6 @@ de: a_limited_post_comment: "Auf diaspora* gibt es einen neuen Kommentar zu einem begrenzten Beitrag." a_post_you_shared: "ein Beitrag." a_private_message: "Auf diaspora* gibt eine neue Private Nachricht für dich." - accept_invite: "Bestätige deine diaspora* Einladung!" also_commented: limited_subject: "Es gibt einen neuen Kommentar zu einem Beitrag, den du kommentiert hast." click_here: "Hier klicken" @@ -799,17 +773,22 @@ de: message: |- Hallo! - Du wurdest eingeladen diaspora* beizutreten! + Du wurdest von %{diaspora_id} eingeladen diaspora* beizutreten! Klick auf diesen Link um loszulegen [%{invite_url}][1] + Falls du bereits eine Konto hast, kannst du %{diaspora_id} zu deinen Kontakten hinzufügen. + Alles Liebe, der diaspora* E-Mail Roboter! + PS: Nur für den Fall das du (bisher) nicht weißt was diaspora* ist, [hier][2] gibt es die Antwort. + [1]: %{invite_url} + [2]%{diasporafoundation_url} invited_you: "%{name} hat dich zu diaspora* eingeladen" liked: liked: "%{name} gefällt dein Beitrag" @@ -817,10 +796,10 @@ de: view_post: "Beitrag betrachten >" mentioned: limited_post: "Du wurdest in einem begrenzten Beitrag erwähnt." - mentioned: "hat dich in einem Beitrag erwähnt:" subject: "%{name} hat dich auf diaspora* erwähnt" private_message: reply_to_or_view: "Antworte oder sieh dir diese Unterhaltung an >" + subject: "Es gibt eine neue private Nachricht für dich" remove_old_user: body: |- Hallo, @@ -864,7 +843,7 @@ de: view_post: "Beitrag anzeigen >" single_admin: admin: "Dein diaspora* Administrator" - subject: "Eine Nachricht über dein diaspora* Konto:" + subject: "Eine Nachricht über dein diaspora*-Konto:" started_sharing: sharing: "hat angefangen mit dir zu teilen!" subject: "%{name} hat angefangen auf diaspora* mit dir zu teilen" @@ -873,20 +852,9 @@ de: to_change_your_notification_settings: "um deine Benachrichtigungs-Einstellungen zu ändern" nsfw: "NSFW (unpassend für den Arbeitsplatz)" ok: "OK" - or: "oder" - password: "Kennwort" - password_confirmation: "Kennwort-Bestätigung" people: add_contact: invited_by: "Du wurdest eingeladen von" - add_contact_small: - add_contact_from_tag: "Füge Kontakt über einen Hashtag hinzu" - aspect_list: - edit_membership: "Bearbeite die Aspekt-Zugehörigkeit" - helper: - is_not_sharing: "%{name} teilt nicht mit dir" - is_sharing: "%{name} teilt mit dir" - results_for: "Ergebnisse für %{params}" index: couldnt_find_them: "Du konntest sie nicht finden?" looking_for: "Suchst du mit %{tag_link} getaggte Beiträge?" @@ -896,87 +864,43 @@ de: search_handle: "Nutze die diaspora* ID (nutzername@pod.tld) deiner Freunde, um sie leichter zu finden." searching: "Suche, bitte warten..." send_invite: "Immer noch nichts? Verschicke eine Einladung!" - one: "einer Person" - other: "%{count} Personen" person: - add_contact: "+ Kontakt hinzufügen" - already_connected: "Bereits verbunden" - pending_request: "Ausstehende Anfrage" thats_you: "Das bist du!" profile_sidebar: bio: "Beschreibung" born: "Geburtstag" - edit_my_profile: "Mein Profil bearbeiten" gender: "Geschlecht" - in_aspects: "in Aspekten" location: "Ort" - photos: "Fotos" - remove_contact: "Kontakt entfernen" - remove_from: "%{name} aus %{aspect} entfernen?" show: closed_account: "Dieses Konto wurde geschlossen." does_not_exist: "Diese Person existiert nicht!" has_not_shared_with_you_yet: "%{name} hat bisher noch keine Beiträge mit dir geteilt!" - ignoring: "Du ignorierst alle Beiträge von %{name}." - incoming_request: "Du hast eine eingehende Anfrage von %{name}." - mention: "Erwähnen" - message: "Nachricht" - not_connected: "Du teilst nicht mit dieser Person" - recent_posts: "Neueste Beiträge" - recent_public_posts: "Neueste, öffentliche Beiträge" - return_to_aspects: "Kehre zu deiner Aspekt-Ãœbersicht zurück." - see_all: "Alle zeigen" - start_sharing: "Fang an zu teilen!" - to_accept_or_ignore: "um zu akzeptieren oder zu ignorieren." - sub_header: - add_some: "Füge neue hinzu" - edit: "Bearbeiten" - you_have_no_tags: "Du hast keine Tags!" - webfinger: - fail: "Entschuldigung, wir konnten %{handle} nicht finden." - zero: "Niemand" photos: - comment_email_subject: "%{name}s Foto" create: integrity_error: "Hochladen des Fotos fehlgeschlagen. Bist du sicher, dass es eine Bilddatei war?" runtime_error: "Hochladen des Fotos fehlgeschlagen. Bist du sicher, dass du deinen Morgenkaffee hattest?" type_error: "Hochladen des Fotos fehlgeschlagen. Bist du sicher, dass ein Bild hinzugefügt wurde?" destroy: notice: "Foto gelöscht." - edit: - editing: "Bearbeiten" - new: - back_to_list: "Zurück zur Liste" - new_photo: "Neues Foto" - post_it: "Teilen!" new_photo: empty: "{file} ist leer, bitte wähle erneut Dateien aus." invalid_ext: "{file} hat keine gültige Erweiterung. Nur {extensions} sind erlaubt." size_error: "{file} ist zu groß. Die maximale Dateigröße beträgt {sizeLimit}." new_profile_photo: - or_select_one_existing: "oder eins deiner bereits hochgeladenen %{photos} auswählen" upload: "Ein neues Profilfoto hochladen" - photo: - view_all: "zeige alle Fotos von %{name}" show: - collection_permalink: "Sammlung Permalink" - delete_photo: "Foto löschen" - edit: "Bearbeiten" - edit_delete_photo: "Fotobeschreibung bearbeiten / Foto löschen" - make_profile_photo: "Als Profilbild verwenden" show_original_post: "Zeige ursprünglichen Beitrag" - update_photo: "Foto aktualisieren" - update: - error: "Bearbeiten des Fotos fehlgeschlagen." - notice: "Foto erfolgreich aktualisiert." + polls: + votes: + one: "Bisher %{count} Stimme" + other: "Bisher %{count} Stimmen" + zero: "Bisher %{count} Stimmen" posts: presenter: title: "Ein Beitrag von %{name}" show: - destroy: "Löschen" forbidden: "Du bist nicht berechtigt, das zu tun" - not_found: "Entschuldige, wir konnten den Beitrag leider nicht finden." - permalink: "Permalink" + location: "Erstellt in: %{location}" photos_by: few: "%{count} Fotos von %{author}" many: "%{count} Fotos von %{author}" @@ -985,19 +909,24 @@ de: two: "Zwei Fotos von %{author}" zero: "Keine Fotos von %{author}" reshare_by: "Weitergesagt von %{author}" - previous: "Vorherige" privacy: "Privatsphäre" - privacy_policy: "Datenschutzrichtlinien" profile: "Profil" profiles: edit: allow_search: "Anderen erlauben, auf diaspora* nach dir zu suchen" - edit_profile: "Profil bearbeiten" + basic: "Mein grundlegendes Profil" + basic_hint: "Jeder Eintrag in deinem Profil ist freiwillig. Dein grundlegendes Profil wird immer öffentlich sein." + extended: "Mein erweitertes Profil" + extended_hint: "Klick auf den Schalter, um die Sichtbarkeit deiner erweiterten Profildaten zu ändern. Öffentlich heißt, dass sie für das Internet sichtbar ist, begrenzt heißt, dass nur Leute, mit denen du teilst, die Informationen sehen werden." + extended_visibility_text: "Sichtbarkeit deines erweiterten Profils:" first_name: "Vorname" last_name: "Nachname" + limited: "Begrenzt" nsfw_check: "Markiere alles, was ich teile, als NSFW" nsfw_explanation: "NSFW („Not safe for work“, dt. „Unpassend für den Arbeitsplatz“) ist Diasporas sich selbst verwaltender Gemeinschafts-Standard für Inhalte, die für das Ansehen während der Arbeit möglicherweise ungeeignet sind. Bitte aktiviere diese Option, wenn du häufig derartiges Material teilen möchtest, damit es in den Streams anderer Leute, die es nicht sehen wollen, ausgeblendet wird." nsfw_explanation2: "Wenn du diese Option nicht auswählst, markiere deine entsprechenden Beiträge dann bitte jeweils mit dem Tag #nsfw." + public: "Öffentlich" + settings: "Profileinstellungen" update_profile: "Profil aktualisieren" your_bio: "Deine Beschreibung" your_birthday: "Dein Geburtstag" @@ -1005,8 +934,6 @@ de: your_location: "Dein Ort" your_name: "Dein Name" your_photo: "Dein Profilbild" - your_private_profile: "Dein privates Profil" - your_public_profile: "Dein öffentliches Profil" your_tags: "Beschreibe dich in 5 Worten" your_tags_placeholder: "Zum Beispiel: #Diaspora #lustig #Kätzchen #Musik" update: @@ -1024,26 +951,16 @@ de: closed: "Neuregistrierungen sind auf diesem diaspora*-Pod geschlossen." create: success: "Du bist diaspora* beigetreten!" - edit: - cancel_my_account: "Mein Konto schließen" - edit: "%{name} bearbeiten" - leave_blank: "(Du willst nichts ändern? Einfach leer lassen.)" - password_to_confirm: "(wir brauchen dein aktuelles Kennwort, um deine Änderungen zu bestätigen)" - unhappy: "Unglücklich?" - update: "Aktualisieren" invalid_invite: "Der von dir erstellte Einladungs-Link ist nicht mehr gültig!" new: - create_my_account: "Konto erstellen!" email: "E-Mail" enter_email: "Gib deine E-Mail-Adresse an" enter_password: "Gib ein Kennwort ein (mindestens sechs Zeichen)" enter_password_again: "Gib das gleiche Kennwort wie zuvor ein" enter_username: "Wähle einen Nutzernamen (nur Buchstaben, Nummern und Unterstriche)" - join_the_movement: "Tritt der Bewegung bei!" - password: "Passwort" - password_confirmation: "Passwort bestätigen" - sign_up: "Registrieren" - sign_up_message: "Soziales Netzwerken mit ♥" + password: "Kennwort" + password_confirmation: "Kennwort bestätigen" + sign_up: "Konto ersellen" submitting: "Absenden…" terms: "Indem du ein Konto erstellst, akzeptierst du die %{terms_link}." terms_link: "Nutzungsbedingungen" @@ -1056,51 +973,18 @@ de: post_label: "<b>Beitrag</b>: %{title}" reason_label: "Grund: %{text}" reported_label: "<b>Gemeldet von</b> %{person}" + reported_user_details: "Details des gemeldeten Benutzers" review_link: "Als überprüft markieren" status: - created: "Eine Meldung wurde erstellt" destroyed: "Der Beitrag wurde gelöscht" failed: "Ein Fehler ist aufgetreten" - marked: "Die Meldung wurde als überprüft markiert" title: "Meldungsübersicht" - requests: - create: - sending: "Senden …" - sent: "Du hast angefragt mit %{name} zu teilen. Er/Sie sollte dies sehen, wenn er/sie sich das nächste Mal bei diaspora* einloggt." - destroy: - error: "Bitte wähle einen Aspekt!" - ignore: "Kontaktanfrage ignoriert." - success: "Du bist jetzt verbunden." - helper: - new_requests: - few: "%{count} neue Anfragen!" - many: "%{count} neue Anfragen!" - one: "Neue Anfrage!" - other: "%{count} neue Anfragen!" - two: "%{count} neue Anfragen!" - zero: "Keine neuen Anfragen" - manage_aspect_contacts: - existing: "Bestehende Kontakte" - manage_within: "Kontakte verwalten in" - new_request_to_person: - sent: "Gesendet!" reshares: comment_email_subject: "%{resharer}s Version von %{author}s Beitrag" - create: - failure: "Ein Fehler trat beim Weitersagen dieses Beitrags auf." reshare: deleted: "Originalbeitrag wurde vom Autor entfernt." - reshare: - few: "%{count} mal weitergesagt" - many: "%{count} mal weitergesagt" - one: "Einmal weitergesagt" - other: "%{count} mal weitergesagt" - two: "%{count} mal weitergesagt" - zero: "Weitersagen" reshare_confirmation: "%{author}s Beitrag weitersagen?" - reshare_original: "Ursprünglichen Beitrag weitersagen" reshared_via: "weitergesagt durch" - show_original: "Original anzeigen" search: "Suche" services: create: @@ -1111,11 +995,7 @@ de: destroy: success: "Authentifizierung erfolgreich gelöscht." failure: - error: "Es gab einen Fehler der Verbindung mit dem Dienst." - finder: - fetching_contacts: "Deine %{service}-Freunde werden momentan eingeladen. Schau in ein paar Minuten noch einmal vorbei!" - no_friends: "Keine Facebook-Freunde gefunden." - service_friends: "%{service}-Freunde" + error: "Es gab einen Fehler beim Verbinden mit dem Dienst." index: connect: "Verbinde" disconnect: "Verbindung entfernen" @@ -1124,60 +1004,28 @@ de: no_services_available: "Auf diesem Pod stehen keine Dienste zur Verfügung." not_logged_in: "Du bist momentan nicht angemeldet." really_disconnect: "Verbindung mit %{service} entfernen?" - services_explanation: "Das Verbinden zu anderen Drittanbieter-Diensten zum Teilen gibt dir die Möglichkeit, Beiträge, die du in diaspora* schreibst, auch dort zu veröffentlichen." - inviter: - click_link_to_accept_invitation: "Öffne diesen Link, um die Einladung zu akzeptieren:" - join_me_on_diaspora: "Folge mir auf diaspora*" + services_explanation: "Das Verbinden zu Drittanbieter-Diensten zum Teilen gibt dir die Möglichkeit, Beiträge, die du in diaspora* schreibst, auch dort zu veröffentlichen." + share_to: "Mit %{provider} teilen" + title: "Verbundene Dienste verwalten" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "Einladen" - not_on_diaspora: "Noch nicht auf diaspora*" - resend: "Erneut senden" settings: "Einstellungen" - share_visibilites: - update: - post_hidden_and_muted: "%{name}'s Beitrag wurde ausgeblendet und die Benachrichtigungen abgeschaltet." - see_it_on_their_profile: "Wenn du Updates zu diesem Beitrag sehen möchtest, besuche %{name}s Profil." shared: - add_contact: - add_new_contact: "Einen neuen Kontakt hinzufügen" - create_request: "Mittels diaspora* ID finden" - diaspora_handle: "diaspora@beispiel.org" - enter_a_diaspora_username: "Gib bitte einen diaspora*-Nutzernamen ein:" - know_email: "Du kennst die E-Mail-Adresse? Sende eine Einladung!" - your_diaspora_username_is: "Dein diaspora*-Nutzername ist: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Kontakt hinzufügen" mobile_row_checked: "%{name} (entfernen)" mobile_row_unchecked: "%{name} (hinzufügen)" toggle: - few: "In %{count} Aspekten" - many: "In %{count} Aspekten" one: "In einem Aspekt" other: "In %{count} Aspekten" - two: "In %{count} Aspekten" - zero: "Kontakt hinzufügen" - contact_list: - all_contacts: "Alle Kontakte" - footer: - logged_in_as: "Angemeldet als %{name}" - your_aspects: "Deine Aspekte" + zero: "In keinem Aspekt" invitations: by_email: "Per E-Mail" - dont_have_now: "Du hast im Moment keine Einladungen zur Verfügung, es wird aber bald wieder neue geben!" - from_facebook: "Von Facebook" - invitations_left: "%{count} übrig" - invite_someone: "Jemanden einladen" invite_your_friends: "Lade deine Freunde ein" invites: "Einladungen" - invites_closed: "Einladungen sind auf diesem diaspora*-Pod derzeit nicht verfügbar." share_this: "Teile diesen Link per Email, Blog oder sozialen Netzwerken!" - notification: - new: "Neue %{type} von %{from}" public_explain: atom_feed: "Atom-Feed" control_your_audience: "Kontrolliere deine Zielgruppe" @@ -1189,12 +1037,9 @@ de: title: "Verbundene Dienste verwalten" visibility_dropdown: "Benutze dieses Auswahlmenü, um die Sichtbarkeit deines Beitrags zu ändern. (Wir empfehlen Dir, diesen ersten Beitrag öffentlich zu machen.)" publisher: - all: "Alle" - all_contacts: "Alle Kontakte" discard_post: "Beitrag verwerfen" formatWithMarkdown: "Du kannst %{markdown_link} verwenden, um deinen Beitrag zu formatieren." get_location: "Deinen Standort ermitteln" - make_public: "veröffentlichen" new_user_prefill: hello: "Hallo zusammen, ich bin #%{new_user_tag}. " i_like: "Ich interessiere mich für %{tags}." @@ -1202,36 +1047,14 @@ de: newhere: "NeuHier" poll: add_a_poll: "Eine Umfrage hinzufügen" - add_poll_answer: "Option hinzufügen" - option: "Antwort 1" - question: "Frage" - remove_poll_answer: "Option entfernen" - post_a_message_to: "Sende eine Nachricht an %{aspect}" posting: "Senden …" - preview: "Vorschau" - publishing_to: "Veröffentlichen an: " remove_location: "Ort entfernen" share: "Teilen" - share_with: "Teile mit" upload_photos: "Fotos hochladen" whats_on_your_mind: "Woran denkst du gerade?" - reshare: - reshare: "Weitersagen" stream_element: - connect_to_comment: "Verbinde dich mit diesem Benutzer, um seinen Beitrag zu kommentieren" - currently_unavailable: "Kommentieren derzeit nicht verfügbar" - dislike: "Gefällt mir nicht" - hide_and_mute: "Beitrag verbergen und stummschalten" - ignore_user: "%{name} ignorieren" - ignore_user_description: "Diesen Benutzer ignorieren und aus allen Aspekten entfernen?" - like: "Gefällt mir" - nsfw: "Dieser Post wurde vom Autor als NSFW markiert. %{link}" - shared_with: "Geteilt mit: %{aspect_names}" - show: "zeigen" - unlike: "Gefällt mir nicht mehr" via: "via %{link}" via_mobile: "Ãœber mobil" - viewable_to_anyone: "Dieser Beitrag ist für jeden im Web sichtbar" simple_captcha: label: "Gib den Code in das Feld ein:" message: @@ -1257,24 +1080,12 @@ de: status_messages: create: success: "Erfolgreich erwähnt: %{names}" - destroy: - failure: "Fehler beim Löschen des Posts" - helper: - no_message_to_display: "Keine Nachricht zum Anzeigen." new: mentioning: "Erwähnt: %{person}" too_long: "Bitte kürze deinen Beitrag auf weniger als %{count} Zeichen. Im Moment enthält er %{current_length} Zeichen" stream_helper: - hide_comments: "Alle Kommentare verbergen" no_more_posts: "Du hast das Ende des Streams erreicht." no_posts_yet: "Es existieren bisher keine Beiträge." - show_comments: - few: "Zeige %{count} weitere Kommentare" - many: "Zeige %{count} weitere Kommentare" - one: "Zeige einen weiteren Kommentar" - other: "Zeige %{count} weitere Kommentare" - two: "Zeige zwei weitere Kommentare" - zero: "Keine weiteren Kommentare" streams: activity: title: "Meine Aktivitäten" @@ -1283,7 +1094,7 @@ de: aspects_stream: "Aspekte" comment_stream: title: "Kommentierte Beiträge" - community_spotlight_stream: "Gemeinschaftsfokus" + community_spotlight_stream: "Gemeinschafts-Schaukasten" followed_tag: add_a_tag: "Füge einen Tag hinzu" follow: "Folgen" @@ -1301,13 +1112,6 @@ de: tags: title: "Getaggte Beiträge: %{tags}" tag_followings: - create: - failure: "Fehler beim Folgen von: #%{name}. Folgst du #%{name} bereits?" - none: "Du kannst keinem leeren Tag folgen!" - success: "Hurra! Du folgst nun #%{name}" - destroy: - failure: "Fehler beim Beenden des Folgens von: #%{name}. Vielleicht hast du schon aufgehört zu folgen?" - success: "Schade! Du folgst #%{name} nun nicht mehr." manage: no_tags: "Du folgst keinen Tags." title: "Gefolgte Tags verwalten" @@ -1315,22 +1119,19 @@ de: name_too_long: "Bitte kürze deinen Tag-Namen auf weniger als %{count} Zeichen. Im Moment enthält er %{current_length} Zeichen" show: follow: "#%{tag} folgen" - following: "Du folgst #%{tag}" none: "Der leere Tag existiert nicht!" stop_following: "#%{tag} nicht mehr folgen" tagged_people: one: "1 Person ist getaggt mit %{tag}" other: "%{count} Personen sind getaggt mit %{tag}" zero: "Niemand ist getaggt mit %{tag}" - terms_and_conditions: "Allgemeine Geschäftsbedingungen" - undo: "Rückgängig machen?" username: "Benutzername" users: confirm_email: email_confirmed: "E-Mail %{email} wurde aktiviert" email_not_confirmed: "Die E-Mail-Adresse konnte nicht aktiviert werden. Falscher Link?" destroy: - no_password: "Bitte gib dein Kennwort ein, um deinen Account zu schließen." + no_password: "Gib bitte dein Kennwort ein, um dein Konto zu schließen." success: "Dein Account wurde gesperrt. Es kann bis zu 20 Minuten dauern, bis dein Account endgültig geschlossen ist. Vielen Dank, dass du diaspora* ausprobiert hast." wrong_password: "Das eingegebene Kennwort stimmt nicht mit deinem aktuellen Kennwort überein." edit: @@ -1338,48 +1139,46 @@ de: auto_follow_aspect: "Aspekt für automatisch gefolgten Benutzern:" auto_follow_back: "Folge Benutzern automatisch, wenn sie dir folgen" change: "Ändern" + change_color_theme: "Farbthema ändern" change_email: "E-Mail-Adresse ändern" change_language: "Sprache ändern" change_password: "Kennwort ändern" character_minimum_expl: "bitte mindestens sechs Zeichen eingeben" close_account: dont_go: "Hey, bitte geh nicht!" - if_you_want_this: "Wenn du das wirklich möchtest, gib unten dein Passwort ein und klicke auf 'Konto schließen'" lock_username: "Dein Benutzername wird gesperrt werden. Du wirst auf diesem Pod kein neues Konto mit derselben ID erstellen können." locked_out: "Du wirst abgemeldet und von deinem Konto ausgesperrt, bis es gelöscht wurde." make_diaspora_better: "Wir würden uns freuen, wenn du bleibst und uns hilfst, diaspora* besser zu machen, anstatt uns zu verlassen. Wenn du uns wirklich verlassen möchtest, wird folgendes passieren:" mr_wiggles: "Mr. Wiggles wird traurig sein, wenn du gehst" - no_turning_back: "Es gibt kein Zurück! Wenn du dir wirklich sicher bist, gib unten dein Passwort ein." + no_turning_back: "Es gibt kein Zurück! Wenn du dir wirklich sicher bist, gib unten dein Kennwort ein." what_we_delete: "Wir löschen alle deine Beiträge und dein Profil so schnell wie möglich. Deine Kommentare auf anderer Leute Beiträge werden weiterhin angezeigt, aber sie werden mit deiner diaspora*-ID statt mit deinem Namen verknüpft." close_account_text: "Konto schließen" - comment_on_post: "… jemand deinen Beitrag kommentiert" + comment_on_post: "jemand deinen Beitrag kommentiert" current_password: "Derzeitiges Kennwort" current_password_expl: "das mit dem Du dich anmeldest..." download_export: "Mein Profil herunterladen" download_export_photos: "Meine Fotos herunterladen" - download_photos: "Meine Fotos herunterladen" edit_account: "Konto bearbeiten" email_awaiting_confirmation: "Wir haben dir einen Aktivierungslink zu %{unconfirmed_email} geschickt. Solange du dem Link nicht gefolgt bist und die neue Adresse aktiviert hast, werden wir weiterhin deine ursprüngliche E-Mail-Adresse %{email} verwenden." export_data: "Daten exportieren" export_in_progress: "Wir verarbeiten momentan deine Daten - schau etwas später noch einmal vorbei." export_photos_in_progress: "Wir sind gerade dabei, deine Fotos zu verarbeiten. Bitte guck in ein paar Augenblicken noch mal vorbei." following: "Folgen-Einstellungen" - getting_started: "Einstellungen für neue Nutzer" last_exported_at: "(Zuletzt aktualisiert: %{timestamp})" - liked: "… jemandem dein Beitrag gefällt" - mentioned: "… du in einem Beitrag erwähnt wirst" + liked: "jemandem dein Beitrag gefällt" + mentioned: "du in einem Beitrag erwähnt wirst" new_password: "Neues Kennwort" - private_message: "… du eine private Nachricht erhältst" + private_message: "du eine private Nachricht erhältst" receive_email_notifications: "E-Mail-Benachrichtigungen empfangen, wenn …" request_export: "Meine Profildaten anfordern" request_export_photos: "Meine Fotos anfragen" request_export_photos_update: "Meine Fotos aktualisieren" request_export_update: "Meine Profildaten aktualisieren" - reshared: "… jemand deinen Beitrag weitersagt" + reshared: "jemand deinen Beitrag weitersagt" show_community_spotlight: "„Gemeinschafts-Schaukasten†im Stream anzeigen" show_getting_started: "Einstiegshinweise wieder aktivieren" someone_reported: "jemand einen Beitrag meldet" - started_sharing: "… jemand anfägt mit dir zu teilen" + started_sharing: "jemand anfägt mit dir zu teilen" stream_preferences: "Stream-Einstellungen" your_email: "Deine E-Mail-Adresse" your_email_private: "Deine E-Mail wird niemals von anderen Nutzern gesehen werden." @@ -1391,7 +1190,6 @@ de: connect_to_facebook_link: "Dein Facebook-Konto mit diaspora* verlinkst" hashtag_explanation: "Hashtags ermöglichen dir, über deine Interessen zu reden und ihnen zu folgen. Sie sind auch ein guter Weg, neue Leute bei diaspora* zu treffen!" hashtag_suggestions: "Probier mal Tags wie #kunst, #musik oder #gif zu folgen." - saved: "Gespeichert!" well_hello_there: "Also, Hallöchen!" what_are_you_in_to: "Was machst du so?" who_are_you: "Wer bist Du?" @@ -1404,6 +1202,8 @@ de: public: does_not_exist: "Benutzer %{username} existiert nicht!" update: + color_theme_changed: "Farbthema erfolgreich geändert." + color_theme_not_changed: "Beim ändern des Farbthemas ist ein Fehler aufgetreten." email_notifications_changed: "E-Mail-Benachrichtigungen geändert" follow_settings_changed: "Folgen-Einstellungen geändert" follow_settings_not_changed: "Ändern der Folgen-Einstellungen fehlgeschlagen." @@ -1415,13 +1215,6 @@ de: settings_updated: "Einstellungen aktualisiert" unconfirmed_email_changed: "E-Mail-Adresse geändert. Benötigt Aktivierung." unconfirmed_email_not_changed: "Fehler bei Änderung der E-Mail-Adresse" - webfinger: - fetch_failed: "konnte Webfinger-Profil für %{profile_url} nicht laden" - hcard_fetch_failed: "es gab Probleme beim Laden der hcard für %{account}" - no_person_constructed: "Konnte keine Person aus dieser hcard erstellen." - not_enabled: "Webfinger scheint nicht für den Server von %{account} verfügbar zu sein." - xrd_fetch_failed: "Die XRD-Datei von %{account} konnte nicht heruntergeladen werden." - welcome: "Willkommen!" will_paginate: next_label: "nächstes »" previous_label: "« voriges" \ No newline at end of file diff --git a/config/locales/diaspora/de_formal.yml b/config/locales/diaspora/de_formal.yml index 1c871411cf7b97f365bdfdfd9a5a3fa99c488023..13f66162e0918fc26968d01cfddbd5f08ab00165 100644 --- a/config/locales/diaspora/de_formal.yml +++ b/config/locales/diaspora/de_formal.yml @@ -6,11 +6,8 @@ de_formal: _applications: "Anwendungen" - _comments: "Kommentare" _contacts: "Kontakte" _help: "Hilfe" - _home: "Startseite" - _photos: "Fotos" _services: "Dienste" _statistics: "Statistik" _terms: "Bedingungen" @@ -53,12 +50,19 @@ de_formal: taken: "wird schon benutzt." admins: admin_bar: + dashboard: "Dashboard" pages: "Seiten" + pod_network: "Pod-Netzwerk" pod_stats: "Pod-Statistiken" report: "Meldungen" sidekiq_monitor: "Sidekiq-Monitor" user_search: "Benutzersuche" weekly_user_stats: "Wöchentliche Benutzerstatistik" + dashboard: + fetching_diaspora_version: "Ermittle neueste diaspora*-Version" + pod_status: "Pod-Status" + pods: + pod_network: "Pod-Netzwerk" stats: 2weeks: "2 Wochen" 50_most: "Die 50 populärsten Tags" @@ -92,6 +96,7 @@ de_formal: email: "E-Mail-Adresse" guid: "GUID" id: "ID" + invite_token: "Einladungstoken" last_seen: "Zuletzt gesehen" ? "no" : Nein @@ -109,7 +114,10 @@ de_formal: are_you_sure_unlock_account: "Sind Sie sicher, dass Sie dieses Konto entsperren möchten?" close_account: "Konto schließen" email_to: "per E-Mail einladen" + invite: "Einladen" + lock_account: "Konto sperren" under_13: "Zeige Benutzer, die unter 13 Jahre alt sind (COPPA)" + unlock_account: "Konto entsperren" users: one: "%{count} Benutzer gefunden" other: "%{count} Benutzer gefunden" @@ -125,13 +133,63 @@ de_formal: other: "Anzahl neuer Benutzer in dieser Woche: %{count}" zero: "Anzahl neuer Benutzer in dieser Woche: keine" current_server: "Das aktuelle Serverdatum ist %{date}" - ago: "Vor %{time}" all_aspects: "Alle Aspekte" - application: - helper: - unknown_person: "Unbekannte Person" - video_title: - unknown: "Unbekannter Videotitel" + api: + openid_connect: + authorizations: + destroy: + fail: "Der Versuch, die Zulassung mit der ID %{id} zu widerrufen, ist fehlgeschlagen" + new: + access: "%{name} benötigt Zugriff auf:" + approve: "Zulassen" + bad_request: "Fehlende Client-ID oder Weiterleitungs-URI" + client_id_not_found: "Kein Client mit client_id %{client_id} und Weiterleitungs-URI %{redirect_uri} gefunden" + deny: "Verweigern" + no_requirement: "%{name} benötigt keine Berechtigungen" + redirection_message: "Sind Sie sich sicher, dass Sie den Zugriff von %{redirect_uri} zulassen möchten?" + error_page: + contact_developer: "Sie sollten den Entwickler der Anwendung kontaktieren und die folgende ausführliche Fehlermeldung beifügen:" + could_not_authorize: "Die Anwendung konnte nicht zugelassen werden" + login_required: "Sie müssen sich erst anmelden, bevor Sie diese Anwendung zulassen können." + title: "Oh! Etwas ist schiefgegangen :(" + scopes: + aud: + description: "Dies gewährt der Anwendung aud-Berechtigungen" + name: "aud" + name: + description: "Dies gewährt der Anwendung Name-Berechtigungen" + name: "Name" + nickname: + description: "Dies gewährt der Anwendung Benutzername-Berechtigungen" + name: "Benutzername" + openid: + description: "Das ermöglicht der Anwendung, Ihr grundlegendes Profil auszulesen" + name: "grundlegendes Profil" + picture: + description: "Dies gewährt der Anwendung Bild-Berechtigungen" + name: "Bild" + profile: + description: "Dies ermöglicht der Anwendung, Ihr erweitertes Profil auszulesen" + name: "erweitertes Profil" + read: + description: "Das ermöglicht der Anwendung, Ihren Stream, Ihre Konversationen und Ihr vollständiges Profil auszulesen" + name: "Profil, Stream und Konversationen lesen" + sub: + description: "Dies gewährt der Anwendung sub-Berechtigungen" + name: "sub" + write: + description: "Dies ermöglicht der Anwendung, neue Beiträge zu senden, Konversationen zu schreiben und Reaktionen zu senden" + name: "Beiträge, Konversationen und Reaktionen senden" + user_applications: + index: + access: "%{name} hat Zugriff auf:" + edit_applications: "Anwendungen" + no_requirement: "%{name} benötigt keine Berechtigungen" + title: "Zugelassene Anwendungen" + no_applications: "Sie haben keine zugelassenen Anwendungen" + policy: "Die Datenschutzerklärung der Anwendung ansehen" + revoke_autorization: "Aufheben" + tos: "Die Nutzungsbedingungen der Anwendung ansehen" are_you_sure: "Sind Sie sicher?" are_you_sure_delete_account: "Möchten Sie Ihr Konto wirklich schließen? Dieser Schritt kann nicht rückgängig gemacht werden!" aspect_memberships: @@ -147,48 +205,27 @@ de_formal: success: "Kontakt erfolgreich zum Aspekt hinzugefügt." aspect_listings: add_an_aspect: "+ Aspekt hinzufügen" - deselect_all: "Auswahl aufheben" - edit_aspect: "Bearbeite %{name}" - select_all: "Alle auswählen" aspect_stream: make_something: "Machen Sie etwas" stay_updated: "Bleiben Sie auf dem Laufenden" stay_updated_explanation: "Ihr Stream ist gefüllt mit all Ihren Kontakten, Tags denen Sie folgen sowie Beiträgen einiger kreativer Mitglieder der Gemeinschaft." - contacts_not_visible: "Kontakte in diesem Aspekt sind nicht in der Lage einander zu sehen." - contacts_visible: "Kontakte in diesem Aspekt können sich untereinander sehen." - create: - failure: "Fehler beim Erstellen des Aspekts." - success: "Ihr neuer Aspekt %{name} wurde erstellt." destroy: failure: "%{name} konnte nicht entfernt werden." success: "%{name} wurde erfolgreich entfernt." success_auto_follow_back: "%{name} wurde erfolgreich entfernt. Sie haben diesen Aspekt benutzt um Nutzern automatisch zu folgen. Ãœberprüfen Sie Ihre Einstellungen um einen neuen Aspekt hierfür festzulegen." edit: - aspect_chat_is_enabled: "Kontakte in diesem Askekt können mit Ihnen chatten." - aspect_chat_is_not_enabled: "Kontakte in diesem Aspekt können nicht mit Ihnen chatten." aspect_list_is_not_visible: "Kontakte in diesem Aspekt können einander nicht sehen." aspect_list_is_visible: "Kontakte in diesem Aspekt können einander sehen." confirm_remove_aspect: "Sind Sie sich sicher, dass Sie diesen Aspekt löschen möchten?" - grant_contacts_chat_privilege: "Kontakten in diesem Aspekt das Chatrecht gewähren?" - make_aspect_list_visible: "Kontakte aus diesem Aspekt öffentlich machen?" - remove_aspect: "Diesen Aspekt löschen" rename: "Umbenennen" - set_visibility: "Sichtbarkeit festlegen" update: "Ändern" updating: "Ändere…" index: - diaspora_id: - content_1: "Ihre diaspora*-ID ist:" - content_2: "Geben Sie diese an andere weiter und sie werden Sie leicht auf diaspora* finden können." - heading: "diaspora*-ID" donate: "Spenden" - handle_explanation: "Das ist Ihre diaspora* ID. Sie können sie wie eine E-Mail-Adresse weitergeben, damit andere Nutzer mit Ihnen Kontakt aufnehmen können." help: any_problem: "Gibt es ein Problem?" contact_podmin: "Kontaktieren Sie den Administrator Ihres Pods!" do_you: "Haben Sie:" - email_feedback: "%{link} Ihr Feedback für diaspora*" - email_link: "E-Mail" feature_suggestion: "… einen %{link} Vorschlag?" find_a_bug: "… einen %{link} gefunden?" have_a_question: "… eine %{link}?" @@ -201,31 +238,21 @@ de_formal: tutorial_link_text: "Anleitungen" tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: Hilfe für Ihre ersten Schritte." introduce_yourself: "Das ist ihr Stream. Legen Sie los und stellen Sie sich vor." - keep_diaspora_running: "Die Entwicklung von diaspora* bleibt schnell, wenn Sie monatlich spenden!" keep_pod_running: "Helfen Sie %{pod} schneller zu arbeiten und kaufen Sie unseren Servern ihren monatlichen Schuss Kaffee!" new_here: follow: "Folgen Sie %{link} und heißen Sie neue Benutzer auf diaspora* willkommen!" learn_more: "Mehr erfahren" title: "Heißen Sie neue Benutzer willkommen" - no_contacts: "Keine Kontakte" - no_tags: "+ Finden Sie einen #Tag zum folgen" - people_sharing_with_you: "Leute, die mit Ihnen teilen" - post_a_message: "Schreiben Sie eine Nachricht >>" services: content: "Sie können die folgenden Dienste mit diaspora* verbinden:" heading: "Dienste verbinden" - unfollow_tag: "#%{tag} nicht mehr folgen" welcome_to_diaspora: "Willkommen bei diaspora*, %{name}!" - new: - create: "Erstellen" - name: "Name (nur für Sie sichtbar)" no_contacts_message: community_spotlight: "Gemeinschafts-Schaukasten" + invite_link_text: "Einladen" or_spotlight: "Sie können auch mit %{link} teilen" - try_adding_some_more_contacts: "Sie können nach Kontakten suchen (oben) oder welche einladen (rechts)." + try_adding_some_more_contacts: "Sie können mehr Kontakte suchen oder %{invite_link}." you_should_add_some_more_contacts: "Sie sollten ein paar neue Kontakte hinzufügen!" - no_posts_message: - start_talking: "Niemand hat bisher etwas gesagt!" seed: acquaintances: "Bekannte" family: "Familie" @@ -234,34 +261,26 @@ de_formal: update: failure: "%{name} ist ein zu langer Name, um gespeichert zu werden." success: "Aspekt %{name} erfolgreich bearbeitet." - back: "Zurück" blocks: create: - failure: "Konnte diesen Benutzer nicht ignorieren. #evasion" + failure: "Konnte diesen Benutzer nicht ignorieren. #evasion" success: "Alles klar, Sie werden diesen Benutzer nicht mehr in ihrem Stream sehen. #silencio!" destroy: - failure: "Konnte das Ignorieren dieses Benutzers nicht aufheben. #evasion" + failure: "Konnte das Ignorieren dieses Benutzers nicht aufheben. #evasion" success: "Sehen Sie, was diese zu sagen haben! #sayhello" bookmarklet: explanation: "Erstellen Sie auf jeder Webseite einen Beitrag für diaspora*, indem Sie %{link} als Lesezeichen speichern." heading: "Lesezeichen" post_something: "Erstellen Sie einen Beitrag in diaspora*" - post_success: "Erstellt! Schließen …" cancel: "Abbrechen" comments: new_comment: comment: "Kommentieren" commenting: "Kommentieren …" - one: "Ein Kommentar" - other: "%{count} Kommentare" - zero: "Keine Kommentare" contacts: - create: - failure: "Fehler beim Erstellen des Kontakts" index: add_a_new_aspect: "Einen neuen Aspekt hinzufügen" add_contact: "Kontakt hinzufügen" - add_to_aspect: "Füge Kontakte zu %{name} hinzu" all_contacts: "Alle Kontakte" community_spotlight: "Gemeinschafts-Schaukasten" my_contacts: "Meine Kontakte" @@ -269,19 +288,14 @@ de_formal: no_contacts_in_aspect: "Sie haben noch keine Kontakte in diesem Aspekt. Unten befindet sich eine Liste Ihrer bestehenden Kontakte, die Sie zu diesem Aspekt hinzufügen können." no_contacts_message: "Erkunden Sie den %{community_spotlight}" only_sharing_with_me: "Nur mit Ihnen Teilende" - remove_contact: "Kontakt entfernen" start_a_conversation: "Starten Sie eine Unterhaltung" title: "Kontakte" user_search: "Kontaktsuche" - your_contacts: "Ihre Kontakte" - sharing: - people_sharing: "Leute, die mit Ihnen teilen:" spotlight: community_spotlight: "Gemeinschafts-Schaukasten" + no_members: "Es gibt noch keine Mitglieder." suggest_member: "Ein Mitglied vorschlagen" conversations: - conversation: - participants: "Teilnehmer" create: fail: "Ungültige Nachricht" no_contact: "Hoppla, Sie müssen den Kontakt erst hinzufügen!" @@ -289,23 +303,13 @@ de_formal: destroy: delete_success: "Unterhaltung erfolgreich gelöscht" hide_success: "Unterhaltung erfolgreich ausgeblendet" - helper: - new_messages: - few: "%{count} neue Nachrichten" - many: "%{count} neue Nachrichten" - one: "Eine neue Nachricht" - other: "%{count} neue Nachrichten" - two: "%{count} neue Nachrichten" - zero: "Keine neuen Nachrichten" index: conversations_inbox: "Konversationen – Eingang" - create_a_new_conversation: "Eine neue Konversation anfangen" inbox: "Eingang" new_conversation: "Neue Konversation" - no_conversation_selected: "Keine Konversation ausgewählt" no_messages: "Keine Nachrichten" new: - abandon_changes: "Änderungen verwerfen?" + message: "Nachricht" send: "Senden" sending: "Senden …" subject: "Betreff" @@ -316,6 +320,7 @@ de_formal: show: delete: "Konversation löschen" hide: "Unterhaltung ausblenden und stummschalten" + last_message: "Letzte Nachricht empfangen %{timeago}" reply: "Antworten" replying: "Antworten …" date: @@ -328,10 +333,7 @@ de_formal: error_messages: helper: correct_the_following_errors_and_try_again: "Korrigieren Sie die folgenden Fehler und versuchen Sie es erneut." - invalid_fields: "Ungültige Felder" - login_try_again: "Bitte <a href='%{login_link}'>melden Sie sich neu an</a> und versuchen Sie es erneut." - post_not_public: "Dieser Beitrag ist nicht öffentlich!" - post_not_public_or_not_exist: "Der Beitrag, den Sie anzusehen versuchen, ist nicht öffentlich oder existiert nicht!" + need_javascript: "Diese Webseite benötigt JavaScript, um ordnungsgemäß zu funktionieren. Falls Sie JavaScript deaktiviert haben, aktivieren Sie es bitte und aktualisieren Sie diese Seite." fill_me_out: "Füllen Sie mich aus" find_people: "Leute oder #Tags finden" help: @@ -426,7 +428,7 @@ de_formal: subscribe_feed_q: "Kann ich die öffentlichen Beiträge einer Person mit einem Feedreader verfolgen?" title: "Diverses" pods: - find_people_a: "Benutzen Sie um Ihre Freunde dazu einzuladen, diaspora* beizutreten, den Einladungs- oder den E-Mail-Link in der Seitenleiste. Folgen Sie #Tags, um Andere zu entdecken, die Ihre Interessen teilen und fügen Sie Leute zu Ihren Aspekten hinzu, die für Sie interessante Sachen posten. Schreiben Sie in einem öffentlichen Post, dass Sie #NeuHier sind." + find_people_a: "Benutzen Sie um Ihre Freunde dazu einzuladen, diaspora* beizutreten, den Einladungs- oder den E-Mail-Link in der Seitenleiste. Folgen Sie #Tags, um andere zu entdecken, die Ihre Interessen teilen und fügen Sie Leute zu Ihren Aspekten hinzu, die für Sie interessante Sachen posten. Schreiben Sie in einem öffentlichen Post, dass Sie #NeuHier sind." find_people_q: "Ich bin gerade erst einem Pod beigetreten, wie finde ich nun Leute zum Teilen?" title: "Pods" use_search_box_a: "Wenn Sie deren vollständige diaspora* ID (z.B. benutzername@podname.org) kennen, können Sie sie finden, indem Sie danach suchen. Wenn Sie sich auf dem selben Pod befinden, reicht es, wenn Sie nur nach dem Benutzernamen suchen. Alternativ können Sie auch nach ihrem Profilnamen (dem angezeigten Namen) suchen. Wenn eine Suche beim ersten Mal keine Ergebnisse liefert, dann versuchen Sie es nochmal." @@ -489,7 +491,7 @@ de_formal: can_comment_reshare_like_a: "Jeder angemeldete diaspora*-Nutzer kann öffentliche Beiträge weitersagen, kommentieren, beziehungsweise „Gefällt mir“ drücken." can_comment_reshare_like_q: "Wer kann meinen öffentlichen Beitrag weitersagen, kommentieren oder bei ihm „Gefällt mir“ drücken?" deselect_aspect_posting_a: "Öffentliche Beiträge werden durch das Abwählen von Aspekten nicht beeinflusst. Sie werden weiterhin öffentlich sein und in den Streams all Ihrer Kontakte angezeigt werden. Um einen Beitrag nur für bestimmte Aspekte sichtbar zu machen, müssen Sie diese mit dem Aspektwähler unter dem Eingabefeld auswählen." - deselect_aspect_posting_q: "Was passiert wenn ich bei öffentlichen Beiträgen die Auswahl eines oder mehrerer Aspekte aufhebe?" + deselect_aspect_posting_q: "Was passiert, wenn ich bei öffentlichen Beiträgen einen oder mehrere Aspekte abwähle?" find_public_post_a: "Ihre öffentlichen Beiträge werden in den Streams aller, die Ihnen folgen, erscheinen. Wenn Sie #Tags in Ihren öffentlichen Beitrag einfügen, werden alle, die diesem Tag folgen, Ihren Beitrag in ihren Streams finden. Außerdem hat jeder öffentliche Beitrag eine spezifische URL, die jeder betrachten kann, auch wenn er oder sie nicht angemeldet ist – öffentlichen Beiträge können daher direkt von Twitter, Blogs, etc. verlinkt werden. Öffentliche Beiträge können außerdem von Suchmaschinen indexiert werden." find_public_post_q: "Wie können andere Nutzer meine öffentlichen Beiträge finden?" see_comment_reshare_like_a: "Die Kommentare, das Weitersagen und das Bekunden von Gefallen an einem öffentlichen Beitrag sind so öffentlich wie der Beitrag selbst. Jeder angemeldete diaspora*-Benutzer und jeder andere im Internet kann Ihre Interaktionen mit öffentlichen Beiträgen sehen." @@ -529,7 +531,7 @@ de_formal: list_not_sharing_q: "Gibt es eine Liste mit Leuten, die ich zu einem meiner Aspekte hinzugefügt habe, die mich aber noch nicht zu einem ihrer Aspekte hinzugefügt haben?" only_sharing_a: "Das sind Leute, die Sie zu einem ihrer Aspekte hinzugefügt haben, die sich aber (noch) nicht in einem Ihrer Aspekte befinden. Anders gesagt: Sie teilen mit Ihnen, aber Sie nicht mit ihnen: Sie können sich dies so vorstellen, dass sie Ihnen „folgenâ€. Wenn Sie sie zu einem Aspekt hinzufügen, werden sie in jenem Aspekt und nicht unter „Nur mit Ihnen Teilende“ zu sehen sein. Siehe oben." only_sharing_q: "Wer sind die Leute, die auf der Kontakteseite unter „Nur mit Ihnen Teilende†gelistet sind?" - see_old_posts_a: "Nein. Er wird ausschließlich neue Beiträge für diesen Aspekt sehen. Er (und alle Anderen) können aber alle älteren öffentlichen Beiträge von Ihnen auf Ihrer Profilseite oder in ihrem Stream sehen." + see_old_posts_a: "Nein. Er wird ausschließlich neue Beiträge für diesen Aspekt sehen. Er (und alle anderen) können aber alle älteren öffentlichen Beiträge von Ihnen auf Ihrer Profilseite oder in ihrem Stream sehen." see_old_posts_q: "Wenn ich jemanden zu einem Aspekt hinzufüge, sieht er dann auch ältere, bereits geschriebene Beiträge in diesem Aspekt?" sharing_notification_a: "Sie sollten jedes Mal, wenn jemand mit Ihnen zu teilen anfängt, eine Benachrichtigung erhalten." sharing_notification_q: "Wie erfahre ich es, wenn jemand anfängt, mit mir zu teilen?" @@ -551,93 +553,77 @@ de_formal: tutorial: "Anleitung" tutorials: "Anleitungen" wiki: "Wiki" - hide: "Ausblenden" - ignore: "Ignorieren" + home: + default: + be_who_you_want_to_be: "Seien Sie, wer Sie sein möchten" + be_who_you_want_to_be_info: "Viele Netzwerke bestehen darauf, dass Sie Ihre wahre Identität verwenden. diaspora* nicht. Hier können Sie entscheiden, wer Sie sein möchten und so viel oder wenig teilen, wie Sie es wünschen. Es liegt ganz an Ihnen, wie Sie mit anderen Personen interagieren möchten." + byline: "Die soziale Onlinewelt, in der Sie Ihre Daten in der Hand haben" + choose_your_audience: "Wählen Sie Ihr Publikum" + choose_your_audience_info: "diaspora*s Aspekte ermöglichen Ihnen, nur mit den Menschen zu teilen, mit denen Sie möchten. Sie können so öffentlich oder privat sein, wie Sie wünschen. Teilen Sie ein witziges Foto mit der ganzen Welt oder ein tiefes Geheimnis nur mit Ihren engsten Freunden. Sie haben es in der Hand." + headline: "Willkommen auf %{pod_name}" + own_your_data: "Ihre Daten, Ihr Eigentum" + own_your_data_info: "Viele Netzwerke nutzen Ihre Daten, um Geld zu verdienen, indem Sie Ihre Interaktionen auswerten und diese Informationen verwenden, um Ihnen Werbung zu zeigen. diaspora* nutzt Ihre Daten zu keinem anderen Zweck, als es Ihnen zu ermöglichen, sich mit anderen zu verbinden und mit ihnen zu teilen." + podmin: + admin_panel: "Administrationsbereich" + byline: "Sie sind im Begriff, das Internet zu ändern. Lassen Sie uns gleich alles einrichten, okay?" + configuration_info: "Öffnen Sie %{database_path} und %{diaspora_path} in Ihrem Lieblingstexteditor und sehen Sie sie gründlich durch, sie sind ausführlich kommentiert." + configure_your_pod: "Richten Sie Ihren Pod ein" + contact_irc: "im IRC" + contribute: "Wirken Sie mit" + contribute_info: "Machen Sie diaspora* noch besser! Falls Sie Fehler finden, bitte %{report_bugs}." + create_an_account: "Erstellen Sie ein Konto" + create_an_account_info: "Jetzt ein %{sign_up_link}." + faq_for_podmins: "häufig gestellte Fragen für Pod-Verwalter in unserem Wiki" + getting_help: "Erhalten Sie Hilfe" + getting_help_info: "Wir haben einige %{faq} aufgelistet, einschließlich einiger zusätzlicher Tipps und Tricks und Lösungen für die häufigsten Probleme. Kontaktieren Sie uns gerne auch %{irc}." + headline: "Willkommen, Freund." + make_yourself_an_admin: "Machen Sie sich zum Admin" + make_yourself_an_admin_info: "Sie können Anweisungen im %{wiki} finden. Das sollte Ihrem Benutzermenü in der Kopfleiste einen Link „Admin“ hinzufügen, wenn Sie angemeldet sind. Er stellt Ihnen Dinge wie Benutzersuche und Statistiken für Ihren Pod zur Verfügung. Für ausführliche Angaben über die betriebsbezogenen Aspekte Ihres Pods, besuchen Sie den %{admin_panel}." + report_bugs: "melden Sie sie" + update_instructions: "Aktualisierungsanweisungen im diaspora*-Wiki" + update_your_pod: "Aktualisieren Sie Ihren Pod" + update_your_pod_info: "Sie können %{update_instructions} finden." invitation_codes: - excited: "%{name} freut sich Sie hier zu sehen." not_valid: "Dieser Einladungscode ist nicht mehr gültig" invitations: a_facebook_user: "Ein Facebook Nutzer" check_token: not_found: "Einladungstoken nicht gefunden" create: - already_contacts: "Sie sind bereits mit dieser Person verbunden" - already_sent: "Sie haben diese Person bereits eingeladen." empty: "Bitte mindestens eine E-Mail-Adresse eingeben." no_more: "Sie haben keine Einladungen mehr." note_already_sent: "Es wurde bereits eine Einladung an %{emails} gesendet" - own_address: "Sie können keine Einladung an Ihre eigene Adresse senden." - rejected: "Mit diesen E-Mail-Adressen gab es Probleme:" - sent: "Einladungen wurden verschickt an:" - edit: - accept_your_invitation: "Ihre Einladung akzeptieren" - your_account_awaits: "Ihr Konto wartet!" + rejected: "Mit diesen E-Mail-Adressen gab es Probleme: " + sent: "Einladungen wurden verschickt an: %{emails}" new: - already_invited: "Die folgenden Personen haben Ihre Einladung nicht angenommen:" - aspect: "Aspekt" - check_out_diaspora: "Erkunden Sie diaspora*!" codes_left: one: "Eine Einladung übrig für diesen Code" other: "%{count} Einladungen übrig für diesen Code" zero: "Keine Einladungen übrig für diesen Code" comma_separated_plz: "Sie können mehrere E-Mail-Adressen, getrennt durch Kommas, eingeben." - if_they_accept_info: "Wenn sie akzeptieren, werden sie zu dem Aspekt hinzugefügt, in den Sie sie eingeladen haben." invite_someone_to_join: "Laden Sie jemanden zu diaspora* ein!" language: "Sprache" paste_link: "Teilen Sie diesen Link mit Ihren Freunden, um sie zu diaspora* einzuladen oder schicken Sie ihnen den Link direkt per E-Mail." - personal_message: "Persönliche Nachricht" - resend: "Erneut senden" send_an_invitation: "Eine Einladung senden" - send_invitation: "Einladung senden" sending_invitation: "Sende Einladung..." - to: "An" layouts: application: back_to_top: "Nach oben" + be_excellent: "Seien Sie nett zueinander! ♥" powered_by: "Betrieben mit diaspora*" public_feed: "Öffentlicher diaspora* Feed von %{name}" source_package: "Quelltextpaket herunterladen" statistics_link: "Pod-Statistiken" toggle: "Mobile Ansicht umschalten" whats_new: "Was gibt’s Neues?" - your_aspects: "Ihre Aspekte" header: - admin: "Administrator" - blog: "Blog" code: "Code" - help: "Hilfe" - login: "Anmelden" logout: "Abmelden" profile: "Profil" - recent_notifications: "Letzte Benachrichtigungen" settings: "Einstellungen" - view_all: "Alle anzeigen" - likes: - likes: - people_dislike_this: - few: "%{count} Personen gefällt das nicht" - many: "%{count} Personen gefällt das nicht" - one: "Einer Person gefällt das nicht" - other: "%{count} Personen gefällt das nicht" - two: "%{count} Personen gefällt das nicht" - zero: "Keinem gefällt das nicht" - people_like_this: - few: "%{count} Personen gefällt das" - many: "%{count} Personen gefällt das" - one: "Einer Person gefällt das" - other: "%{count} Personen gefällt das" - two: "%{count} Personen gefällt das" - zero: "Keinem gefällt das" - people_like_this_comment: - few: "Gefällt %{count}" - many: "Gefällt %{count}" - one: "Gefällt %{count}" - other: "Gefällt %{count}" - two: "%{count} Personen gefällt das" - zero: "Gefällt niemandem" + toggle_navigation: "Navigation umschalten" limited: "Begrenzt" more: "Mehr" - next: "Nächste" no_results: "Keine Ergebnisse gefunden" notifications: also_commented: @@ -655,14 +641,6 @@ de_formal: one: "%{actors} hat Ihren Beitrag %{post_link} kommentiert." other: "%{actors} haben Ihren Beitrag %{post_link} kommentiert." zero: "%{actors} hat Ihren Beitrag %{post_link} kommentiert." - helper: - new_notifications: - few: "%{count} neue Benachrichtigungen" - many: "%{count} neue Benachrichtigungen" - one: "Eine neue Benachrichtigung" - other: "%{count} neue Benachrichtigungen" - two: "%{count} neue Benachrichtigungen" - zero: "Keine neuen Benachrichtigungen" index: all_notifications: "Alle Benachrichtigungen" also_commented: "Auch kommentiert" @@ -700,7 +678,7 @@ de_formal: zero: "Niemandem gefällt Ihr gelöschter Beitrag." mentioned: one: "%{actors} hat Sie in dem Beitrag %{post_link} erwähnt." - other: "%{actors} haben Sie in dem %{post_link} erwähnt." + other: "%{actors} haben Sie in dem Beitrag %{post_link} erwähnt." zero: "Niemand hat Sie in dem Beitrag %{post_link} erwähnt." mentioned_deleted: few: "%{actors} haben Sie in einem gelöschten Beitrag erwähnt." @@ -725,7 +703,7 @@ de_formal: few: "%{actors} haben Ihren gelöschten Beitrag weitergesagt." many: "%{actors} haben Ihren gelöschten Beitrag weitergesagt." one: "%{actors} hat Ihren gelöschten Beitrag weitergesagt." - other: "%{actors} Ihren deinen gelöschten Beitrag weitergesagt." + other: "%{actors} haben Ihren gelöschten Beitrag weitergesagt." two: "%{actors} hat Ihren bereits gelöschten Beitrag weitergeleitet." zero: "%{actors} haben Ihren gelöschten Beitrag weitergesagt." started_sharing: @@ -736,10 +714,9 @@ de_formal: two: "%{actors} haben angefangen mit Ihnen zu teilen." zero: "Niemand hat angefangen mit Ihnen zu teilen." notifier: - a_limited_post_comment: "Auf diaspora* wartet ein neuer Kommentar auf einem begrenzten Beitrag darauf, von Ihnen gelesen zu werden." + a_limited_post_comment: "Auf diaspora* wartet ein neuer Kommentar auf einen begrenzten Beitrag darauf, von Ihnen gelesen zu werden." a_post_you_shared: "ein Beitrag." a_private_message: "Auf diaspora* wartet eine neue private Nachricht darauf, von Ihnen gelesen zu werden." - accept_invite: "Bestätigen Sie Ihre diaspora* Einladung!" also_commented: limited_subject: "Es gibt einen neuen Kommentar zu einem Beitrag, den Sie kommentiert haben" click_here: "Hier klicken" @@ -754,19 +731,21 @@ de_formal: body: |- Hallo %{name}, - Ihre Daten wurden verarbeiten und stehen [hier zum Download bereit](%{url}). + Ihre Daten wurden verarbeiten und können unter [diesem Link](%{url}) heruntergeladen werden. - Gruß, - Der diaspora* email bot! + Grüße, + Der diaspora* E-Mail-Roboter! subject: "Ihre persönlichen Daten sind bereit zum Download, %{name}" export_failure_email: body: |- Hallo %{name}, - Es trat ein Fehler beim Verarbeiten Ihrer Daten auf, bitte versuchen Sie es später noch einmal. + Es ist ein Fehler aufgetreten, während Ihre Daten zum Herunterladen verarbeitet wurden. + Bitte versuchen Sie es noch einmal. Entschuldigung, - Der diaspora* email bot! + + Der diaspora* E-Mail-Roboter! subject: "Entschuldige, es gab einen Fehler beim Verarbeiten Ihrer Daten, %{name}" export_photos_email: body: |- @@ -800,6 +779,8 @@ de_formal: [%{invite_url}][1] + Falls Sie bereits ein Konto besitzen können sie %{diaspora_id} zu Ihren Kontakten hinzufügen. + Alles Liebe, der diaspora* E-Mail Roboter! @@ -815,10 +796,10 @@ de_formal: view_post: "Beitrag betrachten >" mentioned: limited_post: "Sie wurden in einem begrenzten Beitrag erwähnt." - mentioned: "hat Sie in einem Beitrag erwähnt:" subject: "%{name} hat Sie auf diaspora* erwähnt" private_message: reply_to_or_view: "Antworten Sie oder sehen Sie sich diese Unterhaltung an >" + subject: "Es gibt eine neue private Nachricht für Sie" remove_old_user: body: |- Hallo, @@ -841,9 +822,11 @@ de_formal: der %{type} mit der ID %{id} wurde als anstößig markiert. + Grund: "%{reason}" + [%{url}][1] - Bitte überprüfen Sie das so bald wie möglich! + Bitte überprüfen Sie dies so bald wie möglich! Grüße, @@ -859,7 +842,7 @@ de_formal: view_post: "Beitrag anzeigen >" single_admin: admin: "Ihr diaspora* Administrator" - subject: "Eine Nachricht über Ihr diaspora* Konto:" + subject: "Eine Nachricht über Ihr diaspora*-Konto:" started_sharing: sharing: "hat angefangen mit Ihnen zu teilen!" subject: "%{name} hat angefangen mit Ihnen auf diaspora* zu teilen" @@ -868,20 +851,9 @@ de_formal: to_change_your_notification_settings: "um Ihre Benachrichtigungs-Einstellungen zu ändern" nsfw: "NSFW (unpassend für den Arbeitsplatz)" ok: "OK" - or: "oder" - password: "Kennwort" - password_confirmation: "Kennwort-Bestätigung" people: add_contact: invited_by: "Sie wurden eingeladen von" - add_contact_small: - add_contact_from_tag: "Fügen Sie einen Kontakt über einen Hashtag hinzu" - aspect_list: - edit_membership: "Aspekt-Zugehörigkeit bearbeiten" - helper: - is_not_sharing: "%{name} teilt nicht mit Ihnen" - is_sharing: "%{name} teilt mit Ihnen" - results_for: "Ergebnisse für %{params}" index: couldnt_find_them: "Sie konnten sie nicht finden?" looking_for: "Suchen Sie mit %{tag_link} getaggte Beiträge?" @@ -891,105 +863,66 @@ de_formal: search_handle: "Nutzen Sie die diaspora* ID (nutzername@pod.tld) Ihrer Freunde, um sie leichter zu finden." searching: "Suche, bitte warten..." send_invite: "Immer noch nichts? Verschicken Sie eine Einladung!" - one: "Eine Person" - other: "%{count} Personen" person: - add_contact: "Kontakt hinzufügen" - already_connected: "Bereits verbunden" - pending_request: "Ausstehende Anfrage" thats_you: "Das sind Sie!" profile_sidebar: bio: "Beschreibung" born: "Geburtstag" - edit_my_profile: "Mein Profil bearbeiten" gender: "Geschlecht" - in_aspects: "In Aspekten" location: "Ort" - photos: "Fotos" - remove_contact: "Kontakt entfernen" - remove_from: "%{name} aus %{aspect} entfernen?" show: closed_account: "Dieses Konto wurde geschlossen." does_not_exist: "Diese Person existiert nicht!" has_not_shared_with_you_yet: "%{name} hat bisher noch keine Beiträge mit Ihnen geteilt!" - ignoring: "Sie ignorieren sämtliche Beiträge von %{name}." - incoming_request: "Sie haben eine eingehende Anfrage von %{name}." - mention: "Erwähnen" - message: "Nachricht" - not_connected: "Sie teilen nicht mit dieser Person" - recent_posts: "Neueste Beiträge" - recent_public_posts: "Neueste öffentliche Beiträge" - return_to_aspects: "Kehren Sie zu Ihrer Aspekt-Ãœbersicht zurück." - see_all: "Alle zeigen" - start_sharing: "Fangen Sie an zu teilen" - to_accept_or_ignore: "um zu akzeptieren oder zu ignorieren." - sub_header: - add_some: "Füge neue hinzu" - edit: "Bearbeiten" - you_have_no_tags: "Sie haben keine Tags!" - webfinger: - fail: "Entschuldigung, wir konnten %{handle} nicht finden." - zero: "Keine Personen" photos: - comment_email_subject: "%{name}s Foto" create: integrity_error: "Hochladen des Fotos fehlgeschlagen. Sind Sie sicher, dass es eine Bilddatei war?" runtime_error: "Hochladen des Fotos fehlgeschlagen. Sind Sie sicher, dass Sie ihre Morgenkaffee hatten?" type_error: "Hochladen des Fotos fehlgeschlagen. Sind Sie sicher, dass ein Bild hinzugefügt wurde?" destroy: notice: "Foto gelöscht." - edit: - editing: "Bearbeiten" - new: - back_to_list: "Zurück zur Liste" - new_photo: "Neues Foto" - post_it: "Teilen!" new_photo: empty: "{file} ist leer, bitte wählen Sie erneut Dateien aus." invalid_ext: "{file} hat keine gültige Erweiterung. Nur {extensions} sind erlaubt." size_error: "{file} ist zu groß. Die maximale Dateigröße beträgt {sizeLimit}." new_profile_photo: - or_select_one_existing: "oder eins Ihrer bereits hochgeladenen %{photos} auswählen" upload: "Laden Sie ein neues Profilfoto hoch!" - photo: - view_all: "Zeige alle Fotos von %{name}" show: - collection_permalink: "Sammlungs-Permalink" - delete_photo: "Foto löschen" - edit: "Bearbeiten" - edit_delete_photo: "Fotobeschreibung bearbeiten / Foto löschen" - make_profile_photo: "Als Profilbild verwenden" show_original_post: "Zeige ursprünglichen Beitrag" - update_photo: "Foto aktualisieren" - update: - error: "Bearbeiten des Fotos fehlgeschlagen." - notice: "Foto erfolgreich aktualisiert." + polls: + votes: + one: "Bisher eine Stimme." + other: "Bisher %{count} Stimmen." + zero: "Bisher keine Stimmen." posts: presenter: title: "Ein Beitrag von %{name}" show: - destroy: "Löschen" forbidden: "Sie sind nicht berechtigt, das zu tun" - not_found: "Entschuldigen Sie, wir konnten den Beitrag leider nicht finden." - permalink: "Permanentlink" + location: "Erstellt in: %{location}" photos_by: one: "Ein Foto von %{author}" other: "%{count} Fotos von %{author}" zero: "Kein Foto von %{author}" reshare_by: "Weitergesagt von %{author}" - previous: "Vorherige" privacy: "Privatsphäre" - privacy_policy: "Datenschutzerklärung" profile: "Profil" profiles: edit: allow_search: "Erlauben Sie anderen, auf diaspora* nach Ihnen zu suchen" - edit_profile: "Profil bearbeiten" + basic: "Mein grundlegendes Profil" + basic_hint: "Jeder Eintrag in Ihrem Profil ist freiwillig. Ihr grundlegendes Profil wird immer öffentlich sein." + extended: "Mein erweitertes Profil" + extended_hint: "Klicken Sie auf den Schalter, um die Sichtbarkeit Ihrer erweiterten Profildaten zu ändern. Öffentlich heißt, dass sie für das Internet sichtbar sind, begrenzt heißt, dass nur Leute, mit denen Sie teilen, die Informationen sehen werden." + extended_visibility_text: "Sichtbarkeit Ihres erweiterten Profils:" first_name: "Vorname" last_name: "Nachname" + limited: "Begrenzt" nsfw_check: "Markiere alles, was ich teile, als NSFW" nsfw_explanation: "NSFW („Not safe for work“, dt. „Unpassend für den Arbeitsplatz“) ist diaspora*s sich selbst verwaltender Community-Standard für Inhalte, die für das Ansehen während der Arbeit möglicherweise ungeeignet sind. Bitte aktivieren Sie diese Option, falls Sie häufig derartiges Material teilen möchten, damit es in den Streams anderer Leute, die es nicht sehen wollen, ausgeblendet wird." nsfw_explanation2: "Wenn Sie diese Option nicht verwenden möchten, markieren Sie entsprechendes Material bitte mit dem Tag #nsfw." + public: "Öffentlich" + settings: "Profileinstellungen" update_profile: "Profil aktualisieren" your_bio: "Ihre Beschreibung" your_birthday: "Ihr Geburtstag" @@ -997,8 +930,6 @@ de_formal: your_location: "Ihr Ort" your_name: "Ihr Name" your_photo: "Ihr Profilbild" - your_private_profile: "Ihr privates Profil" - your_public_profile: "Ihr öffentliches Profil" your_tags: "Beschreiben Sie sich in 5 Worten" your_tags_placeholder: "Zum Beispiel: #Diaspora #lustig #Kätzchen #Musik" update: @@ -1016,26 +947,16 @@ de_formal: closed: "Neuregistrierungen sind auf diesem Pod geschlossen." create: success: "Sie sind diaspora* beigetreten!" - edit: - cancel_my_account: "Mein Konto schließen" - edit: "%{name} bearbeiten" - leave_blank: "(Sie wollen nichts ändern? Einfach leer lassen.)" - password_to_confirm: "(wir brauchen Ihr aktuelles Passwort, um Ihre Änderungen zu bestätigen)" - unhappy: "Unglücklich?" - update: "Aktualisieren" invalid_invite: "Der von Ihnen erstellte Einladungs-Link ist nicht mehr gültig!" new: - create_my_account: "Konto erstellen" email: "E-Mail" enter_email: "Geben Sie Ihre E-Mail-Adresse an" - enter_password: "Geben Sie ein Kennwort ein (mindestens sechs Zeichen)" - enter_password_again: "Geben Sie das gleiche Kennwort wie zuvor ein" + enter_password: "Geben Sie ein Passwort ein (mindestens sechs Zeichen)" + enter_password_again: "Geben Sie das gleiche Passwort ein wie zuvor" enter_username: "Wählen Sie einen Nutzernamen (nur Buchstaben, Nummern und Unterstriche)" - join_the_movement: "Treten Sie der Bewegung bei!" password: "Passwort" password_confirmation: "Passwort bestätigen" - sign_up: "Registrieren" - sign_up_message: "Soziales Netzwerken mit ♥" + sign_up: "Konto erstellen" submitting: "Absenden..." terms: "Indem Sie ein Konto erstellen, akzeptieren Sie die %{terms_link}." terms_link: "Nutzungsbedingungen" @@ -1048,45 +969,18 @@ de_formal: post_label: "<b>Beitrag</b>: %{title}" reason_label: "Grund: %{text}" reported_label: "<b>Gemeldet von</b> %{person}" + reported_user_details: "Details des gemeldeten Benutzers" review_link: "Als überprüft markieren" status: - created: "Eine Meldung wurde erstellt" destroyed: "Der Beitrag wurde gelöscht" failed: "Ein Fehler ist aufgetreten" - marked: "Die Meldung wurde als überprüft markiert" title: "Meldungsübersicht" - requests: - create: - sending: "Senden …" - sent: "Sie haben angefragt mit %{name} zu teilen. Er/sie sollte dies sehen, wenn er/sie sich das nächste Mal bei diaspora* einloggt." - destroy: - error: "Bitte wählen Sie einen Aspekt!" - ignore: "Kontaktanfrage ignoriert." - success: "Sie sind jetzt verbunden." - helper: - new_requests: - one: "Eine neue Anfrage!" - other: "%{count} neue Anfragen!" - zero: "Keine neuen Anfragen" - manage_aspect_contacts: - existing: "Bestehende Kontakte" - manage_within: "Kontakte verwalten in" - new_request_to_person: - sent: "Gesendet!" reshares: comment_email_subject: "%{resharer}s Version von %{author}s Beitrag" - create: - failure: "Ein Fehler trat beim Weitersagen dieses Beitrags auf." reshare: - deleted: "Originalbeitrag wurde vom Autor entfernt." - reshare: - one: "1 mal weitergesagt" - other: "%{count} mal weitergesagt" - zero: "Weitersagen" + deleted: "Originalbeitrag wurde vom Autor gelöscht." reshare_confirmation: "%{author}'s Beitrag weitersagen?" - reshare_original: "Original weitersagen" reshared_via: "Weitergesagt durch" - show_original: "Original anzeigen" search: "Suche" services: create: @@ -1098,10 +992,6 @@ de_formal: success: "Authentifizierung erfolgreich gelöscht." failure: error: "Es gab einen Fehler der Verbindung mit dem Dienst" - finder: - fetching_contacts: "Ihre %{service}-Freunde werden momentan eingeladen. Schauen Sie bitte in ein paar Minuten noch mal vorbei!" - no_friends: "Keine Facebook-Freunde gefunden." - service_friends: "%{service}-Freunde" index: connect: "Verbinden" disconnect: "Verbindung entfernen" @@ -1111,33 +1001,16 @@ de_formal: not_logged_in: "Sie sind momentan nicht angemeldet." really_disconnect: "Verbindung mit %{service} entfernen?" services_explanation: "Wenn Sie sich mit anderen Diensten verbinden, erhalten Sie die Möglichkeit ihre Beiträge auch dort zu veröffentlichen, indem Sie in diaspora* schreiben." - inviter: - click_link_to_accept_invitation: "Öffnen Sie diesen Link, um die Einladung zu akzeptieren:" - join_me_on_diaspora: "Folgen Sie mir auf diaspora*" + share_to: "Mit %{provider} teilen" + title: "Verbundene Dienste verwalten" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "Einladen" - not_on_diaspora: "Noch nicht auf diaspora*" - resend: "Erneut senden" settings: "Einstellungen" - share_visibilites: - update: - post_hidden_and_muted: "%{name}s Beitrag wurde versteckt und Benachrichtigungen stumm geschaltet." - see_it_on_their_profile: "Wenn Sie Aktualisierungen dieses Beitrags sehen wollen, besuchen Sie %{name}s Profil." shared: - add_contact: - add_new_contact: "Einen neuen Kontakt hinzufügen" - create_request: "Mittels diaspora* ID finden" - diaspora_handle: "diaspora@beispiel.org" - enter_a_diaspora_username: "Geben Sie einen diaspora*-Nutzernamen ein:" - know_email: "Sie kennen die E-Mail-Adresse? Senden Sie eine Einladung!" - your_diaspora_username_is: "Ihr diaspora*-Nutzername ist: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Kontakt hinzufügen" mobile_row_checked: "%{name} (entfernen)" mobile_row_unchecked: "%{name} (hinzufügen)" toggle: @@ -1147,23 +1020,11 @@ de_formal: other: "In %{count} Aspekten" two: "In %{count} Aspekten" zero: "Kontakt hinzufügen" - contact_list: - all_contacts: "Alle Kontakte" - footer: - logged_in_as: "Angemeldet als %{name}" - your_aspects: "Ihre Aspekte" invitations: by_email: "Per E-Mail" - dont_have_now: "Sie haben im Moment keine Einladungen zur Verfügung, es wird aber bald wieder neue geben!" - from_facebook: "Von Facebook" - invitations_left: "%{count} übrig" - invite_someone: "Jemanden einladen" invite_your_friends: "Laden Sie Ihre Freunde ein" invites: "Einladungen" - invites_closed: "Einladungen sind auf diesem diaspora*-Pod derzeit geschlossen" share_this: "Teilen Sie diesen Link per E-Mail, Blog oder soziale Netzwerke!" - notification: - new: "Neue %{type} von %{from}" public_explain: atom_feed: "Atom-Feed" control_your_audience: "Kontrollieren Sie Ihre Zielgruppe" @@ -1175,12 +1036,9 @@ de_formal: title: "Verbundene Dienste verwalten" visibility_dropdown: "Benutzen Sie dieses Auswahlmenü um die Sichtbarkeit Ihres Betrags zu ändern. (Wir empfehlen Ihnen den erst Öffentlich zu machen.)" publisher: - all: "Alle" - all_contacts: "Alle Kontakte" discard_post: "Beitrag verwerfen" formatWithMarkdown: "Sie können %{markdown_link} verwenden, um Ihren Beitrag zu formatieren" get_location: "Ihren Standort ermitteln" - make_public: "Veröffentlichen" new_user_prefill: hello: "Hallo zusammen, ich bin #%{new_user_tag}. " i_like: "Ich interessiere mich für %{tags}." @@ -1188,36 +1046,14 @@ de_formal: newhere: "neuhier" poll: add_a_poll: "Eine Umfrage hinzufügen" - add_poll_answer: "Option hinzufügen" - option: "Option 1" - question: "Frage" - remove_poll_answer: "Option entfernen" - post_a_message_to: "Senden Sie eine Nachricht an %{aspect}" posting: "Senden …" - preview: "Vorschau" - publishing_to: "Veröffentlichen an: " remove_location: "Position entfernen" share: "Teilen" - share_with: "Teilen Sie mit" upload_photos: "Fotos hochladen" whats_on_your_mind: "Woran denken Sie gerade?" - reshare: - reshare: "Weitersagen" stream_element: - connect_to_comment: "Verbinden Sie sich mit diesem Benutzer, um seinen Beitrag zu kommentieren" - currently_unavailable: "Kommentieren derzeit nicht verfügbar" - dislike: "Gefällt mir nicht" - hide_and_mute: "Verbergen und stummschalten" - ignore_user: "%{name} ignorieren" - ignore_user_description: "Benutzer ignorieren und aus allen Aspekten entfernen?" - like: "Gefällt mir" - nsfw: "Dieser Beitrag wurde vom Autor als \"unpassend für den Arbeitsplatz\" (NSFW) markiert. %{link}" - shared_with: "Geteilt mit: %{aspect_names}" - show: "Anzeigen" - unlike: "Gefällt mir nicht mehr" via: "Via %{link}" via_mobile: "Ãœber mobil" - viewable_to_anyone: "Dieser Beitrag ist für jeden im Web sichtbar" simple_captcha: label: "Geben Sie den Code in das Feld ein:" message: @@ -1243,21 +1079,12 @@ de_formal: status_messages: create: success: "Erfolgreich erwähnt: %{names}" - destroy: - failure: "Fehler beim Löschen des Posts" - helper: - no_message_to_display: "Keine Nachricht zum Anzeigen." new: mentioning: "Erwähnt: %{person}" too_long: "Bitte kürzen Sie Ihren Beitrag auf weniger als %{count} Zeichen. Im Moment enthält er %{current_length} Zeichen" stream_helper: - hide_comments: "Alle Kommentare verbergen" no_more_posts: "Sie haben das Ende des Streams erreicht." no_posts_yet: "Es existieren noch keine Beiträge." - show_comments: - one: "Zeige einen weiteren Kommentar" - other: "Zeige %{count} weitere Kommentare" - zero: "Kein weiterer Kommentar" streams: activity: title: "Ihre Aktivitäten" @@ -1284,13 +1111,6 @@ de_formal: tags: title: "Getaggte Beiträge: %{tags}" tag_followings: - create: - failure: "Fehler beim Folgen von: #%{name}" - none: "Sie können keinem leeren Tag folgen!" - success: "Sie folgen nun: #%{name}" - destroy: - failure: "Fehler beim Beenden des Folgens von: #%{name}" - success: "Sie folgen #%{name} nicht mehr" manage: no_tags: "Sie folgen keinen Tags." title: "Gefolgte Tags verwalten" @@ -1298,60 +1118,55 @@ de_formal: name_too_long: "Bitte kürzen Sie Ihren Tag-Namen auf weniger als %{count} Zeichen. Im Moment enthält er %{current_length} Zeichen" show: follow: "#%{tag} folgen" - following: "#%{tag} folgen" none: "Der leere Tag existiert nicht!" stop_following: "#%{tag} nicht mehr folgen" tagged_people: one: "1 Person getaggt mit %{tag}" other: "%{count} Personen getaggt mit %{tag}" zero: "Keiner getaggt mit %{tag}" - terms_and_conditions: "Nutzungsbedingungen" - undo: "Rückgängig machen?" username: "Benutzername" users: confirm_email: email_confirmed: "E-Mail %{email} wurde aktiviert" email_not_confirmed: "Die E-Mail-Adresse konnte nicht aktiviert werden. Falscher Link?" destroy: - no_password: "Bitte geben Sie Ihr Kennwort ein, um Ihren Account zu schließen." - success: "Ihr Account wurde gesperrt. Es kann bis zu 20 Minuten dauern, bis Ihr Account endgültig geschlossen ist. Vielen Dank, dass Sie diaspora* ausprobiert haben." - wrong_password: "Das eingegebene Kennwort stimmt nicht mit Ihrem aktuellen Kennwort überein." + no_password: "Bitte geben Sie Ihr Passwort ein, um Ihr Konto zu schließen." + success: "Ihr Konto wurde gesperrt. Es kann bis zu 20 Minuten dauern, bis Ihr Konto endgültig geschlossen ist. Vielen Dank, dass Sie diaspora* ausprobiert haben." + wrong_password: "Das eingegebene Passwort stimmte nicht mit Ihrem aktuellen Passwort überein." edit: also_commented: "jemand ebenfalls einen Beitrag kommentiert, den Sie kommentiert haben" auto_follow_aspect: "Aspekt für Benutzer mit denen Sie automatisch teilen:" auto_follow_back: "Automatisch mit Benutzern teilen, die anfangen, mit Ihnen zu teilen" change: "Ändern" + change_color_theme: "Farbthema ändern" change_email: "E-Mail-Adresse ändern" change_language: "Sprache ändern" change_password: "Passwort ändern" character_minimum_expl: "bitte mindestens sechs Zeichen eingeben" close_account: dont_go: "Bitte gehen Sie nicht!" - if_you_want_this: "Wenn Sie wirklich möchten, dass das passiert, geben Sie Ihr Kennwort ein und klicken Sie auf „Konto schließenâ€" lock_username: "Ihr Benutzername wird gesperrt werden. Sie werden auf diesem Pod kein neues Konto mit derselben ID erstellen können." - locked_out: "Sie werden abgemeldet und von Ihrem Account ausgesperrt, bis es gelöscht wurde." + locked_out: "Sie werden abgemeldet und von Ihrem Konto ausgesperrt, bis es gelöscht wurde." make_diaspora_better: "Wir würden uns freuen, wenn Sie bleiben und uns helfen, diaspora* besser zu machen, anstatt uns zu verlassen. Wenn Sie uns jedoch wirklich verlassen möchten, wird folgendes passieren:" mr_wiggles: "Mr. Wiggles wird traurig sein, wenn Sie gehen" no_turning_back: "Es gibt kein Zurück! Wenn Sie sich wirklich sicher sind, geben Sie Ihr Passwort unten ein." what_we_delete: "Wir löschen alle Ihre Beiträge und Ihr Profil so schnell wie möglich. Ihre Kommentare auf Beiträge anderer Leute werden noch angezeigt, aber Sie werden mit Ihrer diaspora*-ID anstatt mit Ihrem Namen verknüpft." close_account_text: "Konto schließen" comment_on_post: "jemand Ihren Beitrag kommentiert" - current_password: "Derzeitiges Kennwort" + current_password: "Derzeitiges Passwort" current_password_expl: "das mit dem Sie sich anmelden..." download_export: "Mein Profil herunterladen" download_export_photos: "Meine Fotos herunterladen" - download_photos: "Meine Fotos herunterladen" edit_account: "Konto bearbeiten" email_awaiting_confirmation: "Wir haben Ihnen einen Aktivierungslink zu %{unconfirmed_email} geschickt. Solange Sie dem Link nicht gefolgt sind und die neue Adresse aktiviert haben, werden wir weiterhin Ihre ursprüngliche E-Mail-Adresse %{email} verwenden." export_data: "Daten exportieren" export_in_progress: "Vorbereitung Ihrer Daten läuft - schauen Sie etwas später noch mal vorbei." export_photos_in_progress: "Ihre Fotos werden derzeit verarbeitet. Bitte sehen Sie in wenigen Augenblicken erneut nach." following: "Teilen-Einstellungen" - getting_started: "Einstellungen für neue Nutzer" last_exported_at: "(Zuletzt aktualisiert um %{timestamp})" liked: "wenn jemandem Ihr Beitrag gefällt" mentioned: "Sie in einem Beitrag erwähnt werden" - new_password: "Neues Kennwort" + new_password: "Neues Passwort" private_message: "Sie eine private Nachricht erhalten" receive_email_notifications: "E-Mail-Benachrichtigungen empfangen, wenn:" request_export: "Meine Profildaten anfordern" @@ -1374,7 +1189,6 @@ de_formal: connect_to_facebook_link: "Ihr Facebook-Konto mit diaspora* verlinken" hashtag_explanation: "Hashtags ermöglichen Ihnen, über Ihre Interessen zu reden und ihnen zu folgen. Sie sind auch ein guter Weg, neue Leute bei diaspora* zu treffen!" hashtag_suggestions: "Probieren Sie mal Tags wie #kunst, #musik oder #gif zu folgen." - saved: "Gespeichert!" well_hello_there: "Also, Hallöchen!" what_are_you_in_to: "Was machen Sie so?" who_are_you: "Wer sind Sie?" @@ -1387,24 +1201,19 @@ de_formal: public: does_not_exist: "Benutzer %{username} existiert nicht!" update: + color_theme_changed: "Farbthema erfolgreich geändert." + color_theme_not_changed: "Beim ändern des Farbthemas ist ein Fehler aufgetreten." email_notifications_changed: "E-Mail-Benachrichtigungen geändert" follow_settings_changed: "Folgen-Einstellungen geändert" follow_settings_not_changed: "Ändern der Folgen-Einstellungen fehlgeschlagen." language_changed: "Sprache geändert" language_not_changed: "Fehler beim Ändern der Sprache." - password_changed: "Kennwort geändert. Sie können sich nun mit Ihrem neuen Kennwort anmelden." - password_not_changed: "Fehler beim Ändern des Kennwort." + password_changed: "Passwort geändert. Sie können sich nun mit Ihrem neuen Passwort anmelden." + password_not_changed: "Passwortänderung fehlgeschlagen" settings_not_updated: "Aktualisierung der Einstellungen fehlgeschlagen" settings_updated: "Einstellungen aktualisiert" unconfirmed_email_changed: "E-Mail-Adresse geändert. Benötigt Aktivierung." unconfirmed_email_not_changed: "Fehler bei Änderung der E-Mail-Adresse" - webfinger: - fetch_failed: "Konnte Webfinger-Profil für %{profile_url} nicht laden" - hcard_fetch_failed: "Es gab ein Problem beim Laden der hcard für %{account}" - no_person_constructed: "Konnte keine Person aus dieser hcard erstellen." - not_enabled: "Webfinger scheint nicht für den Server von %{account} verfügbar zu sein." - xrd_fetch_failed: "Die XRD-Datei von %{account} konnte nicht heruntergeladen werden." - welcome: "Willkommen!" will_paginate: next_label: "Weiter »" previous_label: "« Zurück" \ No newline at end of file diff --git a/config/locales/diaspora/el.yml b/config/locales/diaspora/el.yml index 7d247efb0cba51de5fec52e288b5ccf64173712b..381ee15a44405e8c066b830c2eb91e89ba522216 100644 --- a/config/locales/diaspora/el.yml +++ b/config/locales/diaspora/el.yml @@ -6,11 +6,8 @@ el: _applications: "ΕφαÏμογÎÏ‚" - _comments: "Σχόλια" _contacts: "ΕπαφÎÏ‚" _help: "Βοήθεια" - _home: "ΑÏχική" - _photos: "ΦωτογÏαφίες" _services: "ΥπηÏεσίες" account: "ΛογαÏιασμός" activerecord: @@ -99,13 +96,7 @@ el: other: "ΣÏνολο νÎων χÏηστών αυτήν την βδομάδα: %{count}" zero: "ΣÏνολο νÎων χÏηστών αυτήν την βδομάδα: κανείς" current_server: "Η ημεÏομηνία στον server είναι %{date}" - ago: "Ï€Ïιν από %{time}" all_aspects: "Όλες οι πτυχÎÏ‚" - application: - helper: - unknown_person: "Άγνωστο άτομο" - video_title: - unknown: "Άγνωστος τίτλος video" are_you_sure: "Είσαι σίγουÏος;" are_you_sure_delete_account: "ΘÎλεις σίγουÏα να κλείσεις τον λογαÏιασμό σου; Αυτό δεν μποÏεί να αναιÏεθεί!" aspect_memberships: @@ -119,47 +110,26 @@ el: success: "Επιτυχής Ï€Ïοσθήκη επαφής στην πτυχή." aspect_listings: add_an_aspect: "+ Î ÏοσθÎστε μια πτυχή" - deselect_all: "Αποεπιλογή όλων" - edit_aspect: "ΕπεξεÏγασία %{name}" - select_all: "Επιλογή όλων" aspect_stream: make_something: "Κάνε κάτι" stay_updated: "Μείνε ενημεÏωμÎνος" stay_updated_explanation: "Η κεντÏική σου Ïοή απαÏτίζεται από όλες τις επαφÎÏ‚ σου, ετικÎτες που ακολουθείς, και αναÏτήσεις από μεÏικά ενεÏγά μÎλη της κοινότητας." - contacts_not_visible: "Οι επαφÎÏ‚ σ' αυτήν την πτυχή δεν θα μποÏοÏν να δουν ο Îνας τον άλλον." - contacts_visible: "Οι επαφÎÏ‚ σ' αυτήν την πτυχή θα μποÏοÏν να δουν ο Îνας τον άλλον." - create: - failure: "Η δημιουÏγία της πτυχής απÎτυχε." - success: "Η νÎα σου πτυχή %{name} δημιουÏγήθηκε" destroy: failure: "Το %{name} δεν μποÏεί να αφαιÏεθεί." success: "Ο/Η %{name} αφαιÏÎθηκε επιτυχώς." edit: - aspect_chat_is_enabled: "Οι επαφÎÏ‚ σε αυτήν την πτυχή μποÏοÏν να συνομιλήσουν μαζί σου." - aspect_chat_is_not_enabled: "Οι επαφÎÏ‚ σε αυτήν την πτυχή δεν μποÏοÏν να συνομιλήσουν μαζί σου." aspect_list_is_not_visible: "η λίστα σου είναι κÏυφή στους άλλους στην πτυχή" aspect_list_is_visible: "Οι επαφÎÏ‚ αυτής της πτυχής είναι οÏατÎÏ‚ Î¼ÎµÏ„Î±Î¾Ï Ï„Î¿Ï…Ï‚." confirm_remove_aspect: "ΘÎλεις σίγουÏα να διαγÏάψεις αυτή την πτυχή;" - grant_contacts_chat_privilege: "Îα δωθοÏν δικαίωματα συνομιλίας στις επαφÎÏ‚ αυτής της πτυχής;" - make_aspect_list_visible: "ΘÎλεις οι επαφÎÏ‚ αυτής της πτυχής να είναι οÏατÎÏ‚ Î¼ÎµÏ„Î±Î¾Ï Ï„Î¿Ï…Ï‚;" - remove_aspect: "ΔιαγÏαφή αυτής της πτυχής" rename: "Μετονομασία" - set_visibility: "ΟÏισμός οÏατότητας" update: "ΕνημÎÏωση" updating: "ΕνημÎÏωση" index: - diaspora_id: - content_1: "Το diaspora* αναγνωÏιστικό σου (ID) είναι:" - content_2: "Δώσε το σε κάποιον και θα μποÏεί να σε βÏει στο diaspora*." - heading: "ΑναγνωÏιστικό diaspora* (ID)" donate: "Κάνε μια ΔωÏεά" - handle_explanation: "Αυτό είναι το αναγνωÏιστικό σου στο diaspora* (ID). Όπως και με μια διεÏθυνση email, μποÏείς να το δώσεις σε άλλους για να σε βÏουν." help: any_problem: "ΥπάÏχει Ï€Ïόβλημα;" contact_podmin: "Επικοινώνησε με τον διαχειÏιστή του pod!" do_you: "Μήπως.." - email_feedback: "Αν θÎλεις, μποÏείς να στείλεις τα σχόλιά σου με %{link}." - email_link: "Email" feature_suggestion: "... Îχεις να Ï€Ïοτείνεις Îνα χαÏακτηÏιστικό %{link} ;" find_a_bug: "... βÏήκες Îνα σφάλμα %{link} ;" have_a_question: "... Îχεις μία εÏώτηση %{link} ;" @@ -172,31 +142,20 @@ el: tutorial_link_text: "Οδηγοί" tutorials_and_wiki: "%{faq}, %{tutorial} και %{wiki} : Βοήθεια για τα Ï€Ïώτα σου βήματα." introduce_yourself: "Αυτή είναι η Ροή σου. Μπες και συστήσου." - keep_diaspora_running: "ΚÏάτησε την ανάπτυξη του diaspora* σε γÏήγοÏους ÏυθμοÏÏ‚ με μια μηνιαία δωÏεά!" keep_pod_running: "Βοήθησε στην ομαλή λειτουÏγία του %{pod}, Ï€ÏοσφÎÏοντας Îνα κÎÏασμα στους διαχειÏιστÎÏ‚ των servers μας!" new_here: follow: "ΑκολοÏθησε την ετικÎτα %{link} και καλωσόÏισε νÎους χÏήστες στο diaspora*!" learn_more: "Μάθε πεÏισσότεÏα" title: "ΚαλωσόÏισε ÎÎους ΧÏήστες" - no_contacts: "Καμία επαφή" - no_tags: "+ Î’Ïες μια ετικÎτα να ακολουθήσεις" - people_sharing_with_you: "Άτομα που μοιÏάζονται μαζί σου" - post_a_message: "Δημοσίευσε Îνα μήνυμα >>" services: content: "ΜποÏείς να συνδÎσεις τις παÏακάτω υπηÏεσίες στο diaspora*:" heading: "ΣÏνδεσε ΥπηÏεσίες" - unfollow_tag: "Σταμάτα να ακολουθείς την ετικÎτα #%{tag}" welcome_to_diaspora: "ΚαλωσήÏθες στο diaspora*, %{name}!" - new: - create: "ΔημιουÏγία" - name: "Όνομα (εμφανίζετε μόνο σε σÎνα)" no_contacts_message: community_spotlight: "ÎœÎλη της κοινότητας" or_spotlight: "Ή μποÏείς να το μοιÏαστείς με %{link}" try_adding_some_more_contacts: "ΜποÏείς να ψάξεις ή να Ï€ÏοσκαλÎσεις πεÏισσότεÏες επαφÎÏ‚." you_should_add_some_more_contacts: "Î ÏÎπει να Ï€ÏοσθÎσεις πεÏισσότεÏες επαφÎÏ‚!" - no_posts_message: - start_talking: "ΚανÎνας δεν Îχει δημοσιεÏσει κάτι ακόμα!" seed: acquaintances: "ΓνωÏιμίες" family: "ΟικογÎνεια" @@ -205,7 +164,6 @@ el: update: failure: "Η πτυχή σου, %{name}, Îχει Ï€Î¿Î»Ï Î¼ÎµÎ³Î¬Î»Î¿ όνομα για να αποθηκευτεί." success: "Έγινε επιτυχώς η επεξεÏγασία της πτυχής σου, %{name}." - back: "Πίσω" blocks: create: failure: "Δεν μπόÏεσα να αγνοήσω αυτόν τον χÏήστη. #evasion" @@ -217,21 +175,14 @@ el: explanation: "ανάÏτησε στο diaspora* από οπουδήποτε, σÏÏε αυτό τον σÏνδεσμο στα αγαπημÎνα => %{link}." heading: "ΕφαÏμογή σελιδοδείκτη" post_something: "ΑνάÏτησε στο diaspora*" - post_success: "ΑναÏτήθηκε! Κλείνει!" cancel: "ΑκÏÏωση" comments: new_comment: comment: "Σχολίασε" commenting: "Σχολιάζει..." - one: "1 σχόλιο" - other: "%{count} σχόλια" - zero: "ΚανÎνα σχόλιο" contacts: - create: - failure: "Αποτυχία δημιουÏγίας επαφής" index: add_a_new_aspect: "Î Ïόσθεσε μια νÎα πτυχή" - add_to_aspect: "Î Ïόσθεσε επαφÎÏ‚ στο %{name}" all_contacts: "Όλες οι επαφÎÏ‚" community_spotlight: "ΔημοσιεÏσεις κοινότητας" my_contacts: "Οι επαφÎÏ‚ μου" @@ -240,33 +191,18 @@ el: only_sharing_with_me: "ΜοιÏάζονται μόνο με εμÎνα" start_a_conversation: "Ξεκίνα μια συζήτηση" title: "ΕπαφÎÏ‚" - your_contacts: "Οι επαφÎÏ‚ σου" - sharing: - people_sharing: "Άτομα που μοιÏάζονται μαζί σου:" spotlight: community_spotlight: "ΔημοσιεÏσεις κοινότητας" suggest_member: "Î Ïότεινε Îνα μÎλος" conversations: - conversation: - participants: "ΣυμμετÎχοντες" create: fail: "Μη ÎγκυÏο μήνυμα" no_contact: "Î ÏÎπει Ï€Ïώτα να Ï€ÏοσθÎσεις μια επαφή!" sent: "Μήνυμα εστάλη" - helper: - new_messages: - few: "%{count} νÎα μηνÏματα" - many: "%{count} νÎα μηνÏματα" - one: "1 νÎο μήνυμα" - other: "%{count} νÎα μηνÏματα" - two: "%{count} νÎα μηνÏματα" - zero: "ΚανÎνα νÎο μήνυμα" index: inbox: "ΕισεÏχόμενα" - no_conversation_selected: "Δεν επιλÎχτηκε συζήτηση" no_messages: "ΚανÎνα μήνυμα" new: - abandon_changes: "ΑπόÏÏιψη αλλαγών;" send: "Αποστολή" sending: "Αποστολή..." subject: "ΘÎμα" @@ -285,9 +221,6 @@ el: error_messages: helper: correct_the_following_errors_and_try_again: "ΔιόÏθωσε τα ακόλουθα σφάλματα και Ï€Ïοσπάθησε ξανά." - invalid_fields: "ΆκυÏα πεδία" - login_try_again: "ΠαÏακαλώ <a href='%{login_link}'>συνδÎσου</a> και ξαναπÏοσπάθησε." - post_not_public: "Η ανάÏτηση που Ï€Ïοσπαθείς να δεις δεν είναι δημόσια!" fill_me_out: "ΕνημÎÏωσε με" find_people: "Î’Ïες άτομα ή #ετικÎτες" help: @@ -342,45 +275,27 @@ el: tutorial: "οδηγός" tutorials: "οδηγοί" wiki: "wiki" - hide: "ΑπόκÏυψη" - ignore: "Αγνόησε" - invitation_codes: - excited: "Ο/Η %{name} χαίÏεται που σε βλÎπει εδώ." invitations: a_facebook_user: "Ένας χÏήστης του Facebook" check_token: not_found: "Το σÏμβολο της Ï€Ïόσκλησης δεν βÏÎθηκε" create: - already_contacts: "Είσαι ήδη συνδεδεμÎνος με αυτό το άτομο" - already_sent: "Έχεις ήδη Ï€ÏοσκαλÎσει αυτό το άτομο." empty: "ΠαÏακαλώ εισήγαγε τουλάχιστον μία διεÏθυνση email." no_more: "Δεν Îχεις άλλες Ï€Ïοσκλήσεις." note_already_sent: "Î Ïοσκλήσεις Îχουν ήδη σταλεί στα: %{emails}" - own_address: "Δεν μποÏείς να στείλεις Ï€Ïόσκληση στη διεÏθυνση σου." rejected: "Οι παÏακάτω διευθÏνσεις email είχαν Ï€Ïοβλήματα: " sent: "Η Ï€Ïοσκλήσεις σου Îχουν σταλεί στα: %{emails}" - edit: - accept_your_invitation: "ΑποδÎξου την Ï€Ïόσκληση" - your_account_awaits: "Ο λογαÏιασμός σου πεÏιμÎνει!" new: - already_invited: "Τα παÏακάτω άτομα δεν αποδÎχτηκαν την Ï€Ïόσκληση σου:" - aspect: "Πτυχή" - check_out_diaspora: "Δοκίμασε το diaspora*!" codes_left: one: "Μία Ï€Ïόσκληση απομÎνει γι' αυτό τον κωδικό" other: "%{count} Ï€Ïοσκλήσεις απομÎνουν γι' αυτό τον κωδικό" zero: "Δεν απομÎνουν Ï€Ïοσκλήσεις γι' αυτό τον κωδικό" comma_separated_plz: "ΜποÏείς να εισάγεις πολλαπλÎÏ‚ διευθÏνσεις email χωÏισμÎνες με κόμμα." - if_they_accept_info: "αν δεχτοÏν, θα Ï€ÏοστεθοÏν στην πτυχή που τους Ï€Ïοσκάλεσες." invite_someone_to_join: "Î Ïοσκάλεσε κάποιον στο diaspora*!" language: "Γλώσσα" paste_link: "ΜοιÏάσου αυτόν τον σÏνδεσμο με τους φίλους σου για να τους Ï€ÏοσκαλÎσετε στο diaspora*, ή στείλε τον απευθείας με email." - personal_message: "Î Ïοσωπικό μήνυμα" - resend: "Αποστολή ξανά" send_an_invitation: "Στείλε μια Ï€Ïόσκληση" - send_invitation: "Στείλε Ï€Ïόσκληση" sending_invitation: "Αποστολή Ï€Ïόσκλησης..." - to: "Στον" layouts: application: back_to_top: "Πίσω στην αÏχή" @@ -389,38 +304,13 @@ el: source_package: "ΜεταφοÏτώστε το πακÎτο του πηγαίου κώδικα" toggle: "Αλλαγή σε κινητό" whats_new: "Τι νÎα;" - your_aspects: "Οι πτυχÎÏ‚ σου" header: - admin: "ΔιαχειÏιστής" - blog: "Iστολόγιo" code: "Κώδικας" - help: "Βοήθεια" - login: "Είσοδος" logout: "ΑποσÏνδεση" profile: "Î Ïοφίλ" - recent_notifications: "Î Ïόσφατες ειδοποιήσεις" settings: "Ρυθμίσεις" - view_all: "Î Ïοβολή όλων" - likes: - likes: - people_dislike_this: - one: "Δεν αÏÎσει σε 1 άτομο" - other: "Δεν αÏÎσει σε %{count} άτομα" - zero: "ΚανÎνας δεν ανÎφεÏε ότι δεν του αÏÎσει" - people_like_this: - one: "ΑÏÎσει σε 1 άτομο" - other: "ΑÏÎσει σε %{count} άτομα" - zero: "Δεν αÏÎσει σε κανÎναν" - people_like_this_comment: - few: "ΑÏÎσει σε %{count} χÏήστες" - many: "ΑÏÎσει σε %{count} χÏήστες" - one: "ΑÏÎσει σε %{count} χÏήστη" - other: "ΑÏÎσει σε %{count} χÏήστες" - two: "αÏÎσει σε %{count}" - zero: "Δεν αÏÎσει σε κανÎναν " limited: "ΠεÏιοÏισμÎνο" more: "ΠεÏισσότεÏα" - next: "Επόμενο" no_results: "Δεν βÏÎθηκαν αποτελÎσματα" notifications: also_commented: @@ -435,14 +325,6 @@ el: one: "Ο/Η %{actors} σχολίασε στη δημοσίευση σου %{post_link}." other: "Οι %{actors} σχολίασαν στη δημοσίευση σου %{post_link}." zero: "Ο/Η %{actors} σχολίασε στη δημοσίευση σου %{post_link}." - helper: - new_notifications: - few: "%{count} νÎες ειδοποιήσεις" - many: "%{count} νÎες ειδοποιήσεις" - one: "1 νÎα ειδοποίηση" - other: "%{count} νÎες ειδοποιήσεις" - two: "%{count} νÎες ειδοποιήσεις" - zero: "Kαμία νÎα ειδοποίηση" index: and: "και" and_others: @@ -493,7 +375,6 @@ el: zero: "Ο/Η %{actors} άÏχισε να μοιÏάζεται μαζί σου." notifier: a_post_you_shared: "μια δημοσίευση." - accept_invite: "Αποδεχθείτε την Ï€Ïόσκληση στο diaspora*!" click_here: "Κάνε κλικ εδώ" comment_on_post: reply: "Απάντησε ή δες την ανάÏτηση του χÏήστη %{name} >" @@ -526,7 +407,6 @@ el: liked: "στο χÏήστη %{name} αÏÎσει η δημοσίευση σου" view_post: "Δες την ανάÏτηση >" mentioned: - mentioned: "αναφÎÏεται σε σÎνα σε μια δημοσίευση:" subject: "Ο/Η %{name} σε ανÎφεÏε στο diaspora*" private_message: reply_to_or_view: "Απάντησε ή δες τη συζήτηση >" @@ -544,119 +424,55 @@ el: to_change_your_notification_settings: "για να αλλάξεις τις Ïυθμίσεις των ειδοποιήσεων" nsfw: "NSFW" ok: "ΟΚ" - or: "ή" - password: "Κωδικός" - password_confirmation: "Επαλήθευση κωδικοÏ" people: add_contact: invited_by: "Ï€Ïοσκλήθηκες από" - add_contact_small: - add_contact_from_tag: "Î Ïοσθήκη επαφής από ετικÎτα" - aspect_list: - edit_membership: "ΕπεξεÏγασία ιδιοτήτων πτυχής" - helper: - is_not_sharing: "Ο/Η %{name} δεν διαμοιÏάζεται μαζί σου" - is_sharing: "Ο/Η %{name} διαμοιÏάζεται μαζί σου" - results_for: "αποτελÎσματα για %{params}" index: looking_for: "Ψάχνεις για αναÏτήσεις με την ετικÎτα %{tag_link};" no_one_found: "...κανÎνας δεν βÏÎθηκε." no_results: "Επ! ΧÏειάζεται να ψάξεις για κάτι." results_for: "ΧÏήστες που ταιÏιάζουν με %{search_term}" searching: "Γίνεται αναζήτηση, παÏακαλώ πεÏιμÎνετε..." - one: "1 άτομο" - other: "%{count} άτομα" person: - add_contact: "Î Ïοσθήκη επαφής" - already_connected: "Είναι ήδη συνδεδεμÎνο" - pending_request: "Αίτημα σε αναμονή" thats_you: "Î•ÏƒÏ ÎµÎ¯ÏƒÎ±Î¹ αυτός!" profile_sidebar: bio: "ΒιογÏαφικό" born: "ΓενÎθλια" - edit_my_profile: "ΕπεξεÏγασία του Ï€Ïοφίλ μου" gender: "ΦÏλο" - in_aspects: "Στις πτυχÎÏ‚" location: "Τοποθεσία" - photos: "ΦωτογÏαφίες" - remove_contact: "ΔιαγÏαφή επαφής" - remove_from: "ΑφαίÏεση του χÏήστη %{name} από τη πτυχή %{aspect};" show: closed_account: "Αυτός ο λογαÏιασμός Îχει κλείσει." does_not_exist: "Δεν υπάÏχει Ï„Îτοιο άτομα!" has_not_shared_with_you_yet: "Ο/Η %{name} δεν μοιÏάζεται ακόμα κάποια δημοσίευση μαζί σου!" - ignoring: "Αγνοείς όλες τις αναÏτήσεις από %{name}." - incoming_request: "Ο/Η %{name} θÎλει να μοιÏαστεί μαζί σου" - mention: "ΑναφοÏά" - message: "Μήνυμα" - not_connected: "Δεν είσαι συνδεδεμÎνος με αυτόν τον χÏήστη" - recent_posts: "Î Ïόσφατες δημοσιεÏσεις" - recent_public_posts: "Î Ïόσφατες δημόσιες δημοσιεÏσεις" - return_to_aspects: "ΕπιστÏοφή στη σελίδα με τις πτυχÎÏ‚ σου" - see_all: "Εμφάνιση όλων" - start_sharing: "Ξεκίνα να μοιÏάζεις" - to_accept_or_ignore: "να το αποδεχθεί ή να το αγνοήσει." - sub_header: - add_some: "Î Ïόσθεσε κάποιες" - edit: "ΕπεξεÏγασία" - you_have_no_tags: "Δεν Îχεις καμία ετικÎτα!" - webfinger: - fail: "ΛυποÏμαστε, δεν ήταν δυνατή η εÏÏεση του %{handle}." - zero: "ΚανÎνα άτομο" photos: - comment_email_subject: "φωτογÏαφία του χÏήστη %{name}" create: integrity_error: "Η μεταφόÏτωση της φωτογÏαφίας απÎτυχε. Ήταν σίγουÏα φωτογÏαφία;" runtime_error: "Η μεταφόÏτωση της φωτογÏαφίας απÎτυχε. ΣίγουÏα Îχεις φοÏÎσει τη ζώνη ασφαλείας;" type_error: "Η μεταφόÏτωση της φωτογÏαφίας απÎτυχε. ΣίγουÏα Ï€ÏοστÎθηκε μια εικόνα;" destroy: notice: "Η φωτογÏαφία διαγÏάφηκε." - edit: - editing: "ΕπεξεÏγασία" - new: - back_to_list: "ΕπιστÏοφή στη λίστα" - new_photo: "ÎÎα φωτογÏαφία" - post_it: "Δημοσίευσε το!" new_photo: empty: "{file} είναι κενό, επιλÎξτε και πάλι τα αÏχεία χωÏίς αυτό." invalid_ext: "{file} δεν Îχει ÎγκυÏη Ï„Ïπο αÏχείου. Μόνο Ï„Ïποι αÏχείου {extensions} επιτÏÎπονται." size_error: "{file} είναι Ï€Î¿Î»Ï Î¼ÎµÎ³Î¬Î»Î¿, το μÎγιστο μÎγεθος αÏχείου είναι {sizeLimit}." new_profile_photo: - or_select_one_existing: "ή επÎλεξε μια από τις ήδη υπάÏχουσες %{photos}" upload: "ΑνÎβασε μια νÎα φωτογÏαφία Ï€Ïοφίλ!" - photo: - view_all: "Î Ïοβολή όλων των φωτογÏαφιών του χÏήστη %{name}" show: - collection_permalink: "ΣÏνδεσμος συλλογής" - delete_photo: "ΔιαγÏαφή φωτογÏαφίας" - edit: "ΕπεξεÏγασία" - edit_delete_photo: "ΕπεξεÏγασία πεÏιγÏαφής φωτογÏαφίας / διαγÏαφή φωτογÏαφίας" - make_profile_photo: "ΟÏισμός ως φωτογÏαφίας Ï€Ïοφίλ" show_original_post: "Î Ïοβολή αÏχικής ανάÏτησης" - update_photo: "ΕνημÎÏωση φωτογÏαφίας" - update: - error: "Αποτυχία επεξεÏγασίας φωτογÏαφίας." - notice: "Η φωτογÏαφία ενημεÏώθηκε επιτυχώς." posts: presenter: title: "Ένα άÏθÏο από τον/την %{name}" show: - destroy: "ΔιαγÏαφή" - not_found: "ΛυποÏμαστε, δεν καταφÎÏαμε να βÏοÏμε αυτή την ανάÏτηση." - permalink: "Μόνιμος σÏνδεσμος" photos_by: one: "Μια φωτογÏαφεία του/της %{author}" other: "%{count} φωτογÏαφίες του/της %{author}" zero: "Δεν υπάÏχουν φωτογÏαφίες για τον/την %{author}" reshare_by: "Κοινοποίηση από %{author}" - previous: "Î ÏοηγοÏμενο" privacy: "ΑπόÏÏητο" - privacy_policy: "Πολιτική χÏήσης δεδομÎνων" profile: "Î Ïοφίλ" profiles: edit: allow_search: "ΕπÎÏ„Ïεψε σε άλλους ανθÏώπους να σε αναζητοÏν στο diaspora*" - edit_profile: "ΕπεξεÏγασία Ï€Ïοφίλ" first_name: "Όνομα" last_name: "Επώνυμο" update_profile: "ΕνημÎÏωση Ï€Ïοφίλ" @@ -666,8 +482,6 @@ el: your_location: "Η τοποθεσία σου" your_name: "Το όνομά σου" your_photo: "Η φωτογÏαφία σου" - your_private_profile: "Το ιδιωτικό σου Ï€Ïοφίλ" - your_public_profile: "Το δημόσιο Ï€Ïοφίλ σου" your_tags: "ΠεÏιÎγÏαψε τον εαυτό σου με 5 λÎξεις" your_tags_placeholder: "όπως #ταινίες #γατάκια #ταξίδι #δάσκαλος #newyork" update: @@ -685,63 +499,24 @@ el: closed: "Οι εγγÏαφÎÏ‚ είναι κλειστÎÏ‚ σε αυτό το pod του diaspora*." create: success: "Έγινες μÎλος στο diaspora*!" - edit: - cancel_my_account: "ΑκÏÏωση του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Î¼Î¿Ï…" - edit: "ΕπεξεÏγασία %{name}" - leave_blank: "(άφησε το κενό αν δεν θÎλεις να το αλλάξεις)" - password_to_confirm: "(χÏειαζόμαστε τον Ï„ÏÎχοντα κωδικό σου για να επιβεβαιώσουμε τις αλλαγÎÏ‚ σου)" - unhappy: "Δεν είσαι ικανοποιημÎνος;" - update: "ΕνημÎÏωση" invalid_invite: "Ο σÏνδεσμος που Îδωσες δεν είναι πια ÎγκυÏος!" new: - create_my_account: "ΔημιουÏγία λογαÏιασμοÏ!" email: "EMAIL" enter_email: "ΕπÎλεξε μια διεÏθυνση email" enter_password: "ΕπÎλεξε Îναν κωδικό" enter_password_again: "ΕπανÎλαβε τον κωδικό" enter_username: "ΕπÎλεξε Îνα όνομα χÏήστη (μόνο γÏάμματα, νοÏμεÏα και κάτω-παÏλα)" - join_the_movement: "Γίνε μÎλος του κινήματος!" password: "ΚΩΔΙΚΟΣ" password_confirmation: "Επαλήθευση κωδικοÏ" sign_up: "ΕΓΓΡΑΦΗ" - sign_up_message: "Κοινωνική δικτÏωση με ♥" submitting: "Υποβολή..." username: "ΟÎΟΜΑ ΧΡΗΣΤΗ" - requests: - create: - sending: "Αποστολή" - sent: "Σου ζητήθηκε να μοιÏάζεσαι με τον/την %{name}. Θα είναι οÏατό την επόμενη φοÏά που θα συνδεθείς στο diaspora*." - destroy: - error: "ΠαÏακαλώ επÎλεξε μια πτυχή!" - ignore: "Αγνοήθηκε αίτηση επαφής." - success: "ΤώÏα πλÎον μοιÏάζεσαι." - helper: - new_requests: - one: "ÎÎο αίτημα!" - other: "%{count} νÎα αιτήματα!" - zero: "ΚανÎνα νÎο αίτημα" - manage_aspect_contacts: - existing: "Υφιστάμενες επαφÎÏ‚" - manage_within: "ΔιαχείÏιση των επαφών της πτυχής" - new_request_to_person: - sent: "Εστάλη!" reshares: comment_email_subject: "Αναδημοσίευση της ανάÏτησης του χÏήστη %{author} από %{resharer}" - create: - failure: "ΥπήÏξε κάποιο σφάλμα κατά την κοινοποίηση αυτής της δημοσίευσης." reshare: deleted: "Η αÏχική δημοσίευση διαγÏάφτηκε από τον δημιουÏγό της." - reshare: - few: "%{count} κοινοποιήσεις" - many: "%{count} κοινοποιήσεις" - one: "1 κοινοποίηση" - other: "%{count} κοινοποιήσεις" - two: "%{count} κοινοποιήσεις" - zero: "Κοινοποίηση" reshare_confirmation: "Αναδημοσίευση της ανάÏτησης του χÏήστη %{author};" - reshare_original: "Κοινοποίηση αÏχικής" reshared_via: "ΑναδημοσιεÏτηκε μÎσω" - show_original: "Î Ïοεπισκόπηση αÏχικοÏ" search: "Αναζήτηση" services: create: @@ -753,38 +528,15 @@ el: success: "Επιτυχής καταστÏοφή ταυτότητας." failure: error: "Εμφανίστηκε Îνα σφάλμα κατά τη σÏνδεση με αυτή την υπηÏεσία" - finder: - fetching_contacts: "Το diaspora* ανακτά τους %{service} φίλους σου, Îλεγξε ξανά σε μεÏικά λεπτά." - no_friends: "Δεν βÏÎθηκαν φίλοι στο Facebook. " - service_friends: "%{service} φίλοι" index: disconnect: "ΑποσÏνδεση" edit_services: "ΕπεξεÏγασία υπηÏεσιών" logged_in_as: "ΣÏνδεση ως %{nickname}" really_disconnect: "ΑποσÏνδεση %{service};" services_explanation: "Η σÏνδεση με υπηÏεσίες σας δίνει τη δυνατότητα να δημοσιεÏονται τα μηνÏματά σας σε αυτÎÏ‚ την στιγμή που τα γÏάφετε στην diaspora*." - inviter: - click_link_to_accept_invitation: "Κάνε κλικ σ' αυτό το σÏνδεσμο για να αποδεχθείς την Ï€Ïόσκλησή" - join_me_on_diaspora: "ΣυνδÎσου μαζί μου στο diaspora*" - remote_friend: - invite: "Î Ïόσκληση" - not_on_diaspora: "Δεν είναι ακόμα στο diaspora*" - resend: "Αποστολή ξανά" settings: "Ρυθμίσεις" - share_visibilites: - update: - post_hidden_and_muted: "Οι δημοσιεÏσεις του χÏήστη %{name} Îχουν κÏυφτεί, και οι ειδοποιήσεις Îχουν απενεÏγοποιηθεί." - see_it_on_their_profile: "Αν θÎλεις να δεις ενημεÏώσεις για αυτή τη δημοσίευση, επισκÎψου το Ï€Ïοφίλ του χÏήστη %{name}." shared: - add_contact: - add_new_contact: "Î Ïόσθεσε μια νÎα επαφή" - create_request: "ΕÏÏεση βάσει diaspora* ID" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "ΕπÎλεξε όνομα χÏήστη diaspora*:" - know_email: "ΓνωÏίζεις τις διευθÏνσεις email τους; Τότε Ï€ÏÎπει να τους Ï€ÏοσκαλÎσεις" - your_diaspora_username_is: "Το όνομα χÏήστη σου στο diaspora* είναι: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Î Ïοσθήκη επαφής" toggle: few: "Σε %{count} πτυχÎÏ‚" many: "Σε %{count} πτυχÎÏ‚" @@ -792,23 +544,11 @@ el: other: "Σε %{count} πτυχÎÏ‚" two: "Σε %{count} πτυχÎÏ‚" zero: "Î Ïοσθήκη επαφής" - contact_list: - all_contacts: "Όλες οι επαφÎÏ‚" - footer: - logged_in_as: "ΣÏνδεση ως %{name}" - your_aspects: "Οι πτυχÎÏ‚ σου" invitations: by_email: "ÎœÎσω email" - dont_have_now: "Δεν Îχεις κάποια Ï„ÏŽÏα, αλλά πεÏισσότεÏες Ï€Ïοσκλήσεις ÎÏχονται σÏντομα!" - from_facebook: "Από το Facebook" - invitations_left: "απομÎνουν %{count}" - invite_someone: "Î Ïοσκάλεσε κάποιον/α" invite_your_friends: "Î Ïοσκάλεσε φίλους" invites: "Î Ïοσκλήσεις" - invites_closed: "Οι Ï€Ïοσκλήσεις αυτή τη στιγμή είναι κλειστÎÏ‚ σε αυτό το diaspora* pod" share_this: "ΜοιÏάσου αυτόν τον σÏνδεσμο με email, blog, ή σε κάποιο κοινωνικό δίκτυο!" - notification: - new: "ÎÎο %{type} από τον χÏήστη %{from}" public_explain: atom_feed: "" control_your_audience: "Έλεγξε το κοινό σου" @@ -820,62 +560,29 @@ el: title: "ΡÏθμιση συνδεδεμÎνων υπηÏεσιών" visibility_dropdown: "ΧÏησιμοποίησε αυτό το αναδυόμενο Î¼ÎµÎ½Î¿Ï Î³Î¹Î± να αλλάξεις την οÏατότητα της ανάÏτησης σου. (Î Ïοτείνουμε την Ï€Ïώτη σου να την κάνεις δημόσια.)" publisher: - all: "Όλα" - all_contacts: "Όλες οι επαφÎÏ‚" discard_post: "ΑπόÏÏιψη ανάÏτησης" get_location: "Λήψη τοποθεσίας μου" - make_public: "Κάντο δημόσιο" new_user_prefill: hello: "Γεια σε όλους, είμαι #%{new_user_tag}. " i_like: "Με ενδιαφÎÏουν οι ετικÎτες %{tags}." invited_by: "ΕυχαÏιστώ για την Ï€Ïόσκληση, " newhere: "ÎÎοςΕδώ" - post_a_message_to: "ΑνάÏτησε Îνα μήνυμα στην πτυχή %{aspect}" posting: "ΑνάÏτηση..." - preview: "Î Ïοεπισκόπηση" - publishing_to: "Δημοσίευση στο: " share: "Κοινοποίηση" - share_with: "ΜοιÏάσου με" upload_photos: "ΜεταφόÏτωση εικόνων" whats_on_your_mind: "Τι σκÎφτεσαι;" - reshare: - reshare: "Κοινοποίησε" stream_element: - connect_to_comment: "ΣυνδÎσου με αυτόν τον χÏήστη για να σχολιάσεις στην ανάÏτησή του" - currently_unavailable: "Ο σχολιασμός αυτή τη στιγμή δεν είναι διαθÎσιμος" - dislike: "Δεν μ' αÏÎσει" - hide_and_mute: "ΑπόκÏυψη και σίγαση δημοσίευσης" - ignore_user: "Αγνόησε τον/την %{name}" - ignore_user_description: "Αγνόηση και αφαίÏεση χÏήστη από όλες τις πτυχÎÏ‚;" - like: "Μου αÏÎσει" - nsfw: "Αυτή η δημοσίευση Îχει σημανθεί ως μη ασφαλής για δουλειά από τον δημιουÏγό της. %{link}" - shared_with: "ΔιαμοιÏασμÎνο με: %{aspect_names}" - show: "Εμφάνισε" - unlike: "Δεν μου αÏÎσει" via: "ÎœÎσω %{link}" via_mobile: "από κινητό" - viewable_to_anyone: "Αυτή η δημοσίευση είναι εμφανής σε όλους στο διαδίκτυο" status_messages: create: success: "ΑναφÎÏθηκαν επιτυχώς: %{names}" - destroy: - failure: "Αποτυχία διαγÏαφής δημοσίευσης" - helper: - no_message_to_display: "ΚανÎνα μήνυμα" new: mentioning: "ΑναφοÏά σε: %{person}" too_long: "ΠαÏακαλώ μετÎÏ„Ïεψε το μήνυμα κατάστασης σου σε λιγότεÏους από %{count} χαÏακτήÏες. ΤώÏα είναι %{current_length} χαÏακτήÏες." stream_helper: - hide_comments: "ΑπόκÏυψη όλων των σχολίων" no_more_posts: "Έχεις φτάσει το Ï„Îλος της Ïοής." no_posts_yet: "Δεν υπάÏχουν αναÏτήσεις ακόμα." - show_comments: - few: "Εμφάνιση %{count} ακόμα σχολίων" - many: "Εμφάνιση %{count} ακόμα σχολίων" - one: "Εμφάνιση ενός ακόμα σχολίου" - other: "Εμφάνιση %{count} ακόμα σχολίων" - two: "Εμφάνιση δυο ακόμα σχολίων" - zero: "Δεν υπάÏχουν άλλα σχόλια" streams: activity: title: "Η δÏαστηÏιότητα μου" @@ -901,22 +608,11 @@ el: title: "Δημόσια δÏαστηÏιότητα" tags: title: "ΑνάÏτησες με ετικÎτες: %{tags}" - tag_followings: - create: - failure: "Η Ï€Ïοσπάθεια σου να ακολουθήσεις την ετικÎτα #%{name} απÎτυχε. Μήπως την ακολουθείς ήδη;" - none: "Δεν μποÏείς να ακολουθήσεις μια κενή ετικÎτα!" - success: "ΓιοÏπι! Ακολουθείς επιτυχώς την ετικÎτα #%{name}." - destroy: - failure: "Η Ï€Ïοσπάθεια σου να σταματήσεις να ακολουθείς την ετικÎτα #%{name} απÎτυχε. Μήπως Îχεις ήδη σταματήσει να την ακολουθείς;" - success: "Δεν ακολουθείς την ετικÎτα: #%{name} πια." tags: show: follow: "ΑκολοÏθησε την ετικÎτα #%{tag}" - following: "Ακολουθείς την ετικÎτα #%{tag}" none: "Η κενή ετικÎτα δεν υπάÏχει!" stop_following: "Σταμάτησες να ακολουθείς την ετικÎτα #%{tag}" - terms_and_conditions: "ÎŒÏοι και Î ÏοϋποθÎσεις" - undo: "ΑναίÏεση;" username: "Όνομα ΧÏήστη" users: confirm_email: @@ -937,7 +633,6 @@ el: character_minimum_expl: "Ï€ÏÎπει να είναι τουλάχιστον Îξι χαÏακτήÏες" close_account: dont_go: "Σε παÏακαλώ μη φεÏγεις!" - if_you_want_this: "Εάν Ï€Ïαγματικά αυτό θÎλεις, γÏάψε το κωδικό σου παÏακάτω και πάτα \"Κλείσιμο ΛογαÏιασμοÏ\"" lock_username: "Το όνομα χÏήστη σας θα «κλειδωθεί» και δεν θα μποÏείτε να δημιουÏγήσετε νÎο λογαÏιασμό με το ίδιο ID." locked_out: "ÎœÎχÏι ο λογαÏιασμός σας να διαγÏαφεί, θα αποσυνδεθείτε και θα αποκλεισθείτε από αυτόν." make_diaspora_better: "Θα επιθυμοÏσαμε να μας βοηθήσετε να κάνουμε το Diaspora καλÏτεÏο αντί να φÏγετε. Αν Ï€Ïάγματι θÎλετε να φÏγετε, θα θÎλαμε να γνωÏίζετε τι θα συμβεί στην συνÎχεια." @@ -948,12 +643,10 @@ el: comment_on_post: "κάποιος σχολίασε την ανάÏτησή σου" current_password: "ΤÏÎχον κωδικός Ï€Ïόσβασης" current_password_expl: "αυτόν που συνδÎθηκες..." - download_photos: "ΚατÎβασμα των φωτογÏαφιών μου" edit_account: "ΕπεξεÏγασία λογαÏιασμοÏ" email_awaiting_confirmation: "Σου στείλαμε Îναν σÏνδεσμο ενεÏγοποίησης στο %{unconfirmed_email}. ÎœÎχÏι να ακολουθήσεις αυτόν τον σÏνδεσμο και να ενεÏγοποιήσεις τη νÎα διεÏθυνση, θα συνεχίσουμε να χÏησιμοποιοÏμε την αÏχική %{email}." export_data: "Εξαγωγή δεδομÎνων" following: "Ρυθμίσεις διαμοιÏασμοÏ" - getting_started: "Î Ïοτιμήσεις νÎου χÏήστη" liked: "σε κάποιον αÏÎσει η δημοσίευση σου" mentioned: "επισημάνθηκες σε μία φωτογÏαφία" new_password: "ÎÎος κωδικός Ï€Ïόσβασης" @@ -973,7 +666,6 @@ el: connect_to_facebook_link: "Γίνεται ενσωμάτωση του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ±Ï‚ στο Facebook" hashtag_explanation: "Τα hashtags ή ετικÎτες σας επιτÏÎπουν να συζητάτε και να ακολουθείτε συγκεκÏιμÎνα ενδιαφÎÏοντα. Επίσης είναι Îνας εξαιÏετικό Ï„Ïόπος για να εντοπίσετε νÎα Ï€Ïόσωπα στο diaspora*." hashtag_suggestions: "Δοκιμάστε να ακολουθήσεις ετικÎτες όπως #art, #movies, #gif, κτλ." - saved: "ΑποθηκεÏτηκε!" well_hello_there: "Λοιπόν, γεια σου!" what_are_you_in_to: "Με τι ασχολείσαι;" who_are_you: "Ποιος είσαι;" @@ -995,13 +687,6 @@ el: settings_updated: "Οι Ïυθμίσεις ενημεÏώθηκαν" unconfirmed_email_changed: "Η διεÏθυνση email άλλαξε. ΧÏειάζεται ενεÏγοποίηση." unconfirmed_email_not_changed: "Η αλλαγή της διεÏθυνσης email απÎτυχε." - webfinger: - fetch_failed: "Αποτυχία ανάκτησης Ï„oÏ… Ï€Ïοφίλ για %{profile_url} από την υπηÏεσία webfinger" - hcard_fetch_failed: "ΥπάÏχει Ï€Ïόβλημα στην ανάκτηση του hcard για %{account}" - no_person_constructed: "ΚανÎνα άτομο δεν μποÏοÏσε να κατασκευαστεί απο αυτό το hcard." - not_enabled: "Φαίνεται ότι η υπεÏασία webfinger δεν είναι ενεÏγοποιημÎνη στον υπολογιστή που φιλοξενεί τον λογαÏιασμό %{account}" - xrd_fetch_failed: "ΥπάÏχει Ï€Ïόβλημα στη λήψη του xrd απο το λογαÏιασμό %{account}" - welcome: "ΚαλωσόÏισες!" will_paginate: next_label: "επόμενο »" previous_label: "« Ï€ÏοηγοÏμενο" \ No newline at end of file diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 36354accd2408ce22866f93503fff5b418aef696..8d952a2986d5e5d0b4301486da5578f010de8bc3 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -10,42 +10,26 @@ en: profile: "Profile" account: "Account" privacy: "Privacy" - privacy_policy: "Privacy policy" - terms_and_conditions: "Terms and conditions" _services: "Services" _applications: "Applications" - _photos: "Photos" _help: "Help" ok: "OK" cancel: "Cancel" delete: "Delete" - hide: "Hide" - ignore: "Ignore" - undo: "Undo?" - or: "or" - ago: "%{time} ago" username: "Username" email: "Email" - password: "Password" - password_confirmation: "Password confirmation" are_you_sure: "Are you sure?" are_you_sure_delete_account: "Are you sure you want to close your account? This can’t be undone!" fill_me_out: "Fill me out" - back: "Back" public: "Public" limited: "Limited" search: "Search" nsfw: "NSFW" find_people: "Find people or #tags" - _home: "Home" more: "More" - next: "Next" - previous: "Previous" - _comments: "Comments" all_aspects: "All aspects" no_results: "No results found" _contacts: "Contacts" - welcome: "Welcome!" _terms: "Terms" _statistics: "Statistics" @@ -89,20 +73,22 @@ en: already_participated: "You’ve already participated in this poll!" error_messages: helper: - invalid_fields: "Invalid fields" correct_the_following_errors_and_try_again: "Correct the following errors and try again." - post_not_public: "The post you are trying to view is not public!" - post_not_public_or_not_exist: "The post you are trying to view is not public, or does not exist!" - login_try_again: "Please <a href='%{login_link}'>login</a> and try again." + need_javascript: "This website requires JavaScript to function properly. If you disabled JavaScript, please enable it and refresh this page." admins: admin_bar: pages: "Pages" + dashboard: "Dashboard" user_search: "User search" weekly_user_stats: "Weekly user stats" pod_stats: "Pod stats" report: "Reports" sidekiq_monitor: "Sidekiq monitor" + pod_network: "Pod network" + dashboard: + pod_status: "Pod status" + fetching_diaspora_version: "Determining latest diaspora* version..." user_search: you_currently: zero: "You currently have no invites left %{link}" @@ -111,6 +97,8 @@ en: view_profile: "View profile" add_invites: "Add invites" close_account: "Close account" + lock_account: "Lock account" + unlock_account: "Unlock account" are_you_sure: "Are you sure you want to close this account?" are_you_sure_lock_account: "Are you sure you want to lock this account?" are_you_sure_unlock_account: "Are you sure you want to unlock this account?" @@ -118,6 +106,7 @@ en: account_locking_scheduled: "The account of %{name} is scheduled to be locked. It will be processed in a few moments..." account_unlocking_scheduled: "The account of %{name} is scheduled to be unlocked. It will be processed in a few moments..." email_to: "Email to invite" + invite: "Invite" under_13: "Show users that are under 13 (COPPA)" users: zero: "%{count} users found" @@ -132,6 +121,7 @@ en: account_closed: "Account closed" nsfw: "#nsfw" unknown: "Unknown" + invite_token: "Invite token" 'yes': "Yes" 'no': "No" weekly_user_stats: @@ -167,45 +157,24 @@ en: current_segment: "The current segment is averaging <b>%{post_yest}</b> posts per user, from <b>%{post_day}</b>" 50_most: "50 most popular tags" tag_name: "Tag name: <b>%{name_tag}</b> Count: <b>%{count_tag}</b>" - application: - helper: - unknown_person: "Unknown person" - video_title: - unknown: "Unknown video title" + pods: + pod_network: "Pod network" aspects: - contacts_visible: "Contacts in this aspect will be able to see each other." - contacts_not_visible: "Contacts in this aspect will not be able to see each other." edit: - grant_contacts_chat_privilege: "Grant contacts in this aspect chat privilege?" - make_aspect_list_visible: "Make contacts in this aspect visible to each other?" - remove_aspect: "Delete this aspect" confirm_remove_aspect: "Are you sure you want to delete this aspect?" - set_visibility: "Set visibility" rename: "Rename" aspect_list_is_visible: "Contacts in this aspect are able to see each other." aspect_list_is_not_visible: "Contacts in this aspect are not able to see each other." - aspect_chat_is_enabled: "Contacts in this aspect are able to chat with you." - aspect_chat_is_not_enabled: "Contacts in this aspect are not able to chat with you." update: "Update" updating: "Updating" - no_posts_message: - start_talking: "Nobody has said anything yet!" no_contacts_message: you_should_add_some_more_contacts: "You should add some more contacts!" - try_adding_some_more_contacts: "You can search or invite more contacts." + try_adding_some_more_contacts: "You can search or %{invite_link} more contacts." + invite_link_text: "invite" or_spotlight: "Or you can share with %{link}" community_spotlight: "Community spotlight" aspect_listings: - select_all: "Select all" - deselect_all: "Deselect all" - edit_aspect: "Edit %{name}" add_an_aspect: "+ Add an aspect" - new: - name: "Name (only visible to you)" - create: "Create" - create: - success: "Your new aspect %{name} was created" - failure: "Aspect creation failed." destroy: success: "%{name} was successfully removed." success_auto_follow_back: "%{name} was successfully removed. You used this aspect to automatically follow back users. Check your user settings to select a new auto follow back aspect." @@ -224,14 +193,6 @@ en: index: donate: "Donate" keep_pod_running: "Keep %{pod} running fast and buy servers their coffee fix with a monthly donation!" - keep_diaspora_running: "Keep diaspora* development fast with a monthly donation!" - no_tags: "+ Find a tag to follow" - unfollow_tag: "Stop following #%{tag}" - handle_explanation: "This is your diaspora* ID. Like an email address, you can give this to people to reach you." - no_contacts: "No contacts" - post_a_message: "Post a message >>" - people_sharing_with_you: "People sharing with you" - welcome_to_diaspora: "Welcome to diaspora*, %{name}!" introduce_yourself: "This is your stream. Jump in and introduce yourself." @@ -252,15 +213,9 @@ en: tag_feature: "feature" tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: help for your first steps." tutorial_link_text: "Tutorials" - email_feedback: "%{link} your feedback, if you prefer" - email_link: "Email" any_problem: "Got a problem?" contact_podmin: "Contact the administrator of your pod!" mail_podmin: "Podmin email" - diaspora_id: - heading: "diaspora* ID" - content_1: "Your diaspora* ID is:" - content_2: "Give it to anyone and they’ll be able to find you on diaspora*." services: heading: "Connect services" content: "You can connect the following services to diaspora*:" @@ -280,14 +235,10 @@ en: bookmarklet: heading: "Bookmarklet" - post_success: "Posted! Closing!" post_something: "Post to diaspora*" explanation: "Post to diaspora* from anywhere by bookmarking this link => %{link}." comments: - zero: "No comments" - one: "1 comment" - other: "%{count} comments" new_comment: comment: "Comment" commenting: "Commenting..." @@ -298,16 +249,10 @@ en: other: "%{count} reactions" contacts: - create: - failure: "Failed to create contact" - sharing: - people_sharing: "People sharing with you:" index: - add_to_aspect: "Add contacts to %{name}" start_a_conversation: "Start a conversation" add_a_new_aspect: "Add a new aspect" title: "Contacts" - your_contacts: "Your contacts" no_contacts: "Looks like you need to add some contacts!" no_contacts_message: "Check out %{community_spotlight}" community_spotlight: "Community spotlight" @@ -316,39 +261,31 @@ en: all_contacts: "All contacts" only_sharing_with_me: "Only sharing with me" add_contact: "Add contact" - remove_contact: "Remove contact" user_search: "Contact search" spotlight: community_spotlight: "Community spotlight" suggest_member: "Suggest a member" + no_members: "There are no members yet." conversations: index: conversations_inbox: "Conversations – Inbox" new_conversation: "New conversation" - no_conversation_selected: "No conversation selected" - create_a_new_conversation: "Start a new conversation" no_messages: "No messages" inbox: "Inbox" - conversation: - participants: "Participants" show: reply: "Reply" replying: "Replying..." hide: "Hide and mute conversation" delete: "Delete conversation" + last_message: "Last message received %{timeago}" new: to: "To" subject: "Subject" subject_default: "No subject" + message: "Message" send: "Send" sending: "Sending..." - abandon_changes: "Abandon changes?" - helper: - new_messages: - zero: "No new messages" - one: "1 new messages" - other: "%{count} new messages" create: sent: "Message sent" fail: "Invalid message" @@ -582,83 +519,76 @@ en: diaspora_app_q: "Is there a diaspora* app for Android or iOS?" diaspora_app_a: "There have been several Android apps in development by community members. Some are long-abandoned projects and so do not work well with the current version of diaspora*. Don’t expect much from these apps at the moment. There is currently no app for iOS. The best way to access diaspora* from your mobile device is through a browser, because we’ve designed a mobile version of the site which should work well on all devices, although it does not yet have complete functionality." + home: + default: + headline: "Welcome to %{pod_name}" + byline: "The online social world where you are in control" + be_who_you_want_to_be: "Be who you want to be" + be_who_you_want_to_be_info: "A lot of networks insist that you use your real identity. Not diaspora*. Here you can choose who you want to be, and share as much or as little about yourself as you want. It really is up to you how you want to interact with other people." + choose_your_audience: "Choose your audience" + choose_your_audience_info: "diaspora*’s aspects allow you to share with just those people you want to. You can be as public or as private as you like. Share a funny photo with the whole world, or a deep secret just with your closest friends. You’re in control." + own_your_data: "Own your own data" + own_your_data_info: "Many networks use your data to make money by analysing your interactions and using this information to advertise things to you. diaspora* doesn’t use your data for any purpose other than allowing you to connect and share with others." + podmin: + headline: "Welcome, friend." + byline: "You’re about to change the Internet. Let’s get you set up, shall we?" + configure_your_pod: "Configure your pod" + create_an_account: "Create an account" + make_yourself_an_admin: "Make yourself an admin" + update_your_pod: "Update your pod" + getting_help: "Getting help" + contribute: "Contribute" + configuration_info: "Open %{database_path} and %{diaspora_path} in your favourite text editor and carefully review them, they are extensively commented." + create_an_account_info: "%{sign_up_link} for a new account." + make_yourself_an_admin_info: "You can find instructions in the %{wiki}. This should add an “Admin†link to your user menu in the header when you are logged in. It gives you stuff like user search and stats for your pod. For intense detail on the operational aspects of your pod, go to the %{admin_panel}." + admin_panel: "admin panel" + update_your_pod_info: "You can find %{update_instructions}." + update_instructions: "update instructions in the diaspora* wiki" + getting_help_info: "We listed some %{faq} including some additional tips and tricks and solutions for the most common problems. Also feel free to %{irc}." + faq_for_podmins: "FAQ for pod maintainers in our wiki" + contact_irc: "contact us on IRC" + contribute_info: "Make diaspora* even better! If you find any bugs please %{report_bugs}." + report_bugs: "report them" + invitation_codes: - excited: "%{name} is excited to see you here." not_valid: "That invite code is no longer valid" - + invitations: create: sent: "Invitations have been sent to: %{emails}" - rejected: "The following email addresses had problems: " + rejected: "The following email addresses had problems: %{emails}" no_more: "You have no more invitations." - already_sent: "You already invited this person." - already_contacts: "You are already connected with this person" - own_address: "You can’t send an invitation to your own address." empty: "Please enter at least one email address." note_already_sent: "Invitations have already been sent to: %{emails}" + closed: "Invitations are closed on this diaspora* pod." new: language: "Language" invite_someone_to_join: "Invite someone to join diaspora*!" - if_they_accept_info: "if they accept, they will be added to the aspect you invited them." comma_separated_plz: "You can enter multiple email addresses separated by commas." - check_out_diaspora: "Hey! You should check out diaspora*" - to: "To" - personal_message: "Personal message" send_an_invitation: "Send an invitation" sending_invitation: "Sending invitation..." - send_invitation: "Send invitation" paste_link: "Share this link with your friends to invite them to diaspora*, or email them the link directly." codes_left: zero: "No invites left on this code" one: "One invite left on this code" other: "%{count} invites left on this code" - aspect: "Aspect" - already_invited: "The following people have not accepted your invitation:" - resend: "Resend" - check_out_diaspora: "Check out diaspora*!" - check_token: - not_found: "Invitation token not found" - edit: - your_account_awaits: "Your account awaits!" - accept_your_invitation: "Accept your invitation" - a_facebook_user: "A Facebook user" layouts: header: profile: "Profile" settings: "Settings" - help: "Help" logout: "Log out" - blog: "Blog" - login: "Log in" code: "Code" - admin: "Admin" - view_all: "View all" - recent_notifications: "Recent notifications" + toggle_navigation: "Toggle navigation" application: powered_by: "Powered by diaspora*" whats_new: "What’s new?" statistics_link: "Pod statistics" toggle: "Toggle mobile" public_feed: "Public diaspora* feed for %{name}" - your_aspects: "Your aspects" back_to_top: "Back to top" source_package: "Download the source code package" - - likes: - likes: - people_like_this: - zero: "No likes" - one: "%{count} like" - other: "%{count} likes" - people_like_this_comment: - zero: "No likes" - one: "%{count} like" - other: "%{count} likes" - people_dislike_this: - zero: "No dislikes" - one: "%{count} dislike" - other: "%{count} dislikes" + be_excellent: "Be excellent to each other! ♥" notifications: started_sharing: @@ -680,7 +610,7 @@ en: mentioned: zero: "%{actors} have mentioned you in the post %{post_link}." one: "%{actors} has mentioned you in the post %{post_link}." - other: "%{actors} have mentioned you in the %{post_link}." + other: "%{actors} have mentioned you in the post %{post_link}." liked: zero: "%{actors} have liked your post %{post_link}." one: "%{actors} has liked your post %{post_link}." @@ -727,11 +657,6 @@ en: one: "and one more" other: "and %{count} others" and: "and" - helper: - new_notifications: - zero: "No new notifications" - one: "1 new notification" - other: "%{count} new notifications" notifier: a_post_you_shared: "a post." @@ -756,9 +681,9 @@ en: limited_subject: "There's a new comment on a post you commented" mentioned: subject: "%{name} has mentioned you on diaspora*" - mentioned: "mentioned you in a post:" limited_post: "You were mentioned in a limited post." private_message: + subject: "There’s a new private message for you" reply_to_or_view: "Reply to or view this conversation >" liked: liked: "%{name} liked your post" @@ -780,6 +705,8 @@ en: the %{type} with ID %{id} was marked as offensive. + Reason: %{reason} + [%{url}][1] Please review as soon as possible! @@ -832,7 +759,6 @@ en: Sorry, The diaspora* email robot! - accept_invite: "Accept your diaspora* invite!" invited_you: "%{name} invited you to diaspora*" invite: message: |- @@ -871,15 +797,66 @@ en: Hoping to see you again, The diaspora* email robot! + api: + openid_connect: + authorizations: + new: + redirection_message: "Are you sure you want to give access to %{redirect_uri}?" + access: "%{name} requires access to:" + no_requirement: "%{name} requires no permissions" + approve: "Approve" + deny: "Deny" + bad_request: "Missing client id or redirect URI" + client_id_not_found: "No client with client_id %{client_id} with redirect URI %{redirect_uri} found" + destroy: + fail: "The attempt to revoke the authorization with ID %{id} failed" + user_applications: + index: + edit_applications: "Applications" + title: "Authorized applications" + access: "%{name} has access to:" + no_requirement: "%{name} requires no permissions" + no_applications: "You have no authorized applications" + revoke_autorization: "Revoke" + tos: "See the application's terms of service" + policy: "See the application's privacy policy" + scopes: + openid: + name: "basic profile" + description: "This allows the application to read your basic profile" + sub: + name: "sub" + description: "This grants sub permissions to the application" + aud: + name: "aud" + description: "This grants aud permissions to the application" + name: + name: "name" + description: "This grants name permissions to the application" + nickname: + name: "nickname" + description: "This grants nickname permissions to the application" + profile: + name: "extended profile" + description: "This allows the application to read your extended profile" + picture: + name: "picture" + description: "This grants picture permissions to the application" + read: + name: "read profile, stream and conversations" + description: "This allows the application to read your stream, your conversations and your complete profile" + write: + name: "send posts, conversations and reactions" + description: "This allows the application to send new posts, write conversations, and send reactions" + error_page: + title: "Oh! Something went wrong :(" + contact_developer: "You should contact the developer of the application and include the following detailed error message:" + login_required: "You must first login before you can authorize this application" + could_not_authorize: "The application could not be authorized" + people: - zero: "No people" - one: "1 person" - other: "%{count} people" person: - pending_request: "Pending request" - already_connected: "Already connected" thats_you: "That’s you!" - add_contact: "Add contact" index: results_for: "Users matching %{search_term}" no_results: "Hey! You need to search for something." @@ -889,72 +866,25 @@ en: no_one_found: "...and no one was found." searching: "Searching, please be patient..." looking_for: "Looking for posts tagged %{tag_link}?" - webfinger: - fail: "Sorry, we couldn’t find %{handle}." show: has_not_shared_with_you_yet: "%{name} has not shared any posts with you yet!" - incoming_request: "%{name} wants to share with you" - return_to_aspects: "Return to your aspects page" - to_accept_or_ignore: "to accept or ignore it." does_not_exist: "Person does not exist!" - not_connected: "You are not sharing with this person" - recent_posts: "Recent posts" - recent_public_posts: "Recent public posts" - see_all: "See all" - start_sharing: "Start sharing" - message: "Message" - mention: "Mention" - ignoring: "You are ignoring all posts from %{name}." closed_account: "This account has been closed." - sub_header: - you_have_no_tags: "You have no tags!" - add_some: "Add some" - edit: "Edit" profile_sidebar: - remove_contact: "Remove contact" - edit_my_profile: "Edit my profile" bio: "Bio" location: "Location" gender: "Gender" born: "Birthday" - photos: "Photos" - in_aspects: "In aspects" - remove_from: "Remove %{name} from %{aspect}?" - helper: - results_for: " results for %{params}" - is_sharing: "%{name} is sharing with you" - is_not_sharing: "%{name} is not sharing with you" - aspect_list: - edit_membership: "Edit aspect membership" - add_contact_small: - add_contact_from_tag: "Add contact from tag" add_contact: invited_by: "You were invited by" photos: show: - delete_photo: "Delete photo" - make_profile_photo: "Make profile photo" - update_photo: "Update photo" - edit: "Edit" - edit_delete_photo: "Edit photo description / delete photo" - collection_permalink: "Collection permalink" show_original_post: "Show original post" - edit: - editing: "Editing" - photo: - view_all: "View all of %{name}’s photos" - new: - new_photo: "New photo" - back_to_list: "Back to list" - post_it: "Post it!" create: runtime_error: "Photo upload failed. Are you sure that your seatbelt is fastened?" integrity_error: "Photo upload failed. Are you sure that was an image?" type_error: "Photo upload failed. Are you sure an image was added?" - update: - notice: "Photo successfully updated." - error: "Failed to edit photo." destroy: notice: "Photo deleted." new_photo: @@ -963,16 +893,18 @@ en: empty: "{file} is empty, please select files again without it." new_profile_photo: upload: "Upload a new profile photo!" - or_select_one_existing: "or select one from your already existing %{photos}" - comment_email_subject: "%{name}’s photo" + + polls: + votes: + zero: "%{count} votes so far" + one: "%{count} vote so far" + other: "%{count} votes so far" posts: presenter: title: "A post from %{name}" show: - destroy: "Delete" - permalink: "Permalink" - not_found: "Sorry, we couldn’t find that post." + location: "Posted from: %{location}" forbidden: "You are not allowed to do that" photos_by: zero: "No photos by %{author}" @@ -988,23 +920,23 @@ en: reason_label: "Reason: %{text}" review_link: "Mark as reviewed" delete_link: "Delete item" + reported_user_details: "Details on reported user" confirm_deletion: "Are you sure to delete the item?" not_found: "<u>The post/comment was not found. It seems that it was deleted by the user!</u>" status: - marked: "The report was marked as reviewed" destroyed: "The post was destroyed" - created: "A report was created" failed: "Something went wrong" - share_visibilites: - update: - post_hidden_and_muted: "%{name}’s post has been hidden, and notifications have been muted." - see_it_on_their_profile: "If you want to see updates on this post, visit %{name}’s profile page." - profiles: edit: - your_public_profile: "Your public profile" - your_private_profile: "Your private profile" + basic: "My basic profile" + extended: "My extended profile" + settings: "Profile settings" + extended_visibility_text: "Visibility of your extended profile:" + public: "Public" + limited: "Limited" + basic_hint: "Every item in your profile is optional. Your basic profile will always be publicly visible." + extended_hint: "Click the switch to set your extended profile data visibility. Public means it is visible to the internet, limited means only people who you share with will see this information." your_name: "Your name" first_name: "First name" last_name: "Last name" @@ -1019,7 +951,6 @@ en: your_photo: "Your photo" update_profile: "Update profile" allow_search: "Allow for people to search for you within diaspora*" - edit_profile: "Edit profile" nsfw_explanation: "NSFW (“not safe for workâ€) is diaspora*’s self-governing community standard for content which may not be suitable to view while at work. If you plan to share such material frequently, please check this option so that everything you share will be hidden from people’s streams unless they choose to view them." nsfw_explanation2: "If you choose not to select this option, please add the #nsfw tag each time you share such material." nsfw_check: "Mark everything I share as NSFW" @@ -1029,16 +960,11 @@ en: registrations: new: - create_my_account: "Create my account!" - - join_the_movement: "Join the movement!" - sign_up_message: "Social networking with a ♥" - enter_email: "Enter your email address" enter_username: "Pick a username (only letters, numbers, and underscores)" enter_password: "Enter a password (six character minimum)" enter_password_again: "Enter the same password as before" - sign_up: "Sign up" + sign_up: "Create account" email: "Email" username: "Username" password: "Password" @@ -1048,47 +974,14 @@ en: terms_link: "terms of service" create: success: "You’ve joined diaspora*!" - edit: - edit: "Edit %{name}" - leave_blank: "(leave blank if you don’t want to change it)" - password_to_confirm: "(we need your current password to confirm your changes)" - unhappy: "Unhappy?" - update: "Update" - cancel_my_account: "Cancel my account" closed: "Signups are closed on this diaspora* pod." invalid_invite: "The invite link you provided is no longer valid!" - requests: - manage_aspect_contacts: - manage_within: "Manage contacts within" - existing: "Existing contacts" - destroy: - success: "You are now sharing." - error: "Please select an aspect!" - ignore: "Ignored contact request." - create: - sending: "Sending" - sent: "You’ve asked to share with %{name}. They should see it next time they log in to diaspora*." - new_request_to_person: - sent: "Sent!" - helper: - new_requests: - zero: "No new requests" - one: "New request!" - other: "%{count} new requests!" reshares: reshare: reshared_via: "Reshared via" - reshare_original: "Reshare original" - reshare: - zero: "Reshare" - one: "1 reshare" - other: "%{count} reshares" - show_original: "Show original" reshare_confirmation: "Reshare %{author}’s post?" deleted: "Original post deleted by author." - create: - failure: "There was an error resharing this post." comment_email_subject: "%{resharer}’s reshare of %{author}’s post" services: provider: @@ -1097,14 +990,16 @@ en: twitter: "Twitter" wordpress: "WordPress" index: + title: "Manage connected services" connect: "Connect" disconnect: "Disconnect" logged_in_as: "Logged in as %{nickname}." - no_services_available: "There are no services on this pod available." + no_services_available: "There are no services available on this pod." not_logged_in: "Currently not logged in." really_disconnect: "Disconnect %{service}?" edit_services: "Edit services" - services_explanation: "Connecting to services gives you the ability to publish your posts to them as you write them in diaspora*." + services_explanation: "Connecting to third-party sharing services gives you the ability to publish your posts to them as you write them in diaspora*." + share_to: "Share to %{provider}" create: success: "Authentication successful." failure: "Authentication failed." @@ -1114,50 +1009,30 @@ en: success: "Successfully deleted authentication." failure: error: "There was an error connecting to that service" - inviter: - join_me_on_diaspora: "Join me on diaspora*" - click_link_to_accept_invitation: "Follow this link to accept your invitation" - finder: - fetching_contacts: "diaspora* is populating your %{service} friends, please check back in a few minutes." - service_friends: "%{service} friends" - no_friends: "No Facebook friends found." - remote_friend: - resend: "Resend" - invite: "Invite" - not_on_diaspora: "Not yet on diaspora*" blocks: create: success: "All right, you won’t see that user in your stream again. #silencio!" - failure: "I couldn’t ignore that user. #evasion" + failure: "I couldn’t ignore that user. #evasion" destroy: success: "Let’s see what they have to say! #sayhello" - failure: "I couldn’t stop ignoring that user. #evasion" + failure: "I couldn’t stop ignoring that user. #evasion" shared: aspect_dropdown: - add_to_aspect: "Add contact" mobile_row_checked: "%{name} (remove)" mobile_row_unchecked: "%{name} (add)" toggle: - zero: "Add contact" one: "In %{count} aspect" other: "In %{count} aspects" publisher: formatWithMarkdown: "You can use %{markdown_link} to format your post" posting: "Posting..." share: "Share" - preview: "Preview" - post_a_message_to: "Post a message to %{aspect}" - make_public: "Make public" - all: "All" upload_photos: "Upload photos" get_location: "Get your location" remove_location: "Remove location" - all_contacts: "All contacts" - share_with: "Share with" whats_on_your_mind: "What’s on your mind?" - publishing_to: "Publishing to: " discard_post: "Discard post" new_user_prefill: newhere: "newhere" @@ -1165,30 +1040,12 @@ en: i_like: "I’m interested in %{tags}. " invited_by: "Thanks for the invite, " poll: - remove_poll_answer: "Remove option" - add_poll_answer: "Add option" add_a_poll: "Add a poll" - question: "Question" - option: "Option 1" - add_contact: - enter_a_diaspora_username: "Enter a diaspora* username:" - your_diaspora_username_is: "Your diaspora* username is: %{diaspora_handle}" - create_request: "Find by diaspora* ID" - diaspora_handle: "diaspora@pod.org" - know_email: "Know their email address? You should invite them" - add_new_contact: "Add a new contact" invitations: invites: "Invites" - invite_someone: "Invite someone" - invitations_left: "%{count} left" - dont_have_now: "You don’t have any right now, but more invites are coming soon!" - invites_closed: "Invites are currently closed on this diaspora* pod" invite_your_friends: "Invite your friends" - from_facebook: "From Facebook" - by_email: "By email" + by_email: "Invite people by email" share_this: "Share this link via email, blog, or social networks!" - reshare: - reshare: "Reshare" public_explain: control_your_audience: "Control your audience" new_user_welcome_message: "Use #hashtags to classify your posts and find people who share your interests. Call out awesome people with @Mentions" @@ -1199,45 +1056,17 @@ en: logged_in: "Logged in to %{service}" manage: "Manage connected services" atom_feed: "Atom feed" - notification: - new: "New %{type} from %{from}" - contact_list: - all_contacts: "All contacts" stream_element: - viewable_to_anyone: "This post is viewable to anyone on the web" - connect_to_comment: "Connect to this user to comment on their post" - currently_unavailable: "Commenting currently unavailable" via: "Via %{link}" via_mobile: "Via mobile" - ignore_user: "Ignore %{name}" - ignore_user_description: "Ignore and remove user from all aspects?" - hide_and_mute: "Hide and mute post" - like: "Like" - unlike: "Unlike" - dislike: "Dislike" - shared_with: "Shared with: %{aspect_names}" - nsfw: "This post has been flagged as NSFW by its author. %{link}" - show: "Show" - footer: - logged_in_as: "Logged in as %{name}" - your_aspects: "Your aspects" status_messages: new: mentioning: "Mentioning: %{person}" create: success: "Successfully mentioned: %{names}" - helper: - no_message_to_display: "No message to display." - destroy: - failure: "Failed to delete post" too_long: "Please make your status message fewer than %{count} characters. Right now it is %{current_length} characters" stream_helper: - show_comments: - zero: "No more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - hide_comments: "Hide all comments" no_more_posts: "You have reached the end of the stream." no_posts_yet: "There are no posts yet." @@ -1248,19 +1077,11 @@ en: one: "1 person tagged with %{tag}" other: "%{count} people tagged with %{tag}" follow: "Follow #%{tag}" - following: "Following #%{tag}" stop_following: "Stop following #%{tag}" none: "The empty tag does not exist!" name_too_long: "Please make your tag name fewer than %{count} characters. Right now it is %{current_length} characters" tag_followings: - create: - success: "Hooray! You’re now following #%{name}." - failure: "Failed to follow #%{name}. Are you already following it?" - none: "You cannot follow a blank tag!" - destroy: - success: "Alas! You aren’t following #%{name} any more." - failure: "Failed to stop following #%{name}. Maybe you already stopped following it?" manage: title: "Manage followed tags" no_tags: "You aren't following any tags." @@ -1314,11 +1135,11 @@ en: current_password_expl: "the one you sign in with..." character_minimum_expl: "must be at least six characters" change_language: "Change language" + change_color_theme: "Change color theme" close_account_text: "Close account" stream_preferences: "Stream preferences" show_community_spotlight: "Show “community spotlight†in stream" show_getting_started: "Show “getting started†hints" - getting_started: "New user preferences" following: "Sharing settings" auto_follow_back: "Automatically share with users who start sharing with you" auto_follow_aspect: "Aspect for users you automatically share with:" @@ -1340,7 +1161,6 @@ en: download_export_photos: "Download my photos" request_export_photos: "Request my photos" request_export_photos_update: "Refresh my photos" - download_photos: "Download my photos" export_photos_in_progress: "We are currently processing your photos. Please check back in a few moments." close_account: @@ -1351,13 +1171,12 @@ en: locked_out: "You will get signed out and locked out of your account until it has been deleted." lock_username: "Your username will be locked. You will not be able to create a new account on this pod with the same ID." no_turning_back: "There is no turning back! If you’re really sure, enter your password below." - if_you_want_this: "If you really want this to happen, type in your password below and click “Close accountâ€" privacy_settings: title: "Privacy settings" strip_exif: "Strip metadata such as location, author, and camera model from uploaded images (recommended)" ignored_users: "Ignored users" - stop_ignoring: "stop ignoring" + stop_ignoring: "Stop ignoring" no_user_ignored_message: "You are not currently ignoring any other user" destroy: @@ -1375,7 +1194,6 @@ en: what_are_you_in_to: "What are you into?" hashtag_explanation: "Hashtags allow you to talk about and follow your interests. They’re also a great way to find new people on diaspora*." hashtag_suggestions: "Try following tags like #art, #movies, #gif, etc." - saved: "Saved!" update: password_changed: "Password changed. You can now log in with your new password." @@ -1392,6 +1210,8 @@ en: unconfirmed_email_not_changed: "Email change failed" follow_settings_changed: "Follow settings changed" follow_settings_not_changed: "Follow settings change failed." + color_theme_changed: "Color theme successfully changed." + color_theme_not_changed: "An error occurred while changing the color theme." public: does_not_exist: "User %{username} does not exist!" confirm_email: @@ -1402,13 +1222,6 @@ en: previous_label: "« previous" next_label: "next »" - webfinger: - fetch_failed: "Failed to fetch webfinger profile for %{profile_url}" - hcard_fetch_failed: "There was a problem fetching the hcard for %{account}" - xrd_fetch_failed: "There was an error getting the xrd from account %{account}" - not_enabled: "Webfinger does not seem to be enabled for %{account}’s host" - no_person_constructed: "No person could be constructed from this hcard." - simple_captcha: placeholder: "Enter the image value" label: "Enter the code in the box:" diff --git a/config/locales/diaspora/en_1337.yml b/config/locales/diaspora/en_1337.yml index ce07ae1ee23a79c609e490c5bf1485957d7ab39f..0d0abfc329ca4ef0b186abef2762c294e1769a3a 100644 --- a/config/locales/diaspora/en_1337.yml +++ b/config/locales/diaspora/en_1337.yml @@ -6,10 +6,7 @@ en_1337: _applications: "4ppz" - _comments: "5p4mz" _contacts: "n0obz" - _home: "127.0.0.1" - _photos: "p!cz" _services: "53rv!c35" account: "4cc0un7" activerecord: @@ -40,13 +37,7 @@ en_1337: username: invalid: "415 - 0NLY U53 L3773R5, NUMB3R5 & UND3R5C0R35!" taken: "41r34dy pwnd" - ago: "%{time} 4g0" all_aspects: "411 45p3ctz" - application: - helper: - unknown_person: "4n0n no0b" - video_title: - unknown: "un0wn pr0n 7!713" are_you_sure: "j0o 5ur3?" are_you_sure_delete_account: "j0o 5ur3 w4nn4 Shift+Del jo0r 4cc0un7? C4n7 r3570r3!" aspect_memberships: @@ -60,13 +51,6 @@ en_1337: success: "N00B 4DD3D" aspect_listings: add_an_aspect: "+ 4DD 4N 45P3C7" - edit_aspect: "3D17 %{name}" - select_all: "Ctrl+A" - contacts_not_visible: "N00B5 1N 7H15 45P3C7 W0N7 KN0W 34CH 07H3R!" - contacts_visible: "N00B5 1N 7H15 45P3C7 W1LL KN0W 34CH 07H3R!" - create: - failure: "45P3C7 CR34710N F41L3D!" - success: "N3W 45P3C7 %{name} W45 CR4F73D!" destroy: failure: "%{name} N07 3MP7Y -> F41L!" success: "%{name} G07 5UCC35FULLY PWND!" @@ -74,21 +58,13 @@ en_1337: aspect_list_is_not_visible: "45P3C7 L157 15 H1DD3N 2 07H3R5 1N 45P3C7!" aspect_list_is_visible: "45P3C7 L157 15 V151BL3 2 07H3R5 1N 45P3C7!" confirm_remove_aspect: "5UR3?" - make_aspect_list_visible: "M4K3 N00B5 V151BL3 2 34CH 07H3R?" - remove_aspect: "D3L373 7H15 45P3C7!" rename: "R3N4M3" update: "UPD473" updating: "UPD471NG..." index: - diaspora_id: - content_1: "Y0UR D* 1D 15:" - content_2: "G1V3 7H3M 2 N00B5 4ND 7H3Y W1LL F1ND U!" - heading: "D* 1D" donate: "D0N473!" - handle_explanation: "7H15 15 Y0UR D* 1D, N00B5 C4N F1ND U U51NG 17!" help: do_you: "D0 U:" - email_feedback: "%{link} Y0UR F33DB4CK!" feature_suggestion: "... H4V3 4 %{link} 5UGG35710N?" find_a_bug: "... F0UND 4 %{link}?" have_a_question: "... H4V3 4 %{link}?" @@ -97,22 +73,12 @@ en_1337: tag_bug: "#bug" tag_feature: "#feature" tag_question: "#question" - no_contacts: "N0 N00B5" - no_tags: "+ F1ND 4 #74G 2 F0LL0W" - people_sharing_with_you: "N00B5 5H4R1NG W17H U!" - post_a_message: "5P4M 50M37H1NG >>" services: content: "U C4N C0NN3C7 7H3 F0LL0W1NG 53RV1C35 2 D*:" heading: "C0NN3C7 53RV1C35" - unfollow_tag: "570P F0LL0W1NG #%{tag}" - new: - create: "CR3473" - name: "N4M3 (JU57 F0R U)" no_contacts_message: try_adding_some_more_contacts: "U C4N 534RCH (70P) 0R 1NV173 50M3 N00B5 (R1GH7)" you_should_add_some_more_contacts: "U 5H0ULD G37 50M3 N00B5!" - no_posts_message: - start_talking: "N0B0DY 5P4MM3D 4NY7H1NG..." seed: acquaintances: "PR05" family: "RL" @@ -121,53 +87,32 @@ en_1337: update: failure: "45P3C7 %{name} H4D 2 L0NG N4M3 -> F41L!" success: "45P3C7 %{name} H45 B33N 5UCC35FULLY 3D173D!" - back: "<-" bookmarklet: explanation: "5P4M FR0M 4NYWH3R3, 4NY71M3! %{link}." heading: "B00KM4RKL37" post_something: "5P4M 50M37H1NG 2 D*" - post_success: "5P4MM3D! CL051NG!" cancel: "c4nc3l" comments: new_comment: comment: "5P4M" commenting: "5P4MM1NG..." - one: "1 5P4M" - other: "%{count} 5P4M5" - zero: "N0 5P4M5" contacts: - create: - failure: "F41L3D 2 CR3473 C0N74C7!" index: add_a_new_aspect: "4DD 4 N3W 45P3C7!" - add_to_aspect: "4DD N00B5 2: %{name}" all_contacts: "4LL N00B5" my_contacts: "Y0UR N00B5" no_contacts: "L00K5 L1K3 U N33D 70 PWN M0R3 N00B5!" only_sharing_with_me: "0NLY 5H4R1NG W17H U" start_a_conversation: "574R7 4 N3W C0NV3R54710N!" title: "N00B5" - your_contacts: "Y0UR N00B5" - sharing: - people_sharing: "N00B5 5H4R1NG W17H U:" conversations: create: fail: "1NV4L1D M3554G3!" sent: "M3554G3 53N7!" - helper: - new_messages: - few: "%{count} N3W M3554G35" - many: "%{count} N3W M3554G35" - one: "1 N3W M3554G3" - other: "%{count} N3W M3554G35" - two: "%{count} N3W M3554G35" - zero: "N0 N3W M3554G35" index: inbox: "1NB0X" - no_conversation_selected: "N0 C0NV3R54710N 53L3C73D!" no_messages: "N0 5P4M5" new: - abandon_changes: "D0N7 54V3?" send: "5P4M" sending: "5P4MM1NG..." subject: "N00B" @@ -181,77 +126,32 @@ en_1337: error_messages: helper: correct_the_following_errors_and_try_again: "3rr0rz! r37ry!" - invalid_fields: "!nv41!d !npu7" fill_me_out: "!npu7 73x7 h3r3" find_people: "Ctrl+F n0obz, #74g5" - hide: "pwn?" invitations: a_facebook_user: "4 F4C3B00K N00B!" check_token: not_found: "1NV4L1D 1NV174710N 70K3N!" create: - already_contacts: "U 4R3 4LR34DY C0NN3C73D W17H 7H15 N00B!" - already_sent: "U 4LR34DY 1NV173D 7H15 N00B!" no_more: "U H4V3 N0 M0R3 1NV174710N5!" - own_address: "U C4N7 5P4M Y0UR 0WN M41L!" rejected: "7H3 F0LL0W1NG M41L5 H4D PR0BL3M5: " sent: "1NV174710N5 H4V3 B33N 53N7 2: " - edit: - accept_your_invitation: "4CC3P7 Y0UR 1NV174710N!" - your_account_awaits: "Y0UR 4CC0UN7 W4175!" new: - already_invited: "7H3 F0LL0W1NG N00B5 F4C3P4LM3D 7H3M53LV35:" - aspect: "45P3C7" - if_they_accept_info: "1F 7H3Y 4CC3P7, 7H3Y W1LL B3 4DD3D 2 7H3 45P3C7 U 1NV173D 7H3M!" invite_someone_to_join: "5P4M 50M30N3 2 J01N D*!" - personal_message: "P3R50N4L M3554G3" - resend: "R35P4M!" send_an_invitation: "53ND 4 5P4M!" - send_invitation: "53ND 5P4M!" - to: "7o" layouts: application: powered_by: "P0W3R3D BY D*" public_feed: "PUBL1C D* F33D F0R %{name}" toggle: "70GGL3 M0B1L3" whats_new: "WH475 N3W?" - your_aspects: "Y0UR 45P3C75" header: - admin: "G0DM0D3!" - blog: "BL0G" code: "C0D3" - login: "L0G 1N" logout: "K7HXB41" profile: "PR0F1L3" - recent_notifications: "R3C3N7 N071F1C4710N5!" settings: "53771NG5" - view_all: "V13W 4LL!" - likes: - likes: - people_dislike_this: - few: "%{count} </3" - many: "%{count} </3" - one: "%{count} </3" - other: "%{count} </3" - two: "%{count} </3" - zero: "N0 </3" - people_like_this: - few: "%{count} <3" - many: "%{count} <3" - one: "%{count} <3" - other: "%{count} <3" - two: "%{count} <3" - zero: "N0 <3" - people_like_this_comment: - few: "%{count} <3" - many: "%{count} <3" - one: "%{count} <3" - other: "%{count} <3" - two: "%{count} <3" - zero: "N0 <3" limited: "V1P" more: "m04r" - next: "n3x7" no_results: "404" notifications: also_commented: @@ -275,14 +175,6 @@ en_1337: other: "%{actors} C0MM3N73D 0N Y0UR %{post_link}." two: "%{actors} C0MM3N73D 0N Y0UR %{post_link}." zero: "%{actors} C0MM3N73D 0N Y0UR %{post_link}." - helper: - new_notifications: - few: "%{count} N3W N071F1C4710N5" - many: "%{count} N3W N071F1C4710N5" - one: "1 N3W N071F1C4710N" - other: "%{count} N3W N071F1C4710N5" - two: "%{count} N3W N071F1C4710N5" - zero: "N0 N3W N071F1C4710N5" index: and: "4ND" and_others: @@ -365,7 +257,6 @@ en_1337: liked: "%{name} JU57 <3 Y0UR 5P4M!" view_post: "V13W 5P4M >" mentioned: - mentioned: "M3N710N3D U 1N 4 5P4M:" subject: "%{name} H45 M3N710N3D U 0N D*!" private_message: reply_to_or_view: "R3PLY 2 0R V13W 7H15 C0NV3R54710N >" @@ -383,94 +274,38 @@ en_1337: to_change_your_notification_settings: "2 CH4NG3 Y0UR N071F1C4710N 53771NG5" nsfw: "N5FW! 1337z 0n1y!" ok: "K" - or: "XOR" - password: "*****" - password_confirmation: "***** c0nf!rm47!0n" people: - add_contact_small: - add_contact_from_tag: "4DD N00B FR0M 74G" - aspect_list: - edit_membership: "3D17 45P3C7 M3MB3R5H1P" - helper: - results_for: " R35UL75 F0R %{params}" index: no_one_found: "...4ND N0 0N3 W45 F0UND!" no_results: "H3Y! U N33D 2 534RCH F0R 50M37H1NG!" results_for: "534RCH R35UL75 F0R" - one: "1 N00B" - other: "%{count} N00B5" person: - add_contact: "4DD N00B" - already_connected: "4LR34DY C0NN3C73D!" - pending_request: "P3ND1NG R3QU357" thats_you: "7H475 U!" profile_sidebar: bio: "B10" born: "B-D4Y" - edit_my_profile: "3D17 MY PR0F1L3" gender: "G3ND3R" - in_aspects: "1N 45P3C75" location: "1P" - remove_contact: "PWN N00B" - remove_from: "R3M0V3 %{name} FR0M %{aspect}?" show: does_not_exist: "N00B != 3X1571NG" has_not_shared_with_you_yet: "%{name} H45 N07 5H4R3D 4NY 5P4M W17H U!" - incoming_request: "%{name} W4N75 2 5H4R3 W17H U!" - mention: "M3N710N" - message: "5P4M" - not_connected: "U 4R3 N07 5H4R1NG W17H 7H15 P3R50N!" - recent_posts: "R3C3N7 5P4M" - recent_public_posts: "R3C3N7 PUBL1C 5P4M" - return_to_aspects: "R37URN 2 Y0UR 45P3C75 P4G3" - see_all: "533 4LL" - start_sharing: "475R7 5H4R1NG" - to_accept_or_ignore: "2 4CC3P7 0R PWN 7H15 N00B" - sub_header: - add_some: "4DD 50M3" - edit: "3D17" - you_have_no_tags: "U H4V3 N0 74G5!" - webfinger: - fail: "%{handle} != 3X1571NG" - zero: "N0 N00B5" photos: - comment_email_subject: "%{name}'s PR0N" create: integrity_error: "PR0N UPL04D F41L3D! 4R3 U 5UR3 7H47 W45 4N 1M5G3?" runtime_error: "PR0N UPL04D F41L3D! 4R3 U 5UR3 7H47 Y0UR 5347B3L7 15 F4573N3D?" type_error: "PR0N UPL04D F41L3D! 4R3 U 5UR3 4N 1M4G3 W45 4DD3D?" destroy: notice: "PR0N D3L373D!" - edit: - editing: "3D171NG" - new: - back_to_list: "B4CK 2 L157" - new_photo: "N3W PH070!" - post_it: "5P4M 17!" new_photo: empty: "{file} 15 3MP7Y, PLZ 53L3C7 F1L35 4G41N W17H0U7 17!" invalid_ext: "{file} H45 1NV4L1D 3X73N510N! 0NLY {extensions} 4R3 4LL0W3D!" size_error: "{file} 15 2 L4RG3, M4X1MUM F1L3 51Z3 15 {sizeLimit}." new_profile_photo: upload: "UPL04D 4 N3W PR0F1L3 P1C!" - photo: - view_all: "V13W 4LL 0F %{name}'s PR0N" show: - collection_permalink: "C0LL3C710N P3RM4L1NK" - delete_photo: "D3L373 P1C" - edit: "3D17" - edit_delete_photo: "3D17 P1C D35CR1P710N / D3L373 P1C" - make_profile_photo: "M4K3 PR0F1L3 P1C" show_original_post: "5H0W 0R1G1N4L 5P4M!" - update_photo: "UPD473 P1C" - update: - error: "F41L3D 2 3D17 P1C!" - notice: "P1C 5UCC35FULLY UPD473D!" posts: show: - destroy: "D3L373" - not_found: "50RRY, W3 C0ULDN7 F1ND 7H47 5P4M!" - permalink: "P3RM4L1NK" photos_by: few: "%{count} P1CZ BY %{author}" many: "%{count} P1CZ BY %{author}" @@ -478,14 +313,11 @@ en_1337: other: "%{count} P1CZ BY %{author}" two: "2 P1CZ BY %{author}" zero: "N0 P1CZ BY %{author}" - previous: "pr3v!0us" privacy: "u53r pr!vi13935" - privacy_policy: "pr!v4cy p01!cy" profile: "5p3cz" profiles: edit: allow_search: "4LL0W N00B5 2 534RCH F0R U!" - edit_profile: "3D17 PR0F1L3" first_name: "F1R57 N4M3" last_name: "L457 N4M3" update_profile: "UPD473 PR0F1L3" @@ -495,8 +327,6 @@ en_1337: your_location: "Y0UR 1P" your_name: "Y0UR N4M3" your_photo: "Y0UR PR0N" - your_private_profile: "Y0UR PR1V473 PR0F1L3" - your_public_profile: "Y0UR PUBL1C PR0F1L3" your_tags: "D35CR1B3 Y0UR53LF 1N 5 W0RD5" your_tags_placeholder: "L1K3 #4N0N #W0W #G33K #4N0NYM0U5 #1RC" update: @@ -514,60 +344,18 @@ en_1337: closed: "51GNUP5 4R3 CL053D 0N 7H15 D* P0D!" create: success: "U H4V3 J01N3D D*" - edit: - cancel_my_account: "PWN MY 4CC0UN7!" - edit: "3D17 %{name}" - leave_blank: "(L34V3 BL4NK 1F U D0N7 W4N7 2 CH4NG3 17)" - password_to_confirm: "(W3 N33D Y0UR CURR3N7 ***** 2 C0NF1RM CH4NG35!)" - unhappy: "UNH4PPY?" - update: "UPD473" new: - create_my_account: "CR3473 MY 4CC0UN7!" enter_email: "3N73R 4N 3M41L!" enter_password: "3N73R *****" enter_password_again: "3N73R 17 4G41N!" enter_username: "P1CK 4 N1CK (0NLY L3773R5 NUMB3R5 4ND UND3R5C0R35!)" - join_the_movement: "J01N 7H3 M0V3M3N7!" password: "*****" - sign_up_message: "50C14L N37W0RK1NG W17H 4 <3" - requests: - create: - sending: "5P4MM1NG" - sent: "U H4V3 45K3D 2 5H4R3 W17H %{name}. 7H3Y 50ULD 533 17 N3X7 71M3 7H3Y V1517 D*!" - destroy: - error: "PL3453 53L3C7 4N 45P3C7!" - ignore: "PWND N00B R3QU357" - success: "U 4R3 N0W 5H4R1NG" - helper: - new_requests: - few: "%{count} N3W R3QU3575!" - many: "%{count} N3W R3QU3575!" - one: "N3W R3QU357" - other: "%{count} N3W R3QU3575!" - two: "%{count} N3W R3QU3575!" - zero: "N0 N3W R3QU3575!" - manage_aspect_contacts: - existing: "3X1571NG N00B5" - manage_within: "M4N4G3 N00B5 W17H1N" - new_request_to_person: - sent: "5P4MM3D!" reshares: comment_email_subject: "%{resharer}'s R35P4M 0F %{author}'s 5P4M" - create: - failure: "R35P4MM1NG F41L3D!" reshare: deleted: "0R1G1N4L 5P4M PWND BY 4U7H0R!" - reshare: - few: "%{count} R35P4M5" - many: "%{count} R35P4M5" - one: "1 R35P4M" - other: "%{count} R35P4M5" - two: "%{count} R35P4M5" - zero: "R35P4M" reshare_confirmation: "R35P4M %{author}'s 5P4M?" - reshare_original: "R35P4M 0R1G1N4L" reshared_via: "R35P4MM3D V14" - show_original: "5H0W 0R1G1N4L" search: "Ctrl+F" services: create: @@ -577,32 +365,14 @@ en_1337: success: "5UCC35FULLY D3L373D 4U7H3N71F1C4710N!" failure: error: "3RR0R C0NN3C71NG 7H47 53RV1C3!" - finder: - no_friends: "N0 FB N00B5 F0UND!" - service_friends: "%{service} N00B5" index: disconnect: "D15C0NN3C7" edit_services: "3D17 53RV1C35!" logged_in_as: "L0GG3D 1N 45" really_disconnect: "D15C0NN3C7 %{service}?" - inviter: - click_link_to_accept_invitation: "F0LL0W 7H15 L1NK 2 4CC3P7 Y0UR 1NV174710N!" - join_me_on_diaspora: "J01N M3 0N D*" - remote_friend: - invite: "1NV173" - not_on_diaspora: "N07 Y37 0N D*!" - resend: "R35P4M" settings: "~/.config" shared: - add_contact: - add_new_contact: "4DD 4 N3W N00B" - create_request: "F1ND BY D* 1D" - diaspora_handle: "N1CK@P0D.0RG" - enter_a_diaspora_username: "3N73R 4 D* N1CK:" - know_email: "KN0W 7H31R M41L? U 5H0ULD 1NV173 7H3M!" - your_diaspora_username_is: "Y0UR D* N1CK 15: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "4DD N00B" toggle: few: "1N %{count} 45P3C75" many: "1N %{count} 45P3C75" @@ -610,71 +380,32 @@ en_1337: other: "1N %{count} 45P3C75" two: "1N %{count} 45P3C75" zero: "4DD N00B" - contact_list: - all_contacts: "4LL C0N74C75" - footer: - logged_in_as: "CURR3N7 N1CK: %{name}" - your_aspects: "Y0UR 45P3C75" invitations: by_email: "BY M41L" - dont_have_now: "U D0N7 H4V3 4NY R1GH7 N0W, BU7 M0R3 1NV1735 4R3 C0M1NG 500N!" - from_facebook: "FR0M FB" - invitations_left: "%{count} L3F7" - invite_someone: "1NV173 50M30N3!" invite_your_friends: "1NV173 Y0UR FR13ND5!" invites: "1NV1735" - invites_closed: "1NV1735 4R3 CURR3N7LY CL053D 0N 7H15 P0D!" - notification: - new: "N3W %{type} FR0M %{from}" public_explain: logged_in: "L0GG3D 1N 2 %{service}" manage: "M4N4G3 C0NN3C73D 53RV1C35" outside: "PUBL1C 5P4M5 W1LL B3 4V14BL3 2 07H3R5 0U751D3 0F D* 2 533!" title: "537 UP C0NN3C73D 53RV1C35" publisher: - all: "4LL" - all_contacts: "4LL N00B5" discard_post: "D15C4RD P057" - make_public: "M4K3 PUBL1C" new_user_prefill: i_like: "1 575LK: %{tags}." newhere: "#n00b_h3r3" - post_a_message_to: "5P4M 7H15 45P3C7: %{aspect}" posting: "5P4MM1NG..." - publishing_to: "PUBL15H1NG 2: " share: "5P4M" - share_with: "5H4R3 W17H" upload_photos: "UPL04D P1C5" whats_on_your_mind: "WH475 0N Y0UR M1ND?" - reshare: - reshare: "R35P4M" stream_element: - dislike: "PWN" - hide_and_mute: "H1D3 4ND PWN" - like: "<3" - shared_with: "5H4R3D W17H: %{aspect_names}" - unlike: "</3" via: "V14 %{link}" - viewable_to_anyone: "7H15 5P4M 15 V13W4BL3 2 4NY0N3 1N 7H3 W3B!" status_messages: create: success: "5UCC355FULLY M3N710N3D: %{names}" - destroy: - failure: "F41L3D 2 PWN 4 5P4M!" - helper: - no_message_to_display: "N0 5P4M 2 D15PL4Y!" new: mentioning: "M3N710N1NG: %{person}" too_long: "{\"few\"=>\"PL3453 M4K3 Y0UR 5P4M5 L355 7H3N %{count} CH4R4C73R5\", \"many\"=>\"PL3453 M4K3 Y0UR 5P4M5 L355 7H3N %{count} CH4R4C73R5\", \"one\"=>\"PL3453 M4K3 Y0UR 5P4M5 L355 7H3N %{count} CH4R4C73R\\\"\", \"other\"=>\"PL3453 M4K3 Y0UR 5P4M5 L355 7H3N %{count} CH4R4C73R5\", \"two\"=>\"PL3453 M4K3 Y0UR 5P4M5 L355 7H3N %{count} CH4R4C73R5\", \"zero\"=>\"PL3453 M4K3 Y0UR 5P4M5 L355 7H3N %{count} CH4R4C73R5\"}" - stream_helper: - hide_comments: "H1D3 4LL 5P4M5!" - show_comments: - few: "5H0W %{count} M0R3 C0MM3N75" - many: "5H0W %{count} M0R3 C0MM3N75" - one: "5H0W 1 M0R3 C0MM3N75" - other: "5H0W %{count} M0R3 C0MM3N75" - two: "5H0W 2 M0R3 C0MM3N75" - zero: "N0 C0MM3N75!" streams: aspects: title: "UR 45P3C75" @@ -682,20 +413,10 @@ en_1337: title: "Y0UR M3N710N5" tags: title: "5P4M 74GG3D: %{tags}" - tag_followings: - create: - failure: "F41L3D 2 F0LL0W: #%{name}" - success: "5UCC35FULLY F0LL0W1NG: #%{name}" - destroy: - failure: "F41L3D 2 570P F0LL0W1NG: #%{name}" - success: "5UCC35FULLY PWND: #%{name}" tags: show: follow: "F0LL0W #%{tag}" - following: "F0LL0W1NG #%{tag}" stop_following: "570P F0LL0W1NG #%{tag}" - terms_and_conditions: "T&C" - undo: "Ctrl+Z?" username: "n!ck" users: confirm_email: @@ -712,7 +433,6 @@ en_1337: what_we_delete: "W3 D3L373 4LL 0F UR P0575 4ND PR0F1L3 D474 L1K3 4 B055. UR C0MM3N75 W1LL H4NG 4R0UND, BU7 B3 4550C1473D W17H UR D* ID." comment_on_post: "...50M30N3 5P4M5 Y0UR 5P4M?" current_password: "CURR3N7 *****" - download_photos: "D0WNL04D MY PR0N" edit_account: "H4CK Y0UR 4CC0UN7" email_awaiting_confirmation: "4C71V4510N L1NK 53N7 2 %{unconfirmed_email}. UN71L U F0LL0W 7H3 L1NK W3 W1LL C0N71NU3 2 U53 Y0UR 0R1G1N4L M41L %{email}." export_data: "3XP0R7 D474" @@ -737,11 +457,4 @@ en_1337: password_changed: "***** CH4NG3D!" password_not_changed: "***** CH4NG3 F41L3D!" unconfirmed_email_changed: "M41L CH4NG3D, N33D5 4C71V4710N!" - unconfirmed_email_not_changed: "M41L CH4NG3 F41L3D!" - webfinger: - fetch_failed: "F41L3D 70 F37CH W3BF1NG3R PR0F1L3 F0R %{profile_url}!" - hcard_fetch_failed: "3RR0R WH1L3 F37CH1NG HDC4RD F0R %{account}!" - no_person_constructed: "N0 P3R50N C0ULD B3 C0N57RUC73D FR0M 7H15 HC4RD!" - not_enabled: "W3BF1NG3R D035 N07 533M 70 B3 3N4BL3D F0R %{account}'s H057!" - xrd_fetch_failed: "3RR0R G3771NG XRD F0R %{account}!" - welcome: "w31c0m3" \ No newline at end of file + unconfirmed_email_not_changed: "M41L CH4NG3 F41L3D!" \ No newline at end of file diff --git a/config/locales/diaspora/en_pirate.yml b/config/locales/diaspora/en_pirate.yml index 4bca12ff51b8028a3fbb07902f3d0f90ea3efec8..55e69a3ab485d62b43908cf82792b415dbdad9c9 100644 --- a/config/locales/diaspora/en_pirate.yml +++ b/config/locales/diaspora/en_pirate.yml @@ -6,10 +6,7 @@ en_pirate: _applications: "Applications" - _comments: "Comments" _contacts: "Mateys" - _home: "Home Port" - _photos: "Portraits" _services: "Ye Services" account: "Ye account" activerecord: @@ -40,13 +37,7 @@ en_pirate: username: invalid: "is invalid. We only allow letters, numbers, 'n underscores." taken: "has been hornswaggled!" - ago: "%{time} ago arrr" all_aspects: "Yer Crews" - application: - helper: - unknown_person: "unknown scallywag" - video_title: - unknown: "Arrgh! Unknown Video Title" are_you_sure: "Are ye sure?" are_you_sure_delete_account: "Are ye sure you want t' walk the plank? Yer account will be shark bait!" aspect_memberships: @@ -60,17 +51,9 @@ en_pirate: success: "Successfully added contact to crew." aspect_listings: add_an_aspect: "+ Add a crew" - deselect_all: "Unchoose all" - edit_aspect: "Edit %{name}" - select_all: "Choose all" aspect_stream: stay_updated: "Stay up 't date" stay_updated_explanation: "Yer main stream is populated with all of yer contacts, tags ye follow, and posts from some creative members of the community." - contacts_not_visible: "Mateys in this crew will nah be able to see each other." - contacts_visible: "Contacts in this crew will be able to see each other." - create: - failure: "Crew creation failed." - success: "Yer new crew %{name} was created" destroy: failure: "%{name} not be empty and could not be removed YARGH!" success: "%{name} was removed successfully mate." @@ -78,21 +61,13 @@ en_pirate: aspect_list_is_not_visible: "Yer crew list is hidden to others in crew" aspect_list_is_visible: "Yer crew list is visible to others in crew" confirm_remove_aspect: "Are ye sure ye wants t' scuttle this crew?" - make_aspect_list_visible: "make crew list visible?" - remove_aspect: "Fire this crew" rename: "rename" update: "update" updating: "updatin'" index: - diaspora_id: - content_1: "Ye ship name be:" - content_2: "Give it to anyone 'n they'll be able to find ye on diaspora*. Yargh." - heading: "diaspora* ID" donate: "Give some dubloons!" - handle_explanation: "This is yer diaspora id. Like a ship name, ye can give this to mates to reach ye." help: do_you: "Do ye:" - email_feedback: "%{link} yer feedback, if ye prefer" feature_suggestion: "... do ye have a %{link} suggestion?" find_a_bug: "... ye find a %{link}?" have_a_question: "do ye have a %{link}?" @@ -106,25 +81,15 @@ en_pirate: follow: "Follow %{link} 'n welcome new mateys 't diaspora*!" learn_more: "Learn more matey" title: "Welcome New Buccaneers" - no_contacts: "No mateys" - no_tags: "+ Find an interestin' somethin' t' follow" - people_sharing_with_you: "Buccaneers sharin' with ye" - post_a_message: "send a letter" services: content: "Ye can connect the following services to diaspora*:" heading: "Connect ye services" - unfollow_tag: "Stop followin' #%{tag}" welcome_to_diaspora: "Welcome to diaspora*, %{name}. Ye old seadog!" - new: - create: "Forge" - name: "Name" no_contacts_message: community_spotlight: "crew spotlight" or_spotlight: "Or ye can share with %{link}" try_adding_some_more_contacts: "You can search (top) or invite (right) more mateys." you_should_add_some_more_contacts: "Ye should add some more contacts!" - no_posts_message: - start_talking: "None of yer mates has said anything yet!" seed: acquaintances: "Landlubbers" family: "Kin" @@ -133,7 +98,6 @@ en_pirate: update: failure: "Yer crew, %{name}, had too many words, YARGH!" success: "Yer crew, %{name}. has been edited matey!" - back: "Backs" blocks: create: failure: "Could not send'em to the brig!" @@ -144,45 +108,28 @@ en_pirate: explanation: "Post to diaspora* from anywhere by marking this link on yer map => %{link}" heading: "Mark on ye map" post_something: "Post 't d*" - post_success: "Sent! Closing!" cancel: "Nevermind" comments: new_comment: comment: "Comm'nt" commenting: "Commentin'" - one: "1 comment mate" - other: "%{count} comments mate" - zero: "no comments mate" contacts: - create: - failure: "Failed 't create contact" index: add_a_new_aspect: "Add a new crew" - add_to_aspect: "Add more mateys to %{name}" all_contacts: "All yer mateys" my_contacts: "Me Mateys" no_contacts: "No Mateys." only_sharing_with_me: "Mateys only sharin' with me" start_a_conversation: "Send a letter" title: "Mateys" - your_contacts: "Yer Mateys" - sharing: - people_sharing: "Buccaneers sharin' with ye:" conversations: create: fail: "Problem with letter, YARGH!" sent: "Letter sent" - helper: - new_messages: - one: "1 new letter" - other: "%{count} new letters" - zero: "No new letters" index: inbox: "Pigeon's nest" - no_conversation_selected: "no message chosen, mate" no_messages: "no letters" new: - abandon_changes: "Abandon ye changes?" sending: "Sendin'..." to: "'t" show: @@ -194,32 +141,18 @@ en_pirate: error_messages: helper: correct_the_following_errors_and_try_again: "Correct ye blunders 'n try again ye scallywag!" - invalid_fields: "N'valid fields" fill_me_out: "Fill me out arrr" find_people: "Scour fer mates or treasures" - hide: "Cover" invitations: a_facebook_user: "A Facebook scallywag" create: - already_contacts: "Ye are already mates with this buccaneer!" - already_sent: "Ye already invited this bucko." no_more: "Ye have no more invitations." - own_address: "Ye can't send an invitation t' yer own address ye scallywag." rejected: "Yer pigeon can't deliver to the followin' addresses: " sent: "Invitations have been sent t': %{emails}" - edit: - accept_your_invitation: "Accept yer invitation" - your_account_awaits: "Yer ship awaits!" new: - already_invited: "The following landblubbers have not accepted yer invitation:" - aspect: "Crew" - check_out_diaspora: "Avast ye! Check out diaspora*! ARRR!!" - if_they_accept_info: "if they accept, they will be added to the crew ye invited them." invite_someone_to_join: "Invite a bucko t' diaspora*!" language: "What do ye speak?" - personal_message: "Personal letter" send_an_invitation: "Send n' invitation" - to: "Who's this goin' t'?" layouts: application: back_to_top: "Back to crow's nest" @@ -227,40 +160,12 @@ en_pirate: public_feed: "Sea-wide diaspora* feed for %{name}" toggle: "toggl' mobile site" whats_new: "what be new?" - your_aspects: "yer crews" header: - admin: "cap'n" - login: "check in with ye captain" logout: "Abandon Ship" profile: "Ye Ship" settings: "Ye Ships Rigging" - view_all: "Show all" - likes: - likes: - people_dislike_this: - few: "%{count} dislikes" - many: "%{count} dislikes" - one: "%{count} dislike" - other: "%{count} dislikes" - two: "%{count} dislikes" - zero: "no dislikes" - people_like_this: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" - people_like_this_comment: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" limited: "Only ye crews" more: "More!" - next: "next" no_results: "Ye results be in davey jones' locker. Yargh!" notifications: also_commented: @@ -284,14 +189,6 @@ en_pirate: other: "%{actors} commented on yer %{post_link}." two: "%{actors} commented on yer %{post_link}." zero: "%{actors} commented on yer %{post_link}." - helper: - new_notifications: - few: "%{count} new notifications" - many: "%{count} new notifications" - one: "1 new notifications" - other: "%{count} new notifications" - two: "%{count} new notifications" - zero: "No new notifications" index: and: "'n" and_others: @@ -370,7 +267,6 @@ en_pirate: liked: "%{name} just like'd yer post" view_post: "Read post >" mentioned: - mentioned: "mention'd ye in a post:" subject: "%{name} has mention'd ye on diaspora*" private_message: reply_to_or_view: "Reply 't or read this conversation >" @@ -387,87 +283,42 @@ en_pirate: to_change_your_notification_settings: "t' change yer notification settin's" nsfw: "Not safe for lad's or lasses'" ok: "Aye" - or: "er" - password: "Secret pact" - password_confirmation: "Confirm yer secret pact!" people: - add_contact_small: - add_contact_from_tag: "add matey from tag" - helper: - results_for: " results fer %{params}" index: looking_for: "Lookin' fer posts tagged %{tag_link}?" no_one_found: "...and no landblubbers were found." no_results: "Ahoy! Ye need 't search fer somethin'." results_for: "Scallywags matchin' %{search_term}" - one: "1 person" - other: "%{count} people" person: - add_contact: "add mate" - pending_request: "Pendin' request" thats_you: "That's ye!" profile_sidebar: born: "date o' birth" - edit_my_profile: "Edit me profile" gender: "Ye gender" location: "Sea I be in" - remove_contact: "remove matey" show: closed_account: "This ship has been sunk." does_not_exist: "Matey does not exist! Arrr" has_not_shared_with_you_yet: "%{name} has not shared any posts with ye yet!" - ignoring: "Yer ignorin' all posts from %{name}." - incoming_request: "%{name} wants 't share with ye" - not_connected: "Yer not sharin' with this scallywag." - return_to_aspects: "Return 't yer mateys page" - start_sharing: "start sharin'" - to_accept_or_ignore: "'t accept or deny it." - sub_header: - you_have_no_tags: "ye have no tags!" - webfinger: - fail: "Sorry mate, we couldnt spot %{handle}." - zero: "no people" photos: - comment_email_subject: "%{name}'s portrait" create: integrity_error: "Portrait hanging failed. Are ye sure that was a portrait?" runtime_error: "Portrait hanging failed. Are ye sure yer hatches be battened down?" type_error: "Portrait hangin' failed. Are ye sure a portrait was added mate?" destroy: notice: "Portrait scuttled!" - edit: - editing: "Editin'" - new: - new_photo: "New Portrait" - post_it: "Fire!" new_photo: empty: "{file} be empty, choose yer files again without it mate." invalid_ext: "{file} not be valid ye scallywag. Only {extensions} be allowed." size_error: "{file} be 't large mate, the biggest file size be {sizeLimit}." new_profile_photo: - or_select_one_existing: "or choose one from yer already existin' %{photos}" upload: "Hang a new portrait in ye ship!" - photo: - view_all: "look at all of %{name}'s portraits" - show: - delete_photo: "Delete Portrait" - edit_delete_photo: "Edit portrait tale / get rid of portrait" - make_profile_photo: "make profile portrait" - update_photo: "Update Portrait" - update: - error: "Failed to change portrait cap'n!" - notice: "Portrait changed, cap'n!" posts: show: - destroy: "Scuttle" - not_found: "Sorry cap'n, we couldn't find that X." photos_by: one: "One portrait by %{author}" other: "%{count} portraits by %{author}" zero: "No portraits by %{author}" - previous: "previous" privacy: "Ye privacy settin's" - privacy_policy: "Ye privacy policy" profile: "Ye duffle" profiles: edit: @@ -478,8 +329,6 @@ en_pirate: your_location: "Where ye be in the sea?" your_name: "Yer name" your_photo: "Ye portrait" - your_private_profile: "Ye private profile" - your_public_profile: "Ye public profile" your_tags: "Describe yerself in 5 words, mate." your_tags_placeholder: "like #treasure #ships #plunderin #sea #rum" update: @@ -496,64 +345,15 @@ en_pirate: closed: "Signups be closed on this ship!" create: success: "Ye've joined diaspora*! YARGH!" - edit: - cancel_my_account: "Walk the plank" - leave_blank: "(leave blank if ye dont want 't change it)" - password_to_confirm: "we need yer current password 'to confirm yer changes)" - new: - create_my_account: "Create my account" - join_the_movement: "Join the pirate life, YARGH!" - sign_up_message: "Social Networking with a <3" - requests: - create: - sending: "Sendin'" - sent: "Ye've asked 't share with %{name}. They should be able 't see it next time they come aboard diaspora*." - destroy: - error: "Select a crew!" - ignore: "The brig." - success: "Ye are now sharin'." - helper: - new_requests: - few: "%{count} new requests!" - many: "%{count} new requests!" - one: "new request!" - other: "%{count} new requests!" - two: "%{count} new requests!" - zero: "no new requests" - manage_aspect_contacts: - existing: "Existin' mates" - manage_within: "Manage mates within" - reshares: - create: - failure: "There be an error resharin' this post." - reshare: - reshare: - few: "%{count} reshares" - many: "%{count} reshares" - one: "1 reshare" - other: "%{count} reshares" - two: "%{count} reshares" - zero: "Reshare" search: "Scour" services: create: already_authorized: "A matey named %{diaspora_id} already authorized that %{service_name} record. ARR!" failure: error: "there be an error connectin' that service" - finder: - fetching_contacts: "diaspora* is populatin' yer %{service} mates, come back in a bit mate." - no_friends: "Couldnt find any Facebook mateys." - service_friends: "%{service} Mateys" - inviter: - click_link_to_accept_invitation: "Click this link t' accept yer invitation" settings: "Settin's" - share_visibilites: - update: - post_hidden_and_muted: "%{name}'s be hidden, 'n notifications be muted." - see_it_on_their_profile: "If ye be wantin' 't see updates on this post, look at %{name}'s ship, ARRGH!" shared: aspect_dropdown: - add_to_aspect: "Add to aspect" toggle: few: "In %{count} aspects" many: "In %{count} aspects" @@ -561,15 +361,12 @@ en_pirate: other: "In %{count} aspects" two: "In %{count} aspects" zero: "Add to aspect" - footer: - your_aspects: "yer mateys" public_explain: logged_in: "on deck at %{service}" new_user_welcome_message: "Use #hashtags t' classify yer posts n' find mateys. Call out mateys with @Mentions" outside: "Sea-wide messages will be available fer others outside of diaspora* t' see." visibility_dropdown: "Use this dropdown t' change the visibility of yer post. (It's good idear ye make this first one sea-wide.)" publisher: - all_contacts: "all mateys" discard_post: "Scuttle post" new_user_prefill: i_like: "I be interested in %{tags}." @@ -578,30 +375,12 @@ en_pirate: share: "Fire!" upload_photos: "Hang up portraits" whats_on_your_mind: "What be botherin' you?" - stream_element: - connect_to_comment: "Connect t' this scallywag t' comm'nt on their post" - currently_unavailable: "comm'ntin currently not working" - hide_and_mute: "Hide and Mute" - shared_with: "Fired at: %{aspect_names}" status_messages: create: success: "Ye've successfully mentioned: %{names}" - destroy: - failure: "Failed t' get rid of post" - helper: - no_message_to_display: "No message t' display." new: mentioning: "Mentionin': %{person}" too_long: "{\"few\"=>\"Ye scallywag, make yer status messages less than %{count} characters\", \"many\"=>\"Ye scallywag,make yer status messages less than %{count} characters\", \"one\"=>\"Ye scallywag, make yer status messages less than %{count} character\", \"other\"=>\"Ye scallywag, make yer status messages less than %{count} characters\", \"two\"=>\"Ye scallywag, make yer status messages less than %{count} characters\", \"zero\"=>\"Ye scallywag,make yer status messages less than %{count} characters\"}" - stream_helper: - hide_comments: "Hide all comm'nts" - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: aspects: title: "Yer Aspects" @@ -610,20 +389,9 @@ en_pirate: title: "Yer Mentions" multi: title: "Sea" - tag_followings: - create: - failure: "Failed to follow: #%{name}" - none: "Ye cannot follow a blank tag!" - success: "Successfully followin': #%{name}" - destroy: - failure: "Failed to stop followin': #%{name}" - success: "Avast! Successfully stopped followin': #%{name}" tags: show: - following: "Followin' #%{tag}" stop_following: "Stop Followin' #%{tag}" - terms_and_conditions: "Terms 'n conditions" - undo: "Undo?" username: "Yer Username" users: edit: @@ -633,9 +401,7 @@ en_pirate: make_diaspora_better: "We want ye t' make diaspora* better arr, so ye should help before ye walk the plank and feed the fishes. If ye do want t' walk, we want ye t' be savvy on what happens next ye old seadog arrr." mr_wiggles: "Mr Wiggles will be sad t' see ye go mate." what_we_delete: "We scuttle all of yer posts, profile data, as soon as humanly possible. Yer comments will hang around, but be associated with yer Diaspora Handle." - download_photos: "download ye portraits" show_community_spotlight: "Show Community Spotlight in sea" stream_preferences: "Sea settin's" your_email: "Yer email" - your_handle: "Yer diaspora id" - welcome: "Ahoy, matey!" \ No newline at end of file + your_handle: "Yer diaspora id" \ No newline at end of file diff --git a/config/locales/diaspora/en_shaw.yml b/config/locales/diaspora/en_shaw.yml index ff64bf42a260e6b749d8b7b5c2dcf22d6b6d4164..61c2667741ff17b18456249198b70c644e83d08d 100644 --- a/config/locales/diaspora/en_shaw.yml +++ b/config/locales/diaspora/en_shaw.yml @@ -6,9 +6,7 @@ en_shaw: _applications: "ð‘¨ð‘ð‘¤ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯" - _comments: "ð‘’ð‘ªð‘¥ð‘©ð‘¯ð‘‘ð‘•" _contacts: "ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘•" - _photos: "ð‘“ð‘´ð‘‘ð‘´ð‘Ÿ" account: "ð‘©ð‘’ð‘¬ð‘¯ð‘‘" activerecord: errors: @@ -39,11 +37,6 @@ en_shaw: invalid: "is invalid. We only allow letters, numbers, and underscores" taken: "ð‘¦ð‘Ÿ ð‘·ð‘¤ð‘®ð‘§ð‘›ð‘¦ ð‘‘ð‘±ð‘’ð‘©ð‘¯." all_aspects: "ð‘·ð‘¤ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ð‘•" - application: - helper: - unknown_person: "ð‘©ð‘¯ð‘¯ð‘´ð‘¯ ð‘ð‘»ð‘•ð‘©ð‘¯" - video_title: - unknown: "ð‘©ð‘¯ð‘¯ð‘´ð‘¯ ð‘ð‘¦ð‘›ð‘¦ð‘´ ð‘‘ð‘²ð‘‘ð‘©ð‘¤" are_you_sure: "𑸠𑿠ð‘–ð‘»?" aspect_memberships: destroy: @@ -56,11 +49,6 @@ en_shaw: success: "ð‘•ð‘©ð‘’ð‘•ð‘§ð‘•ð‘“ð‘«ð‘¤ð‘¦ ð‘¨ð‘›ð‘©ð‘› ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ ð‘‘ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘." aspect_listings: add_an_aspect: "+ ð‘¨ð‘› ð‘©ð‘¯ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘" - contacts_not_visible: "ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘• ð‘¦ð‘¯ ð‘žð‘¦ð‘• ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ ð‘¢ð‘¦ð‘¤ ð‘¯ð‘ªð‘‘ ð‘šð‘° ð‘±ð‘šð‘©ð‘¤ ð‘‘ ð‘•ð‘° ð‘°ð‘— ð‘³ð‘žð‘¼." - contacts_visible: "ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘• ð‘¦ð‘¯ ð‘žð‘¦ð‘• ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ ð‘¢ð‘¦ð‘¤ ð‘¯ð‘ªð‘‘ ð‘šð‘° ð‘±ð‘šð‘©ð‘¤ ð‘‘ ð‘•ð‘° ð‘°ð‘— ð‘³ð‘žð‘¼." - create: - failure: "ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ ð‘’ð‘®ð‘¦ð‘±ð‘–ð‘©ð‘¯ ð‘“ð‘±ð‘¤ð‘›." - success: "ð‘¿ð‘¼ ð‘¯ð‘¿ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ %{name} ð‘¢ð‘ªð‘Ÿ ð‘’ð‘®ð‘¦ð‘±ð‘‘ð‘©ð‘›" destroy: failure: "%{name} ez dago hutsik eta ezin izan da ezabatu." success: "%{name} ð‘¢ð‘ªð‘Ÿ ð‘•ð‘©ð‘’ð‘•ð‘§ð‘•ð‘“ð‘«ð‘¤ð‘¦ ð‘®ð‘¦ð‘¥ð‘µð‘ð‘›." @@ -68,37 +56,21 @@ en_shaw: aspect_list_is_not_visible: "ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ ð‘¤ð‘¦ð‘•ð‘‘ ð‘¦ð‘Ÿ ð‘£ð‘¦ð‘›ð‘©ð‘¯ ð‘‘ ð‘³ð‘žð‘¼ð‘Ÿ ð‘¦ð‘¯ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘" aspect_list_is_visible: "ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ ð‘¤ð‘¦ð‘•ð‘‘ ð‘¦ð‘Ÿ ð‘ð‘¦ð‘Ÿð‘¦ð‘šð‘©ð‘¤ ð‘‘ ð‘³ð‘žð‘¼ð‘Ÿ ð‘¦ð‘¯ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘" confirm_remove_aspect: "𑸠𑿠ð‘–ð‘» ð‘¿ ð‘¢ð‘³ð‘¯ð‘‘ ð‘‘ ð‘›ð‘¦ð‘¤ð‘°ð‘‘ ð‘žð‘¦ð‘• ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘?" - make_aspect_list_visible: "ð‘¥ð‘±ð‘’ ð‘žð‘¦ð‘• ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ ð‘¤ð‘¦ð‘•ð‘‘ ð‘ð‘¦ð‘Ÿð‘¦ð‘šð‘©ð‘¤?" - remove_aspect: "ð‘›ð‘¦ð‘¤ð‘°ð‘‘ ð‘žð‘¦ð‘• ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘" rename: "ð‘®ð‘¦ð‘¯ð‘±ð‘¥" update: "ð‘³ð‘ð‘›ð‘±ð‘‘" updating: "ð‘³ð‘ð‘›ð‘±ð‘‘ð‘¦ð‘™" index: - diaspora_id: - content_1: "ð‘¿ð‘¼ ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘²ð‘›ð‘§ð‘¯ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–𑯠ð‘¦ð‘Ÿ:" - content_2: "ð‘œð‘¦ð‘ ð‘¦ð‘‘ ð‘‘ ð‘§ð‘¯ð‘¦ð‘¢ð‘©ð‘¯ 𑯠ð‘žð‘±ð‘¤ ð‘šð‘° ð‘±ð‘šð‘©ð‘¤ ð‘‘ ð‘“ð‘²ð‘¯ð‘› ð‘¿ ð‘ªð‘¯ ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘©." - heading: "·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘²ð‘›ð‘§ð‘¯ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯" donate: "ð‘›ð‘´ð‘¯ð‘±ð‘‘" - handle_explanation: "ð‘žð‘¦ð‘• ð‘¦ð‘Ÿ ð‘¿ð‘¼ ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘²ð‘›ð‘§ð‘¯ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯. ð‘¤ð‘²ð‘’ ð‘©ð‘¯ ð‘¦-ð‘¥ð‘±ð‘¤ ð‘¨ð‘›ð‘®ð‘§ð‘•, ð‘¿ ð‘’ð‘¨ð‘¯ ð‘œð‘¦ð‘ ð‘žð‘¦ð‘• ð‘‘ ð‘ð‘°ð‘ð‘©ð‘¤ ð‘‘ ð‘®ð‘°ð‘— ð‘¿." help: here_to_help: "Diaspora community is here to help!" tag_bug: "#bug" tag_feature: "#feature" tag_question: "#question" - no_contacts: "ð‘¯ð‘´ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘•" - no_tags: "ð‘¯ð‘´ ð‘‘ð‘¨ð‘œð‘Ÿ" - people_sharing_with_you: "ð‘ð‘°ð‘ð‘©ð‘¤ ð‘–ð‘ºð‘¦ð‘™ ð‘¢ð‘¦ð‘ž ð‘¿" - post_a_message: "ð‘ð‘´ð‘•ð‘‘ ð‘© ð‘¥ð‘§ð‘•ð‘©ð‘¡ >>" services: content: "ð‘¿ ð‘’ð‘¨ð‘¯ ð‘’ð‘©ð‘¯ð‘§ð‘’ð‘‘ ð‘ž ð‘“ð‘ªð‘¤ð‘´ð‘¦ð‘™ ð‘•ð‘»ð‘ð‘¦ð‘•ð‘©ð‘Ÿ 𑑠·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘©:" heading: "ð‘’ð‘©ð‘¯ð‘§ð‘’ð‘‘ ð‘•ð‘»ð‘ð‘¦ð‘•ð‘©ð‘Ÿ" - new: - create: "ð‘’ð‘®ð‘¦ð‘±ð‘‘" - name: "ð‘¯ð‘±ð‘¥" no_contacts_message: try_adding_some_more_contacts: "You can search (top) or invite (right) more contacts." - no_posts_message: - start_talking: "ð‘¯ð‘´ð‘šð‘©ð‘›ð‘¦ ð‘£ð‘¨ð‘Ÿ ð‘•ð‘§ð‘› ð‘§ð‘¯ð‘¦ð‘”ð‘¦ð‘™ ð‘˜ð‘§ð‘‘!" seed: acquaintances: "ð‘©ð‘’ð‘¢ð‘±ð‘‘ð‘©ð‘¯ð‘•ð‘©ð‘Ÿ" family: "ð‘“ð‘¨ð‘¥ð‘¦ð‘¤ð‘¦" @@ -107,52 +79,31 @@ en_shaw: update: failure: "ð‘¿ð‘¼ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘, %{name}, ð‘£ð‘¨ð‘› ð‘‘𑵠ð‘¤ð‘ªð‘™ ð‘© ð‘¯ð‘±ð‘¥ ð‘‘ ð‘šð‘° ð‘•ð‘±ð‘ð‘›." success: "ð‘¿ð‘¼ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘, %{name}, ð‘£ð‘¨ð‘Ÿ ð‘šð‘§ð‘¯ ð‘•ð‘©ð‘’ð‘•ð‘§ð‘•ð‘“ð‘«ð‘¤ð‘¦ ð‘§ð‘›ð‘¦ð‘‘ð‘©ð‘›." - back: "ð‘šð‘¨ð‘’" bookmarklet: explanation: "ð‘ð‘´ð‘•ð‘‘ 𑑠·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘“ð‘®ð‘³ð‘¥ ð‘¨ð‘¯ð‘¦ð‘¢ð‘º ð‘šð‘² ð‘šð‘«ð‘’ð‘¥ð‘¸ð‘’ð‘¦ð‘™ %{link}." heading: "ð‘šð‘«ð‘’ð‘¥ð‘¸ð‘’ð‘¤ð‘§ð‘‘" post_something: "ð‘ð‘´ð‘•ð‘‘ ð‘•ð‘³ð‘¥ð‘”ð‘¦ð‘™ 𑑠·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘©" - post_success: "ð‘ð‘´ð‘•ð‘‘ð‘©ð‘›! ð‘’ð‘¤ð‘´ð‘Ÿð‘¦ð‘™!" cancel: "ð‘’ð‘¨ð‘¯ð‘•ð‘©ð‘¤" comments: new_comment: comment: "ð‘’ð‘ªð‘¥ð‘©ð‘¯ð‘‘" commenting: "ð‘’ð‘ªð‘¥ð‘©ð‘¯ð‘‘ð‘¦ð‘™..." - one: "1 ð‘’ð‘ªð‘¥ð‘©ð‘¯ð‘‘" - other: "%{count} ð‘’ð‘ªð‘¥ð‘©ð‘¯ð‘‘ð‘•" - zero: "ð‘¯ð‘´ ð‘’ð‘ªð‘¥ð‘©ð‘¯ð‘‘ð‘•" contacts: - create: - failure: "ð‘“ð‘±ð‘¤ð‘› ð‘‘ ð‘’ð‘®ð‘¦ð‘±ð‘‘ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘" index: add_a_new_aspect: "ð‘¨ð‘› ð‘¯ð‘¿ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘" - add_to_aspect: "Add contacts to %{name}" all_contacts: "ð‘·ð‘¤ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘•" my_contacts: "ð‘¥ð‘² ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘•" no_contacts: "ð‘¯ð‘´ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘•." only_sharing_with_me: "ð‘´ð‘¯ð‘¤ð‘¦ ð‘–ð‘ºð‘¦ð‘™ ð‘¢ð‘¦ð‘ž ð‘¥ð‘°" start_a_conversation: "ð‘•ð‘‘ð‘¸ð‘‘ ð‘© ð‘’ð‘ªð‘¯ð‘ð‘¼ð‘•ð‘±ð‘–ð‘©ð‘¯" title: "ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘•" - your_contacts: "ð‘¿ð‘¼ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘•" - sharing: - people_sharing: "ð‘ð‘°ð‘ð‘©ð‘¤ ð‘–ð‘ºð‘¦ð‘™ ð‘¢ð‘¦ð‘ž ð‘¿:" conversations: create: sent: "ð‘¥ð‘§ð‘•ð‘©ð‘¡ ð‘•ð‘§ð‘¯ð‘‘" - helper: - new_messages: - few: "%{count} ð‘¯ð‘¿ ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ" - many: "%{count} ð‘¯ð‘¿ ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ" - one: "1 ð‘¯ð‘¿ ð‘¥ð‘§ð‘•ð‘©ð‘¡" - other: "%{count} ð‘¯ð‘¿ ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ" - two: "%{count} new messages" - zero: "ð‘¯ð‘´ ð‘¯ð‘¿ ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ" index: inbox: "ð‘¦ð‘¯ð‘šð‘ªð‘’ð‘•" - no_conversation_selected: "ð‘¯ð‘´ ð‘’ð‘ªð‘¯ð‘ð‘¼ð‘•ð‘±ð‘–ð‘©ð‘¯ ð‘•ð‘©ð‘¤ð‘§ð‘’ð‘‘ð‘©ð‘›" no_messages: "ð‘¯ð‘´ ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ" new: - abandon_changes: "ð‘©ð‘šð‘¨ð‘¯ð‘›ð‘©ð‘¯ ð‘—ð‘±ð‘¯ð‘¡ð‘©ð‘Ÿ?" send: "ð‘•ð‘§ð‘¯ð‘›" sending: "ð‘•ð‘§ð‘¯ð‘›ð‘¦ð‘™..." subject: "ð‘•ð‘³ð‘šð‘¡ð‘§ð‘’ð‘‘" @@ -165,73 +116,31 @@ en_shaw: error_messages: helper: correct_the_following_errors_and_try_again: "ð‘’ð‘©ð‘®ð‘§ð‘’ð‘‘ ð‘ž ð‘“ð‘ªð‘¤ð‘´ð‘¦ð‘™ ð‘ºð‘¼ð‘Ÿ 𑯠ð‘‘ð‘®ð‘² ð‘©ð‘œð‘§ð‘¯." - invalid_fields: "ð‘¦ð‘¯ð‘ð‘¨ð‘¤ð‘¦ð‘› ð‘“ð‘°ð‘¤ð‘›ð‘Ÿ" fill_me_out: "ð‘“ð‘¦ð‘¤ ð‘¥ð‘° ð‘¬ð‘‘" find_people: "ð‘“ð‘²ð‘¯ð‘› ð‘ð‘°ð‘ð‘©ð‘¤" - hide: "ð‘£ð‘²ð‘›" invitations: check_token: not_found: "ð‘¦ð‘¯ð‘ð‘¦ð‘‘ð‘±ð‘–ð‘©ð‘¯ ð‘‘ð‘´ð‘’ð‘©ð‘¯ ð‘¯ð‘ªð‘‘ ð‘“ð‘¬ð‘¯ð‘›" create: - already_contacts: "ð‘¿ ð‘£ð‘¨ð‘ ð‘·ð‘¤ð‘®ð‘§ð‘›ð‘¦ ð‘’ð‘©ð‘¯ð‘§ð‘’ð‘‘ð‘©ð‘› ð‘¢ð‘¦ð‘ž ð‘žð‘¦ð‘• ð‘ð‘»ð‘•ð‘©ð‘¯" - already_sent: "ð‘¿ ð‘·ð‘¤ð‘®ð‘§ð‘›ð‘¦ ð‘¦ð‘¯ð‘ð‘²ð‘‘ð‘©ð‘› ð‘žð‘¦ð‘• ð‘ð‘»ð‘•ð‘©ð‘¯." no_more: "ð‘¿ ð‘£ð‘¨ð‘ ð‘¯ð‘´ ð‘¥ð‘¹ ð‘¦ð‘¯ð‘ð‘¦ð‘‘ð‘±ð‘–ð‘©ð‘¯ð‘Ÿ." - own_address: "ð‘¿ ð‘’ð‘¨ð‘¯ð‘‘ ð‘•ð‘§ð‘¯ð‘› ð‘©ð‘¯ ð‘¦ð‘¯ð‘ð‘¦ð‘‘ð‘±ð‘–ð‘©ð‘¯ ð‘‘ ð‘¿ð‘¼ ð‘´ð‘¯ ð‘©ð‘›ð‘®ð‘§ð‘•." rejected: "ð‘ž ð‘“ð‘ªð‘¤ð‘´ð‘¦ð‘™ ð‘¦-ð‘¥ð‘±ð‘¤ ð‘©ð‘›ð‘®ð‘§ð‘• ð‘£ð‘¨ð‘› ð‘ð‘®ð‘ªð‘šð‘¤ð‘©ð‘¥ð‘Ÿ: " sent: "ð‘¦ð‘¯ð‘ð‘¦ð‘‘ð‘±ð‘–ð‘©ð‘¯ð‘Ÿ ð‘£ð‘¨ð‘ ð‘šð‘§ð‘¯ ð‘•ð‘§ð‘¯ð‘‘ ð‘‘: " new: - already_invited: "ð‘ž ð‘“ð‘ªð‘¤ð‘´ð‘¦ð‘™ ð‘ð‘°ð‘ð‘©ð‘¤ ð‘£ð‘¨ð‘ ð‘¯ð‘ªð‘‘ ð‘©ð‘’ð‘•ð‘§ð‘ð‘‘ð‘©ð‘› ð‘¿ð‘¼ ð‘¦ð‘¯ð‘ð‘¦ð‘‘ð‘±ð‘–ð‘©ð‘¯:" - aspect: "ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘" - if_they_accept_info: "ð‘¦ð‘“ ð‘žð‘± ð‘©ð‘’ð‘•ð‘§ð‘ð‘‘, ð‘žð‘± ð‘¢ð‘¦ð‘¤ ð‘šð‘° ð‘¨ð‘›ð‘©ð‘› ð‘‘ ð‘ž ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ ð‘¿ ð‘¦ð‘¯ð‘ð‘²ð‘‘ð‘©ð‘› ð‘žð‘§ð‘¥." invite_someone_to_join: "ð‘¦ð‘¯ð‘ð‘²ð‘‘ ð‘•ð‘³ð‘¥ð‘¢ð‘©ð‘¯ ð‘‘ ð‘¡ð‘¶ð‘¯ ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘©!" - personal_message: "ð‘ð‘»ð‘•ð‘©ð‘¯ð‘©ð‘¤ ð‘¥ð‘§ð‘•ð‘©ð‘¡" - resend: "ð‘®ð‘¦ð‘•ð‘§ð‘¯ð‘›" send_an_invitation: "ð‘•ð‘§ð‘¯ð‘› ð‘©ð‘¯ ð‘¦ð‘¯ð‘ð‘¦ð‘‘ð‘±ð‘–ð‘©ð‘¯" - send_invitation: "ð‘•ð‘§ð‘¯ð‘› ð‘¦ð‘¯ð‘ð‘¦ð‘‘ð‘±ð‘–ð‘©ð‘¯" - to: "ð‘‘" layouts: application: powered_by: "ð‘ð‘¬ð‘®ð‘› ð‘šð‘² ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘©*" public_feed: "ð‘ð‘³ð‘šð‘¤ð‘¦ð‘’ ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘“ð‘°ð‘› ð‘“𑹠%{name}" toggle: "ð‘‘ð‘ªð‘œð‘©ð‘¤ ð‘¥ð‘´ð‘šð‘©ð‘¤ ð‘•ð‘²ð‘‘" whats_new: "ð‘¢ð‘ªð‘‘ð‘• ð‘¯ð‘¿?" - your_aspects: "ð‘¿ð‘¼ ð‘¨ð‘•ð‘’ð‘ð‘§ð‘’ð‘‘ð‘•" header: - admin: "ð‘©ð‘›ð‘¥ð‘¦ð‘¯" - blog: "ð‘šð‘¤ð‘ªð‘œ" code: "ð‘’ð‘´ð‘›" - login: "ð‘¤ð‘ªð‘œ ð‘¦ð‘¯" logout: "ð‘¤ð‘ªð‘œ ð‘¬ð‘‘" profile: "ð‘ð‘®ð‘´ð‘“ð‘²ð‘¤" - recent_notifications: "ð‘®ð‘°ð‘•ð‘©ð‘¯ð‘‘ ð‘¯ð‘´ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯ð‘Ÿ" settings: "ð‘•ð‘§ð‘‘ð‘¦ð‘™ð‘Ÿ" - view_all: "ð‘ð‘¿ ð‘·ð‘¤" - likes: - likes: - people_dislike_this: - few: "%{count} ð‘›ð‘¦ð‘•ð‘¤ð‘²ð‘’ð‘•" - many: "%{count} ð‘›ð‘¦ð‘•ð‘¤ð‘²ð‘’ð‘•" - one: "%{count} ð‘›ð‘¦ð‘•ð‘¤ð‘²ð‘’" - other: "%{count} ð‘›ð‘¦ð‘•ð‘¤ð‘²ð‘’ð‘•" - two: "%{count} dislikes" - zero: "ð‘¯ð‘´ ð‘›ð‘¦ð‘•ð‘¤ð‘²ð‘’ð‘•" - people_like_this: - few: "%{count} ð‘¤ð‘²ð‘’ð‘•" - many: "%{count} ð‘¤ð‘²ð‘’ð‘•" - one: "%{count} ð‘¤ð‘²ð‘’" - other: "%{count} ð‘¤ð‘²ð‘’ð‘•" - two: "%{count} likes" - zero: "ð‘¯ð‘´ ð‘¤ð‘²ð‘’ð‘•" - people_like_this_comment: - few: "%{count} ð‘¤ð‘²ð‘’ð‘•" - many: "%{count} ð‘¤ð‘²ð‘’ð‘•" - one: "%{count} ð‘¤ð‘²ð‘’" - other: "%{count} ð‘¤ð‘²ð‘’ð‘•" - two: "%{count} likes" - zero: "ð‘¯ð‘´ ð‘¤ð‘²ð‘’ð‘•" limited: "ð‘¤ð‘¦ð‘¥ð‘¦ð‘‘ð‘©ð‘›" more: "ð‘¥ð‘¹" - next: "ð‘¯ð‘§ð‘’ð‘•ð‘‘" no_results: "ð‘¯ð‘´ ð‘®ð‘¦ð‘Ÿð‘«ð‘¤ð‘‘ð‘• ð‘“ð‘¬ð‘¯ð‘›" notifications: also_commented: @@ -255,14 +164,6 @@ en_shaw: other: "%{actors} ð‘’ð‘ªð‘¥ð‘©ð‘¯ð‘‘ð‘©ð‘› ð‘ªð‘¯ ð‘¿ð‘¼ %{post_link}." two: "%{actors} commented on your %{post_link}." zero: "%{actors} ð‘’ð‘ªð‘¥ð‘©ð‘¯ð‘‘ð‘©ð‘› ð‘ªð‘¯ ð‘¿ð‘¼ %{post_link}." - helper: - new_notifications: - few: "%{count} ð‘¯ð‘¿ ð‘¯ð‘´ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯ð‘Ÿ" - many: "%{count} ð‘¯ð‘¿ ð‘¯ð‘´ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯ð‘Ÿ" - one: "1 ð‘¯ð‘¿ ð‘¯ð‘´ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯" - other: "%{count} ð‘¯ð‘¿ ð‘¯ð‘´ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯ð‘Ÿ" - two: "%{count} new notifications" - zero: "ð‘¯ð‘´ ð‘¯ð‘¿ ð‘¯ð‘´ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯ð‘Ÿ" index: and: "ð‘¯" and_others: @@ -344,7 +245,6 @@ en_shaw: liked: "%{name} ð‘¡ð‘³ð‘•ð‘‘ ð‘¤ð‘²ð‘’ð‘‘ ð‘¿ð‘¼ ð‘ð‘´ð‘•ð‘‘" view_post: "ð‘ð‘¿ ð‘ð‘´ð‘•ð‘‘ >" mentioned: - mentioned: "ð‘¥ð‘§ð‘¯ð‘–ð‘©ð‘¯ð‘› ð‘¿ ð‘¦ð‘¯ ð‘© ð‘ð‘´ð‘•ð‘‘:" subject: "%{name} ð‘£ð‘¨ð‘Ÿ ð‘¥ð‘§ð‘¯ð‘–ð‘©ð‘¯ð‘› ð‘¿ ð‘ªð‘¯ ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘©*" private_message: reply_to_or_view: "ð‘®ð‘¦ð‘ð‘¤ð‘² 𑑠𑹠ð‘ð‘¿ ð‘žð‘¦ð‘• ð‘’ð‘ªð‘¯ð‘ð‘¼ð‘•ð‘±ð‘–ð‘©ð‘¯ >" @@ -360,51 +260,21 @@ en_shaw: thanks: "ð‘”ð‘±ð‘™ð‘’ð‘•," to_change_your_notification_settings: "ð‘‘ ð‘—ð‘±ð‘¯ð‘¡ ð‘¿ð‘¼ ð‘¯ð‘´ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯ ð‘•ð‘§ð‘‘ð‘¦ð‘™ð‘Ÿ" ok: "ð‘´ð‘’ð‘±" - or: "ð‘¹" - password_confirmation: "ð‘ð‘¨ð‘•ð‘¢ð‘¼ð‘› ð‘’ð‘ªð‘¯ð‘“ð‘¼ð‘¥ð‘±ð‘–ð‘©ð‘¯" people: - add_contact_small: - add_contact_from_tag: "ð‘¨ð‘› ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ ð‘“ð‘®ð‘ªð‘¥ ð‘‘ð‘¨ð‘œ" - aspect_list: - edit_membership: "ð‘§ð‘›ð‘¦ð‘‘ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ ð‘¥ð‘§ð‘¥ð‘šð‘¼ð‘–ð‘¦ð‘" - helper: - results_for: " ð‘®ð‘¦ð‘Ÿð‘«ð‘¤ð‘‘ ð‘“𑹠%{params}" index: no_one_found: "...𑯠ð‘¯ð‘´ ð‘¢ð‘³ð‘¯ ð‘¢ð‘ªð‘Ÿ ð‘“ð‘¬ð‘¯ð‘›." no_results: "ð‘£ð‘±! ð‘¿ ð‘¯ð‘°ð‘› ð‘‘ ð‘•ð‘»ð‘— ð‘“𑹠ð‘•ð‘³ð‘¥ð‘”ð‘¦ð‘™." results_for: "ð‘•ð‘»ð‘— ð‘®ð‘¦ð‘Ÿð‘«ð‘¤ð‘‘ð‘• ð‘“ð‘¹" - one: "1 ð‘ð‘»ð‘•ð‘©ð‘¯" - other: "%{count} ð‘ð‘°ð‘ð‘©ð‘¤" person: - add_contact: "ð‘¨ð‘› ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘" - already_connected: "ð‘·ð‘¤ð‘®ð‘§ð‘›ð‘¦ ð‘’ð‘©ð‘¯ð‘§ð‘’ð‘‘ð‘©ð‘›" - pending_request: "ð‘ð‘§ð‘¯ð‘›ð‘¦ð‘™ ð‘®ð‘¦ð‘’ð‘¢ð‘§ð‘•ð‘‘" thats_you: "ð‘žð‘¨ð‘‘ð‘• ð‘¿!" profile_sidebar: bio: "ð‘šð‘²ð‘´" born: "ð‘šð‘»ð‘”ð‘›ð‘±" - edit_my_profile: "ð‘§ð‘›ð‘¦ð‘‘ ð‘¥ð‘² ð‘ð‘®ð‘´ð‘“ð‘²ð‘¤" gender: "ð‘¡ð‘§ð‘¯ð‘›ð‘¼" - in_aspects: "ð‘¦ð‘¯ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ð‘•" location: "ð‘¤ð‘´ð‘’ð‘±ð‘–ð‘©ð‘¯" - remove_contact: "ð‘®ð‘¦ð‘¥ð‘µð‘ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘" - remove_from: "ð‘®ð‘¦ð‘¥ð‘µð‘ %{name} ð‘“ð‘®ð‘ªð‘¥ %{aspect}?" show: does_not_exist: "ð‘ð‘»ð‘•ð‘©ð‘¯ ð‘›ð‘³ð‘Ÿ ð‘¯ð‘ªð‘‘ ð‘§ð‘œð‘Ÿð‘¦ð‘•ð‘‘!" has_not_shared_with_you_yet: "%{name} ð‘£ð‘¨ð‘Ÿ ð‘¯ð‘ªð‘‘ ð‘–ð‘ºð‘› ð‘§ð‘¯ð‘¦ ð‘ð‘´ð‘•ð‘‘ð‘• ð‘¢ð‘¦ð‘ž ð‘¿ ð‘˜ð‘§ð‘‘!" - incoming_request: "%{name} ð‘¢ð‘³ð‘¯ð‘‘ð‘• ð‘‘ ð‘–𑺠ð‘¢ð‘¦ð‘ž ð‘¿" - mention: "ð‘¥ð‘§ð‘¯ð‘–ð‘©ð‘¯" - message: "ð‘¥ð‘§ð‘•ð‘©ð‘¡" - not_connected: "𑿠𑸠ð‘¯ð‘ªð‘‘ ð‘–ð‘ºð‘¦ð‘™ ð‘¢ð‘¦ð‘ž ð‘žð‘¦ð‘• ð‘ð‘»ð‘•ð‘©ð‘¯ %{name}" - recent_posts: "ð‘®ð‘°ð‘•ð‘©ð‘¯ð‘‘ ð‘ð‘´ð‘•ð‘‘ð‘•" - recent_public_posts: "ð‘®ð‘°ð‘•ð‘©ð‘¯ð‘‘ ð‘ð‘³ð‘šð‘¤ð‘¦ð‘’ ð‘ð‘´ð‘•ð‘‘ð‘•" - return_to_aspects: "ð‘®ð‘¦ð‘‘ð‘»ð‘¯ ð‘‘ ð‘¿ð‘¼ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ð‘• ð‘ð‘±ð‘¡" - see_all: "ð‘•ð‘° ð‘·ð‘¤" - start_sharing: "ð‘•ð‘‘ð‘¸ð‘‘ ð‘–ð‘ºð‘¦ð‘™" - to_accept_or_ignore: "ð‘‘ ð‘©ð‘’ð‘•ð‘§ð‘𑑠𑹠ð‘¦ð‘œð‘¯ð‘¹ ð‘¦ð‘‘." - webfinger: - fail: "ð‘•ð‘ªð‘®ð‘¦, ð‘¢ð‘° ð‘’ð‘«ð‘›ð‘¯ð‘‘ ð‘“ð‘²ð‘¯ð‘› %{handle}." - zero: "ð‘¯ð‘´ ð‘ð‘°ð‘ð‘©ð‘¤" photos: create: integrity_error: "ð‘“ð‘´ð‘‘ð‘´ ð‘³ð‘ð‘¤ð‘´ð‘› ð‘“ð‘±ð‘¤ð‘›. 𑸠𑿠ð‘–ð‘» ð‘žð‘¨ð‘‘ ð‘¢ð‘ªð‘Ÿ ð‘©ð‘¯ ð‘¦ð‘¥ð‘©ð‘¡?" @@ -412,35 +282,14 @@ en_shaw: type_error: "ð‘“ð‘´ð‘‘ð‘´ ð‘©ð‘ð‘¤ð‘´ð‘› ð‘“ð‘±ð‘¤ð‘›. 𑸠𑿠ð‘–ð‘» ð‘©ð‘¯ ð‘¦ð‘¥ð‘©ð‘¡ ð‘¢ð‘ªð‘Ÿ ð‘¨ð‘›ð‘©ð‘›?" destroy: notice: "ð‘“ð‘´ð‘‘ð‘´ ð‘›ð‘¦ð‘¤ð‘°ð‘‘ð‘©ð‘›." - edit: - editing: "ð‘§ð‘›ð‘¦ð‘‘ð‘¦ð‘™" - new: - back_to_list: "ð‘šð‘¨ð‘’ ð‘‘ ð‘¤ð‘¦ð‘•ð‘‘" - new_photo: "ð‘¯ð‘¿ ð‘“ð‘´ð‘‘ð‘´" - post_it: "ð‘ð‘´ð‘•ð‘‘ ð‘¦ð‘‘!" new_photo: empty: "{file} ð‘¦ð‘Ÿ ð‘§ð‘¥ð‘ð‘‘ð‘¦, ð‘ð‘¤ð‘°ð‘Ÿ ð‘•ð‘©ð‘¤ð‘§ð‘’ð‘‘ ð‘“ð‘²ð‘¤ð‘Ÿ ð‘©ð‘œð‘§ð‘¯ ð‘¢ð‘¦ð‘žð‘¬ð‘‘ ð‘¦ð‘‘." invalid_ext: "{file} ð‘£ð‘¨ð‘Ÿ ð‘¦ð‘¯ð‘ð‘¨ð‘¤ð‘¦ð‘› ð‘§ð‘’ð‘•ð‘‘ð‘§ð‘¯ð‘–ð‘©ð‘¯. ð‘´ð‘¯ð‘¤ð‘¦ {extensions} 𑸠ð‘©ð‘¤ð‘¬ð‘›." size_error: "{file} ð‘¦ð‘Ÿ ð‘‘𑵠ð‘¤ð‘¸ð‘¡, ð‘¥ð‘¨ð‘’ð‘•ð‘¦ð‘¥ð‘©ð‘¥ ð‘“ð‘²ð‘¤ ð‘•ð‘²ð‘Ÿ ð‘¦ð‘Ÿ {sizeLimit}." new_profile_photo: upload: "ð‘©ð‘ð‘¤ð‘´ð‘› ð‘© ð‘¯ð‘¿ ð‘ð‘®ð‘´ð‘“ð‘²ð‘¤ ð‘“ð‘´ð‘‘ð‘´!" - photo: - view_all: "ð‘ð‘¿ ð‘·ð‘¤ ð‘ %{name}ð‘Ÿ ð‘“ð‘´ð‘‘ð‘´ð‘Ÿ" - show: - collection_permalink: "ð‘’ð‘©ð‘¤ð‘§ð‘’ð‘–ð‘©ð‘¯ ð‘ð‘»ð‘¥ð‘©ð‘¤ð‘¦ð‘™ð‘’" - delete_photo: "ð‘›ð‘¦ð‘¤ð‘°ð‘‘ ð‘“ð‘´ð‘‘ð‘´" - edit: "ð‘§ð‘›ð‘¦ð‘‘" - edit_delete_photo: "ð‘§ð‘›ð‘¦ð‘‘ ð‘“ð‘´ð‘‘ð‘´ ð‘›ð‘¦ð‘•ð‘’ð‘®ð‘¦ð‘ð‘–ð‘©ð‘¯ / ð‘›ð‘¦ð‘¤ð‘°ð‘‘ ð‘“ð‘´ð‘‘ð‘´" - make_profile_photo: "ð‘¥ð‘±ð‘’ ð‘ð‘®ð‘´ð‘“ð‘²ð‘¤ ð‘“ð‘´ð‘‘ð‘´" - update_photo: "ð‘©ð‘ð‘›ð‘±ð‘‘ ð‘“ð‘´ð‘‘ð‘´" - update: - error: "ð‘“ð‘±ð‘¤ð‘› ð‘‘ ð‘§ð‘›ð‘¦ð‘‘ ð‘“ð‘´ð‘‘ð‘´." - notice: "ð‘“ð‘´ð‘‘ð‘´ ð‘•ð‘©ð‘’ð‘•ð‘§ð‘•ð‘“ð‘«ð‘¤ð‘¦ ð‘³ð‘ð‘›ð‘±ð‘‘ð‘©ð‘›." posts: show: - destroy: "ð‘›ð‘¦ð‘¤ð‘°ð‘‘" - not_found: "ð‘•ð‘ªð‘®ð‘¦, ð‘¢ð‘° ð‘’ð‘«ð‘›ð‘¯ð‘‘ ð‘“ð‘²ð‘¯ð‘› ð‘žð‘¨ð‘‘ ð‘ð‘´ð‘•ð‘‘." - permalink: "ð‘ð‘»ð‘¥ð‘©ð‘¤ð‘¦ð‘™ð‘’" photos_by: few: "%{count} photos by %{author}" many: "%{count} photos by %{author}" @@ -448,12 +297,10 @@ en_shaw: other: "%{count} photos by %{author}" two: "Two photos by %{author}" zero: "No photos by %{author}" - previous: "ð‘ð‘®ð‘°ð‘ð‘¾ð‘•" profile: "ð‘ð‘®ð‘´ð‘“ð‘²ð‘¤" profiles: edit: allow_search: "ð‘©ð‘¤ð‘¬ ð‘“𑹠ð‘ð‘°ð‘ð‘©ð‘¤ ð‘‘ ð‘•ð‘»ð‘— ð‘“𑹠𑿠ð‘¢ð‘¦ð‘žð‘¦ð‘¯ ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘©" - edit_profile: "ð‘§ð‘›ð‘¦ð‘‘ ð‘ð‘®ð‘´ð‘“ð‘²ð‘¤" first_name: "ð‘“ð‘»ð‘•ð‘‘ ð‘¯ð‘±ð‘¥" last_name: "ð‘¤ð‘¨ð‘•ð‘‘ ð‘¯ð‘±ð‘¥" update_profile: "ð‘³ð‘ð‘›ð‘±ð‘‘ ð‘ð‘®ð‘´ð‘“ð‘²ð‘¤" @@ -463,8 +310,6 @@ en_shaw: your_location: "ð‘¿ð‘¼ ð‘¤ð‘´ð‘’ð‘±ð‘–ð‘©ð‘¯" your_name: "ð‘¿ð‘¼ ð‘¯ð‘±ð‘¥" your_photo: "ð‘¿ð‘¼ ð‘“ð‘´ð‘‘ð‘´" - your_private_profile: "ð‘¿ð‘¼ ð‘ð‘®ð‘²ð‘ð‘©ð‘‘ ð‘ð‘®ð‘´ð‘“ð‘²ð‘¤" - your_public_profile: "ð‘¿ð‘¼ ð‘ð‘³ð‘šð‘¤ð‘¦ð‘’ ð‘ð‘®ð‘´ð‘“ð‘²ð‘¤" your_tags: "ð‘›ð‘¦ð‘•ð‘’ð‘®ð‘²ð‘š ð‘¿ð‘¼ð‘•ð‘§ð‘¤ð‘“ ð‘¦ð‘¯ 5 ð‘¢ð‘»ð‘›ð‘Ÿ" your_tags_placeholder: "ð‘¤ð‘²ð‘’ #diaspora #ironing #kittens #music #newyork" update: @@ -482,56 +327,15 @@ en_shaw: closed: "ð‘•ð‘²ð‘¯ð‘©ð‘𑕠𑸠ð‘’ð‘¤ð‘´ð‘Ÿð‘› ð‘ªð‘¯ ð‘žð‘¦ð‘• ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘ð‘ªð‘›." create: success: "ð‘¿'ð‘ ð‘¡ð‘¶ð‘¯ð‘› ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘©!" - edit: - cancel_my_account: "ð‘’ð‘¨ð‘¯ð‘•ð‘©ð‘¤ ð‘¥ð‘² ð‘©ð‘’ð‘¬ð‘¯ð‘‘" - edit: "ð‘§ð‘›ð‘¦ð‘‘ %{name}" - leave_blank: "(ð‘¤ð‘°ð‘ ð‘šð‘¤ð‘±ð‘™ð‘’ ð‘¦ð‘“ ð‘¿ ð‘›ð‘´ð‘¯ð‘‘ ð‘¢ð‘³ð‘¯ð‘‘ ð‘‘ ð‘—ð‘±ð‘¯ð‘¡ ð‘¦ð‘‘)" - password_to_confirm: "(ð‘¢ð‘° ð‘¯ð‘°ð‘› ð‘¿ð‘¼ ð‘’ð‘»ð‘©ð‘¯ð‘‘ ð‘ð‘¨ð‘•ð‘¢ð‘¼ð‘› ð‘‘ ð‘’ð‘©ð‘¯ð‘“ð‘»ð‘¥ ð‘¿ð‘¼ ð‘—ð‘±ð‘¯ð‘¡ð‘©ð‘Ÿ)" - unhappy: "ð‘©ð‘¯ð‘£ð‘¨ð‘ð‘¦?" - update: "ð‘³ð‘ð‘›ð‘±ð‘‘" new: - create_my_account: "Create my account" enter_email: "ð‘§ð‘¯ð‘‘𑼠ð‘©ð‘¯ ð‘¦-ð‘¥ð‘±ð‘¤" enter_password: "ð‘§ð‘¯ð‘‘𑼠𑩠ð‘ð‘¨ð‘•ð‘¢ð‘¼ð‘›" enter_password_again: "ð‘§ð‘¯ð‘‘𑼠𑞠ð‘•ð‘±ð‘¥ ð‘ð‘¨ð‘•ð‘¢ð‘¼ð‘› ð‘¨ð‘Ÿ ð‘šð‘¦ð‘“ð‘¹" enter_username: "ð‘ð‘¦ð‘’ ð‘© ð‘¿ð‘Ÿð‘¼ð‘¯ð‘±ð‘¥ (ð‘´ð‘¯ð‘¤ð‘¦ ð‘¤ð‘§ð‘‘ð‘¼ð‘Ÿ, ð‘¯ð‘³ð‘¥ð‘šð‘¼ð‘Ÿ, 𑯠ð‘³ð‘¯ð‘›ð‘¼ð‘•ð‘’ð‘¹ð‘Ÿ)" - sign_up_message: "Social Networking with a <3" - requests: - create: - sending: "ð‘•ð‘§ð‘¯ð‘›ð‘¦ð‘™" - sent: "ð‘¿'ð‘ ð‘¨ð‘•ð‘’ð‘‘ ð‘‘ ð‘–𑺠ð‘¢ð‘¦ð‘ž %{name}. ð‘žð‘± ð‘–ð‘«ð‘› ð‘•ð‘° ð‘¦ð‘‘ ð‘ž ð‘¯ð‘§ð‘’ð‘•ð‘‘ ð‘‘ð‘²ð‘¥ ð‘žð‘± ð‘¤ð‘ªð‘œ ð‘¦ð‘¯ 𑑠·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘©." - destroy: - error: "ð‘ð‘¤ð‘°ð‘Ÿ ð‘•ð‘©ð‘¤ð‘§ð‘’ð‘‘ ð‘©ð‘¯ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘!" - ignore: "ð‘¦ð‘œð‘¯ð‘¹ð‘› ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ ð‘®ð‘¦ð‘’ð‘¢ð‘§ð‘•ð‘‘." - success: "𑿠𑸠ð‘¯ð‘¬ ð‘–ð‘ºð‘¦ð‘™." - helper: - new_requests: - few: "%{count} ð‘¯ð‘¿ ð‘®ð‘¦ð‘’ð‘¢ð‘§ð‘•ð‘‘ð‘•!" - many: "%{count} ð‘¯ð‘¿ ð‘®ð‘¦ð‘’ð‘¢ð‘§ð‘•ð‘‘ð‘•!" - one: "ð‘¯ð‘¿ ð‘®ð‘¦ð‘’ð‘¢ð‘§ð‘•ð‘‘!" - other: "%{count} ð‘¯ð‘¿ ð‘®ð‘¦ð‘’ð‘¢ð‘§ð‘•ð‘‘ð‘•!" - two: "%{count} new requests!" - zero: "ð‘¯ð‘´ ð‘¯ð‘¿ ð‘®ð‘¦ð‘’ð‘¢ð‘§ð‘•ð‘‘ð‘•" - manage_aspect_contacts: - existing: "ð‘§ð‘œð‘Ÿð‘¦ð‘•ð‘‘ð‘¦ð‘™ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘•" - manage_within: "ð‘¥ð‘¨ð‘¯ð‘©ð‘¡ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘• ð‘¢ð‘¦ð‘žð‘¦ð‘¯" - new_request_to_person: - sent: "ð‘•ð‘§ð‘¯ð‘‘!" reshares: - create: - failure: "ð‘žð‘º ð‘¢ð‘³ð‘Ÿ ð‘©ð‘¯ ð‘ºð‘¼ ð‘®ð‘¦ð‘–ð‘ºð‘¦ð‘™ ð‘žð‘¦ð‘• ð‘ð‘´ð‘•ð‘‘." reshare: deleted: "ð‘©ð‘®ð‘¦ð‘¡ð‘©ð‘¯ð‘©ð‘¤ ð‘ð‘´ð‘•ð‘‘ ð‘›ð‘¦ð‘¤ð‘°ð‘‘ð‘©ð‘› ð‘šð‘² ð‘ž ð‘·ð‘”ð‘¼." - reshare: - few: "%{count} ð‘®ð‘¦ð‘–ð‘ºð‘Ÿ" - many: "%{count} ð‘®ð‘¦ð‘–ð‘ºð‘Ÿ" - one: "1 ð‘®ð‘¦ð‘–ð‘º" - other: "%{count} ð‘®ð‘¦ð‘–ð‘ºð‘Ÿ" - two: "%{count} reshares" - zero: "ð‘®ð‘¦ð‘–ð‘º" reshare_confirmation: "ð‘®ð‘¦ð‘–𑺠%{author} - %{text}?" - reshare_original: "ð‘®ð‘¦ð‘–𑺠ð‘©ð‘®ð‘¦ð‘¡ð‘©ð‘¯ð‘©ð‘¤" - show_original: "ð‘–ð‘´ ð‘©ð‘®ð‘¦ð‘¡ð‘©ð‘¯ð‘©ð‘¤" search: "ð‘•ð‘»ð‘—" services: create: @@ -545,23 +349,9 @@ en_shaw: edit_services: "ð‘§ð‘›ð‘¦ð‘‘ ð‘•ð‘»ð‘ð‘¦ð‘•ð‘©ð‘Ÿ" logged_in_as: "ð‘¤ð‘ªð‘œð‘› ð‘¦ð‘¯ ð‘¨ð‘Ÿ" really_disconnect: "ð‘›ð‘¦ð‘•ð‘’ð‘©ð‘¯ð‘§ð‘’ð‘‘ %{service}?" - inviter: - click_link_to_accept_invitation: "ð‘’ð‘¤ð‘¦ð‘’ ð‘žð‘¦ð‘• ð‘¤ð‘¦ð‘™ð‘’ ð‘‘ ð‘©ð‘’ð‘•ð‘§ð‘ð‘‘ ð‘¿ð‘¼ ð‘¦ð‘¯ð‘ð‘¦ð‘‘ð‘±ð‘–ð‘©ð‘¯" - join_me_on_diaspora: "ð‘¡ð‘¶ð‘¯ ð‘¥ð‘° ð‘ªð‘¯ ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘©*" - remote_friend: - invite: "ð‘¦ð‘¯ð‘ð‘²ð‘‘" - resend: "ð‘®ð‘¦ð‘•ð‘§ð‘¯ð‘›" settings: "ð‘•ð‘§ð‘‘ð‘¦ð‘™ð‘Ÿ" shared: - add_contact: - add_new_contact: "ð‘¨ð‘› ð‘¯ð‘¿ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘" - create_request: "ð‘“ð‘²ð‘¯ð‘› ð‘šð‘²Â·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘²ð‘›ð‘§ð‘¯ð‘‘ð‘¦ð‘“ð‘¦ð‘’ð‘±ð‘–ð‘©ð‘¯" - diaspora_handle: "diaspora@handle.org" - enter_a_diaspora_username: "ð‘§ð‘¯ð‘‘𑼠𑩠·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘¿ð‘Ÿð‘¼ð‘¯ð‘±ð‘¥:" - know_email: "ð‘¯ð‘´ ð‘žð‘º ð‘¦-ð‘¥ð‘±ð‘¤ ð‘©ð‘›ð‘®ð‘§ð‘•? ð‘¿ ð‘–ð‘«ð‘› ð‘¦ð‘¯ð‘ð‘²ð‘‘ ð‘žð‘§ð‘¥" - your_diaspora_username_is: "ð‘¿ð‘¼ ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘¿ð‘Ÿð‘¼ð‘¯ð‘±ð‘¥ ð‘¦ð‘Ÿ: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Add to aspect" toggle: few: "In %{count} aspects" many: "In %{count} aspects" @@ -569,88 +359,40 @@ en_shaw: other: "In %{count} aspects" two: "In %{count} aspects" zero: "Add to aspect" - contact_list: - all_contacts: "ð‘·ð‘¤ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘•" - footer: - logged_in_as: "ð‘¤ð‘ªð‘œð‘› ð‘¦ð‘¯ ð‘¨ð‘Ÿ %{name}" - your_aspects: "ð‘¿ð‘¼ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘ð‘•" invitations: by_email: "ð‘šð‘² ð‘¦-ð‘¥ð‘±ð‘¤" - dont_have_now: "ð‘¿ ð‘›ð‘´ð‘¯ð‘‘ ð‘£ð‘¨ð‘ ð‘¨ð‘¯ð‘¦ ð‘®ð‘²ð‘‘ ð‘¯ð‘¬, ð‘šð‘³ð‘‘ ð‘¥ð‘¹ ð‘¦ð‘¥ð‘ð‘²ð‘‘𑕠𑸠ð‘’ð‘³ð‘¥ð‘¦ð‘™ ð‘•ð‘µð‘¯!" - from_facebook: "ð‘“ð‘®ð‘ªð‘¥ ·ð‘“ð‘±ð‘•ð‘šð‘«ð‘’" - invitations_left: "%{count} ð‘¤ð‘§ð‘“ð‘‘" - invite_someone: "ð‘¦ð‘¯ð‘ð‘²ð‘‘ ð‘•ð‘³ð‘¥ð‘¢ð‘©ð‘¯" invite_your_friends: "ð‘¦ð‘¯ð‘ð‘²ð‘‘ ð‘¿ð‘¼ ð‘“ð‘®ð‘§ð‘¯ð‘›ð‘Ÿ" invites: "ð‘¦ð‘¯ð‘ð‘²ð‘‘ð‘•" - invites_closed: "ð‘¦ð‘¯ð‘ð‘²ð‘‘𑕠𑸠ð‘’ð‘»ð‘©ð‘¯ð‘‘ð‘¤ð‘¦ ð‘’ð‘¤ð‘´ð‘Ÿð‘› ð‘ªð‘¯ ð‘žð‘¦ð‘• ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘ð‘ªð‘›" - notification: - new: "ð‘¯ð‘¿ %{type} ð‘“ð‘®ð‘ªð‘¥ %{from}" public_explain: logged_in: "ð‘¤ð‘ªð‘œð‘› ð‘¦ð‘¯ ð‘‘ %{service}" manage: "ð‘¥ð‘¨ð‘¯ð‘©ð‘¡ ð‘’ð‘©ð‘¯ð‘§ð‘’ð‘‘ð‘©ð‘› ð‘•ð‘»ð‘ð‘¦ð‘•ð‘©ð‘Ÿ" outside: "ð‘ð‘³ð‘šð‘¤ð‘¦ð‘’ ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ ð‘¢ð‘¦ð‘¤ ð‘šð‘° ð‘©ð‘ð‘±ð‘¤ð‘©ð‘šð‘©ð‘¤ ð‘“𑹠ð‘³ð‘žð‘¼ð‘Ÿ ð‘¬ð‘‘ð‘•ð‘²ð‘› ð‘ ·ð‘›ð‘¦ð‘¨ð‘•ð‘ð‘¹ð‘© ð‘‘ ð‘•ð‘°." title: "ð‘•ð‘§ð‘‘ ð‘³ð‘ ð‘’ð‘©ð‘¯ð‘§ð‘’ð‘‘ð‘©ð‘› ð‘•ð‘»ð‘ð‘¦ð‘•ð‘©ð‘Ÿ" publisher: - all: "ð‘·ð‘¤" - all_contacts: "ð‘·ð‘¤ ð‘’ð‘ªð‘¯ð‘‘ð‘¨ð‘’ð‘‘ð‘•" discard_post: "ð‘›ð‘¦ð‘•ð‘’ð‘¸ð‘› ð‘ð‘´ð‘•ð‘‘" - make_public: "ð‘¥ð‘±ð‘’ ð‘ð‘³ð‘šð‘¤ð‘¦ð‘’" new_user_prefill: i_like: "I'm interested in %{tags}." - post_a_message_to: "ð‘ð‘´ð‘•ð‘‘ ð‘© ð‘¥ð‘§ð‘•ð‘©ð‘¡ ð‘‘ %{aspect}" posting: "ð‘ð‘´ð‘•ð‘‘ð‘¦ð‘™..." - publishing_to: "ð‘ð‘³ð‘šð‘¤ð‘¦ð‘–ð‘¦ð‘™ ð‘‘: " share: "ð‘–ð‘º" - share_with: "ð‘–𑺠ð‘¢ð‘¦ð‘ž %{aspect}" upload_photos: "ð‘³ð‘ð‘¤ð‘´ð‘› ð‘“ð‘´ð‘‘ð‘´ð‘Ÿ" whats_on_your_mind: "ð‘¢ð‘³ð‘‘ð‘• ð‘ªð‘¯ ð‘¿ð‘¼ ð‘¥ð‘²ð‘¯ð‘›?" - reshare: - reshare: "ð‘®ð‘¦ð‘–ð‘º" stream_element: - dislike: "ð‘›ð‘¦ð‘•ð‘¤ð‘²ð‘’" - hide_and_mute: "Hide and Mute" - like: "ð‘¤ð‘²ð‘’" - shared_with: "ð‘–ð‘ºð‘› ð‘¢ð‘¦ð‘ž: %{aspect_names}" - unlike: "ð‘©ð‘¯ð‘¤ð‘²ð‘’" via: "ð‘𑾠%{link}" - viewable_to_anyone: "ð‘žð‘¦ð‘• ð‘ð‘´ð‘•ð‘‘ ð‘¦ð‘Ÿ ð‘ð‘¿ð‘©ð‘šð‘©ð‘¤ ð‘‘ ð‘§ð‘¯ð‘¦ð‘¢ð‘©ð‘¯ ð‘ªð‘¯ ð‘ž ð‘¢ð‘§ð‘š" status_messages: create: success: "ð‘•ð‘©ð‘’ð‘•ð‘§ð‘•ð‘“ð‘«ð‘¤ð‘¦ ð‘¥ð‘§ð‘¯ð‘–ð‘©ð‘¯ð‘›: %{names}" - destroy: - failure: "ð‘“ð‘±ð‘¤ð‘› ð‘‘ ð‘›ð‘¦ð‘¤ð‘°ð‘‘ ð‘ð‘´ð‘•ð‘‘" - helper: - no_message_to_display: "ð‘¯ð‘´ ð‘¥ð‘§ð‘•ð‘©ð‘¡ ð‘‘ ð‘›ð‘¦ð‘•ð‘ð‘¤ð‘±." new: mentioning: "ð‘¥ð‘§ð‘¯ð‘–ð‘©ð‘¯ð‘¦ð‘™: %{person}" too_long: "{\"few\"=>\"ð‘ð‘¤ð‘°ð‘Ÿ ð‘¥ð‘±ð‘’ ð‘¿ð‘¼ ð‘•ð‘‘ð‘¨ð‘‘ð‘©ð‘• ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ ð‘¤ð‘§ð‘• ð‘žð‘¨ð‘¯ %{count} ð‘’ð‘ºð‘©ð‘’ð‘‘ð‘¼ð‘Ÿ\", \"many\"=>\"ð‘ð‘¤ð‘°ð‘Ÿ ð‘¥ð‘±ð‘’ ð‘¿ð‘¼ ð‘•ð‘‘ð‘¨ð‘‘ð‘©ð‘• ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ ð‘¤ð‘§ð‘• ð‘žð‘¨ð‘¯ %{count} ð‘’ð‘ºð‘©ð‘’ð‘‘ð‘¼ð‘Ÿ\", \"one\"=>\"ð‘ð‘¤ð‘°ð‘Ÿ ð‘¥ð‘±ð‘’ ð‘¿ð‘¼ ð‘•ð‘‘ð‘¨ð‘‘ð‘©ð‘• ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ ð‘¤ð‘§ð‘• ð‘žð‘¨ð‘¯ %{count} ð‘’ð‘ºð‘©ð‘’ð‘‘ð‘¼\", \"other\"=>\"ð‘ð‘¤ð‘°ð‘Ÿ ð‘¥ð‘±ð‘’ ð‘¿ð‘¼ ð‘•ð‘‘ð‘¨ð‘‘ð‘©ð‘• ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ ð‘¤ð‘§ð‘• ð‘žð‘¨ð‘¯ %{count} ð‘’ð‘ºð‘©ð‘’ð‘‘ð‘¼ð‘Ÿ\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"ð‘ð‘¤ð‘°ð‘Ÿ ð‘¥ð‘±ð‘’ ð‘¿ð‘¼ ð‘•ð‘‘ð‘¨ð‘‘ð‘©ð‘• ð‘¥ð‘§ð‘•ð‘©ð‘¡ð‘©ð‘Ÿ ð‘¤ð‘§ð‘• ð‘žð‘¨ð‘¯ %{count} ð‘’ð‘ºð‘©ð‘’ð‘‘ð‘¼ð‘Ÿ\"}" - stream_helper: - hide_comments: "ð‘£ð‘²ð‘› ð‘·ð‘¤ ð‘’ð‘ªð‘¥ð‘©ð‘¯ð‘‘ð‘•" - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: aspects: title: "Your Aspects" mentions: title: "Your Mentions" - tag_followings: - create: - failure: "ð‘“ð‘±ð‘¤ð‘› ð‘‘ ð‘“ð‘ªð‘¤ð‘´: #%{name}" - success: "ð‘•ð‘©ð‘’ð‘•ð‘§ð‘•ð‘“ð‘«ð‘¤ð‘¦ ð‘“ð‘ªð‘¤ð‘´ð‘¦ð‘™: #%{name}" - destroy: - failure: "ð‘“ð‘±ð‘¤ð‘› ð‘‘ ð‘•ð‘‘ð‘ªð‘ ð‘“ð‘ªð‘¤ð‘´ð‘¦ð‘™: #%{name}" - success: "ð‘•ð‘©ð‘’ð‘•ð‘§ð‘•ð‘“ð‘«ð‘¤ð‘¦ ð‘•ð‘‘ð‘ªð‘ð‘‘ ð‘“ð‘ªð‘¤ð‘´ð‘¦ð‘™: #%{name}" tags: show: follow: "ð‘“ð‘ªð‘¤ð‘´ #%{tag}" - following: "ð‘“ð‘ªð‘¤ð‘´ð‘¦ð‘™ #%{tag}" stop_following: "ð‘•ð‘‘ð‘ªð‘ ð‘“ð‘ªð‘¤ð‘´ð‘¦ð‘™ #%{tag}" - undo: "ð‘©ð‘¯ð‘›ð‘µ?" username: "ð‘¿ð‘Ÿð‘¼ð‘¯ð‘±ð‘¥" users: confirm_email: @@ -667,7 +409,6 @@ en_shaw: what_we_delete: "We delete all of your posts, profile data, as soon as humanly possible. Your comments will hang around, but be associated with your Diaspora Handle." comment_on_post: "...ð‘•ð‘³ð‘¥ð‘¢ð‘©ð‘¯ ð‘’ð‘ªð‘¥ð‘©ð‘¯ð‘‘ð‘• ð‘ªð‘¯ ð‘¿ð‘¼ ð‘ð‘´ð‘•ð‘‘?" current_password: "ð‘’ð‘»ð‘©ð‘¯ð‘‘ ð‘ð‘¨ð‘•ð‘¢ð‘¼ð‘›" - download_photos: "ð‘›ð‘¬ð‘¯ð‘¤ð‘´ð‘› ð‘¥ð‘² ð‘“ð‘´ð‘‘ð‘´ð‘Ÿ" edit_account: "ð‘§ð‘›ð‘¦ð‘‘ ð‘©ð‘’ð‘¬ð‘¯ð‘‘" email_awaiting_confirmation: "ð‘¢ð‘° ð‘£ð‘¨ð‘ ð‘•ð‘§ð‘¯ð‘‘ ð‘¿ ð‘©ð‘¯ ð‘¨ð‘’ð‘‘ð‘¦ð‘ð‘±ð‘–ð‘©ð‘¯ ð‘¤ð‘¦ð‘™ð‘’ ð‘‘ %{unconfirmed_email}. ð‘©ð‘¯ð‘‘ð‘¦ð‘¤ ð‘¿ ð‘“ð‘ªð‘¤ð‘´ ð‘žð‘¦ð‘• ð‘¤ð‘¦ð‘™ð‘’ 𑯠ð‘¨ð‘’ð‘‘ð‘¦ð‘ð‘±ð‘‘ ð‘ž ð‘¯ð‘¿ ð‘¨ð‘›ð‘®ð‘§ð‘•, ð‘¢ð‘° ð‘¢ð‘¦ð‘¤ ð‘’ð‘©ð‘¯ð‘‘ð‘¦ð‘¯ð‘¿ ð‘‘ ð‘¿ð‘Ÿ ð‘¿ð‘¼ ð‘©ð‘®ð‘¦ð‘¡ð‘©ð‘¯ð‘©ð‘¤ ð‘¨ð‘›ð‘®ð‘§ð‘• %{email}." export_data: "ð‘§ð‘’ð‘•ð‘ð‘¹ð‘‘ ð‘›ð‘±ð‘‘ð‘©" @@ -690,7 +431,4 @@ en_shaw: password_changed: "ð‘ð‘¨ð‘•ð‘¢ð‘¼ð‘› ð‘—ð‘±ð‘¯ð‘¡. ð‘¿ ð‘’ð‘¨ð‘¯ ð‘¯ð‘¬ ð‘¤ð‘ªð‘œ ð‘¦ð‘¯ ð‘¢ð‘¦ð‘ž ð‘¿ð‘¼ ð‘¯ð‘¿ ð‘ð‘¨ð‘•ð‘¢ð‘¼ð‘›." password_not_changed: "ð‘ð‘¨ð‘•ð‘¢ð‘¼ð‘› ð‘—ð‘±ð‘¯ð‘¡ ð‘“ð‘±ð‘¤ð‘›" unconfirmed_email_changed: "ð‘¦-ð‘¥ð‘±ð‘¤ ð‘—ð‘±ð‘¯ð‘¡. ð‘¯ð‘°ð‘›ð‘Ÿ ð‘¨ð‘’ð‘‘ð‘¦ð‘ð‘±ð‘–ð‘©ð‘¯." - unconfirmed_email_not_changed: "ð‘¦-ð‘¥ð‘±ð‘¤ ð‘—ð‘±ð‘¯ð‘¡ ð‘“ð‘±ð‘¤ð‘›" - webfinger: - no_person_constructed: "ð‘¯ð‘´ ð‘ð‘»ð‘•ð‘©ð‘¯ ð‘’ð‘«ð‘› ð‘šð‘° ð‘’ð‘©ð‘¯ð‘•ð‘‘ð‘®ð‘³ð‘’ð‘‘ð‘©ð‘› ð‘“ð‘®ð‘ªð‘¥ ð‘žð‘¦ð‘• ð‘£-ð‘’ð‘¸ð‘›." - not_enabled: "ð‘¢ð‘§ð‘šð‘“ð‘¦ð‘™ð‘œð‘¼ ð‘›ð‘³ð‘Ÿ ð‘¯ð‘ªð‘‘ ð‘•ð‘°ð‘¥ ð‘‘ ð‘šð‘° ð‘¦ð‘¯ð‘±ð‘šð‘©ð‘¤ð‘› ð‘“𑹠%{account}ð‘Ÿ ð‘£ð‘´ð‘•ð‘‘" \ No newline at end of file + unconfirmed_email_not_changed: "ð‘¦-ð‘¥ð‘±ð‘¤ ð‘—ð‘±ð‘¯ð‘¡ ð‘“ð‘±ð‘¤ð‘›" \ No newline at end of file diff --git a/config/locales/diaspora/en_valspeak.yml b/config/locales/diaspora/en_valspeak.yml index bba338953505f90fab3139ea9803ed5f430bfb4c..bac0391f1c98843237d201a8dcc806c903b8776f 100644 --- a/config/locales/diaspora/en_valspeak.yml +++ b/config/locales/diaspora/en_valspeak.yml @@ -6,11 +6,8 @@ en_valspeak: _applications: "Appz" - _comments: "Txts" _contacts: "BFFs <3" _help: "Need halp!!" - _home: "ur place" - _photos: "Picz n selfiez" _services: "Other socialz" _statistics: "statsss" _terms: "boring legal stuff" @@ -123,13 +120,7 @@ en_valspeak: other: "Number of new ppl this week: %{count}" zero: "Number of new ppl this week: none :\\" current_server: "So like... the current server date ish like... %{date}" - ago: "it was like... %{time} ago" all_aspects: "All aspectz" - application: - helper: - unknown_person: "this person is like... not known... sry bout that :\\" - video_title: - unknown: "this video title is like... not known... sry bout that :\\" are_you_sure: "R u like, for sure?" are_you_sure_delete_account: "R u like, mental? U like, wanna close ur account? U should like stay! YOLO! Well if u do, remember, like, this CANT b undone. Kay?" aspect_memberships: @@ -144,46 +135,26 @@ en_valspeak: success: "OMG! Movin them like, totally WORKED! <333" aspect_listings: add_an_aspect: "+ Addn aspect" - deselect_all: "unhighlight everythin" - edit_aspect: "Like edit %{name}" - select_all: "highlight everythin" aspect_stream: make_something: "Make somethin.." stay_updated: "stay like... up 2 date" stay_updated_explanation: "Ur wall has like... ur BFFs n tagz n junk on it..." - contacts_not_visible: "Ppl in this group will like... not b able 2 c each other n stuff" - contacts_visible: "Ppl in this aspect will like.. b able 2 c each other n stuff" - create: - failure: "group makin failed." - success: "Ur new group %{name} was like... created" destroy: failure: "%{name} is like... not gone n so it like... cant b removed... sry bout tht :\\" success: "%{name} is nao like... gone n stuff." edit: - aspect_chat_is_not_enabled: "ppl in this aspect are like, not able to chat wit u. sry bout tht :\\" aspect_list_is_not_visible: "Ppl in this aspect r like.. not able 2 c each other." aspect_list_is_visible: "Ppl in this aspect r like.. able 2 c each other." confirm_remove_aspect: "R u sure u want 2 like... remove this aspect?" - grant_contacts_chat_privilege: "Give the ppl in this aspect chat privies?" - make_aspect_list_visible: "make ppl in this group like... able 2 see each other?" - remove_aspect: "Git rid of this aspect" rename: "bag this name.." - set_visibility: "Set look at prefs" update: "make like... newer..." updating: "makin like... newer..." index: - diaspora_id: - content_1: "ur diaspora* id is:" - content_2: "give it 2 ne1, except for creepers, n theyll b able to like... find u.." - heading: "ur like... id" donate: "give like... free money" - handle_explanation: "This is like... ur name thingy. Its like an email... like.. that thing that my mom uses... she's like... so totally disgustin... she like, wheres mom jeans its like barf out! Gag me with a spoon! So like, neway, this will like... let ppl reach u n stuff." help: any_problem: "Havin drama?" contact_podmin: "Contact the dude that manages ur pod!" do_you: "do u... like:" - email_feedback: "%{link} ur feedback n junk" - email_link: "Emailll <3" feature_suggestion: "... do u like... have a %{link} suggestion?" find_a_bug: "... find a like... %{link}?" have_a_question: "... have a like... %{link}?" @@ -196,31 +167,20 @@ en_valspeak: tutorial_link_text: "Tutorialz!!" tutorials_and_wiki: "%{faq}, %{tutorial}, && %{wiki}: Halp for ur first stepz." introduce_yourself: "so this is like, ur stream thing... its like facebooks wall thingy but like... less annoyin n wit like... less adz n picz of food and stuff... like, post sumthin n see if ne1 repliez... like... yeah" - keep_diaspora_running: "Keep d* from suckin wit a monthly donation! :D<3" keep_pod_running: "So like, keep %{pod} from bein all slow n stupid by like... donatin monthly n stuff! <3(:" new_here: follow: "follow %{link} n like ... welcome new ppl 2 diaspora*!" learn_more: "like... learn moar n stuff..." title: "dude! u should like, totally whalecum the new diaspora ppl. its a blast like... yeah.." - no_contacts: "No BFFs :(" - no_tags: "+ Find a tag 2 like... follow n junk" - people_sharing_with_you: "ppl sharin wit u" - post_a_message: "txt somethin >>" services: content: "U can like... connect the followin things 2 d*:" heading: "connect like... other stuff.." - unfollow_tag: "Stop creepin on ppl who like... post stuff usin %{tag}" welcome_to_diaspora: "OMG HEY! Like, welcome to diaspora*, %{name}. its pretty bitchin' n has electrolytes(;" - new: - create: "Make like.. a new aspect" - name: "Name (only like... u can c it)" no_contacts_message: community_spotlight: "d* celebz" or_spotlight: "Or u can like... share wit %{link}" try_adding_some_more_contacts: "U can like... search or like... invite moar ppl." you_should_add_some_more_contacts: "U should like... add some moar ppl!" - no_posts_message: - start_talking: "No 1z gossiped yet! Lame :\\" seed: acquaintances: "Some ppl I sorta kno" family: "Fam" @@ -229,7 +189,6 @@ en_valspeak: update: failure: "Ur group, %{name}, had like... a rlly long name.. so yeah... it wasnt saved... sry :\\" success: "Ur aspect, %{name}, has like... not flipped out. So ur good!(:" - back: "go back" blocks: create: failure: "couldnt ignore the h8ter. #lame" @@ -241,41 +200,28 @@ en_valspeak: explanation: "post 2 d* from like.. anywhere by like... saving this thing => %{link}" heading: "save page thingy" post_something: "put it on d* n stuff" - post_success: "its like posted nao... byez! <3" cancel: "Nvm" comments: new_comment: comment: "say somethin" commenting: "sayin somethin" - one: "OMG! u got a comment!!!" - other: "OMG! u got like %{count} commentz!!!" - zero: "like... no commentz :(" contacts: - create: - failure: "there was like... drama when makin a BFF" index: add_a_new_aspect: "add a new aspect!" add_contact: "Add BFF <3" - add_to_aspect: "add BFFs 2 %{name}" all_contacts: "All BFFs!!" community_spotlight: "d* celebz <33" my_contacts: "My BFFs!!! <333" no_contacts: "u like... need 2 add sum ppl" no_contacts_message: "OMG! u should like... check out %{community_spotlight}" only_sharing_with_me: "only sharin wit me" - remove_contact: "Trash BFF :(" start_a_conversation: "start a like... convo" title: "BFFs" user_search: "Ppl stalk" - your_contacts: "ur BFFs" - sharing: - people_sharing: "ppl sharin wit u:" spotlight: community_spotlight: "d* celebz!! <3" suggest_member: "Suggest a membah!!(:" conversations: - conversation: - participants: "Ppl participatin" create: fail: "bad txt" no_contact: "Umm HELLO, u need 2 like, add them first! Duh!" @@ -283,20 +229,12 @@ en_valspeak: destroy: delete_success: "convo successfully deleted YAAAAY!((:" hide_success: "convo be hidden!(:" - helper: - new_messages: - one: "1 new txts! ZOMG!!!" - other: "%{count} new txts! ZOMG!!!" - zero: "No new txts :(" index: conversations_inbox: "Convos - Inbox" - create_a_new_conversation: "start a new convo" inbox: "Txts <3" new_conversation: "New convo" - no_conversation_selected: "no convo picked :\\" no_messages: "therez like... no messagez :( </3" new: - abandon_changes: "nvm?" send: "txt" sending: "txtin..." subject: "topic" @@ -319,10 +257,6 @@ en_valspeak: error_messages: helper: correct_the_following_errors_and_try_again: "so much drama! chillax n try again, k?" - invalid_fields: "not the like... rite fieldz..." - login_try_again: "Plz <a href='%{login_link}'> like login</a> n like... try again. Kthx <3" - post_not_public: "Umm, the postie u r tryin 2 look at is like... not public! derrp" - post_not_public_or_not_exist: "So like, the postie u r tryin to look at is not public or it like.. doesnt exist. sry bout tht :\\" fill_me_out: "Like, put ur txt into here like, K?" find_people: "find new BFFs or #stuff" help: @@ -529,45 +463,27 @@ en_valspeak: tutorial: "tutorial<3" tutorials: "tutorialz!!" wiki: "ZOMG D*'s OWN WIKIPEDIA!! :DDD" - hide: "Cover" - ignore: "Talk to the hand" - invitation_codes: - excited: "%{name} is like so TOTALLY excited 2 see u!! :D" invitations: a_facebook_user: "a like... fb usah" check_token: not_found: "invite token was like... not found :\\" create: - already_contacts: "u r like.. already talkin 2 this ppl" - already_sent: "u like... already invited this ppl." empty: "Plz enter at least 1 email addy, thx<3" no_more: "u have like... no moar invites." note_already_sent: "Invites have like... already been sent 2: %{emails}" - own_address: "Umm, u like... cant send an invite 2 ur own address.. duh." rejected: "the followin email addys made drama: " sent: "Ur invites have like... ben sent 2: %{emails}" - edit: - accept_your_invitation: "RSVP" - your_account_awaits: "ur account like.. awaits! OMG! TOTALLY!" new: - already_invited: "The followin ppl didnt like accept ur invite:" - aspect: "Aspectt" - check_out_diaspora: "check out d* dude!!" codes_left: one: "So theres like... one invite left on this code. Yup." other: "ZOMG! theres like %{count} invites left on this code... yeah..." zero: "sry, theres like no invites left on this code. omg like totally lame.... yeah... wanna go 2 taco bell?(:" comma_separated_plz: "U can enter lots of different email addies by usin commaz! <3" - if_they_accept_info: "if they like... accept, they will b added 2 the group u like invited them 2..." invite_someone_to_join: "invite sum1 2 da partay!!!" language: "what do u like... speak?" paste_link: "Share this link wit ur BFFs 2 invite them 2 d*, or like... txt them the link n stuff." - personal_message: "sext(;" - resend: "Re-txt" send_an_invitation: "send an invite" - send_invitation: "send invite" sending_invitation: "Sendin invite, hold up..." - to: "2" layouts: application: back_to_top: "Go back 2 the top" @@ -576,35 +492,13 @@ en_valspeak: source_package: "dl code n stuff.." toggle: "make like... phone friendly..." whats_new: "sup?" - your_aspects: "ur like... aspectz" header: - admin: "the man" - blog: "bllllooog" code: "code" - help: "Halp" - login: "check in" logout: "Bounce" profile: "Wall" - recent_notifications: "Recent noties! <3" settings: "Settins" - view_all: "Look at all" - likes: - likes: - people_dislike_this: - one: "%{count} dislike :(" - other: "%{count} dislikes :(((" - zero: "no dislikes(:" - people_like_this: - one: "1 like!! OMG!!!" - other: "%{count} likes!!! OMFG!!!" - zero: "omg, theres like.. no likes :(" - people_like_this_comment: - one: "%{count} like!!!" - other: "%{count} likez!!! :D" - zero: "no likes :(" limited: "Only ur BFFs can c these! OMG!" more: "Moar" - next: "next!" no_results: "no results found... lame..." notifications: also_commented: @@ -619,11 +513,6 @@ en_valspeak: one: "%{actors} commented on ur postie %{post_link}. OMG!" other: "%{actors} commented on ur postie %{post_link}. OMG!" zero: "%{actors} like... commented on ur postie %{post_link}." - helper: - new_notifications: - one: "1 new notie!!" - other: "%{count} new noties!!! :D" - zero: "no new noties :(" index: all_notifications: "All noties" also_commented: "Also comment'd" @@ -681,7 +570,6 @@ en_valspeak: notifier: a_limited_post_comment: "OMG!!! YOU GOT A NEW COMMENTT!!! But its like.. on a post that ppl cant see.. so like.. go check it out!" a_post_you_shared: "a postie!!" - accept_invite: "RSVP ur d* invite!!" click_here: "click this txt" comment_on_post: reply: "Reply or like... look at %{name}'s postie >" @@ -725,7 +613,6 @@ en_valspeak: liked: "OMG! %{name} has like liked ur postie!!!" view_post: "Look at postie >" mentioned: - mentioned: "mentioned u in a postie:" subject: "OMG! %{name} has like... mentioned u on d*" private_message: reply_to_or_view: "Reply 2 or like... look at this convo >" @@ -786,20 +673,9 @@ en_valspeak: to_change_your_notification_settings: "2 change ur notie settins" nsfw: "OMG! GROODY!" ok: "For SURE" - or: "or like" - password: "Passwerd" - password_confirmation: "2 make sure u put in the right passwerd n junk" people: add_contact: invited_by: "u were like... invited by" - add_contact_small: - add_contact_from_tag: "add BFF frum tag" - aspect_list: - edit_membership: "like.. edit aspect membership n junk" - helper: - is_not_sharing: "%{name} is not sharin wit u :(" - is_sharing: "%{name} is sharin wit u!!" - results_for: " ur like.. resultz for %{params}" index: couldnt_find_them: "couldnt find them? thats totally lame :(" looking_for: "U like... lookin for posties tagged %{tag_link}?" @@ -809,100 +685,47 @@ en_valspeak: search_handle: "use their d* ID (usahname@pod.tld) to b for sure 2 find ur BFFs." searching: "im lookin, brb... <3" send_invite: "still nothin? :( send an invite!!! :DDD" - one: "1 personz" - other: "%{count} ppl" person: - add_contact: "add BFF <3" - already_connected: "ur like... already connected n stuff" - pending_request: "waitin' on request" thats_you: "OMG! thats u!!!! FAR OUT!" profile_sidebar: bio: "all about meee <333" born: "Bday" - edit_my_profile: "change my stuff.." gender: "dude or dudette or whatev..." - in_aspects: "in aspectz" location: "my crib" - photos: "Picz n selfiez" - remove_contact: "delete BFF" - remove_from: "Do u like... wanna trash %{name} from %{aspect}?" show: closed_account: "this profile is gone dude..." does_not_exist: "they dont like... exist :\\" has_not_shared_with_you_yet: "%{name} has like... not shared ne posties wit u yet!" - ignoring: "U r like... ignorin all posties from %{name}." - incoming_request: "%{name} wants 2 like... share wit u" - mention: "Tag person" - message: "Txt" - not_connected: "ur not like... sharin wit this person... im sure!" - recent_posts: "Recent posties!!!" - recent_public_posts: "Recent posties that like... every1 can c!!!" - return_to_aspects: "bounce back 2 ur aspectz page... thingy..." - see_all: "C all!!!" - start_sharing: "start like... sharin" - to_accept_or_ignore: "2 like... accept or not accept.." - sub_header: - add_some: "like... add sum" - edit: "edit!" - you_have_no_tags: "Umm, u like have no tagz! Duh!" - webfinger: - fail: "sry, we cant find %{handle}" - zero: "no ppl" photos: - comment_email_subject: "%{name}'s pic!" create: integrity_error: "The pic didnt like... upload. R u like for sure that was a pic n not somethin else?" runtime_error: "Pic didnt like... upload. R u like for sure ur duck face is like.. ducky enough?" type_error: "So like... ur pic wasnt added. r u like... sure u actually like... added it?" destroy: notice: "Pic deleted :o" - edit: - editing: "Editin" - new: - back_to_list: "Go back to the like... list" - new_photo: "New pic!! OMG! -duck face-" - post_it: "OMG! post it!" new_photo: empty: "{file} is like... empty, plz pick the filez again witout that 1. kthx" invalid_ext: "{file} is like... not able2 b uploaded cuz like... its not the right kinda file.. only like... these {extensions} r allowed... sry bout tht :\\" size_error: "OMG {file} is 2 big!! the biggest i can take is like... {sizeLimit}.(;" new_profile_photo: - or_select_one_existing: "or like... pick 1 from ur %{photos}" upload: "Upload a new selfie!!! OMG!!" - photo: - view_all: "look at all of %{name}'z picz" show: - collection_permalink: "the like... collection permalink... thing.." - delete_photo: "Delete pic" - edit: "edit picz and selfiez" - edit_delete_photo: "Edit pic topic / trash pic" - make_profile_photo: "make profile pic" show_original_post: "Show da original postie" - update_photo: "Change Pic" - update: - error: "the pic wasnt like... edited... sry bout that :\\" - notice: "pic changed <3" posts: presenter: title: "A postie from %{name}" show: - destroy: "Trash ur pic" forbidden: "So like, ur not allowed to do tht..." - not_found: "Sry, but we like... couldnt find that postie. :\\" - permalink: "like... permalink" photos_by: one: "One pic by %{author}" other: "%{count} picz by %{author}" zero: "No picz by %{author}" reshare_by: "Reshare is like... by %{author}" - previous: "prevy!" privacy: "OMG give me some privacy!" - privacy_policy: "Wat like... privacy u have" profile: "Like ur profile" profiles: edit: allow_search: "Do u wanna like... let ppl stalk u within d*?" - edit_profile: "Edit profie!!" first_name: "First name? Kthx" last_name: "Last name? Kthx" nsfw_check: "Like, mark everythin i share as groody" @@ -915,8 +738,6 @@ en_valspeak: your_location: "Ur place" your_name: "Ur name" your_photo: "Ur pic" - your_private_profile: "Ur like... private profile..." - your_public_profile: "Ur like... profile where every1 can like... c it..." your_tags: "Describe urself in like... 5 werdz" your_tags_placeholder: "like #twilight #selfies #Belieber #iphone #mtv" update: @@ -931,26 +752,16 @@ en_valspeak: closed: "Signups r like... closed on here... sry bout that :\\ totally lame, right?" create: success: "u've joined d*!!! OMFG YAAAAAYYY!! :DDD" - edit: - cancel_my_account: "Trash mah account! Plz Kthx" - edit: "edit %{name} n junk" - leave_blank: "(dont like... type nething if u like.. dont wanna change it kthx)" - password_to_confirm: "(we liek... need ur current secret code thingy to make sure it like.. matches the other 1... kthx)" - unhappy: "Butthurt? :(" - update: "Like... update" invalid_invite: "OMG, dude, ur invite link is like... SOOOO old... like... gross. so like, sry but its no longer valid. Kthxbye<3" new: - create_my_account: "Make ur account!!! :DD" email: "EMAIL<3" enter_email: "Enter like... an email" enter_password: "Enter a like... secret code thats like... moar than 6 keys n junk" enter_password_again: "enter what u liek... entered b4" enter_username: "So like.. pick a name that ppl will like... call u by.. n sry but u can only like.. use letters numbers n these things \"_\" but like.. witout the up n down lines n junk..." - join_the_movement: "Join the awesomeness!!!" password: "PASSWERD<3" password_confirmation: "PASSWERD CONFIRMATION!!" sign_up: "SIGN UP!!" - sign_up_message: "This is like.. social networkin with a <3" submitting: "Submittin... just a sec..." terms: "By creatin an account u like... accept the %{terms_link}." terms_link: "more boring legal stuff" @@ -965,43 +776,15 @@ en_valspeak: reported_label: "<b>Like, reported by</b> %{person}" review_link: "Mark as like, reviewed n stuff" status: - created: "OMG some1s in troubleee!! A report was made :o" destroyed: "The postie went bye byez!" failed: "Somethin screwed up. sry bout that :\\" - marked: "So umm, like, the report was like, marked as reviewed and stuff." title: "Reportz Ovahview" - requests: - create: - sending: "Sendin" - sent: "U've like... asked 2 share wit %{name}. They should like... c it the like.. next time they check into d* <3" - destroy: - error: "Plz pick an aspect!! Kthx<3" - ignore: "Ignored h8ter request" - success: "U r nao sharin!" - helper: - new_requests: - one: "new request!!!" - other: "%{count} new requests!!! :D" - zero: "no new requests :(" - manage_aspect_contacts: - existing: "Existin BFFs" - manage_within: "Manage BFFs within" - new_request_to_person: - sent: "sent!!!" reshares: comment_email_subject: "%{resharer}'s like... reshare of %{author}'s postie" - create: - failure: "There was drama when resharin this postie :(" reshare: deleted: "The original postie was like... deleted by the person who made it :(" - reshare: - one: "1 reshare!!!" - other: "%{count} reshares!! :DD" - zero: "Like... reshare" reshare_confirmation: "Like... reshare %{author}'z postie n stuff?" - reshare_original: "Reshare the like, original" reshared_via: "like reshared via" - show_original: "Show the like... original" search: "like look for stuff like #shoes!" services: create: @@ -1013,10 +796,6 @@ en_valspeak: success: "Yay! Trashed eet woo!!" failure: error: "there was drama when connectin 2 that thing :\\" - finder: - fetching_contacts: "d* is like... populatin ur %{service} BFFs, plz check back n liek... a few mins. Kthxbye <3" - no_friends: "No FB friendz found. :\\" - service_friends: "Ur like... %{service} BFFs" index: disconnect: "like disconnect" edit_services: "Edit servies!!!" @@ -1024,54 +803,23 @@ en_valspeak: not_logged_in: "ur like.. currently not logged in and stuffz" really_disconnect: "drop %{service}?" services_explanation: "Connectin 2 servies gives u like... the ability 2 post ur posties 2 them as u write them in d*! :p" - inviter: - click_link_to_accept_invitation: "so like... follow this link 2 like... accept ur invite" - join_me_on_diaspora: "Chill wit me on diaspora*!" provider: facebook: "fb" tumblr: "tmblr" twitter: "Twittar<333" wordpress: "WurdPress" - remote_friend: - invite: "invite!!" - not_on_diaspora: "Not yet on d* :(" - resend: "retxt" settings: "Like ur settinz" - share_visibilites: - update: - post_hidden_and_muted: "%{name}'s has like... ben hidden, n noties have been like... made quiet." - see_it_on_their_profile: "If u like... want 2 c updates on this postie, go 2 %{name}'z profile n stuff." shared: - add_contact: - add_new_contact: "add a new BFF" - create_request: "Find by d* id thing.." - diaspora_handle: "nick@pod.org" - enter_a_diaspora_username: "Enter a d* usernameeee:" - know_email: "do u liek... kno their email addy? U should like TOTALLY invite them!!" - your_diaspora_username_is: "Ur d* username is like: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Add BFF" toggle: one: "In like... %{count} aspect" other: "In like... %{count} aspectz" zero: "add BFF" - contact_list: - all_contacts: "All BFFs!!" - footer: - logged_in_as: "checkin in as %{name}" - your_aspects: "ur aspectz" invitations: by_email: "By email(:" - dont_have_now: "U dont like.. have ne right nao :\\ BUT moar invites r comin soon! yay! :D" - from_facebook: "From FB" - invitations_left: "so like... theres %{count} left" - invite_someone: "Invite ppl!" invite_your_friends: "Invite ur BFFs!!" invites: "Invites!!" - invites_closed: "so like... invites r closed for this pod... sry bout that :\\" share_this: "Share this link like... via email, blogg, or social netz!" - notification: - new: "OMG new %{type} from %{from}!!!" public_explain: atom_feed: "Feed thingy" control_your_audience: "Control ur ppl" @@ -1083,12 +831,9 @@ en_valspeak: title: "Set up other servies" visibility_dropdown: "Use dis dropdown 2 change who can like... c ur postie. (we like... recommend u make this first 1 2 where ne1 can c it.)" publisher: - all: "allll" - all_contacts: "all ppl" discard_post: "Trash postie" formatWithMarkdown: "U can like... use %{markdown_link} to make ur postie totally awesome!!(:" get_location: "Get ur place in the world!" - make_public: "make it so like... every1 can c it" new_user_prefill: hello: "OMG liek HEY PPL! im #%{new_user_tag} " i_like: "im like... rlly into %{tags}. " @@ -1096,36 +841,14 @@ en_valspeak: newhere: "Newbie<3" poll: add_a_poll: "Add a pole" - add_poll_answer: "Like, add an optionnnn" - option: "Option #1" - question: "q4u" - remove_poll_answer: "Trash option" - post_a_message_to: "Txt 2 %{aspect}" posting: "Postin..." - preview: "Look at b4 its a postie" - publishing_to: "publish 2: " remove_location: "Trash where u r" share: "Share!!!" - share_with: "share wit" upload_photos: "Upload picz!!" whats_on_your_mind: "Sup dude?" - reshare: - reshare: "Liek... reshare" stream_element: - connect_to_comment: "Connect 2 this peep 2 comment on their postie" - currently_unavailable: "commenting isnt workin right nao... sry bout that :\\" - dislike: "Thumbs down" - hide_and_mute: "Hide n like... make postie quiet" - ignore_user: "h8te %{name}" - ignore_user_description: "Block n delete h8ter from all aspectz?" - like: "Thumbs up" - nsfw: "This postie has lyke... been flagged as Groody by its author. %{link} n stuff" - shared_with: "Shared wit: %{aspect_names}" - show: "make seen" - unlike: "</3" via: "like... via %{link}" via_mobile: "via mobilez!!" - viewable_to_anyone: "This postie can b seen by ne1 on the internetz" simple_captcha: label: "enter teh stuff in the box:" message: @@ -1151,21 +874,12 @@ en_valspeak: status_messages: create: success: "YAY! %{names} has been mentioned!! :D" - destroy: - failure: "so like... ur postie didnt get trashed... sry bout that :\\" - helper: - no_message_to_display: "No txt 2 display :(" new: mentioning: "Mentionin: %{person}" too_long: "Plz make ur status txt smaller than %{count} key presses. Right nao its like... %{current_length} key presses" stream_helper: - hide_comments: "Cover up... like... all commentz" no_more_posts: "youre at the end :(" no_posts_yet: "Therez no posties yet.." - show_comments: - one: "Show like... 1 moar comment" - other: "Show like... %{count} moar commentz" - zero: "No moar commentz :(" streams: activity: title: "My happenins" @@ -1191,22 +905,11 @@ en_valspeak: title: "Stuff every1 can like... c" tags: title: "Posties tagged: %{tags}" - tag_followings: - create: - failure: "So like... followin %{name} didnt like... work. R u like... already followin it?" - none: "Umm, u like... cant follow a blank tag! Duh." - success: "OMG! Ur nao followin #%{name}. YAAAAY! :DD" - destroy: - failure: "So like... there was drama when tryin 2 stop followin %{name}. Mayb u already like... stopped followin it?" - success: "So like, u rnt followin #%{name} nemore..." tags: show: follow: "Follow like... #%{tag}" - following: "Followin #%{tag}" none: "Umm, so the like... empty tag doesnt like... exist :\\" stop_following: "Stop like... followin #%{tag}" - terms_and_conditions: "wat ur like... allowed to do and stuff" - undo: "do u wanna like.. undo?" username: "ur like... name ppl will find u by or whatever" users: confirm_email: @@ -1227,7 +930,6 @@ en_valspeak: character_minimum_expl: "must b like... 6 buttons..." close_account: dont_go: "DUDE! WTF!? Dont leave!" - if_you_want_this: "If u like... rlly want this, type in ur passwerd below n click on 'Trash Account'" lock_username: "So this will liek.. lock ur username thingy if u decided 2 sign back up n stuff." locked_out: "U will like... get like.. automagically bounced n locked out of ur account." make_diaspora_better: "We like... want u 2 help make d* bettah n stuff, so u should like.. help us out instead of leavin(: if u do wanna leave, we like... wanna make sure u know wat happens next. K?" @@ -1240,14 +942,12 @@ en_valspeak: current_password_expl: "the 1 u like sign in wit... OMG" download_export: "dl my profileee" download_export_photos: "dl my pics" - download_photos: "dl mah picz" edit_account: "Edit ur account <3" email_awaiting_confirmation: "So we like... sent u a link 2 like activate %{unconfirmed_email}. Until u like... follow this link && activate this new addy, we will continue 2 like.. use ur original addy %{email}. Kay?" export_data: "dl data!!!" export_in_progress: "We're gettin ur data... bbl!!!! <3" export_photos_in_progress: "So like, we're currently gettin ur photos and junk. Bbl! <3" following: "Sharin settins" - getting_started: "New user prefies" last_exported_at: "(So like, last updated @ %{timestamp})" liked: "some1 likes ur postie" mentioned: "u r mentioned in a postie" @@ -1273,7 +973,6 @@ en_valspeak: connect_to_facebook_link: "hookin up ur FB account" hashtag_explanation: "Ok so like, hashtags allow u 2 talk bout n follow ur interests. theyre like... also a sweet way 2 find new ppl on d* :D" hashtag_suggestions: "Try followin tags like #justinbeiber #16andpregnant #monster #xbox and stuff.." - saved: "Saved!!!(:" well_hello_there: "Ohai thar! <3" what_are_you_in_to: "Wat r u into?" who_are_you: "Umm like, who r u?" @@ -1296,13 +995,6 @@ en_valspeak: settings_updated: "Settins updated!!! <33" unconfirmed_email_changed: "Ur email was like... changed. N nao it needs activation. K?" unconfirmed_email_not_changed: "so like, the email change didnt work. sry bout that :\\" - webfinger: - fetch_failed: "so like... i couldnt fetch the like... webfinger profile thingy for %{profile_url}. sry bout that :\\" - hcard_fetch_failed: "so like, there was like... drama when gettin the hcard for %{account}. yeah, sry bout that :\\" - no_person_constructed: "No person could like... b made from this hcard thingy..." - not_enabled: "so like... webfinger doesnt seem 2 b enabled for %{account}'s host :\\" - xrd_fetch_failed: "there like... was drama when tryin 2 get the xrd from account %{account}..." - welcome: "Like, OMG, hey!" will_paginate: next_label: "next!! »" previous_label: "« previe!!" \ No newline at end of file diff --git a/config/locales/diaspora/eo.yml b/config/locales/diaspora/eo.yml index b295bee4fe57a62f97646177e9b72389353125d5..d2ae114af09a296979702b7626440ee726e842bf 100644 --- a/config/locales/diaspora/eo.yml +++ b/config/locales/diaspora/eo.yml @@ -6,11 +6,8 @@ eo: _applications: "Aplikaĵoj" - _comments: "Komentoj" _contacts: "Kontaktoj" _help: "Helpo" - _home: "Hejmo" - _photos: "bildoj" _services: "Servoj" account: "Konto" activerecord: @@ -89,13 +86,7 @@ eo: other: "Kiomo de novaj uzantoj ĉi-semajne: %{count}" zero: "Kiomo de novaj uzantoj ĉi-semajne: %{count}" current_server: "Aktuala dato de servilo estas %{date}" - ago: "antaÅ %{time}" all_aspects: "Ĉiuj aspektoj" - application: - helper: - unknown_person: "nekonata persono" - video_title: - unknown: "Nekonata titolo de filmeto" are_you_sure: "Ĉu vi certas?" are_you_sure_delete_account: "Ĉu vi certe volas forigi vian konton? Vi ne povas malfari tion!" aspect_memberships: @@ -109,18 +100,10 @@ eo: success: "Sukcese aldonis kontakton al aspekto." aspect_listings: add_an_aspect: "+ Aldoni aspekton" - deselect_all: "Malelekti ĉion" - edit_aspect: "Redakti %{name}" - select_all: "Elekti ĉion" aspect_stream: make_something: "Faru ion" stay_updated: "Restu Äisdatigata" stay_updated_explanation: "Via ĉefa torento enhavas ĉiujn viajn kontaktojn, sekvatajn etikedojn kaj afiÅojn de kelkaj kreemaj anoj de la komunumo." - contacts_not_visible: "Kontaktoj en ĉi tiu aspekto ne povos vidi unu la alian." - contacts_visible: "Kontaktoj en ĉi tiu aspekto povos vidi unu la alian." - create: - failure: "Aspekto ne kreeblas." - success: "Via nova aspekto %{name} kreiÄis" destroy: failure: "%{name} ne malplenas kaj do ne povis esti forigita." success: "%{name} estis sukcese forigita." @@ -128,24 +111,15 @@ eo: aspect_list_is_not_visible: "la aspekto-listo estas kaÅita al la aliaj en ĉi tiu aspekto" aspect_list_is_visible: "la aspekto-listo estas montrata al la aliaj en ĉi tiu aspekto" confirm_remove_aspect: "Ĉu vi certe volas forigi ĉi tiun aspekton?" - make_aspect_list_visible: "Ĉu kontaktoj en ĉi tiu aspekto povu vidi unu la alian?" - remove_aspect: "Forigi ĉi tiun aspekton" rename: "alinomigi" update: "Äisdatigi" updating: "Äisdatigante" index: - diaspora_id: - content_1: "Via DIASPORA* uzantnomo estas:" - content_2: "Donu Äin al iu ajn, kaj tiu povos trovi vin ĉe DIASPORA*." - heading: "DIASPORA* uzantnomo" donate: "Donaci" - handle_explanation: "Tiu ĉi estas via DIASPORA*-uzantnomo. Vi povas doni Äin al aliaj homoj same kiel retpoÅtan adreson, por ke ili vin kontaktu." help: any_problem: "Ĉu iu problemo?" contact_podmin: "Kontaktu vian pod-estron!" do_you: "Ĉu vi:" - email_feedback: "%{link} viajn respondojn, se vi volas" - email_link: "RetpoÅtadreso" feature_suggestion: "... havas %{link} proponon?" find_a_bug: "... trovis %{link}n?" have_a_question: "... havas %{link}n?" @@ -158,31 +132,20 @@ eo: tutorial_link_text: "Enkondukoj" tutorials_and_wiki: "%{faq}, %{tutorial} kaj %{wiki}: helpoj por via unuaj paÅoj." introduce_yourself: "Tio estas via torento. Ensaltu kaj prezentu vin mem." - keep_diaspora_running: "Tenu la DIASPORA-evoluadon rapida per monata donacado!" keep_pod_running: "Helpu al %{pod} rapide funkcii kaj aĉeti por niaj servistoj ilian \"kaforiparon\" per ĉiumonata donacado!" new_here: follow: "Sekvu %{link} kaj bonvenigu novajn uzantojn al Diaspora*!" learn_more: "Lerni pli" title: "Bonvenigu novajn uzantojn" - no_contacts: "neniuj kontaktoj" - no_tags: "+ Trovi etikedon aboni" - people_sharing_with_you: "Homoj, kiuj konigas al vi" - post_a_message: "AfiÅu mesaÄon »" services: content: "Vi povas konekti la postajn servojn kun DIASPORA*:" heading: "Konekti Servojn" - unfollow_tag: "Ne plu abonas #%{tag}." welcome_to_diaspora: "Bonvenon al diaspora*, %{name}!" - new: - create: "Krei" - name: "Nomo (nur videblas de vi)" no_contacts_message: community_spotlight: "en komunuma ĉeflumo" or_spotlight: "AÅ vi povas kunhavigi kun %{link}" try_adding_some_more_contacts: "Vi povas serĉi aÅ inviti pliajn kontaktojn." you_should_add_some_more_contacts: "Vi devus aldoni pliajn kontaktojn!" - no_posts_message: - start_talking: "AnkoraÅ neniu diris ion ajn!" seed: acquaintances: "Konatoj" family: "Familio" @@ -191,7 +154,6 @@ eo: update: failure: "Via aspekto, %{name}, havis tro longan nomon por konserviÄi." success: "Via aspekto, %{name}, sukcese redaktiÄis." - back: "MalantaÅen" blocks: create: failure: "Mi ne povis ignori tiun uzanton. #evasion" @@ -203,21 +165,14 @@ eo: explanation: "Vi povas afiÅi en DIASPORA* de ĉie ajn per paÄosigno montranta al %{link}." heading: "Legosigneto" post_something: "AfiÅi ion en DIASPORA*" - post_success: "AfiÅita! Fermanta!" cancel: "Nuligi" comments: new_comment: comment: "Komenti" commenting: "Komentanta..." - one: "1 komento" - other: "%{count} komentoj" - zero: "neniuj komentoj" contacts: - create: - failure: "Ne povis krei kontakton" index: add_a_new_aspect: "Aldoni novan aspekton" - add_to_aspect: "aldoni kontaktojn al %{name}" all_contacts: "Ĉiuj kontaktoj" community_spotlight: "En la ĉeflumo de la komunumo" my_contacts: "Miaj kontaktoj" @@ -226,30 +181,18 @@ eo: only_sharing_with_me: "Nur koniganta al mi" start_a_conversation: "Komenci interparoladon" title: "Kontaktoj" - your_contacts: "Viaj kontaktoj" - sharing: - people_sharing: "Homoj, kiuj konigas al vi:" spotlight: community_spotlight: "Komunuma ĉeflumo" suggest_member: "Sugesti membron" conversations: - conversation: - participants: "Partoprenantoj" create: fail: "MalÄusta mesaÄo" no_contact: "Hej, unue devas vi aldoni la kontakton." sent: "MesaÄo sendiÄis." - helper: - new_messages: - one: "1 nova mesaÄo" - other: "%{count} novaj mesaÄoj" - zero: "Neniuj novaj mesaÄoj" index: inbox: "PoÅtujo" - no_conversation_selected: "neniu interparolado elektita" no_messages: "neniuj mesaÄoj" new: - abandon_changes: "Ĉu forlasi ÅanÄojn?" send: "Sendi" sending: "PoÅtanta..." subject: "temo" @@ -268,9 +211,7 @@ eo: error_messages: helper: correct_the_following_errors_and_try_again: "Äœustigu la sekvajn erarojn kaj reprovu." - invalid_fields: "Nevalidaj kampoj" - login_try_again: "Bonvole <a href='%{login_link}'>ensalutu</a> kaj provu denove." - post_not_public: "La afiÅo, kiun vi klopodas vidi, ne estas publika!" + need_javascript: "Ĉi tiu retejo postulas JavaScript por funkcii Äuste. Se vi malebligis JavaScript, bonvole reebligu Äin kaj reÅarÄu la paÄon." fill_me_out: "Plenumigu min" find_people: "Trovi homojn aÅ #etikedojn" help: @@ -286,44 +227,27 @@ eo: tutorial: "enkonduko" tutorials: "enkondukoj" wiki: "vikio" - hide: "KaÅi" - invitation_codes: - excited: "%{name} estas Äojega vidi vin ĉi tie." invitations: a_facebook_user: "Facebook-uzanto" check_token: not_found: "Ne povis trovi invitan ĵetonon" create: - already_contacts: "Vi jam konektiÄis kun tiu persono." - already_sent: "Vi jam invitis tiun personon." empty: "Bonvole tajpu almenaÅ unu retpoÅtadreson." no_more: "Vi ne plu havas invitojn." note_already_sent: "Invitiloj estas jam senditaj al: %{emails}" - own_address: "Vi ne povas sendi inviton al via propra adreso." rejected: "La postaj retpoÅtadresoj estis problemaj:" sent: "Invitoj estas senditaj al: %{emails}" - edit: - accept_your_invitation: "Akcepti vian inviton" - your_account_awaits: "Via konto atendas!" new: - already_invited: "Tiuj homoj ankoraÅ ne akceptis vian inviton:" - aspect: "Aspekto" - check_out_diaspora: "Esploru en DIASPORA!" codes_left: one: "%{count} invito restas por tiu ĉi kodo" other: "%{count} invitoj restas por tiu ĉi kodo" zero: "%{count} invitoj restas por tiu ĉi kodo" comma_separated_plz: "Vi povas enmeti plurajn retpoÅtadresojn disigitajn per komoj." - if_they_accept_info: "se tiu akceptos, tiu aldoniÄos al la aspekto, en kiun vi invitis tiun." invite_someone_to_join: "Invitu iun aniÄi al DIASPORA*!" language: "Lingvo" paste_link: "Konigu ĉi tiun ligon kun viaj amikoj por inviti ilin al DIASPORA* aÅ rekte retmesaÄu al ili la ligon." - personal_message: "Persona mesaÄo" - resend: "Resendi" send_an_invitation: "Sendu inviton" - send_invitation: "Sendu la inviton" sending_invitation: "Sendado de invito..." - to: "Al" layouts: application: back_to_top: "Reen al la supro" @@ -332,37 +256,13 @@ eo: source_package: "elÅutu la pakaĵon kun la fontkodo" toggle: "Åalti inter tiu kaj poÅtelefona versio" whats_new: "kio estas nova?" - your_aspects: "viaj aspektoj" header: - admin: "administranto" - blog: "blogo" code: "kodo" - login: "ensaluti" logout: "Elsaluti" profile: "Profilo" - recent_notifications: "FreÅaj sciigoj" settings: "Agordoj" - view_all: "Vidi ĉiujn" - likes: - likes: - people_dislike_this: - one: "%{count} malÅato" - other: "%{count} malÅatoj" - zero: "neniuj malÅatoj" - people_like_this: - few: "%{count} Åatantoj" - many: "%{count} Åatantoj" - one: "%{count} Åatanto" - other: "%{count} Åatantoj" - two: "%{count} Åatadoj" - zero: "neniuj Åatantoj" - people_like_this_comment: - one: "%{count} Åato" - other: "%{count} Åatoj" - zero: "neniuj Åatoj" limited: "Limigita" more: "Pli" - next: "sekva" no_results: "Neniuj rezultoj trovitaj" notifications: also_commented: @@ -383,14 +283,6 @@ eo: other: "%{actors} komentis pri via %{post_link}." two: "%{actors} komentis pri via %{post_link}." zero: "%{actors} komentis pri via %{post_link}." - helper: - new_notifications: - few: "%{count} novaj sciigoj" - many: "%{count} novaj sciigoj" - one: "1 nova sciigo" - other: "%{count} novaj sciigoj" - two: "%{count} novaj sciigoj" - zero: "neniuj novaj sciigoj" index: and: "kaj" and_others: @@ -447,7 +339,6 @@ eo: zero: "%{actors} komencis konigi al vi." notifier: a_post_you_shared: "afiÅo." - accept_invite: "Akceptu vian DIASPORA*-inviton!" click_here: "klaku tie ĉi" comment_on_post: reply: "Respondi aÅ vidi afiÅon de %{name} >" @@ -477,7 +368,6 @@ eo: liked: "%{name} Åatas vian afiÅon" view_post: "Vidi afiÅon >" mentioned: - mentioned: "menciis vin en afiÅo:" subject: "%{name} menciis vin ĉe DIASPORA*" private_message: reply_to_or_view: "Respondi al aÅ vidi tiun ĉi interparoladon >" @@ -495,106 +385,45 @@ eo: to_change_your_notification_settings: "ÅanÄi viajn sciigajn agordojn" nsfw: "NSĈL" ok: "Bone" - or: "aÅ" - password: "Pasvorto" - password_confirmation: "Konfirmado de pasvorto" people: add_contact: invited_by: "vi estis invitita de" - add_contact_small: - add_contact_from_tag: "aldoni kontakton de etikedo" - aspect_list: - edit_membership: "redakti membraron de aspekto" - helper: - is_not_sharing: "%{name} ne kunhavigas kun vi" - is_sharing: "%{name} nun kunhavigas kun vi" - results_for: "rezultoj por %{params}" index: looking_for: "Ĉu vi serĉas afiÅojn etikeditaj %{tag_link}?" no_one_found: "...kaj neniu troviÄis." no_results: "Hej! Vi devas serĉi ion." results_for: "serĉrezultoj por" searching: "serĉanta, bv. pacienci..." - one: "1 persono" - other: "%{count} personoj" person: - add_contact: "aldoni kontakton" - already_connected: "Jam ligita" - pending_request: "Pritraktata peto" thats_you: "Jen vi!" profile_sidebar: bio: "pri mi" born: "naskiÄtago" - edit_my_profile: "Redakti mian profilon" gender: "sekso" - in_aspects: "en aspektoj" location: "loko" - photos: "Fotoj" - remove_contact: "forigi kontakton" - remove_from: "Ĉu forigi %{name} de %{aspect}?" show: closed_account: "Tiu ĉi konto estas fermita." does_not_exist: "Persono ne ekzistas!" has_not_shared_with_you_yet: "%{name} ne jam konigis iun ajn afiÅon al vi!" - ignoring: "Vi estas ignoranta ĉiujn afiÅojn de %{name}." - incoming_request: "%{name} volas konigi al vi" - mention: "Mencii" - message: "MesaÄo" - not_connected: "Vi ne estas koniganta al tiu ĉi homo" - recent_posts: "FreÅaj AfiÅoj" - recent_public_posts: "FreÅaj Publikaj AfiÅoj" - return_to_aspects: "Reiri al via aspekto-paÄo" - see_all: "Vidu ĉion" - start_sharing: "komencu konigi" - to_accept_or_ignore: "por akcepti aÅ ignori Äin." - sub_header: - add_some: "aldoni iujn" - edit: "redakti" - you_have_no_tags: "vi ne havas etikedojn!" - webfinger: - fail: "Ni bedaÅras, sed ni ne povis trovi je %{handle}." - zero: "neniuj personoj" photos: - comment_email_subject: "la bildo de %{name}" create: integrity_error: "AlÅuti bildon malsukcesis. Ĉu vi certas, ke tiu estis bilda dosiero?" runtime_error: "AlÅuti bildon malsukcesis. Probable estis la farado de unu el tiuj Volapukistoj." type_error: "AlÅuti bildon malsukcesis. Ĉu vi certas, ke vi aldonis bildon?" destroy: notice: "Bildo forviÅiÄis." - edit: - editing: "Redaktanta" - new: - back_to_list: "Revenu al Listo" - new_photo: "Nova bildo" - post_it: "afiÅu Äin!" new_photo: empty: "{file} malplenas; bonvolu reelekti dosierojn sen Äi." invalid_ext: "{file} havas malvalidan sufikson. Nur {extensions} estas validaj." size_error: "{file} estas tro granda; la maksimuma dosiergrandeco estas {sizeLimit}." new_profile_photo: - or_select_one_existing: "aÅ elektu unu el viaj jam ekzistantaj %{photos}" upload: "AlÅutu novan profilbildon!" - photo: - view_all: "Vidi ĉiujn bildojn de %{name}" show: - collection_permalink: "konstanta ligilo de la kolekto" - delete_photo: "ForviÅu bildon" - edit: "redakti" - edit_delete_photo: "Redakti bildpriskribon / forviÅi bildon" - make_profile_photo: "estigi profilbildon" show_original_post: "Montri originan afiÅon." - update_photo: "Äœisdatigi bildon" - update: - error: "Ne povis redakti bildon." - notice: "Bildo sukcese ÄisdatiÄis." posts: presenter: title: "MesaÄo de %{name}" show: - destroy: "ForviÅi" - not_found: "Ni bedaÅras, sed ni ne povis trovi tiun afiÅon." - permalink: "daÅra ligilo" photos_by: few: "%{count} bildoj de %{author}" many: "%{count} bildoj de %{author}" @@ -603,14 +432,11 @@ eo: two: "Du bildoj de %{author}" zero: "Neniuj bildoj de %{author}" reshare_by: "Rekonigo de %{author}" - previous: "antaÅa" privacy: "Privateco" - privacy_policy: "Politiko pri privateco" profile: "Profilo" profiles: edit: allow_search: "Permesu al homoj serĉi vin ene de DIASPORA*" - edit_profile: "Redakti profilon" first_name: "Persona nomo" last_name: "Familinomo" update_profile: "Äœisdatigi profilon" @@ -620,8 +446,6 @@ eo: your_location: "Via loko" your_name: "Via nomo" your_photo: "Via bildo" - your_private_profile: "Via nepublika profilo" - your_public_profile: "Via publika profilo" your_tags: "Per kvin vortoj priskribu vin mem." your_tags_placeholder: "ekz. #filmoj #katidoj #vojaÄi #instruisto #novjorko" update: @@ -636,65 +460,23 @@ eo: closed: "Registrado estas fermita ĉe tiu ĉi DIASPORA* 'pod' (servilo)." create: success: "Vi aniÄis al DIASPORA*!" - edit: - cancel_my_account: "ForviÅi mian konton" - edit: "Redakti je %{name}" - leave_blank: "(lasu blanka, se vi ne volas ÅanÄi Äin)" - password_to_confirm: "(ni bezonas vian nunan pasvorton por konfirmi viajn ÅanÄojn)" - unhappy: "ĉu vi malfeliĉas?" - update: "Äœisdatigi" invalid_invite: "La invitoligilo, kiun vi donis, ne plu validas!" new: - create_my_account: "Krei mian konton!" email: "RetpoÅtadreso" enter_email: "Enskribu retpoÅtadreson" enter_password: "Enskribu kodvorton (almenaÅ 6 signoj)" enter_password_again: "Enskribu la saman pasvorton, kiel antaÅe" enter_username: "Elektu uzantnomon (nur literojn, nombrojn, kaj substrekojn)" - join_the_movement: "AniÄu je la movado!" password: "Pasvorto" password_confirmation: "KONFIRMADO DE PASVORTO" sign_up: "EnskribiÄi" - sign_up_message: "Interkona retkonektado kun ♥" username: "Uzantnomo" - requests: - create: - sending: "Sendanta" - sent: "Vi petis konigi al %{name}. Via peto al ili videblos ĉe ilia venonta ensaluto en DIASPORA*." - destroy: - error: "Bonvolu elekti aspekton!" - ignore: "Ignoris kontaktan peton." - success: "Vi nun konigas." - helper: - new_requests: - few: "%{count} novaj petoj!" - many: "%{count} novaj petoj!" - one: "nova peto!" - other: "%{count} novaj petoj!" - two: "%{count} novaj petoj!" - zero: "neniuj novaj petoj" - manage_aspect_contacts: - existing: "Ekzistantaj kontaktoj" - manage_within: "Administri kontaktojn ene de" - new_request_to_person: - sent: "sendita!" reshares: comment_email_subject: "Rekonigo de %{resharer} de la afiÅo de %{author}" - create: - failure: "Estis eraro dum rekonigado de ĉi tiu afiÅo." reshare: deleted: "Originala afiÅo forviÅiÄis de l' afiÅinto." - reshare: - few: "%{count} rekonigoj" - many: "%{count} rekonigoj" - one: "1 rekonigo" - other: "%{count} rekonigoj" - two: "%{count} rekonigoj" - zero: "Rekonigi" reshare_confirmation: "Ĉu rekonigi la afiÅon de %{author}?" - reshare_original: "Rekonigi la originalon" reshared_via: "rekonigita per" - show_original: "Montri la originalon" search: "Serĉi" services: create: @@ -705,38 +487,16 @@ eo: success: "Sukcese forigis identigon." failure: error: "estis eraro, kiam ni provis konekti tiun servon" - finder: - fetching_contacts: "Diaspora estas okupita akcepti viajn %{service} amikojn, bv. reveni post kelkaj minutoj." - no_friends: "Neniuj Facebook amikoj trovitaj." - service_friends: "%{service} Amikoj" index: disconnect: "malkonekti" edit_services: "Redakti servojn" logged_in_as: "ensalutinta kiel" really_disconnect: "ĉu vi volas malkonekti %{service}?" services_explanation: "KonektiÄo al servoj ebligas al vi publikigi viajn afisojn al tiuj, dum vi en diaspora* verkas ilin." - inviter: - click_link_to_accept_invitation: "Sekvu tiun ligilon por akcepti vian inviton" - join_me_on_diaspora: "Renkontu min ĉe DIASPORA*" - remote_friend: - invite: "inviti" - not_on_diaspora: "Ne jam ĉe DIASPORA*" - resend: "resendi" + share_to: "Havigi al %{provider}" settings: "Agordoj" - share_visibilites: - update: - post_hidden_and_muted: "La afiÅo de %{name} kaÅiÄis kaj sciigoj malÅaltiÄis." - see_it_on_their_profile: "Se vi volas vidi Äisdatigojn pri tiu afiÅo, vizitu la profilon de %{name}." shared: - add_contact: - add_new_contact: "Aldoni novan kontakton" - create_request: "Trovi per DIASPORA* uzantnomo" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Enmetu DIASPORA* uzantnomon:" - know_email: "Ĉu vi scias iliajn retpoÅtadresojn? Vi devus inviti ilin" - your_diaspora_username_is: "Via DIASPORA* uzantnomo estas: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Aldoni kontakton" toggle: few: "En %{count} aspektoj" many: "En %{count} aspektoj" @@ -744,23 +504,11 @@ eo: other: "En %{count} aspektoj" two: "En %{count} aspektoj" zero: "Aldoni kontakton" - contact_list: - all_contacts: "Ĉiuj kontaktoj" - footer: - logged_in_as: "ensalutinta, kiel %{name}" - your_aspects: "viaj aspektoj" invitations: by_email: "Per retpoÅto" - dont_have_now: "Vi ne havas iujn ajn nun, sed pli da invitoj baldaÅ venos!" - from_facebook: "El Facebook" - invitations_left: "ankoraÅ %{count}" - invite_someone: "Inviti iun" invite_your_friends: "Invitu viajn amikojn" invites: "Invitoj" - invites_closed: "Invitoj aktuale ne eblas ĉe tiu ĉi DIASPORA* 'pod' (servilo)" share_this: "Konigi tiun ĉi ligilon per retmesaÄo, reta taglibro aÅ via Åatata socia reto!" - notification: - new: "Nova %{type} de %{from}" public_explain: atom_feed: "'Atoma' abonrilato" control_your_audience: "Kontrolu vian spektantaron" @@ -772,60 +520,26 @@ eo: title: "Agordi ligitajn servojn" visibility_dropdown: "Uzu tiun falmenuon por ÅanÄi videblecon de via afiÅo. (Ni sugestas, ke vi igu publika tiun unuan afiÅon.)" publisher: - all: "ĉiuj" - all_contacts: "ĉiuj kontaktoj" discard_post: "ForviÅi afiÅon" get_location: "Obteni lokadon" - make_public: "publikigi" new_user_prefill: hello: "Saluton al ĉiu, mi estas #%{new_user_tag}. " i_like: "Mi interesiÄas pri %{tags}." invited_by: "Dankon pro la invito," newhere: "NewHere" - post_a_message_to: "AfiÅi al %{aspect}" posting: "AfiÅanta..." - preview: "AntaÅrigardo" - publishing_to: "koniganta al: " share: "Konigi" - share_with: "konigi al" upload_photos: "AlÅuti bildojn" whats_on_your_mind: "Kion vi nun pensas?" - reshare: - reshare: "Rekonigi" stream_element: - connect_to_comment: "konektiÄu al tiu uzanto por komenti pri ties afiÅo" - currently_unavailable: "komentado aktuale ne eblas" - dislike: "MalÅati" - hide_and_mute: "KaÅi kaj silentigi afiÅon" - ignore_user: "Ignori %{name}" - ignore_user_description: "Ignori kaj forigi uzanton el ĉiuj aspektoj?" - like: "Åœati" - nsfw: "Ĉi tiun afiÅon la aÅtoro markis kiel NSFW (ne sekura). %{link}" - shared_with: "Partoprenita kun: %{aspect_names}" - show: "montri" - unlike: "Ne plu Åati" via: "per %{link}" via_mobile: "per poÅtelefono" - viewable_to_anyone: "Tiu ĉi afiÅo videblas de iu ajn en la reto" status_messages: create: success: "Sukcese menciis: %{names}" - destroy: - failure: "forviÅi afiÅon malsukcesis" - helper: - no_message_to_display: "Neniu afiÅo montrenda." new: mentioning: "Mencianta: %{person}" too_long: "{\"one\"=>\"bonvolu igi viajn afiÅojn malpli longaj ol %{count} signoj\", \"other\"=>\"bonvolu igi viajn afiÅojn malpli longaj ol %{count} signoj\", \"zero\"=>\"bonvolu igi viajn afiÅojn malpli longaj ol %{count} signoj\"}" - stream_helper: - hide_comments: "kaÅi ĉiujn komentojn" - show_comments: - few: "Montri %{count} pliajn komentojn" - many: "Montri %{count} pliajn komentojn" - one: "Montri unu plian komenton" - other: "Montri %{count} pliajn komentojn" - two: "Montri du pliajn komentojn" - zero: "Neniuj pliaj komentoj" streams: activity: title: "Mia aktiveco" @@ -851,22 +565,11 @@ eo: title: "publika aktiveco" tags: title: "AfiÅoj etikeditaj: %{tags}" - tag_followings: - create: - failure: "Malsukcesis aboni je #%{name}. Ĉu vi jam sekvas Äin?" - none: "Vi ne povas sekvi senenhavan etikedon!" - success: "Hura! Vi nun sekvas je #%{name}." - destroy: - failure: "Ne povis malaboni je #%{name}. Ĉu eble vi jam malabonis?" - success: "Nu! Vi ne plu sekvas je #%{name}." tags: show: follow: "Aboni al #%{tag}" - following: "Abonita al #%{tag}" none: "Malplena etikedo ne ekzistas!" stop_following: "Malaboni de #%{tag}" - terms_and_conditions: "Reguloj kaj kondiĉoj" - undo: "Ĉu malfari?" username: "Uzantnomo" users: confirm_email: @@ -887,7 +590,6 @@ eo: character_minimum_expl: "devas havi minimume ses signojn" close_account: dont_go: "Hej, bv. ne foriri!" - if_you_want_this: "Se vi vere volas tion ĉi, tajpu vian kodvorton sube kaj klaku al 'Close Account'/'Fermi konton'" lock_username: "Tio ĉi baros vian uzantonomon kaze ke vi decidas reensaluti." locked_out: "Vi elsalutos kaj estos barita de via konto." make_diaspora_better: "Ni deziras helpi al vi plibonigi DIASPORA-on, do vi prefere helpu al ni anstataÅ ol foriri. Se vi vere deziras foriri, ni volas informi vin, kio sekve okazas." @@ -898,12 +600,10 @@ eo: comment_on_post: "...iu komentas pri via afiÅo?" current_password: "Nuna pasvorto" current_password_expl: "tiu per kiu vi ensalutis..." - download_photos: "elÅuti miajn bildojn" edit_account: "Redakti konton" email_awaiting_confirmation: "Ni sendis al vi aktivigan ligilon ĉe %{unconfirmed_email}. Äœis kiam vi klakos tiun ĉi ligilon kaj aktivigos la novan repoÅtadreson, ni uzados vian Äisnunan retpoÅtadreson %{email}." export_data: "Eksporti datumojn" following: "Agordoj pri sekvado" - getting_started: "Novaj uzanto-agordoj" liked: "...iu Åatis vian afiÅon?" mentioned: "...vi estas menciita en afiÅo?" new_password: "Nova pasvorto" @@ -922,7 +622,6 @@ eo: connect_to_facebook_link: "Konektante vian Facebook-konton" hashtag_explanation: "Etikedoj permesas al vi priparoli kaj aboni viajn interesojn. Ili estas ankaÅ bona metodo por trovi novajn homojn ĉe DIASPORA*." hashtag_suggestions: "Provu sekvi etikedojn kiel #arto, #filmoj, #gif, ktp." - saved: "Konservita!" well_hello_there: "Bone, saluton al vi tie!" what_are_you_in_to: "Pri kio vi ÅatokupiÄas?" who_are_you: "Kiu vi estas?" @@ -944,13 +643,6 @@ eo: settings_updated: "Agordoj ÄisdatiÄis" unconfirmed_email_changed: "RetpoÅtadreso ÅanÄiÄis. Bezonas aktivigadon." unconfirmed_email_not_changed: "ÅœanÄo de retpoÅtadreso malsukcesis." - webfinger: - fetch_failed: "ne povas alporti webfinger-an profilon por %{profile_url}" - hcard_fetch_failed: "estis problemo venigi la hcard-on de @{account}" - no_person_constructed: "Neniu persono povis esti kreita per tiu ĉi hcard." - not_enabled: "'webfinger' Åajne ne estas Åaltita por la servilo de %{account}" - xrd_fetch_failed: "estis eraro dum la venigado de 'xrd' de konto %{account}" - welcome: "Bonvenon!" will_paginate: next_label: "sekva »" previous_label: "« antaÅa" \ No newline at end of file diff --git a/config/locales/diaspora/es-AR.yml b/config/locales/diaspora/es-AR.yml index 5ca26f10195e06bde5505a57ed607469bf79c511..1d5627a079e8b84a0de5a0a358efeb8fe6206919 100644 --- a/config/locales/diaspora/es-AR.yml +++ b/config/locales/diaspora/es-AR.yml @@ -6,11 +6,8 @@ es-AR: _applications: "Aplicaciones" - _comments: "Comentarios" _contacts: "Contactos" _help: "Ayuda" - _home: "Inicio" - _photos: "Fotos" _services: "Servicios" _statistics: "EstadÃsticas" _terms: "Términos y condiciones" @@ -53,12 +50,19 @@ es-AR: taken: "ya está ocupado." admins: admin_bar: + dashboard: "Panel de control" pages: "Páginas" + pod_network: "Red de pods" pod_stats: "EstadÃsticas del Pod (servidor)" report: "Reportes" sidekiq_monitor: "Monitor Sidekiq" user_search: "Búsqueda de usuarios" weekly_user_stats: "EstadÃsticas semanales de usuario" + dashboard: + fetching_diaspora_version: "Determinando la última versión de diaspora*..." + pod_status: "Estado del pod" + pods: + pod_network: "Red de pods" stats: 2weeks: "2 semanas" 50_most: "Las 50 etiquetas más populares" @@ -92,6 +96,7 @@ es-AR: email: "Correo electrónico" guid: "GUID" id: "Identificador ID" + invite_token: "Identificador de invitación" last_seen: "Visto por última vez" ? "no" : "No" @@ -109,7 +114,10 @@ es-AR: are_you_sure_unlock_account: "¿Estás seguro que quieres desbloquear esta cuenta?" close_account: "Cerrar cuenta" email_to: "Mandar invitación por correo electrónico a" + invite: "Invitar" + lock_account: "Bloquear cuenta" under_13: "Mostrar usuarios menores de 13 años (COPPA)" + unlock_account: "Desbloquear cuenta" users: one: "%{count} usuario encontrado" other: "%{count} usuarios encontrados" @@ -125,13 +133,63 @@ es-AR: other: "Cantidad de nuevos usuarios esta semana: %{count}" zero: "Cantidad de nuevos usuarios esta semana: ninguno" current_server: "La fecha actual del servidor es %{date}" - ago: "hace %{time}" all_aspects: "Todos los aspectos" - application: - helper: - unknown_person: "Persona desconocida" - video_title: - unknown: "TÃtulo de video desconocido" + api: + openid_connect: + authorizations: + destroy: + fail: "Falló el intento de cancelar la autorización con la ID %{id}" + new: + access: "%{name} solicita acceso a:" + approve: "Aprobar" + bad_request: "Falta el ID del cliente o URI de redireccionamiento" + client_id_not_found: "No se encontró ningún cliente con el ID de cliente %{client_id} o con la URI de redireccionamiento %{redirect_uri}" + deny: "Denegar" + no_requirement: "%{name} no necesita permisos" + redirection_message: "¿Estás seguro que quieres dar acceso a %{redirect_uri}?" + error_page: + contact_developer: "DeberÃas contactar con el desarrollador de la aplicación y enviarle el siguiente mensaje de error:" + could_not_authorize: "No se pudo autorizar la aplicación" + login_required: "Tienes que loguearte para poder autorizar a esta aplicación" + title: "¡Oh! Algo salió mal :(" + scopes: + aud: + description: "Esto otorga permisos aud a la aplicación" + name: "aud" + name: + description: "Esto otorga permisos de nombre a la aplicación" + name: "nombre" + nickname: + description: "Esto otorga permisos de apodo a la aplicación" + name: "apodo" + openid: + description: "Permite que la aplicación lea tu perfil básico" + name: "perfil básico" + picture: + description: "Esto otorga permisos de imagen a la aplicación" + name: "imagen" + profile: + description: "Permite que la aplicación lea tu perfil extendido" + name: "perfil extendido" + read: + description: "Esto permite a la aplicación leer tu Entrada, tus conversaciones y tu perfil completo" + name: "leer perfil, Entrada y conversaciones" + sub: + description: "Esto otorga permisos sub a la aplicación" + name: "sub" + write: + description: "Permite a la aplicación enviar nuevos posts, escribir conversaciones y enviar reacciones" + name: "enviar publicaciones, conversaciones y reacciones" + user_applications: + index: + access: "%{name} tiene acceso a:" + edit_applications: "Aplicaciones" + no_requirement: "%{name} no necesita permisos" + title: "Aplicaciones autorizadas" + no_applications: "No tienes aplicaciones autorizadas" + policy: "Mira las polÃticas de privacidad de la aplicación" + revoke_autorization: "Revocar" + tos: "Ver los Términos de Servicio de la aplicación" are_you_sure: "¿Estás seguro?" are_you_sure_delete_account: "¿Seguro que quieres eliminar tu cuenta? ¡Esto no se podrá deshacer!" aspect_memberships: @@ -147,48 +205,27 @@ es-AR: success: "Se agregó el contacto al aspecto." aspect_listings: add_an_aspect: "+ Agregar un aspecto" - deselect_all: "Deseleccionar todo" - edit_aspect: "Editar %{name}" - select_all: "Seleccionar todo" aspect_stream: make_something: "Siente la libertad" stay_updated: "Mantenete actualizado" stay_updated_explanation: "En tu stream principal aparecen las publicaciones de tus contactos, más las de las etiquetas que sigues, y si lo deseas, las de algunos miembros creativos de la comunidad." - contacts_not_visible: "Los contactos en este aspecto no van a poder verse entre ellos." - contacts_visible: "Los contactos en este aspecto van a poder verse entre ellos." - create: - failure: "Error creando el aspecto." - success: "Tu nuevo aspecto %{name} fue creado" destroy: failure: "%{name} no está vacÃo y no puede ser eliminado." success: "%{name} se eliminó con éxito." success_auto_follow_back: "Se borró correctamente %{name}. Este aspecto se usaba para seguir automáticamente a los usuarios, revisa tu configuración para seleccionar un nuevo aspecto de autoseguimiento." edit: - aspect_chat_is_enabled: "Los contactos de este aspecto pueden chatear con vos." - aspect_chat_is_not_enabled: "Los contactos de este aspecto no pueden chatear con vos." aspect_list_is_not_visible: "La lista de contactos de este aspecto NO es visible" aspect_list_is_visible: "La lista de contactos de este aspecto es visible" confirm_remove_aspect: "¿Estás seguro de que querés eliminar este aspecto?" - grant_contacts_chat_privilege: "¿Conceder privilegio a los contactos de este aspecto para poder chatear?" - make_aspect_list_visible: "¿Hacer visible los contactos de este aspecto entre ellos?" - remove_aspect: "Eliminar este aspecto" rename: "Renombrar" - set_visibility: "Establecer visibilidad" update: "Actualizar" updating: "Actualizando" index: - diaspora_id: - content_1: "Tu ID de diaspora* es:" - content_2: "Dáselo a cualquiera y podrá encontrarte en diaspora*." - heading: "ID de diaspora*" donate: "Donar" - handle_explanation: "Ésta es tu identificación de diaspora*. Es como una dirección de correo electrónico, podes dársela a la gente para que te encuentren." help: any_problem: "¿Algún problema?" contact_podmin: "Contacta al administrador de tu pod!" do_you: "Tal vez:" - email_feedback: "Si lo prefieres, enviá tus comentarios a este %{link}." - email_link: "Correo electrónico" feature_suggestion: "...tengas una %{link} o sugerencia?" find_a_bug: "...encontraste un %{link}?" have_a_question: "...tengas una %{link}?" @@ -201,31 +238,21 @@ es-AR: tutorial_link_text: "Tutoriales" tutorials_and_wiki: "%{faq}, %{tutorial} y %{wiki}: Ayuda para tus primeros pasos en diaspora*." introduce_yourself: "Este es tu stream. Zambullite en el y presentate." - keep_diaspora_running: "¡Haz que el desarrollo de diaspora* vaya más rápido con una donación mensual!" keep_pod_running: "¡Haz que %{pod} siga corriendo rápido, y compra a nuestros servidores su dosis de café con una donación mensual!" new_here: follow: "Sigue la etiqueta %{link} y da la bienvenida a los nuevos usuarios de Diaspora*!" learn_more: "Más información" title: "Bienvenida" - no_contacts: "No hay contactos" - no_tags: "+ Encuentra una etiqueta para seguir" - people_sharing_with_you: "Comparten con vos" - post_a_message: "Publicar un mensaje >>" services: content: "Podés conectar los siguientes servicios a diaspora*:" heading: "Conectar Servicios" - unfollow_tag: "Dejar de seguir #%{tag}" welcome_to_diaspora: "¡Bienvenid@ a diaspora*, %{name}!" - new: - create: "Crear" - name: "Nombre (solo visible para ti)" no_contacts_message: community_spotlight: "Comunidad creativa" + invite_link_text: "invitar" or_spotlight: "O lo podés compartir con %{link}" - try_adding_some_more_contacts: "Podés buscar o invitar a más contactos." + try_adding_some_more_contacts: "Podés buscar o %{invite_link} a más contactos." you_should_add_some_more_contacts: "¡DeberÃas agregar más contactos!" - no_posts_message: - start_talking: "Nadie dijo nada todavÃa. ¡Inicia una conversación!" seed: acquaintances: "Conocidos" family: "Familia" @@ -234,7 +261,6 @@ es-AR: update: failure: "Tu aspecto, %{name}, tenÃa un nombre muy largo para guardarlo." success: "Tu aspecto, %{name}, se editó con éxito." - back: "Atrás" blocks: create: failure: "No se puede ignorar a ese usuario. #evasión" @@ -246,22 +272,15 @@ es-AR: explanation: "Publicá en diaspora* desde cualquier página agregando a tus marcadores este enlace: %{link}" heading: "Marcador" post_something: "Publicar en diaspora*" - post_success: "¡Publicado! Cerrando." cancel: "Cancelar" comments: new_comment: comment: "Comentar" commenting: "Comentando..." - one: "1 comentario" - other: "%{count} comentarios" - zero: "No hay comentarios" contacts: - create: - failure: "No pudo crearse el contacto" index: add_a_new_aspect: "Añadir un nuevo aspecto" add_contact: "Agregar contacto" - add_to_aspect: "Agregar contactos a %{name}" all_contacts: "Todos los contactos" community_spotlight: "Comunidad Creativa" my_contacts: "Mis contactos" @@ -269,19 +288,14 @@ es-AR: no_contacts_in_aspect: "Aún no tienes contactos en este aspecto. Debajo hay una lista de tus contactos existentes que puedes agregar a este aspecto." no_contacts_message: "Echa un vistazo a %{community_spotlight}" only_sharing_with_me: "Compartiendo solo conmigo" - remove_contact: "Eliminar contacto" start_a_conversation: "Empezar una conversación" title: "Contactos" user_search: "Búsqueda de usuarios" - your_contacts: "Tus contactos" - sharing: - people_sharing: "Compartiendo con vos:" spotlight: community_spotlight: "Comunidad Creativa" + no_members: "TodavÃa no hay miembros." suggest_member: "Sugiere un usuario" conversations: - conversation: - participants: "Participantes" create: fail: "Mensaje inválido" no_contact: "¡Primero necesitas agregar al contacto!" @@ -289,23 +303,13 @@ es-AR: destroy: delete_success: "La conversación ha sido eliminada" hide_success: "La conversación se ha ocultado" - helper: - new_messages: - few: "%{count} mensajes nuevos" - many: "%{count} mensajes nuevos" - one: "1 mensaje nuevo" - other: "%{count} mensajes nuevos" - two: "%{count} mensajes nuevos" - zero: "No hay mensajes nuevos" index: conversations_inbox: "Conversaciones - Bandeja de entrada" - create_a_new_conversation: "Iniciar una nueva conversación" inbox: "Mensajes" new_conversation: "Nueva conversación" - no_conversation_selected: "Ninguna conversación seleccionada" no_messages: "No hay mensajes" new: - abandon_changes: "¿Descartar los cambios?" + message: "Mensaje" send: "Enviar" sending: "Enviando..." subject: "Asunto" @@ -316,6 +320,7 @@ es-AR: show: delete: "Eliminar y bloquear conversación" hide: "Ocultar y silenciar la conversación" + last_message: "Último mensaje recibido %{timeago}" reply: "Responder" replying: "Contestando..." date: @@ -328,10 +333,7 @@ es-AR: error_messages: helper: correct_the_following_errors_and_try_again: "Corregà los siguientes errores e intentá de nuevo." - invalid_fields: "Campos inválidos" - login_try_again: "Por favor <a href='%{login_link}'>acceder</a> e intenta de nuevo." - post_not_public: "¡La publicación que estás tratando de ver no es pública!" - post_not_public_or_not_exist: "¡La publicación que estás tratando de abrir no es pública, o no existe!" + need_javascript: "Esta web necesita JavaScript para funcionar correctamente. Si lo desactivaste, por favor actÃvalo y actualiza la página." fill_me_out: "Completame" find_people: "Encontrá gente o #etiquetas" help: @@ -372,7 +374,7 @@ es-AR: who_sees_post_a: "Si haces una publicación restringida (limitada, privada), ésta solo será visible para las personas que hayas incluido en ese aspecto (o esos aspectos, si la hiciste para varios aspectos). Los contactos que no pertenecen a ese o esos aspectos no tendrán forma de ver la publicación, a menos que la hagas pública. Solo las publicaciones públicas serán visibles para cualquiera que no hayas incluido en uno o varios de tus aspectos." who_sees_post_q: "Cuando publico en un aspecto, ¿quienes pueden verlo?" chat: - add_contact_roster_a: "Primero, necesitas activar el chat para uno de los aspectos en donde está el usuario. Para hacer eso, ve a la %{contacts_page}, selecciona el aspecto que quieras y haz clic en el icono de chat para activar el chat en ese aspecto. %{toggle_privilege} Si lo prefieres, puedes crear un aspecto especial llamado 'Chat' y agregar allà a los usuarios con los que quieres chatear. Una vez que hayas hecho esto, abre la interface de chat y selecciona al usuario con quien quieres chatear." + add_contact_roster_a: "Primero, necesitas activar el chat para uno de los aspectos en donde está el usuario. Para hacer eso, ve a la %{contacts_page}, selecciona el aspecto que quieras y haz clic en el icono de chat para activarlo en ese aspecto. %{toggle_privilege} Si lo prefieres, puedes crear un aspecto especial llamado \"Chat\" y agregar allà a los usuarios con los que quieres chatear. Una vez que hayas hecho ésto, abre la interfaz de chat ubicada a la derecha de tu Entrada y selecciona al usuario con quien quieres chatear." add_contact_roster_q: "¿Cómo hago para chatear con alguien en diaspora*?" contacts_page: "página de contactos" title: "Chat" @@ -416,29 +418,29 @@ es-AR: what_is_a_mention_a: "Una mención es un enlace a la página de perfil de la o las personas que aparecen en la publicación. Cuando alguien es mencionado, recibe una notificación que llama su atención sobre la publicación." what_is_a_mention_q: "¿Qué es una \"mención\"?" miscellaneous: - back_to_top_a: "SÃ. Después de haberse desplazado hacia abajo en la página, haciendo un click en la flecha gris que aparece en la esquina inferior derecha de la ventana de tú navegador." + back_to_top_a: "SÃ. Después de haberse desplazado hacia abajo en la página, haciendo un clic en la flecha gris y blanca que aparece en la esquina inferior derecha de la ventana del navegador." back_to_top_q: "¿Existe una manera rápida de regresar a la parte superior de la página después de haberme desplazado hacia abajo?" - diaspora_app_a: "Existen muchas aplicaciones para Android en una etapa temprana de desarrollo. Muchos son proyectos hace tiempo abandonados y no funcionan bien con la versión actual de diaspora*. No esperes demasiado de estas aplicaciones por el momento. Actualmente la mejor manera de acceder a diaspora* desde tu dispositivo móvil es a través de tu navegador, porque hemos diseñado una versión móvil de este sitio que deberÃa funcionar correctamente en todos los teléfonos. No existe actualmente una aplicación para iOS. Nuevamente, diaspora* deberÃa funcionar bien a través de tu navegador." + diaspora_app_a: "Existen muchas aplicaciones para Android en una etapa temprana de desarrollo. Muchos son proyectos hace tiempo abandonados y no funcionan bien con la versión actual de diaspora*. No esperes demasiado de estas aplicaciones por el momento. Actualmente la mejor manera de acceder a diaspora* desde tu dispositivo móvil es a través de tu navegador, porque hemos diseñado una versión móvil de este sitio que deberÃa funcionar correctamente en todos los teléfonos. Sin embargo, existen algunas apps móviles de diaspora* en F-Droid que han sido probadas y funcionan correctamente." diaspora_app_q: "¿Existe una aplicación diaspora* para Android o iOS?" - photo_albums_a: "No, no actualmente. De todas formas puedes ver las actualizaciones de sus fotos desde la sección de Fotos en la barra lateral de su pagina de perfil." + photo_albums_a: "No, no actualmente. De todas formas puedes ver las actualizaciones de fotos de un usuario desde la pestaña \"Fotos\" en su página de perfil." photo_albums_q: "¿Hay álbumes de fotos o videos?" - subscribe_feed_a: "SÃ, pero ésta aún no es una funcionalidad completamente pulida y el formateo de los resultados es todavÃa un poco tosco. Si de todas maneras deseas probarla, ve hacia alguna página de perfil y haz clic en el botón feed de tu navegador, o puedes copiar la URL del perfil (ej.: https://joindiaspora.com/people/número), y pegarla dentro del lector de feeds. La dirección que resulta de ésto es parecida a: https//joindiaspora.com/public/usuario.atom - diaspora* usa Atom en lugar de RSS." + subscribe_feed_a: "SÃ, pero ésta aún no es una funcionalidad completamente pulida y el formateo de los resultados es todavÃa un poco tosco. Si de todas maneras deseas probarla, ve hacia alguna página de perfil y haz clic en el botón feed de tu navegador, o puedes copiar la URL del perfil (ej.: https://nombredelpod.org/people/número), y pegarla dentro del lector de feeds. La dirección que resulta de ésto es parecida a: https//nombredelpod.org/public/usuario.atom - diaspora* usa Atom en lugar de RSS." subscribe_feed_q: "¿Puedo suscribirme a las publicaciones públicas de alguien usando un lector de feeds?" title: "Opciones varias" pods: - find_people_a: "Invitá a tus amigos usando el enlace de correo electrónico en la barra lateral. Sigue las etiquetas (#tags) para descubrir a otras personas con intereses en común, y agrega a tus aspectos a aquellos que publican cosas interesantes. Preséntate y saluda a la comunidad con una publicación pública usando la etiqueta #hola." + find_people_a: "Invitá a tus amigos usando el enlace de correo electrónico en la barra lateral. Sigue las #etiquetas para descubrir a otras personas con intereses en común, y agrega a tus aspectos a aquellos que publican cosas que te interesan. Preséntate y saluda a la comunidad con una publicación pública usando la etiqueta #hola." find_people_q: "Me acabo de registrar en un \"pod\", ¿cómo puedo encontrar a gente con quien compartir?" title: "Pods" - use_search_box_a: "Si conoces su ID completa de diaspora* (por ejemplo nombredeusuario@nombredelpod.org), puedes encontrarlo mediante la búsqueda con estos datos. Si te encuentras en la misma vaina (servidor) lo puedes buscar solo por su nombre de usuario. Una alternativa es la búsqueda por su nombre de perfil (el nombre que ves en la pantalla). Si una búsqueda no funciona la primera vez, inténtalo de nuevo." + use_search_box_a: "Si conoces su ID completa de diaspora* (por ejemplo nombredeusuario@nombredelpod.org), puedes encontrarlo mediante la búsqueda con ese dato. Si te encuentras en el mismo pod lo puedes buscar solo por su nombre de usuario. Una alternativa es la búsqueda por su nombre de perfil (el nombre que ves en la pantalla). Si una búsqueda no funciona la primera vez, inténtalo de nuevo." use_search_box_q: "¿Cómo utilizo el campo de búsqueda para encontrar a otras personas?" - what_is_a_pod_a: "Un pod es un servidor con el software de diaspora* y conectado a la red de diaspora*. \"Pod\" (vaina) es una metáfora que hace referencia a las vainas de las plantas que contienen las semillas, por la manera en que los servidores contienen las cuentas de usuarios. Existen muchos pods diferentes. Puedes agregar a tus amigos de otros pods y comunicarte con ellos. (Puedes pensar en un pod de diaspora* como algo similar a un proveedor de correo electrónico: existen pods publicos, pods privados, y con algo de esfuerzo puedes instalar y correr tu propio pod)." + what_is_a_pod_a: "Un pod es un servidor con el software de diaspora* y conectado a la red de diaspora*. \"Pod\" -vaina- es una metáfora que hace referencia a las vainas de las plantas que contienen las semillas, por la manera en que los servidores contienen las cuentas de usuarios. Existen muchos pods diferentes. Puedes agregar a tus amigos de otros pods y comunicarte con ellos. No es necesario que abras una cuenta en diferentes pods, con uno solo es suficiente. Puedes pensar en un pod de diaspora* como algo similar a un proveedor de correo electrónico: existen pods publicos, pods privados, y con algo de esfuerzo puedes instalar y correr tu propio pod." what_is_a_pod_q: "¿Qué es un \"pod\"?" posts_and_posting: - char_limit_services_a: "En el caso de que tu publicación sea limitada a una cantidad menor de caracteres (140 en el caso de Twitter, 1000 en el caso de Tumblr), y el número de caracteres restantes se mostrará cuando el icono del servicio esté seleccionado. Aun podrás publicar en esos servicios si tu publicación es más extensa del lÃmite de éstos, pero el texto será recortado." - char_limit_services_q: "¿Cuál es el lÃmite de caracteres para publicaciones compartidas con servicios conectados que tienen una cantidad más pequeña de caracteres permitidos?" + char_limit_services_a: "En el caso de que tu publicación sea limitada a una cantidad menor de caracteres (140 en el caso de Twitter, 1000 en el caso de Tumblr), el número de caracteres restantes se mostrará cuando el icono del servicio esté seleccionado. Aún podrás publicar en esos servicios si tu publicación es más extensa del lÃmite de éstos, pero el texto será recortado." + char_limit_services_q: "¿Qué sucede si comparto mi post con servicios conectados que tienen una cantidad más pequeña de caracteres permitidos?" character_limit_a: "65.535 caracteres. Es decir, ¡65.395 caracteres más de los que permite Twitter! ;)" character_limit_q: "¿Cuál es el lÃmite de caracteres para una publicación?" - embed_multimedia_a: "Generalmente puedes pegar la URL (ej.: http://www.youyube.com/watch?v=nnnnnnnnnnn) dentro de tu publicación y el video o audio será añadido automáticamente. Algunos de los sitios que soportados son: YouTube, Vimeo, SoundCloud, Flickr y algunos más. diaspora* usa oEmbed para ésto. Estamos agregando nuevos sitios todo el tiempo. Recuerda siempre publicar simple y claro, con enlaces completos: sin enlaces acortados, ni operadores después de la URL base; y dale algo de tiempo antes de refrescar la página después de publicar para ver la vista previa." + embed_multimedia_a: "Generalmente puedes pegar la URL (ej.: http://www.youyube.com/watch?v=nnnnnnnnnnn) dentro de tu publicación y el vÃdeo o audio será añadido automáticamente. Algunos de los sitios que están soportados son: YouTube, Vimeo, SoundCloud, Flickr y algunos más. diaspora* utiliza oEmbed para esta funcionalidad. Estamos agregando nuevos sitios todo el tiempo. Recuerda siempre publicar simple y claro, con enlaces completos: sin enlaces cortados, ni operadores después de la URL base; y dale algo de tiempo antes de refrescar la página, después de publicar, para ver la vista previa." embed_multimedia_q: "¿Cómo hago para insertar video, audio u otro contenido multimedia en una publicación?" format_text_a: "Usando un sistema simplificado llamado %{markdown}. Puedes encontrar la sintaxis completa de Markdown %{here}. El botón de vista previa es realmente útil en este caso, ya que puedes ver como se verá tu mensaje antes de compartirlo." format_text_q: "¿Cómo puedo darle formato al texto de mis publicaciones (negrita, itálica, etc.)?" @@ -447,7 +449,7 @@ es-AR: image_text: "texto de la imagen" image_url: "URL de la imagen" insert_images_a: "Haz clic en el icono pequeño con forma de cámara para insertar imágenes en una publicación. Presiona el icono de imágenes nuevamente para añadir otra foto, o selecciona varias al mismo tiempo." - insert_images_comments_a1: "Siguiendo el código Markdown" + insert_images_comments_a1: "No puedes subir imágenes en los comentarios, pero puedes insertarlas usando el código Markdown" insert_images_comments_a2: "puede ser utilizada para insertar imágenes desde la web en los comentarios y también en las publicaciones." insert_images_comments_q: "¿Puedo insertar imágenes en los comentarios?" insert_images_q: "¿Cómo puedo insertar imágenes en las publicaciones?" @@ -459,7 +461,7 @@ es-AR: post_poll_q: "¿Cómo agrego una encuesta a mi publicación?" post_report_a: "Pulsa en el icono de alerta en la esquina superior derecha de la publicación para denunciarla al administrador. Escribe una razón para denunciar la publicación en el cuadro de texto." post_report_q: "¿Cómo denuncio una publicación ofensiva?" - size_of_images_a: "No. El tamaño de las imágenes automáticamente se ajusta a la Entrada. Markdown no tiene un código para especificar el tamaño de una imagen." + size_of_images_a: "No. El tamaño de las imágenes se ajusta automáticamente a la Entrada. Markdown no tiene un código para especificar el tamaño de una imagen." size_of_images_q: "¿Puedo modificar el tamaño de las imágenes en las publicaciones o comentarios?" stream_full_of_posts_a1: "Tu Entrada está compuesta por tres tipos de publicaciones:" stream_full_of_posts_li1: "Las publicaciones de las personas que comparten contigo, se dividen en dos tipos: publicaciones publicas y publicaciones limitadas al aspecto en el que estas incluido. Para eliminar esas publicaciones de tu entrada, simplemente deja de compartir el aspecto con esta persona." @@ -468,18 +470,18 @@ es-AR: stream_full_of_posts_q: "¿Porqué mi Entrada está repleta de publicaciones de gente que no conozco y que no tengo en mis aspectos?" title: "Publicaciones y cómo publicar" private_posts: - can_comment_a: "Solo los usuarios de diaspora* conectados que estén en ese aspecto podrán comentar o marcar \"Me gusta\" en tu publicación restringida." + can_comment_a: "Solo los usuarios de diaspora* que hayas agregado a ese aspecto podrán comentar o marcar \"Me gusta\" en tu publicación restringida." can_comment_q: "¿Quién puede comentar o marcar \"Me gusta\" una publicación limitada?" - can_reshare_a: "Nadie. Las publicaciones restringidas no se pueden volver a compartir. Los usuarios de diaspora* conectados que estén en ese aspecto pueden, sin embargo, copiarlo y pegarlo." + can_reshare_a: "Nadie. Las publicaciones restringidas no se pueden volver a compartir. Los usuarios de diaspora* que estén en ese aspecto pueden, sin embargo, copiar y pegar la publicación en un nuevo post." can_reshare_q: "¿Quién puede volver a compartir una publicación limitada?" see_comment_a: "Solo las personas a quienes se les compartió la publicación (las personas que están en los aspectos seleccionados por la persona que la publicó) pueden ver los comentarios y los \"Me gusta\". " see_comment_q: "Cuando comento o hago \"Me gusta\" en una publicación limitada, ¿quién puede verlo?" title: "Publicaciones privadas" - who_sees_post_a: "Solo los usuarios de diaspora* conectados que estén en ese aspecto podrán ver tu publicación restringida." + who_sees_post_a: "Solo los usuarios de diaspora* que hayas agregado a ese aspecto podrán ver tu publicación restringida." who_sees_post_q: "Cuando publico un mensaje en un aspecto (es decir, una publicación restringida o limitada), ¿quienes pueden verlo?" private_profiles: title: "Perfiles privados" - whats_in_profile_a: "Tu biografÃa, ubicación, género y fecha de cumpleaños. Están ubicadas en la parte inferior de la página de edición de perfil. Toda esta información es opcional -depende de vos si la llenás o no-. Los usuarios conectados que tengas agregados a tus aspectos son las únicas personas que podrán ver tu perfil privado. Ellos también podrán ver las publicaciones privadas que hagas en él o los aspectos a los que pertenecen, mezcladas con tus publicaciones públicas, cuando visiten tu página de perfil." + whats_in_profile_a: "Tu perfil privado contiene tu biografÃa, ubicación, género y fecha de cumpleaños, si es que has completado esas secciones. Están ubicadas en la parte inferior de la página de edición de perfil. Toda esa información es opcional -depende de vos si la llenás o no-. Los usuarios que tengas agregados a tus aspectos son las únicas personas que podrán ver tu perfil privado. Ellos también podrán ver las publicaciones privadas que hagas en él o los aspectos a los que pertenecen, mezcladas con tus publicaciones públicas, cuando visiten tu página de perfil." whats_in_profile_q: "¿Qué hay en mi perfil privado?" who_sees_profile_a: "Cualquier usuario conectado que esta compartiendo contigo (es decir, que tú tienes en uno de tus aspectos). Sin embargo, las personas que te siguen, pero que tu no sigues, solo verán tu información publica." who_sees_profile_q: "¿Quiénes pueden ver mi perfil privado?" @@ -488,11 +490,11 @@ es-AR: public_posts: can_comment_reshare_like_a: "Cualquier usuario de diaspora* conectado puede comentar, volver a compartir o marcar como \"Me gusta\" tus publicaciones públicas." can_comment_reshare_like_q: "¿Quién puede comentar, volver a compartir o poner \"Me gusta\" en mis publicaciones públicas?" - deselect_aspect_posting_a: "El destildar aspectos no afecta una publicación pública. Está aún puede aparecer en la entrada de todos tus contactos. Para hacer una publicación visible solo a aspectos especÃficos, necesitas seleccionar esos aspectos desde el botón bajo el editor." + deselect_aspect_posting_a: "El destildar aspectos no afecta una publicación pública. Está aún puede aparecer en la Entrada de todos tus contactos. Para hacer una publicación visible sólo a aspectos especÃficos, necesitas seleccionar esos aspectos al publicar, desde el botón que está bajo el editor." deselect_aspect_posting_q: "¿Qué sucede cuando quito la selección de uno o más aspectos al momento de hacer una publicación pública?" - find_public_post_a: "Tus publicaciones públicas aparecerán en las Entradas de todos aquellos que te sigan. Si incluyes etiquetas (#tags) en tus publicaciones públicas, cualquiera que siga esas etiquetas podrá ver tu publicación en su Entrada. Cualquier publicación pública también tiene una URL especÃfica que cualquiera puede ver, incluso si no ha iniciado sesión, por lo que pueden ser enlazadas directamente desde Twitter, blogs, etc. Las publicaciones públicas también pueden ser indexadas por los motores de búsqueda." + find_public_post_a: "Tus publicaciones públicas aparecerán en la Entrada de todos aquellos usuarios que te sigan. Si incluyes #etiquetas en tus publicaciones públicas, cualquiera que siga esas etiquetas podrá ver tu publicación en su Entrada. Cualquier publicación pública también tiene una URL especÃfica que todos pueden ver, incluso si no han iniciado sesión, por lo que pueden ser enlazadas directamente desde Twitter, blogs, etc. Las publicaciones públicas también pueden ser indexadas por los motores de búsqueda de Internet." find_public_post_q: "¿Cómo pueden los demás usuarios encontrar mis publicaciones públicas?" - see_comment_reshare_like_a: "Cualquier usuario de diaspora* conectado y cualquier persona en Internet. Tanto los comentarios como las acciones de los \"Me gusta\" y \"Compartir\" de una publicación pública son también públicos." + see_comment_reshare_like_a: "Tanto los comentarios como las acciones de los \"Me gusta\" y \"Compartir\" de una publicación pública son también públicos. Cualquier usuario de diaspora* y cualquier persona en Internet puede ver tus interacciones en una publicación pública." see_comment_reshare_like_q: "Cuando comento, comparto o hago \"Me gusta\" en una publicación pública, ¿quién puede verlo?" title: "Publicaciones públicas" who_sees_post_a: "Cualquiera que use Internet puede potencialmente ver una publicación que hayas marcado como pública, asà que asegúrate de que realmente quieres que tu publicación sea pública. Es una buena forma de hacerse escuchar en todo el mundo." @@ -501,34 +503,34 @@ es-AR: title: "Perfiles públicos" what_do_tags_do_a: "Las etiquetas ayudan a la gente a conocerte. Las fotos de perfil también aparecerán en el lado izquierdo de las páginas de esas etiquetas, junto con cualquier otra persona que las tenga en su perfil público." what_do_tags_do_q: "¿Qué hacen las etiquetas de mi perfil público?" - whats_in_profile_a: "Tu nombre, las cinco etiquetas que elijas para describirte a ti mismo, y tu foto. Están en la sección superior de la pagina de edición de perfil. Tú puedes hacer que esta información de perfil sea identificable o anónima. También, tu página de perfil muestra cualquier publicación pública que hayas hecho." + whats_in_profile_a: "Tu perfil público contiene tu nombre, las cinco etiquetas que elijas para describirte a ti mismo, y tu foto. Están en la sección superior de la página de edición de perfil. Puedes hacer que esta información de perfil sea identificable o anónima. También, tu página de perfil muestra cualquier publicación pública que hayas hecho." whats_in_profile_q: "¿Qué hay en mi perfil público?" who_sees_profile_a: "Cualquier usuario de diaspora* conectado, asà como la inmensidad de Internet, puede verlo. Cada perfil tiene una URL directa, asà que puede ser enlazado directamente desde sitios externos y puede ser indexado por los motores de búsqueda." who_sees_profile_q: "¿Quién puede ver mi perfil público?" who_sees_updates_a: "Cualquier persona puede ver los cambios si visitan tu página de perfil." who_sees_updates_q: "¿Quién puede ver las actualizaciones de mi perfil público?" resharing_posts: - reshare_private_post_aspects_a: "No es posible volver a compartir una publicación privada. Es por respeto a las intenciones del publicador original de solo compartirla con un grupo determinado de personas." - reshare_private_post_aspects_q: "¿Puedo volver a compartir una publicación limitada solo con ciertos aspectos?" + reshare_private_post_aspects_a: "No, no es posible volver a compartir una publicación privada. Es por respeto a las intenciones del autor original de sólo compartirla con un grupo determinado de personas." + reshare_private_post_aspects_q: "¿Puedo volver a compartir una publicación limitada sólo con ciertos aspectos?" reshare_public_post_aspects_a: "No, cuando vuelves a compartir una publicación pública automáticamente se convierte en una de tus publicaciones públicas. Para compartirla con ciertos aspectos, copia y pega el contenido en una nueva publicación." - reshare_public_post_aspects_q: "¿Puedo compartir una publicación pública solo con ciertos aspectos?" + reshare_public_post_aspects_q: "¿Puedo compartir una publicación pública sólo con ciertos aspectos?" title: "Volver a compartir una publicación" sharing: add_to_aspect_a1: "Digamos que Amy agrega a Ben a un aspecto, pero Ben (aún) no ha agregado a Amy a un aspecto:" - add_to_aspect_a2: "Esto es conocido como intercambio asimétrico. Si Ben también agrega a Amy a sus aspectos entonces pasarÃa a ser un intercambio mutuo, con las publicaciones públicas de Amy y Ben y las publicaciones privadas importantes apareciendo en las Entradas de ambos, etc. " + add_to_aspect_a2: "Esto es conocido como intercambio asimétrico. Si Ben también agrega a Amy a sus aspectos entonces pasarÃa a ser un intercambio mutuo, con las publicaciones públicas de Amy y Ben y las publicaciones privadas importantes apareciendo en la Entrada de ambos, además de que Amy podrá ver el perfil privado de Ben. Esto también permitirá que puedan enviarse mensajes privados." add_to_aspect_li1: "Ben recibe una notificación de que Amy \"comenzó a compartir\" con Ben." add_to_aspect_li2: "Amy comenzará a ver las publicaciones públicas de Ben en su Entrada." add_to_aspect_li3: "Amy no podrá ver ninguna de las publicaciones restringidas de Ben." add_to_aspect_li4: "Ben no verá las publicaciones públicas o restringidas de Amy en su Entrada." - add_to_aspect_li5: "Pero si Ben va a la página de perfil de Amy, entonces él podrá ver las publicaciones privadas que ella ha enviado a sus aspectos en los cuales él está incluido (asà como sus publicaciones públicas que cualquiera puede ver allÃ)." + add_to_aspect_li5: "Pero si Ben va a la página de perfil de Amy, entonces podrá ver las publicaciones privadas que ella ha enviado a los aspectos en los cuales él esté incluido (asà como sus publicaciones públicas que cualquiera puede ver allÃ)." add_to_aspect_li6: "Ben podrá ver el perfil privado de Amy (biografÃa, ubicación, género y fecha de nacimiento)." add_to_aspect_li7: "Amy aparecerá como \"Compartiendo solo conmigo\" en la página de contactos de Ben." add_to_aspect_li8: "Amy también será capaz de @mencionar a Ben en una publicación." add_to_aspect_q: "¿Qué sucede cuando agrego a alguien a uno de mis aspectos?, ¿o cuando alguien me agrega a uno de sus aspectos?" - list_not_sharing_a: "No, pero puedes ver si alguien esta compartiendo contigo visitando su página de perfil. Si es asÃ, la barra bajo su foto de perfil aparecerá de color verde; si no, será gris. DeberÃas recibir una notificación cada vez que alguien comienza a compartir contigo." + list_not_sharing_a: "No, pero puedes ver si alguien esta compartiendo contigo visitando su página de perfil. Si es asÃ, verás un tilde de color verde a la derecha de su nombre; si no, sólo verás un cÃrculo gris. DeberÃas recibir una notificación cada vez que alguien comienza a compartir contigo." list_not_sharing_q: "¿Hay una lista de las personas a las que he agregado a uno de mis aspectos, pero ellos a mà no?" - only_sharing_a: "Estas son las personas que lo han agregado en uno de sus aspectos, pero que no están (aún) en ninguno de tus aspectos. En otras palabras, ellos están compartiendo contigo, pero tú no compartes con ellos (distribución asimétrica). Si tú los agregas a cualquiera de tus aspectos, entonces ellos aparecerán bajo este aspecto y no bajo \"solo compartiendo contigo\". Véase más arriba." - only_sharing_q: "¿Quienes son las personas que figuran en mi lista de contactos como \"Compartiendo solo conmigo\"?" + only_sharing_a: "Estas son las personas que te han agregado en uno de sus aspectos, pero que no están (aún) en ninguno de tus aspectos. En otras palabras, ellos están compartiendo con vos, pero vos no compartes con ellos. Si los agregas a cualquiera de tus aspectos, entonces ellos aparecerán en ese aspecto y no en \"Compartiendo solo conmigo\". Véase más arriba." + only_sharing_q: "¿Quiénes son las personas que figuran en mi lista de contactos como \"Compartiendo solo conmigo\"?" see_old_posts_a: "No. Ellos no podrán ver nuevas publicaciones de ese aspecto. Ellos (y cualquier otra persona) podrán ver tus publicaciones públicas viejas en tú página de perfil, y también podrán verlas en sus entradas." see_old_posts_q: "Cuando agrego a alguien a un aspecto, ¿puede ver lo que he publicado anteriormente en ese aspecto?" sharing_notification_a: "DeberÃas recibir una notificación cada vez que alguien empieza a compartir contigo." @@ -537,98 +539,91 @@ es-AR: tags: filter_tags_a: "Esta opción aún no está disponible directamente mediante diaspora*, pero algunos colaboradores %{third_party_tools} han escrito algo que permite hacerlo." filter_tags_q: "¿Como puedo filtrar/excluir algunas etiquetas de mi entrada?" - followed_tags_a: "Después de buscar una etiqueta puedes hacer clic en el botón \"Seguir\", ubicado en la parte superior de la página de la etiqueta, para seguirla. Entonces aparecerá en tu lista de etiquetas seguidas a la izquierda. Al hacer clic en una de las etiquetas seguidas te enviará a la página de esa etiqueta para que puedas ver las publicaciones más recientes que contengan esa etiqueta. Haz clic en #Etiquetas que sigues para ver en la Entrada las publicaciones que incluyan una o cualquiera de las etiquetas seguidas. " + followed_tags_a: "Después de buscar una etiqueta puedes hacer clic en el botón \"Seguir\", ubicado en la parte superior derecha de la página de la etiqueta, para seguirla. Entonces aparecerá en tu lista de etiquetas seguidas en la barra lateral izquierda de tu Entrada. Al hacer clic en una de las etiquetas seguidas te enviará a la página de esa etiqueta para que puedas ver las publicaciones más recientes que la contengan. Haz clic en \"#Etiquetas que sigues\" para ver en la Entrada las publicaciones que incluyan una o cualquiera de las etiquetas seguidas." followed_tags_q: "¿Qué son las \"#Etiquetas que sigues\" y cómo hago para seguir una etiqueta?" people_tag_page_a: "Son personas que han puesto esta etiqueta para describirse a si mismos en sus perfiles públicos." people_tag_page_q: "¿Quienes son las personas listadas a la izquierda de la página de etiquetas?" tags_in_comments_a: "Una etiqueta agregada a un comentario seguirá apareciendo como un enlace hacia la página de la etiqueta, pero no hará aparecer la publicación (o comentario) en la página de la etiqueta. Esto solo funciona para las etiquetas en las publicaciones." tags_in_comments_q: "¿Puedo agregar etiquetas en los comentarios o solo en las publicaciones?" title: "Etiquetas" - what_are_tags_for_a: "Las etiquetas son una manera de categorizar una publicación, usualmente por un tema. Buscando por etiquetas se mostraran todas las publicaciones con dicha etiqueta que puedes ver (ambos públicos y privados). Esto permite a las personas que están interesadas en un tema en particular encontrar todas las publicaciones públicas sobre él." + what_are_tags_for_a: "Las etiquetas son una manera de categorizar una publicación, usualmente por un tema. Buscando por etiquetas se mostrarán todas las publicaciones con dicha etiqueta, tanto públicas como privadas. Esto permite a las personas que están interesadas en un tema en particular encontrar todas las publicaciones públicas sobre él." what_are_tags_for_q: "¿Para qué sirven las etiquetas?" third_party_tools: "Herramientas de terceros" title_header: "Ayuda" tutorial: "tutorial" tutorials: "tutoriales" wiki: "wiki" - hide: "Ocultar" - ignore: "Ignorar" + home: + default: + be_who_you_want_to_be: "Sé quien quieras ser" + be_who_you_want_to_be_info: "Muchas redes insisten en que uses tu identidad real. diaspora* no. Aquà tú puedes elegir quién quieres ser y compartir tanto o tan poco sobre vos como tú quieras. Realmente depende de ti cómo deseas interactuar con otras personas." + byline: "La red social Libre donde tú tienes el control" + choose_your_audience: "Elige tu público" + choose_your_audience_info: "Los aspectos de diaspora* te permiten compartir sólamente con las personas que quieras. Puedes ser tan público o privado como prefieras. Comparte una foto divertida con el mundo entero, o un oscuro secreto con tus amigos más cercanos. Tú tienes el control." + headline: "Bienvenido a %{pod_name}" + own_your_data: "Sé el dueño de tus datos" + own_your_data_info: "Muchas redes usan tus datos para hacer dinero analizando tus interacciones y usando esa información para mostrarte anuncios publicitarios. diaspora* no usa tus datos para ningún propósito más que permitirte estar en contacto con otras personas." + podmin: + admin_panel: "panel de administración" + byline: "Estás a punto de cambiar Internet. Vamos a configurarlo, ¿dale?" + configuration_info: "Abre %{database_path} y %{diaspora_path} en tu editor de texto favorito y revÃsalos cuidadosamente, están comentados al detalle." + configure_your_pod: "Configura tu pod" + contact_irc: "contáctanos en el IRC" + contribute: "Contribuir" + contribute_info: "¡Haz que diaspora* sea aún mejor! Si encuentras algún fallo, por favor %{report_bugs}." + create_an_account: "Crear una cuenta" + create_an_account_info: "%{sign_up_link} para crear una cuenta." + faq_for_podmins: "FAQ para administradores de pod en nuestra wiki" + getting_help: "Obtener ayuda" + getting_help_info: "Mostramos algunas %{faq} incluyendo consejos adicionales, trucos y soluciones para los problemas más comunes. También puedes probar el chat %{irc}." + headline: "¡Bienvenido!" + make_yourself_an_admin: "Conviértete en administrador" + make_yourself_an_admin_info: "Puedes encontrar instrucciones en la %{wiki}. Esto añadirá un enlace de \"Administrador\" a tu menú de usuario en el encabezado cuando inicies sesión. Asimismo, te dará funciones como búsqueda de usuarios y estadÃsticas de tu pod. Para detalles avanzados en el aspecto operacional, ve al %{admin_panel}." + report_bugs: "repórtalos" + update_instructions: "instrucciones de actualización en la wiki de diaspora*" + update_your_pod: "Actualiza tu pod" + update_your_pod_info: "Puedes encontrar %{update_instructions}" invitation_codes: - excited: "%{name} está encantado de verte por aquÃ." not_valid: "El código de invitación ya no es válido" invitations: a_facebook_user: "Un usuario de Facebook" check_token: not_found: "No se encontró la udentificación de invitación" create: - already_contacts: "Ya estás conectado con esta persona" - already_sent: "Ya invitaste a esta persona." empty: "Por favor ingresa al menos una dirección de correo electrónico." no_more: "No tenés más invitaciones." note_already_sent: "Las invitaciones han sido enviadas a: %{emails}" - own_address: "No podés enviar una invitación a tu propia dirección." rejected: "Las siguientes direcciones tuvieron problemas: " sent: "Las invitaciones se han enviado a: %{emails}" - edit: - accept_your_invitation: "Aceptá tu invitación" - your_account_awaits: "Tu cuenta está esperando!" new: - already_invited: "Las siguientes personas no aceptaron tu invitación:" - aspect: "Aspecto" - check_out_diaspora: "¡Echa un vistazo a diaspora*!" codes_left: one: "Queda %{count} invitación con este código" other: "Quedan %{count} invitaciones con este código" zero: "No quedan invitaciones con este código" comma_separated_plz: "Puedes introducir múltiples direcciones de correo electrónico separadas por comas." - if_they_accept_info: "si aceptan, serán agregados al aspecto que selecciones." invite_someone_to_join: "¡Invitá a alguien a unirse a diaspora*!" language: "Idioma" paste_link: "Comparte este enlace con tus amigos para invitarlos a diaspora*, o envÃales directamente el enlace por correo electrónico." - personal_message: "Mensaje personal" - resend: "Reenviar" send_an_invitation: "Enviar una invitación" - send_invitation: "Enviar invitación" sending_invitation: "Enviando invitación..." - to: "Para" layouts: application: back_to_top: "Volver al inicio" + be_excellent: "¡La cruzada por una red social Libre! ♥" powered_by: "Impulsado por diaspora*" public_feed: "Canal público para %{name}" source_package: "Descargar el paquete con el código fuente" statistics_link: "EstadÃsticas del pod" toggle: "Cambiar a celular" whats_new: "¿Qué hay de nuevo?" - your_aspects: "Tus aspectos" header: - admin: "Administrar" - blog: "Blog" code: "Código" - help: "Ayuda" - login: "Conectarse" logout: "Salir" profile: "Perfil" - recent_notifications: "Notificaciones recientes" settings: "Configuración" - view_all: "Ver todo" - likes: - likes: - people_dislike_this: - one: "a %{count} le disgusta esto" - other: "a %{count} les disgusta esto" - zero: "a nadie le disgusta esto" - people_like_this: - one: "a %{count} le gusta esto" - other: "a %{count} les gusta esto" - zero: "a nadie le gusta esto" - people_like_this_comment: - one: "a %{count} le gusta este comentario" - other: "a %{count} les gusta este comentario" - zero: "a nadie le gusta este comentario" + toggle_navigation: "Cambiar navegación" limited: "Limitado" more: "Más" - next: "Siguiente" no_results: "No hay resultados" notifications: also_commented: @@ -646,14 +641,6 @@ es-AR: one: "%{actors} comentó en tu publicación %{post_link}." other: "%{actors} comentaron en tu publicación %{post_link}." zero: "%{actors} comentó en tu publicación %{post_link}." - helper: - new_notifications: - few: "%{count} notificaciones nuevas" - many: "%{count} notificaciones nuevas" - one: "1 notificación nueva" - other: "%{count} notificaciones nuevas" - two: "%{count} notificaciones nuevas" - zero: "Ninguna notificacÃon nueva" index: all_notifications: "Todas las notificaciones" also_commented: "También comentados" @@ -727,7 +714,6 @@ es-AR: a_limited_post_comment: "Hay un nuevo comentario para vos en una publicación limitada de diaspora*" a_post_you_shared: "una publicación." a_private_message: "Hay un nuevo mensaje privado para vos en diaspora*" - accept_invite: "¡Aceptá tu invitación a diaspora*!" also_commented: limited_subject: "Hay un nuevo comentario en una publicación que comentaste" click_here: "Haz clic aquÃ" @@ -807,10 +793,10 @@ es-AR: view_post: "Ver publicación >" mentioned: limited_post: "Se te mencionó en una publicación privada." - mentioned: "te mencionó en una publicación:" subject: "%{name} te mencionó en diaspora*" private_message: reply_to_or_view: "Responder o ver esta conversación >" + subject: "Tienes un nuevo mensaje privado en diaspora*" remove_old_user: body: |- Hola, @@ -834,6 +820,8 @@ es-AR: la %{type} con la ID %{id} ha sido marcada como ofensiva. + Motivo: "%{reason}" + [%{url}][1] ¡Por favor revÃsala lo antes posible! @@ -862,20 +850,9 @@ es-AR: to_change_your_notification_settings: "para cambiar la configuración de tus notificaciones" nsfw: "No apto para todo público" ok: "OK" - or: "o" - password: "Contraseña" - password_confirmation: "Confirmación de contraseña" people: add_contact: invited_by: "Fuiste invitado por" - add_contact_small: - add_contact_from_tag: "Agregar contacto desde una etiqueta" - aspect_list: - edit_membership: "Editar el Aspecto donde está el contacto" - helper: - is_not_sharing: "%{name} no está compartiendo con vos" - is_sharing: "%{name} está compartiendo con vos" - results_for: " resultados para %{params}" index: couldnt_find_them: "¿No puedes encontrarlos?" looking_for: "¿Buscando publicaciones sobre %{tag_link}?" @@ -885,105 +862,66 @@ es-AR: search_handle: "Utiliza la ID de diaspora* (usuario@pod.tld) para estar seguro/a de que encontrarás a tus amigos." searching: "Buscando, por favor sé paciente..." send_invite: "¿TodavÃa nada? ¡EnvÃa una invitación!" - one: "1 persona" - other: "%{count} personas" person: - add_contact: "Agregar contacto" - already_connected: "Ya estás conectado" - pending_request: "Solicitud pendiente" thats_you: "¡Ése sos vos!" profile_sidebar: bio: "BiografÃa" born: "Fecha de nacimiento" - edit_my_profile: "Editar mi perfil" gender: "Género/sexo" - in_aspects: "En aspectos" location: "Ubicación" - photos: "Fotos" - remove_contact: "Eliminar contacto" - remove_from: "¿Querés eliminar a %{name} de %{aspect}?" show: closed_account: "Esta cuenta ha sido cerrada." does_not_exist: "¡Ese usuario no existe!" has_not_shared_with_you_yet: "¡%{name} no compartió ninguna publicación con vos todavÃa!" - ignoring: "Estás ignorando todas las publicaciones de %{name}." - incoming_request: "%{name} quiere compartir con vos" - mention: "Mención" - message: "Mensaje" - not_connected: "No estás conectado con esa persona" - recent_posts: "Publicaciones recientes" - recent_public_posts: "Últimas publicaciones públicas" - return_to_aspects: "Volver a tu página de aspectos" - see_all: "Ver todo" - start_sharing: "Comenzar a compartir" - to_accept_or_ignore: "aceptar o ignorar." - sub_header: - add_some: "Agregar algo" - edit: "Editar" - you_have_no_tags: "¡No tenés etiquetas!" - webfinger: - fail: "Lo sentimos, no pudimos encontrar a %{handle}." - zero: "No se encontró a nadie" photos: - comment_email_subject: "La foto de %{name}" create: integrity_error: "Error subiendo la foto. ¿Estás seguro de que era una imagen válida?" runtime_error: "Error subiendo la foto. ¿Hay alguna restricción de seguridad?" type_error: "Error subiendo la foto. ¿Estás seguro que agregaste una imagen?" destroy: notice: "La foto fue eliminada." - edit: - editing: "Editando" - new: - back_to_list: "Volver a la lista" - new_photo: "Nueva foto" - post_it: "¡Publicalo!" new_photo: empty: "{file} está vacÃo, por favor seleccioná archivos sin él." invalid_ext: "{file} tiene una extensión incorrecta. Sólo se permiten {extensions}." size_error: "{file} es demasiado grande, el tamaño máximo de archivo es {sizeLimit}." new_profile_photo: - or_select_one_existing: "o selecciona una %{photos} de las existentes" upload: "¡Subir una nueva foto de perfil!" - photo: - view_all: "Ver todas las fotos de %{name}" show: - collection_permalink: "Enlace permanente a la colección" - delete_photo: "Eliminar foto" - edit: "Editar" - edit_delete_photo: "Editar descripción de foto / eliminar foto" - make_profile_photo: "Convertir en foto de perfil" show_original_post: "Mostrar la publicación original" - update_photo: "Actualizar foto" - update: - error: "Error al editar la foto." - notice: "La foto se subió correctamente." + polls: + votes: + one: "%{count} voto hasta ahora" + other: "%{count} votos hasta ahora" + zero: "%{count} votos hasta ahora" posts: presenter: title: "Una publicación de %{name}" show: - destroy: "Eliminar" forbidden: "No tienes permiso para hacer eso" - not_found: "No se pudo encontrar la publicación." - permalink: "Enlace permanente" + location: "Publicado desde: %{location}" photos_by: one: "Una foto de %{author}" other: "%{count} fotos de %{author}" zero: "Ninguna foto de %{author}" reshare_by: "Compartido por %{author}" - previous: "Anterior" privacy: "Privacidad" - privacy_policy: "PolÃtica de Privacidad" profile: "Perfil" profiles: edit: allow_search: "Permitir que la gente te encuentre en diaspora*" - edit_profile: "Editar perfil" + basic: "Mi perfil básico" + basic_hint: "Cada campo de tu perfil es opcional. Tu perfil básico siempre será visible para todos." + extended: "Mi perfil extendido" + extended_hint: "Pulsa el interruptor para configurar la visibilidad de los datos del perfil extendido. Público significa que es visible en internet, limitado significa que sólo las personas con quien compartes verán esta información." + extended_visibility_text: "Visibilidad de tu perfil extendido" first_name: "Tu nombre de pila" last_name: "Tu apellido" + limited: "Limitado" nsfw_check: "Marcar todo lo que comparto como NSFW (\"no es seguro para el trabajo\")" nsfw_explanation: "\"No es seguro para el trabajo\" (NSFW-'not safe for work') es un estándar autónomo de la comunidad de diaspora* para el contenido que puede no ser adecuado para ver mientras estás trabajando. Si planeas compartir este material con frecuencia, por favor marca esta opción para que todo lo que compartas esté oculto para los demás usuarios a menos que ellos elijan verlo." nsfw_explanation2: "Si eliges no marcar esta opción, por favor agrega la etiqueta #nsfw cada vez que compartas un material de este tipo." + public: "Público" + settings: "Configuración del perfil" update_profile: "Actualizar perfil" your_bio: "Tu biografÃa" your_birthday: "Tu cumpleaños" @@ -991,8 +929,6 @@ es-AR: your_location: "Tu ubicación" your_name: "Tu nombre" your_photo: "Tu foto" - your_private_profile: "Tu perfil privado" - your_public_profile: "Tu perfil público" your_tags: "Vos en 5 palabras" your_tags_placeholder: "Por ejemplo #arte #viajes #linux #música #cine" update: @@ -1010,26 +946,16 @@ es-AR: closed: "Los registros están cerrados en este servidor de diaspora*." create: success: "¡Te has unido a diaspora*!" - edit: - cancel_my_account: "Cancelá tu cuenta" - edit: "Editar %{name}" - leave_blank: "(dejalo en blanco si no querés cambiarlo)" - password_to_confirm: "(necesitamos tu contraseña actual para confirmar los cambios)" - unhappy: "¿Insatisfecho?" - update: "Actualizar" invalid_invite: "¡El enlace de la invitación ya no es válido!" new: - create_my_account: "¡Crear mi cuenta!" email: "Correo electrónico" enter_email: "Ingresá tu correo electrónico" enter_password: "Ingresa una contraseña (seis caracteres mÃnimo)" enter_password_again: "Repetà la misma contraseña" enter_username: "Elegà un nombre de usuario (sólo letras, números y guión bajo)" - join_the_movement: "Unite al movimiento!" password: "Contraseña" password_confirmation: "Confirmación de contraseña" sign_up: "Registrarse" - sign_up_message: "Redes Sociales con un <3" submitting: "Enviar" terms: "Con la creación de una cuenta aceptas los %{terms_link}." terms_link: "Términos de Servicio" @@ -1042,48 +968,18 @@ es-AR: post_label: "<b>Publicación</b>: %{title}" reason_label: "Motivo: %{text}" reported_label: "<b>Reportada por</b> %{person}" + reported_user_details: "Detalles del usuario denunciado" review_link: "Marcar como revisada" status: - created: "El reporte ha sido creado" destroyed: "La publicación ha sido eliminada" failed: "Algo salió mal" - marked: "El reporte ha sido marcado como revisado" title: "Resumen de reportes" - requests: - create: - sending: "Enviando" - sent: "Has solicitado compartir con %{name}. DeberÃa verlo la próxima vez que se conecte a diaspora*." - destroy: - error: "¡Por favor, seleccioná un aspecto!" - ignore: "Se ignoró la solicitud de contacto." - success: "Ahora estás compartiendo." - helper: - new_requests: - few: "¡%{count} solicitudes nuevas!" - many: "¡%{count} solicitudes nuevas!" - one: "¡Una solicitud nueva!" - other: "¡%{count} solicitudes nuevas!" - two: "%{count} nuevas solicitudes!" - zero: "No hay solicitudes nuevas" - manage_aspect_contacts: - existing: "Contactos existentes" - manage_within: "Gestioná tus contactos" - new_request_to_person: - sent: "¡Enviado!" reshares: comment_email_subject: "%{resharer} compartió una publicación de %{author}" - create: - failure: "Ocurrió un error al compartir esta publicación." reshare: deleted: "La publicación original fue eliminada por su autor." - reshare: - one: "Compartido 1 vez" - other: "Compartido %{count} veces" - zero: "No compartido" reshare_confirmation: "¿Compartir la publicación de %{author}?" - reshare_original: "Compartir orignial" reshared_via: "Compartido a través de" - show_original: "Mostrar original " search: "Buscar" services: create: @@ -1095,10 +991,6 @@ es-AR: success: "Autenticación eliminada." failure: error: "Hubo un error al conectar con el servicio" - finder: - fetching_contacts: "diaspora* está trasladando tus contactos de %{service}, por favor regresa en unos minutos." - no_friends: "No se han encontrado contactos de Facebook." - service_friends: "diaspora* se está llenando de tus amigos de %{service}, por favor regresa en unos minutos." index: connect: "Conectar" disconnect: "Desconectar" @@ -1107,57 +999,28 @@ es-AR: no_services_available: "No hay servicios disponibles en este pod." not_logged_in: "Actualmente no conectado." really_disconnect: "¿Querés desconectarte de %{service}?" - services_explanation: "Conectar con otros servicios te ofrece la posibilidad de publicar tus publicaciones a medida que las escribes en diaspora*." - inviter: - click_link_to_accept_invitation: "Seguà este enlace para aceptar la invitación" - join_me_on_diaspora: "Unite, nos vemos en diaspora*" + services_explanation: "Conectar con otros servicios te ofrece la posibilidad de publicar tus posts a medida que los escribes en diaspora*." + share_to: "Compartir con %{provider}" + title: "Gestionar servicios conectados" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "Invitar" - not_on_diaspora: "TodavÃa no está en diaspora*" - resend: "Reenviar" settings: "Configuración" - share_visibilites: - update: - post_hidden_and_muted: "La publicación de %{name} ha sido ocultada y sus notificaciones desactivadas." - see_it_on_their_profile: "Si querés ver actualizaciones sobre esta publicación, visitá la página de perfil de %{name}." shared: - add_contact: - add_new_contact: "Añadir contacto" - create_request: "Encontrar por el ID de diaspora*" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Ingresá el nombre de usuario de diaspora*:" - know_email: "¿Conocés sus direcciones de correo? ¡Podés invitarlos a unirse!" - your_diaspora_username_is: "Tu nombre de usuario de diaspora* es: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Añadir contacto" mobile_row_checked: "%{name} (eliminar)" mobile_row_unchecked: "%{name} (agregar)" toggle: one: "En %{count} aspecto" other: "En %{count} aspectos" - zero: "Añadir contacto" - contact_list: - all_contacts: "Todos los contactos" - footer: - logged_in_as: "Conectado como %{name}" - your_aspects: "Tus aspectos" + zero: "En %{count} aspectos" invitations: by_email: "VÃa correo electrónico" - dont_have_now: "No tenés ninguna invitación por ahora, pero ¡pronto tendrás más!" - from_facebook: "Desde Facebook" - invitations_left: "quedan %{count}" - invite_someone: "Invitá a alguien" invite_your_friends: "Invitá a tus contactos" invites: "Invitaciones" - invites_closed: "Las invitaciones en este servidor diaspora* están cerradas actualmente" share_this: "¡Comparte este enlace a través de correo electrónico, blog o tu red social favorita!" - notification: - new: "Nueva %{type} de %{from}" public_explain: atom_feed: "canal Atom" control_your_audience: "Controlá tu audiencia" @@ -1169,12 +1032,9 @@ es-AR: title: "Gestioná los servicios conectados" visibility_dropdown: "Usa este menú para cambiar la visibilidad de tu publicación. (Sugerimos hacer público el primero.)" publisher: - all: "Todo" - all_contacts: "Todos los contactos" discard_post: "Descartar publicación" formatWithMarkdown: "Puedes usar %{markdown_link} para darle formato a tu publicación" get_location: "Obtener tu ubicación" - make_public: "Hacer público" new_user_prefill: hello: "#%{new_user_tag}, acabo de llegar aquÃ." i_like: " Tengo interés en %{tags}." @@ -1182,36 +1042,14 @@ es-AR: newhere: "Hola" poll: add_a_poll: "Crear una encuesta" - add_poll_answer: "Añadir opción" - option: "Opción 1" - question: "Pregunta" - remove_poll_answer: "Quitar opción" - post_a_message_to: "Publicar un mensaje en %{aspect}" posting: "Publicando..." - preview: "Vista previa" - publishing_to: "Publicar en: " remove_location: "Eliminar ubicación" share: "Compartir" - share_with: "Compartir con" upload_photos: "Subir fotos" whats_on_your_mind: "¿Qué tenés en mente?" - reshare: - reshare: "Compartir" stream_element: - connect_to_comment: "Conecta con este usuario para comentar en su publicación" - currently_unavailable: "Comentar no está actualmente disponible" - dislike: "Me disgusta" - hide_and_mute: "Ignorar la publicación" - ignore_user: "Ignorar a %{name}" - ignore_user_description: "¿Ignorar y quitar al usuario de todos los aspectos?" - like: "Me gusta" - nsfw: "Esta publicación ha sido marcada por su autor como no apta para todo público. %{link}" - shared_with: "Compartido con: %{aspect_names}" - show: "Mostrar" - unlike: "No me gusta" via: "A través de %{link}" via_mobile: "Desde el celular" - viewable_to_anyone: "Esta publicación puede ser vista por cualquiera en la web" simple_captcha: label: "Ingresa el código en el recuadro de abajo" message: @@ -1237,24 +1075,12 @@ es-AR: status_messages: create: success: "Se mencionó a: %{names}" - destroy: - failure: "No pudo eliminarse la publicación" - helper: - no_message_to_display: "No hay mensajes que mostrar." new: mentioning: "Mencionar a: %{person}" too_long: "Por favor haz que tu mensaje de estado tenga menos de %{count} caracteres. En este momento el máximo permitido es de %{current_length} caracteres." stream_helper: - hide_comments: "Ocultar comentarios" no_more_posts: "No hay más posts, llegaste al final de la \"Entrada\"." no_posts_yet: "TodavÃa no hay publicaciones." - show_comments: - few: "Mostrar %{count} comentarios más" - many: "Mostrar %{count} comentarios más" - one: "Mostrar 1 comentario más" - other: "Mostrar %{count} comentarios más" - two: "Mostrar 2 comentarios más" - zero: "No hay más comentarios" streams: activity: title: "Mi actividad" @@ -1281,13 +1107,6 @@ es-AR: tags: title: "Mensajes tagueados: %{tags}" tag_followings: - create: - failure: "No has podido seguir a #%{name}. Tal vez ya lo hagas..." - none: "No se puedes seguir una etiqueta en blanco!" - success: "¡Bien ahÃ! Ahora estás siguiendo a #%{name}." - destroy: - failure: "No has podido dejar de seguir a: #%{name}. Tal vez ya lo hiciste..." - success: "¡Epa! Dejaste de seguir a #%{name}." manage: no_tags: "No estás siguiendo ninguna etiqueta." title: "Administrar las etiquetas que sigues" @@ -1295,15 +1114,12 @@ es-AR: name_too_long: "Por favor haz que el nombre de la etiqueta tenga menos de %{count} caracteres. En este momento el máximo permitido es de %{current_length} caracteres." show: follow: "Seguir #%{tag}" - following: "Siguiendo #%{tag}" none: "La etiqueta en blanco no existe!" stop_following: "Dejar de seguir #%{tag}" tagged_people: one: "1 persona etiquetada con %{tag}" other: "%{count} personas etiquetadas con %{tag}" zero: "Ninguna persona etiquetada con %{tag}" - terms_and_conditions: "Términos y Condiciones" - undo: "¿Deshacer?" username: "Nombre de usuario" users: confirm_email: @@ -1318,13 +1134,13 @@ es-AR: auto_follow_aspect: "Selecciona el aspecto al que se incluirán los usuarios que sigues automáticamente:" auto_follow_back: "Seguir automáticamente a los usuarios que te sigan" change: "Cambiar" + change_color_theme: "Cambiar el color del tema" change_email: "Cambiar E-Mail" change_language: "Cambiar idioma" change_password: "Cambiar contraseña" character_minimum_expl: "debe tener al menos seis caracteres" close_account: dont_go: "Hey, ¡por favor no te vayas!" - if_you_want_this: "Si realmente es lo que deseás, ingresá tu contraseña debajo y pulsá «Eliminar cuenta»." lock_username: "Tu nombre de usuario se ha bloqueado. No será posible crear una nueva cuenta con el mismo ID en este pod." locked_out: "Se cerrará tu sesión y serás bloqueado hasta que tu cuenta sea eliminada." make_diaspora_better: "Nos encantarÃa que te quedes y que nos ayudes a mejorar diaspora*. Pero, si en verdad querés irte, ésto es lo que va a suceder a continuación:" @@ -1337,14 +1153,12 @@ es-AR: current_password_expl: "con la que inicias sesión…" download_export: "Descargar mi perfil" download_export_photos: "Descargar mis fotos" - download_photos: "Descargar mis fotos" edit_account: "Editar cuenta" email_awaiting_confirmation: "Te hemos enviado un link de activación a %{unconfirmed_email}. Hasta que sigas este link y actives la nueva dirección, continuaremos utilizando tu dirección original %{email}." export_data: "Exportar datos" export_in_progress: "En este momento estamos procesando tus datos. Por favor regresa en unos minutos." export_photos_in_progress: "En este momento estamos procesando tus fotos. Por favor vuelve a chequear en unos minutos." following: "Opciones de seguimiento" - getting_started: "Preferencias de Nuevos Usuarios" last_exported_at: "(Última actualización en %{timestamp})" liked: "...a alguien le gusta una publicación tuya?" mentioned: "...te mencionan en una publicación?" @@ -1371,19 +1185,20 @@ es-AR: connect_to_facebook_link: "Conectando tu cuenta de Facebook" hashtag_explanation: "Las etiquetas te permiten seguir y hablar sobre tus intereses. También son una gran manera de encontrar gente interesante y divertida en diaspora*." hashtag_suggestions: "Probá siguiendo tags como #arte, #pelÃculas, #activismo, #geek." - saved: "¡Guardado!" well_hello_there: "Bueno, ¡hola!" what_are_you_in_to: "¿Qué sos por dentro?" who_are_you: "¿Quién sos?" privacy_settings: ignored_users: "Usuarios ignorados" no_user_ignored_message: "En este momento no estás ignorando a ningún otro usuario" - stop_ignoring: "dejar de ignorar" + stop_ignoring: "Dejar de ignorar" strip_exif: "Evita metadatos como la ubicación, autor y modelo de cámara de fotos en las imágenes subidas (recomendado)" title: "Configuración de Privacidad" public: does_not_exist: "¡El usuariuo %{username} no existe!" update: + color_theme_changed: "Se cambió correctamente el color del tema." + color_theme_not_changed: "Ha ocurrido un error cambiando el color del tema." email_notifications_changed: "Tus notificaciones por correo fueron cambiadas" follow_settings_changed: "La configuración de seguimiento se cambió" follow_settings_not_changed: "Error al cambiar la configuración de seguimiento." @@ -1395,13 +1210,6 @@ es-AR: settings_updated: "Configuración actualizada" unconfirmed_email_changed: "E-Mail Cambiado. Activación necesaria." unconfirmed_email_not_changed: "El cambio de E-Mail fallo" - webfinger: - fetch_failed: "No pudo encontrarse el perfil webfinger de %{profile_url}" - hcard_fetch_failed: "Hubo un problema al buscar el \"hcard\" de %{account}" - no_person_constructed: "No pudo crearse ninguna persona a partir de esta 'hcard'." - not_enabled: "Parece que webfinger no está habilitado para el servidor de %{account}" - xrd_fetch_failed: "Hubo un error al buscar el \"xrd\" de %{account}" - welcome: "¡Bienvenido!" will_paginate: next_label: "siguiente »" previous_label: "« anterior" \ No newline at end of file diff --git a/config/locales/diaspora/es-BO.yml b/config/locales/diaspora/es-BO.yml index 4da55c3ab6b81283309e4a479c460c5a9edc0264..47048b491bfa2a497f95f0130d2f00d7bd1e62d0 100644 --- a/config/locales/diaspora/es-BO.yml +++ b/config/locales/diaspora/es-BO.yml @@ -6,10 +6,7 @@ es-BO: _applications: "Aplicaciones" - _comments: "Comentarios" _contacts: "Contactos" - _home: "Inicio" - _photos: "Fotos" _services: "Servicios" account: "Cuenta" activerecord: @@ -40,13 +37,7 @@ es-BO: username: invalid: "no es válido. Solo se permiten letras, números y guiones bajos." taken: "ya esta siendo usado" - ago: "hace %{time}" all_aspects: "Todos los aspectos" - application: - helper: - unknown_person: "persona desconocida" - video_title: - unknown: "TÃtulo de video desconocido" are_you_sure: "¿Estás seguro/a?" are_you_sure_delete_account: "¿Estás seguro/a de que quieres cerrar tu cuenta? ¡Esto no se puede deshacer!" aspects: @@ -55,14 +46,6 @@ es-BO: success: "Contacto añadido exitosamente al aspecto." aspect_listings: add_an_aspect: "+ Añadir un aspecto" - deselect_all: "Anular selección" - edit_aspect: "Editar %{name}" - select_all: "Seleccionar todo" - contacts_not_visible: "Los contactos en este aspecto no podrán verse entre ellos." - contacts_visible: "Los contactos en este aspecto podrán verse entre ellos." - create: - failure: "Error al crear el aspecto." - success: "Tu nuevo aspecto %{name} ha sido creado" destroy: failure: "%{name} no esta vacio y no pudo ser eliminado." success: "%{name} ha sido eliminado con éxito." @@ -70,30 +53,17 @@ es-BO: aspect_list_is_not_visible: "la lista de aspectos está oculta a otros en este aspecto" aspect_list_is_visible: "la lista de contactos del aspecto es visible" confirm_remove_aspect: "¿Estás seguro de que quieres eliminar este aspecto?" - make_aspect_list_visible: "¿hacer que los contactos en este aspecto puedan verse entre ellos?" - remove_aspect: "Eliminar este aspecto" rename: "Cambiar nombre" update: "actualizar" updating: "actualizando" index: donate: "Donar" - handle_explanation: "Esta es tu dirección de Diaspora. Como una dirección de correo electrónico, puedes dársela a la gente para que te encuentre." - no_contacts: "No hay contactos" - no_tags: "+ Encuentra una etiqueta para seguir" - people_sharing_with_you: "Personas que comparten contigo" - post_a_message: "publica un mensaje >>" - unfollow_tag: "Dejar de seguir #%{tag}" welcome_to_diaspora: "Bienvenido a Diaspora, %{name}!" - new: - create: "Crear" - name: "Nombre (solo es visible para tÃ)" no_contacts_message: community_spotlight: "lo más destacado de la comunidad" or_spotlight: "o puedes compartir con %{link}" try_adding_some_more_contacts: "Puedes buscar o invitar a más contactos." you_should_add_some_more_contacts: "¡DeberÃas añadir algunos contactos!" - no_posts_message: - start_talking: "¡Nadie ha dicho nada aún!" seed: acquaintances: "Conocidos" family: "Familia" @@ -102,34 +72,22 @@ es-BO: update: failure: "Tu aspecto, %{name}, tiene un nombre muy largo para ser guardado." success: "Tu aspecto %{name}, ha sido editado con éxito." - back: "atrás" cancel: "Cancelar" delete: "Borrar" email: "correo electrónico" error_messages: helper: correct_the_following_errors_and_try_again: "Corrige los siguientes errores e inténtalo de nuevo." - invalid_fields: "Campos inválidos" fill_me_out: "Complétame" find_people: "Encontrar personas o #tags" - hide: "Ocultar" limited: "Limitado" more: "Más" - next: "Siguiente" no_results: "No hay resultados" nsfw: "No apto para todo público" ok: "Aceptar" - or: "o" - password: "Contraseña" - password_confirmation: "Confirmación de contraseña" - previous: "Anterior" privacy: "privacidad" - privacy_policy: "PolÃtica de privacidad" profile: "Perfil" public: "público\n" search: "Búsqueda" settings: "configuración" - terms_and_conditions: "Términos y condiciones" - undo: "¿Deshacer?" - username: "Nombre de usuario" - welcome: "¡Bienvenido/a!" \ No newline at end of file + username: "Nombre de usuario" \ No newline at end of file diff --git a/config/locales/diaspora/es-CL.yml b/config/locales/diaspora/es-CL.yml index f4e663ca5065006cae6d8be5b5080ffa91e8f47b..5c69fb5089e3bdbb739a50b7435c1206c3b342f2 100644 --- a/config/locales/diaspora/es-CL.yml +++ b/config/locales/diaspora/es-CL.yml @@ -6,11 +6,8 @@ es-CL: _applications: "Aplicaciones" - _comments: "Comentarios" _contacts: "Contactos" _help: "Ayuda" - _home: "Inicio" - _photos: "fotos" _services: "Servicios" account: "Cuenta" activerecord: @@ -91,13 +88,7 @@ es-CL: other: "Número de usuarios esta semana: %{count} usuarios" zero: "Número de usuarios esta semana: ninguno" current_server: "La fecha actual del servidor es %{date}" - ago: "hace %{time}" all_aspects: "Todos los Aspectos" - application: - helper: - unknown_person: "persona desconocida" - video_title: - unknown: "Titulo de vÃdeo desconocido" are_you_sure: "¿Estás seguro?" are_you_sure_delete_account: "¿Estás seguro de que quieres cerrar tu cuenta? ¡Esto no se puede deshacer!" aspect_memberships: @@ -111,18 +102,10 @@ es-CL: success: "Contacto agregado correctamente al aspecto." aspect_listings: add_an_aspect: "+ Añadir un aspecto" - deselect_all: "Desmarcar todo" - edit_aspect: "Editar %{name}" - select_all: "Marcar todo" aspect_stream: make_something: "Haz algo" stay_updated: "Mantente Actualizado" stay_updated_explanation: "Tu corriente principal está llena con todos tus contactos, tags que sigues, y posts de algunos miembros creativos de la comunidad." - contacts_not_visible: "Los contactos en este Aspecto no se podrán ver entre ellos." - contacts_visible: "Los contactos en este Aspecto se podrán ver entre ellos." - create: - failure: "Error al crear el aspecto." - success: "Tu nuevo aspecto %{name} fué creado" destroy: failure: "El aspecto %{name} no esta vacÃo y no se puede eliminar." success: "%{name} fue correctamente eliminado." @@ -130,24 +113,15 @@ es-CL: aspect_list_is_not_visible: "Lista de contactos oculta para los demás en el Aspecto" aspect_list_is_visible: "Lista de contactos visible para los demás en el Aspecto" confirm_remove_aspect: "¿Estás seguro que quieres eliminar este aspecto?" - make_aspect_list_visible: "hacer visible el aspecto?" - remove_aspect: "Eliminar este aspecto" rename: "renombrar" update: "Actualizar" updating: "actualizando" index: - diaspora_id: - content_1: "Tu ID de Diaspora es:" - content_2: "Daselo a quien quieras y podrán encontrarte en Diaspora." - heading: "ID de Diaspora " donate: "Donar" - handle_explanation: "Este es tu ID de Diaspora. Como una dirección de correo, puedes dársela a la gente para que te encuentren." help: any_problem: "¿Algún problema?" contact_podmin: "Contacta al administrador de tu servidor!" do_you: "Acaso tu:" - email_feedback: "Si lo prefieres envÃanos un %{link} con tu opinión" - email_link: "Correo Electrónico" feature_suggestion: "... tienes una %{link}?" find_a_bug: "... encontraste errores (%{link})?" have_a_question: "... tienes una %{link}?" @@ -160,31 +134,20 @@ es-CL: tutorial_link_text: "Tutoriales" tutorials_and_wiki: "%{tutorial} y %{wiki}: Ayuda para tus primeros pasos en diaspora*." introduce_yourself: "Esta es tu corriente. Entra y preséntate." - keep_diaspora_running: "¡Haz que el desarrollo de Diaspora vaya más rápido con una donación mensual!" keep_pod_running: "¡Haz que %{pod} siga siendo rápido, y compra a nuestros administradores su dosis de café con una donación mensual!" new_here: follow: "Sigue %{link} y bienvenido nuevo usuario de Diaspora*!" learn_more: "Aprende más" title: "Bienvenidos Nuevos Usuarios" - no_contacts: "No hay contactos" - no_tags: "+ Busca un tag para seguir" - people_sharing_with_you: "Personas compartiendo contigo" - post_a_message: "postea un mensaje >>" services: content: "Puedes enlazar los siguientes servicios a Diaspora:" heading: "Servicios que puedes enlazar" - unfollow_tag: "Dejar de seguir #%{tag}" welcome_to_diaspora: "Bienvenido a Diaspora, %{name}!" - new: - create: "Crear" - name: "Nombre(solo visible para ti)" no_contacts_message: community_spotlight: "foco de atención de la comunidad" or_spotlight: "O puedes compartir con %{link}" try_adding_some_more_contacts: "Puedes buscar o invitar a más contactos." you_should_add_some_more_contacts: "DeberÃas añadir mas contactos!" - no_posts_message: - start_talking: "Nadie ha dicho nada aún!" seed: acquaintances: "Conocidos" family: "Familia" @@ -193,7 +156,6 @@ es-CL: update: failure: "Tu aspecto, %{name}, tenÃa el nombre muy largo para ser guardado." success: "Tu aspecto, %{name}, ha sido correctamente editado." - back: "Atrás" blocks: create: failure: "No pude ignorar ese usuario. #evasión" @@ -205,21 +167,14 @@ es-CL: explanation: "%{link} donde sea agregando a marcadores este link." heading: "Diaspora en tus marcadores" post_something: "Publica algo en Diaspora" - post_success: "Posteado! Cerrando!" cancel: "Cancelar" comments: new_comment: comment: "Comentar" commenting: "Comentando..." - one: "1 comentario" - other: "%{count} comentarios" - zero: "no hay comentarios" contacts: - create: - failure: "Error al crear contacto" index: add_a_new_aspect: "Agregar un nuevo aspecto" - add_to_aspect: "Añadir contactos a %{name}" all_contacts: "Todos los Contactos" community_spotlight: "Comunidad Creativa" my_contacts: "Mis Contactos" @@ -228,33 +183,19 @@ es-CL: only_sharing_with_me: "Solo compartiendo conmigo" start_a_conversation: "Comenzar una conversación" title: "Contactos" - your_contacts: "Tus Contactos" - sharing: - people_sharing: "Personas compartiendo contigo:" spotlight: community_spotlight: "Comunidad Creativa" + no_members: "TodavÃa no hay usuarios." suggest_member: "Sugiere un usuario" conversations: - conversation: - participants: "Participantes" create: fail: "Mensaje invalido" no_contact: "¡Tranquilo, primero tienes que añadir el contacto!" sent: "Mensaje enviado" - helper: - new_messages: - few: "%{count} nuevos mensajes" - many: "%{count} nuevos mensajes" - one: "1 nuevo mensaje" - other: "%{count} nuevos mensajes" - two: "%{count} nuevos mensajes" - zero: "sin nuevos mensajes" index: inbox: "Buzón de Entrada" - no_conversation_selected: "ninguna conversación seleccionada" no_messages: "Sin mensajes" new: - abandon_changes: "Descartar los cambios?" send: "Enviar" sending: "Enviando..." subject: "asunto" @@ -273,9 +214,6 @@ es-CL: error_messages: helper: correct_the_following_errors_and_try_again: "Corrige los siguientes errores e inténtalo de nuevo." - invalid_fields: "Campos Inválidos" - login_try_again: "Por favor <a href='%{login_link}'>accede</a> e intenta de nuevo." - post_not_public: "¡La publicación que estás tratando de ver no es pública!" fill_me_out: "Complétame" find_people: "Buscar personas o #tags" help: @@ -430,44 +368,27 @@ es-CL: tutorial: "tutorial" tutorials: "tutoriales" wiki: "Wiki" - hide: "Ocultar" - invitation_codes: - excited: "%{name} está emocionado(a) por verte aquÃ." invitations: a_facebook_user: "Un usuario de Facebook" check_token: not_found: "Identificación de invitación no encontrada" create: - already_contacts: "Ya estás conectado con esta persona" - already_sent: "Ya has invitado a esta persona." empty: "Por favor ingresa al menos una dirección de correo electrónico." no_more: "No tienes más invitaciones." note_already_sent: "Las invitaciones han sido enviadas a: %{emails}" - own_address: "No puedes enviar una invitación a tu email." rejected: "Las siguientes direcciones de correo han tenido problemas:" sent: "Las invitaciones han sido enviadas a: %{emails}" - edit: - accept_your_invitation: "Acepta tu invitación" - your_account_awaits: "Tu cuenta te espera!" new: - already_invited: "Las siguientes personas no aceptaron tu invitación:" - aspect: "Aspecto" - check_out_diaspora: "¡Échale un vistazo a Diaspora!" codes_left: one: "Quedan %{count} invitaciones disponibles con este código" other: "Quedan %{count} invitaciones disponibles con este código" zero: "Queda una invitación disponible con este código" comma_separated_plz: "Puedes introducir múltiples direcciones de correo electrónico separadas por comas." - if_they_accept_info: "Si aceptan, ellos se agregarán al aspecto que los invitaste." invite_someone_to_join: "¡Invita a alguien a unirse a Diaspora!" language: "Idioma" paste_link: "Comparte este enlace con tus amigos para invitarlos a Diaspora*, o envÃales el enlace directamente por correo electrónico." - personal_message: "Mensaje personal" - resend: "Reenviar" send_an_invitation: "Enviar una invitación" - send_invitation: "Enviar invitación" sending_invitation: "Enviando invitación…" - to: "A" layouts: application: back_to_top: "Volver al principio" @@ -476,34 +397,13 @@ es-CL: source_package: "descargar paquete de código fuente" toggle: "cambiar sitio móvil" whats_new: "¿Qué hay de nuevo?" - your_aspects: "Tus Aspectos" header: - admin: "administrar" - blog: "blog" code: "codigo" - login: "entrar" logout: "Salir" profile: "Perfil" - recent_notifications: "Notificaciones recientes" settings: "Configuración" - view_all: "Ver todo" - likes: - likes: - people_dislike_this: - one: "a 1 persona no le gusta esto" - other: "a %{count} personas no les gusta esto" - zero: "a ninguna persona le disgusta esto" - people_like_this: - one: "a %{count} persona le gusta esto" - other: "a %{count} personas les gusta esto" - zero: "a nadie le gusta esto aun" - people_like_this_comment: - one: "a %{count} persona le gusta esto" - other: "a %{count} personas les gusta esto" - zero: "a nadie le gusta esto aun" limited: "Restringido" more: "Más" - next: "Siguiente" no_results: "No se encontraron resultados" notifications: also_commented: @@ -521,14 +421,6 @@ es-CL: one: "%{actors} comentó en tu %{post_link}." other: "%{actors} comentaron en tu %{post_link}." zero: "%{actors} ha comentado en tu %{post_link}." - helper: - new_notifications: - few: "%{count} nuevas notificaciones" - many: "%{count} nuevas notificaciones" - one: "1 nueva notificación" - other: "%{count} nuevas notificaciones" - two: "%{count} nuevas notificaciones" - zero: "sin nuevas notificaciones" index: and: "y" and_others: @@ -591,7 +483,6 @@ es-CL: zero: "%{actors} está compartiendo contigo." notifier: a_post_you_shared: "un post." - accept_invite: "¡Acepta tu invitación a Diaspora*!" click_here: "haz click aquÃ" comment_on_post: reply: "Responde o mira el post de %{name}>" @@ -619,10 +510,10 @@ es-CL: liked: "A %{name} le gustó tu post" view_post: "Ver post >" mentioned: - mentioned: "Te mencionó en un post:" subject: "%{name} te mencionó en Diaspora*" private_message: reply_to_or_view: "Responder o ver esta conversación >" + subject: "Hay un nuevo mensaje privado para ti" reshared: reshared: "%{name} compartió tu post" view_post: "Ver el post >" @@ -637,106 +528,45 @@ es-CL: to_change_your_notification_settings: "para cambiar tu configuración de notificaciones" nsfw: "No apto para todo público" ok: "OK" - or: "o" - password: "Contraseña" - password_confirmation: "Confirmar contraseña" people: add_contact: invited_by: "fuiste invitado por" - add_contact_small: - add_contact_from_tag: "agrega un contacto desde una etiqueta" - aspect_list: - edit_membership: "Editar el Aspecto donde está el contacto" - helper: - is_not_sharing: "%{name} no está compartiendo contigo" - is_sharing: "%{name} está compartiendo contigo" - results_for: "resultados para %{params}" index: looking_for: "Buscando post etiquetados con %{tag_link}?" no_one_found: "...y nadie fue encontrado." no_results: "¡Oye! Tienes que buscar algo." results_for: "resultados de búsqueda para" searching: "Buscando, por favor sé paciente..." - one: "1 persona" - other: "%{count} personas" person: - add_contact: "agregar contacto" - already_connected: "Ya conectado" - pending_request: "Solicitud pendiente" thats_you: "¡Ese eres tú!" profile_sidebar: bio: "BiografÃa" born: "Cumpleaños" - edit_my_profile: "Editar mi perfil" gender: "Género" - in_aspects: "en aspectos" location: "Ubicación" - photos: "Fotos" - remove_contact: "eliminar contacto" - remove_from: "¿Eliminar a %{name} de %{aspect}?" show: closed_account: "Esta cuenta ha sido cerrada." does_not_exist: "¡La persona no existe!" has_not_shared_with_you_yet: "%{name} todavÃa no ha compartido ningún post contigo!" - ignoring: "Estas ignorando todos los post de %{name}." - incoming_request: "Tienes una solicitud pendiente de %{name}" - mention: "Mencionar" - message: "Mensaje" - not_connected: "No estás conectado con esa persona" - recent_posts: "Posteos Recientes" - recent_public_posts: "Posteos Públicos Recientes" - return_to_aspects: "Volver a tu página de aspectos" - see_all: "Ver todos" - start_sharing: "Empezar a compartir" - to_accept_or_ignore: "aceptar o ignorar." - sub_header: - add_some: "Agrega algunos" - edit: "editar" - you_have_no_tags: "No tienes ningún tag!" - webfinger: - fail: "Lo siento, no pudimos encontrar %{handle}." - zero: "ninguna persona" photos: - comment_email_subject: "foto de %{name}" create: integrity_error: "Error al subir la foto. ¿Estás seguro que eso era una imagen?" runtime_error: "Error al subir la foto. ¿Estás seguro que tienes puesto el cinturon de seguridad?" type_error: "Error al subir la foto. ¿Estás seguro que agregaste una imagen?" destroy: notice: "Foto eliminada." - edit: - editing: "Editando" - new: - back_to_list: "Volver a la lista" - new_photo: "Nueva Foto" - post_it: "¡postéalo!" new_photo: empty: "{file} está vacÃo, por favor, seleccione los archivos nuevamente sin éste último" invalid_ext: "{file} tiene una extensión no válida. Solo están permitidas {extensions}." size_error: "{file} es demasiado grande, el tamaño máximo por archivo es {sizeLimit}." new_profile_photo: - or_select_one_existing: "o selecciona una de las fotos(%{photos}) existentes" upload: "¡Sube una nueva foto de perfil!" - photo: - view_all: "ver todas las fotos de %{name}" show: - collection_permalink: "enlace permanente a la colección" - delete_photo: "Borrar Foto" - edit: "editar" - edit_delete_photo: "Editar descripción de foto / borrar foto" - make_profile_photo: "convertir en foto de perfil" show_original_post: "Mostrar post original" - update_photo: "Actualizar Foto" - update: - error: "Error al editar foto." - notice: "Foto actualizada correctamente." posts: presenter: title: "Una publicación de %{name}" show: - destroy: "ELiminar" - not_found: "Lo sentimos, no pudimos encontrar ese post." - permalink: "permalink" photos_by: few: "%{count} photos by %{author}" many: "%{count} photos by %{author}" @@ -745,14 +575,11 @@ es-CL: two: "Two photos by %{author}" zero: "No photos by %{author}" reshare_by: "Compartido por %{author}" - previous: "Anterior" privacy: "Privacidad" - privacy_policy: "PolÃtica de Privacidad" profile: "Perfil" profiles: edit: allow_search: "Permitir que la gente te busque dentro de Diaspora" - edit_profile: "Editar perfil" first_name: "Nombre" last_name: "Apellido" update_profile: "Actualizar perfil" @@ -762,8 +589,6 @@ es-CL: your_location: "Tú ubicación" your_name: "Tu nombre" your_photo: "Tu foto" - your_private_profile: "Tú perfil privado" - your_public_profile: "Tú perfil publico" your_tags: "Describite en 5 palabras" your_tags_placeholder: "como #peliculas #carrete #gatitos #viajes #profesora" update: @@ -781,65 +606,23 @@ es-CL: closed: "Los registros están cerrados en este servidor de Diaspora." create: success: "¡Te has unido a Diaspora!" - edit: - cancel_my_account: "Cerrar mi cuenta" - edit: "Editar %{name}" - leave_blank: "(déjalo en blanco si no quieres cambiarlo)" - password_to_confirm: "(necesitamos tu contraseña actual para confirmar los cambios)" - unhappy: "¿Triste?" - update: "Actualizar" invalid_invite: "¡El enlace de invitación ya no es válido!" new: - create_my_account: "¡Crear mi cuenta!" email: "Correo Electrónico" enter_email: "Ingresa un email" enter_password: "Ingresar contraseña" enter_password_again: "Ingresa la misma contraseña anterior" enter_username: "Escoge un nick (solo letras, números, y guión bajo)" - join_the_movement: "Unete al movimiento!" password: "Contraseña" password_confirmation: "Confirme Contraseña" sign_up: "RegÃstrate" - sign_up_message: "Redes Sociales con un ♥" username: "Nombre de usuario" - requests: - create: - sending: "Enviando" - sent: "Has pedido compartir con %{name}. Ellos deberÃan ver esto la próxima vez que entren a Diaspora." - destroy: - error: "¡Por favor selecciona un aspecto!" - ignore: "Ignorar la solicitud de contacto." - success: "Ahora estás compartiendo." - helper: - new_requests: - few: "%{count} nuevas solicitudes!" - many: "%{count} nuevas solicitudes!" - one: "nueva solicitud!" - other: "%{count} nuevas solicitudes!" - two: "%{count} nuevas solicitudes!" - zero: "sin nuevas solicitudes" - manage_aspect_contacts: - existing: "Los contactos existen" - manage_within: "Manejar los contactos en" - new_request_to_person: - sent: "¡enviado!" reshares: comment_email_subject: "%{resharer} compartió el post de %{author}" - create: - failure: "Hubo un error al compartir este post." reshare: deleted: "Post original eliminado por el autor." - reshare: - few: "Se ha compartido %{count} veces" - many: "Se ha compartido %{count} veces" - one: "Se ha compartido 1 vez" - other: "Se ha compartido %{count} veces" - two: "se ha compartido %{count} veces" - zero: "Compartir" reshare_confirmation: "Compartir el post de %{author}? " - reshare_original: "Compartir el original" reshared_via: "Compartido vÃa" - show_original: "Mostrar Original" search: "Buscar" services: create: @@ -851,38 +634,15 @@ es-CL: success: "Autenticación eliminada correctamente." failure: error: "ocurrió un error al conectarse con ese servicio" - finder: - fetching_contacts: "Diaspora se está llenando de tus amigos de %{service} por favor regresa en unos minutos." - no_friends: "Ningún amigo de Facebook encontrado." - service_friends: "Contactos de %{service}" index: disconnect: "desconectar" edit_services: "Editar servicios" logged_in_as: "has entrado como" really_disconnect: "¿desconectar %{service}?" services_explanation: "Conectando otros servicios tendrás la posibilidad de publicar tus mensajes en ellos a medida que los escribes en diaspora." - inviter: - click_link_to_accept_invitation: "Haz click en este enlace para aceptar tu invitación" - join_me_on_diaspora: "Únete a mi en DIASPORA*" - remote_friend: - invite: "invitar" - not_on_diaspora: "Aun no en Diaspora" - resend: "reenviar" settings: "Configuración" - share_visibilites: - update: - post_hidden_and_muted: "Los post de %{name} se han escondido, y las notificaciones se han silenciado." - see_it_on_their_profile: "Si quieres ver las actualizaciones en este post, visita la página de perfil de %{name}." shared: - add_contact: - add_new_contact: "Agregar un nuevo contacto" - create_request: "Encontrar por el ID de Diaspora" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Ingresa tu nombre de usuario Diaspora:" - know_email: "¿Conoces sus direcciones de correo? DeberÃas invitarlos" - your_diaspora_username_is: "Tu nombre de usuario Diaspora es: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Agregar contacto" toggle: few: "En %{count} aspectos" many: "En %{count} aspectos" @@ -890,23 +650,11 @@ es-CL: other: "En %{count} aspectos" two: "En %{count} aspectos" zero: "Agregar contacto" - contact_list: - all_contacts: "Todos los contactos" - footer: - logged_in_as: "Conectado como %{name}" - your_aspects: "Tus Aspectos" invitations: by_email: "Por email" - dont_have_now: "No tienes ninguna ahora, ¡pero pronto vendrán mas invitaciones!" - from_facebook: "Desde Facebook" - invitations_left: "quedan %{count}" - invite_someone: "Invita a alguien" invite_your_friends: "Invita a tus contactos" invites: "Invitaciones" - invites_closed: "Las invitaciones están temporalmente cerradas en este servidor de Diaspora" share_this: "¡Compartir este enlace a través de email, blog o red social favorita!" - notification: - new: "Nuevo %{type} de %{from}" public_explain: atom_feed: "canal Atom" control_your_audience: "Controla tu público" @@ -918,60 +666,26 @@ es-CL: title: "Configurar los servicios conectados" visibility_dropdown: "Usa este menú desplegable para cambiar la visibilidad de tu post. (Te sugerimos hacer el primer post público.)" publisher: - all: "todo" - all_contacts: "todos los contactos" discard_post: "Descartar post" get_location: "Obtener tu ubicación" - make_public: "hacer público" new_user_prefill: hello: "#%{new_user_tag}, acabo de llegar aquÃ." i_like: " Tengo interés en %{tags}." invited_by: "Gracias por la invitación," newhere: "Hola" - post_a_message_to: "Postear un mensaje a %{aspect}" posting: "Posteando..." - preview: "Vista previa" - publishing_to: "publicar en: " share: "Compartir" - share_with: "Compartir con " upload_photos: "Subir fotos" whats_on_your_mind: "¿Que pasa por tu cabeza?" - reshare: - reshare: "Compartir de nuevo" stream_element: - connect_to_comment: "Conéctate con este usuario para comentar en sus post" - currently_unavailable: "comentarios actualmente inaccesibles" - dislike: "No me gusta esto" - hide_and_mute: "Ignorar este post" - ignore_user: "Ignorar a %{name}" - ignore_user_description: "Ignorar y remover al usuario de todos tus aspectos?" - like: "Me gusta esto" - nsfw: "Esta publicación ha sido marcada por su autor como no apta para todo público. %{link}" - shared_with: "Compartir con: %{aspect_names}" - show: "mostrar" - unlike: "No me gusta" via: "vÃa %{link}" via_mobile: "vÃa celular" - viewable_to_anyone: "Este post es visible para cualquiera en la web" status_messages: create: success: "Se ha mencionado con éxito a: %{names}" - destroy: - failure: "Error al eliminar el post" - helper: - no_message_to_display: "No hay mensaje que mostrar." new: mentioning: "Mencionar a: %{person}" too_long: "{\"few\"=>\"Tu mensaje de estado debe tener menos de %{count} caracteres\", \"many\"=>\"Tu mensaje de estado debe tener menos de %{count} caracteres\", \"one\"=>\"Tu mensaje de estado debe tener menos de %{count} caracter\", \"other\"=>\"Tu mensaje de estado debe tener menos de %{count} caracteres\", \"two\"=>\"tu mensaje de estado tiene que tener menos de %{count} caracteres\", \"zero\"=>\"Tu mensaje de estado debe tener menos de %{count} caracteres\"}" - stream_helper: - hide_comments: "ocultar todos los comentarios" - show_comments: - few: "Mostrar %{count} comentarios más" - many: "Mostrar %{count} comentarios más" - one: "Mostrar un comentario más" - other: "Mostrar %{count} comentarios más" - two: "Mostrar 2 comentarios más" - zero: "No más comentarios" streams: activity: title: "Mi Actividad" @@ -997,22 +711,11 @@ es-CL: title: "Actividad publica" tags: title: "Posts con el tag: %{tags}" - tag_followings: - create: - failure: "Error al seguir: #%{name}. Tal vez ya lo hiciste..." - none: "¡No puedes seguir una etiqueta vacÃa!" - success: "Bien, ahora sigues: #%{name}." - destroy: - failure: "Error al dejar de seguir: #%{name}. Tal vez ya lo hiciste..." - success: "Bien, ya no sigues más: #%{name}" tags: show: follow: "Seguir a #%{tag}" - following: "Siguiendo a #%{tag}" none: "¡La etiqueta vacÃa no existe!" stop_following: "Dejar de seguir a #%{tag}" - terms_and_conditions: "Términos y Condiciones" - undo: "Deshacer?" username: "Nombre de usuario" users: confirm_email: @@ -1033,7 +736,6 @@ es-CL: character_minimum_expl: "debe tener al menos seis caracteres" close_account: dont_go: "¡Oye, por favor no te vayas!" - if_you_want_this: "Si realmente es lo que deseas, ingresa tu contraseña debajo y pulsa «Eliminar cuenta»." lock_username: "Esto bloquerá tu nombre de usuario si decides volver a registrarte." locked_out: "Saldrás y bloquearás tu cuenta." make_diaspora_better: "Nos gustarÃa que nos ayudaras a hacer mejor a Diaspora, asà que deberÃas ayudarnos en vez de irte. Si de verdad quieres irte, queremos que sepas lo que se viene después." @@ -1044,12 +746,10 @@ es-CL: comment_on_post: "...alguien comenta en tu post?" current_password: "Contraseña actual" current_password_expl: "con la que inicias sesión…" - download_photos: "descargar mis fotos" edit_account: "Editar cuenta" email_awaiting_confirmation: "Te enviamos un link de activación a %{unconfirmed_email}. Hasta que sigas ese link y actives la nueva dirección, nosotros seguiremos usando tu dirección original %{email}." export_data: "Exportar Datos" following: "Ajustes de Seguimiento" - getting_started: "Preferencias del Nuevo Usuario" liked: "...a alguien le gusta tu post?" mentioned: "...te mencionan en un post?" new_password: "Nueva Contraseña" @@ -1069,7 +769,6 @@ es-CL: connect_to_facebook_link: "conectando a tu cuenta de Facebook" hashtag_explanation: "Los Hashtags te permiten hablar y seguir sobre tus intereses. También son una manera genial de encontrar nuevas personas en Diaspora." hashtag_suggestions: "Prueba siguiendo tags como #arte, #pelÃculas, #gif, etc." - saved: "Guardado!" well_hello_there: "Bueno, hola!" what_are_you_in_to: "En que estas?" who_are_you: "Quien eres tu?" @@ -1091,13 +790,6 @@ es-CL: settings_updated: "Configuración actualizada" unconfirmed_email_changed: "Se ha cambiado el email. Pero se requiere su activación." unconfirmed_email_not_changed: "Error al cambiar el email" - webfinger: - fetch_failed: "error al buscar el perfil webfinger para %{profile_url}" - hcard_fetch_failed: "hubo un problema buscando la hcard de %{account}" - no_person_constructed: "Ninguna persona puede ser construida a partir de ésta hcard" - not_enabled: "el webfinger parece no estar disponible para el host de %{account}" - xrd_fetch_failed: "hubo un error al recibir el crd desde la cuenta %{account}" - welcome: "Bienvenido!" will_paginate: next_label: "siguiente »" previous_label: "« anterior" \ No newline at end of file diff --git a/config/locales/diaspora/es-CO.yml b/config/locales/diaspora/es-CO.yml index 9cd1598a4418fd7c8650c5916c45f77e61b6134b..a2e2c11267368640778e77fe76bd7047dc1ad87e 100644 --- a/config/locales/diaspora/es-CO.yml +++ b/config/locales/diaspora/es-CO.yml @@ -6,10 +6,7 @@ es-CO: _applications: "Aplicaciones" - _comments: "Comentarios" _contacts: "Contactos" - _home: "Inicio" - _photos: "fotos" _services: "Servicios" account: "Cuenta" activerecord: @@ -40,13 +37,7 @@ es-CO: username: invalid: "no es válido. Solo se permiten letras, números y guiones bajos." taken: "ya está ocupado." - ago: "hace %{time}" all_aspects: "Todos los aspectos" - application: - helper: - unknown_person: "persona desconocida" - video_title: - unknown: "TÃtulo de video desconocido" are_you_sure: "¿Estas seguro/a?" are_you_sure_delete_account: "¿Estás seguro de que quieres cerrar tu cuenta? ¡Esto no se puede deshacer!" aspect_memberships: @@ -60,17 +51,9 @@ es-CO: success: "Contacto añadido exitosamente al aspecto." aspect_listings: add_an_aspect: "+ Añadir un aspecto" - deselect_all: "No seleccionar nada" - edit_aspect: "Editar %{name}" - select_all: "Seleccionar todo" aspect_stream: stay_updated: "Mantente actualizado" stay_updated_explanation: "Tu entrada principal esta formada por todos tus contactos, las etiquetas que sigues, y publicaciones de algunos miembros creativos de la comunidad." - contacts_not_visible: "Los contactos en este aspecto no podrán verse entre ellos." - contacts_visible: "Los contactos en este aspecto podrán verse entre ellos." - create: - failure: "Error al crear el aspecto." - success: "Tu nuevo aspecto %{name} fue creado" destroy: failure: "%{name} no está vacÃo y no puede ser eliminado." success: "%{name} fue eliminado exitosamente." @@ -78,21 +61,13 @@ es-CO: aspect_list_is_not_visible: "La lista de aspectos permanece oculta a los demás en este aspecto" aspect_list_is_visible: "La lista de aspectos es visible a los demás en este aspecto" confirm_remove_aspect: "¿Estás seguro que quieres eliminar este aspecto?" - make_aspect_list_visible: "¿Hacer visibles entre ellos a los contactos de este aspecto?" - remove_aspect: "Eliminar este aspecto" rename: "renombrar" update: "actualizar" updating: "actualizando" index: - diaspora_id: - content_1: "Tu ID de Diaspora es:" - content_2: "Dáselo a quien quieras y podrán encontrarte en Diaspora." - heading: "Tu ID de Diaspora" donate: "Donar" - handle_explanation: "Esta es tu dirección de Diaspora. Como una dirección de correo electrónico, puedes dársela a la gente para que te encuentre." help: do_you: "¿Tú:" - email_feedback: "Si lo prefieres, %{link} tus opiniones" feature_suggestion: "... sugieres alguna %{link}?" find_a_bug: "... encontraste un %{link}?" have_a_question: "... tienes una %{link}?" @@ -106,25 +81,15 @@ es-CO: follow: "¡Sigue la etiqueta %{link} y da la bienvenida a los nuevos usuarios de Diaspora*!" learn_more: "Conoce más" title: "Da la bienvenida a nuevos usuarios" - no_contacts: "No hay contactos" - no_tags: "+ Encuentra una etiqueta para seguir" - people_sharing_with_you: "Personas que comparten contigo" - post_a_message: "publica un mensaje >>" services: content: "Puedes conectar los siguientes servicios a Diaspora:" heading: "Conectar Servicios" - unfollow_tag: "Dejar de seguir #%{tag}" welcome_to_diaspora: "¡Bienvenido/a a Diaspora, %{name}!" - new: - create: "Crear" - name: "Nombre (solo es visible para ti)" no_contacts_message: community_spotlight: "Comunidad Creativa" or_spotlight: "O puedes compartir con %{link}" try_adding_some_more_contacts: "Puedes buscar o invitar a más contactos." you_should_add_some_more_contacts: "¡DeberÃas añadir algunos contactos!" - no_posts_message: - start_talking: "¡Nadie ha dicho nada aún!" seed: acquaintances: "Conocidos" family: "Familia" @@ -133,26 +98,18 @@ es-CO: update: failure: "Tu aspecto, %{name}, tenÃa un nombre muy largo para ser guardado." success: "Tu aspecto, %{name}, fue editado exitosamente." - back: "Atrás" bookmarklet: explanation: "Publica en Diaspora desde cualquier lugar, agregando a tus marcadores este enlace => %{link}." heading: "Marcador" post_something: "Publica algo en Diaspora" - post_success: "¡Publicado! ¡Cerrando!" cancel: "Cancelar" comments: new_comment: comment: "Comenta" commenting: "Comentando…" - one: "1 comentario" - other: "%{count} comentarios" - zero: "no hay comentarios" contacts: - create: - failure: "No se pudo crear el contacto" index: add_a_new_aspect: "Añade un nuevo aspecto" - add_to_aspect: "Añade contactos a %{name}" all_contacts: "Todos los Contactos" community_spotlight: "Comunidad Creativa" my_contacts: "Mis Contactos" @@ -161,26 +118,16 @@ es-CO: only_sharing_with_me: "Compartiendo solo conmigo" start_a_conversation: "Inicia una conversación" title: "Contactos" - your_contacts: "Tus Contactos" - sharing: - people_sharing: "Personas que comparten contigo:" spotlight: community_spotlight: "Comunidad Creativa" conversations: create: fail: "Mensaje inválido" sent: "Mensaje enviado" - helper: - new_messages: - one: "%{count} mensaje nuevo" - other: "%{count} mensajes nuevos" - zero: "No hay mensajes nuevos" index: inbox: "Buzón de Entrada" - no_conversation_selected: "ninguna conversación seleccionada" no_messages: "no hay mensajes" new: - abandon_changes: "¿Descartar los cambios?" send: "Enviar" sending: "Enviando..." subject: "asunto" @@ -199,70 +146,33 @@ es-CO: error_messages: helper: correct_the_following_errors_and_try_again: "Corrige los siguientes errores e inténtalo de nuevo." - invalid_fields: "Campos inválidos" fill_me_out: "Complétame" find_people: "Encontrar personas o #tags" - hide: "Ocultar" invitations: a_facebook_user: "Un usuario de Facebook" check_token: not_found: "No se encontró la identificación de invitación" create: - already_contacts: "Ya estás conectado/a con esta persona" - already_sent: "Ya has invitado a esta persona." no_more: "No tienes más invitaciones." - own_address: "No puedes enviar una invitación a tu propio correo." rejected: "Las siguientes direcciones tuvieron problemas: " sent: "Las invitaciones han sido enviadas a: %{emails}" - edit: - accept_your_invitation: "Acepta tu invitación" - your_account_awaits: "¡Tu cuenta te está esperando!" new: - already_invited: "Las siguientes personas no aceptaron tu invitación:" - aspect: "Aspecto" - check_out_diaspora: "¡Échale un vistazo a Diaspora!" - if_they_accept_info: "si aceptan, serán añadidos al aspecto al cual los invitaste." invite_someone_to_join: "¡Invita a alguien a unirse a Diaspora!" language: "Idioma" - personal_message: "Mensaje personal" - resend: "Reenviar" send_an_invitation: "Enviar una invitación" - send_invitation: "Enviar invitación" - to: "A" layouts: application: back_to_top: "Volver al principio" public_feed: "Canal público de Diaspora para %{name}" toggle: "Cambiar a interfaz móvil" whats_new: "¿Qué hay de nuevo?" - your_aspects: "tus aspectos" header: - admin: "administrar" - blog: "blog" code: "código" - login: "Iniciar sesión" logout: "Salir" profile: "Perfil" - recent_notifications: "Notificaciones Recientes" settings: "Ajustes" - view_all: "Ver todo" - likes: - likes: - people_dislike_this: - one: "a %{count} persona no le gusta esto" - other: "a %{count} personas les disgusta esto" - zero: "a nadie le disgusta esto" - people_like_this: - one: "a %{count} persona le gusta esto" - other: "a %{count} personas les gusta esto" - zero: "nadie ha dado \"Me gusta\" aún" - people_like_this_comment: - one: "a %{count} persona le gusta este comentario" - other: "a %{count} personas les gusta este comentario" - zero: "nadie ha dado me gusta a este comentario" limited: "Limitado" more: "Más" - next: "siguiente" no_results: "No se encontraron resultados" notifications: also_commented: @@ -308,7 +218,6 @@ es-CO: liked: "A %{name} le gustó tu publicación" view_post: "Ver publicación >" mentioned: - mentioned: "te mencionó en una publicación:" subject: "%{name} te mencionó en Diaspora*" private_message: reply_to_or_view: "Responder o ver esta conversación >" @@ -326,101 +235,39 @@ es-CO: to_change_your_notification_settings: "para cambiar la configuración de tus notificaciones" nsfw: "No apto para todo público" ok: "OK" - or: "o" - password: "Contraseña" - password_confirmation: "Confirme Contraseña" people: - add_contact_small: - add_contact_from_tag: "añadir contacto desde una etiqueta" - aspect_list: - edit_membership: "editar miembros del aspecto" - helper: - results_for: " resultados para %{params}" index: looking_for: "¿Buscando publicaciones etiquetadas con %{tag_link}?" no_one_found: "…no se encontró a nadie." no_results: "¡Oye! Necesitas buscar algo." results_for: "buscar resultados para" - one: "1 persona" - other: "%{count} personas" person: - add_contact: "añadir contacto" - already_connected: "Ya estás conectado" - pending_request: "Solicitud pendiente" thats_you: "¡Ese eres tú!" profile_sidebar: bio: "BiografÃa" born: "Cumpleaños" - edit_my_profile: "Editar mi perfil" gender: "Género" - in_aspects: "en aspectos" location: "Ubicación" - remove_contact: "quitar contacto" - remove_from: "¿Eliminar a %{name} de %{aspect}?" show: closed_account: "Esta cuenta ha sido cerrada." does_not_exist: "¡La persona no existe!" has_not_shared_with_you_yet: "¡%{name} no ha compartido ninguna publicación contigo todavÃa!" - ignoring: "Estás ignorando todas las publicaciones de %{name}." - incoming_request: "%{name} quiere compartir contigo" - mention: "Mención" - message: "Mensaje" - not_connected: "No estás compartiendo con esta persona" - recent_posts: "Publicaciones Recientes" - recent_public_posts: "Publicaciónes Públicas Recientes" - return_to_aspects: "Volver a tu página de aspectos" - see_all: "Ver todo" - start_sharing: "comenzar a compartir" - to_accept_or_ignore: "aceptar o ignorar." - sub_header: - add_some: "agregar algunas" - edit: "editar" - you_have_no_tags: "¡no tienes etiquetas!" - webfinger: - fail: "Perdón, no pudimos encontrar %{handle}." - zero: "Sin personas" photos: - comment_email_subject: "Foto de %{name}" create: integrity_error: "Error al subir la foto. ¿Estás seguro de que era una imagen?" runtime_error: "Error al subir la foto. ¿Hay alguna restricción de seguridad?" type_error: "Error al subir la foto. ¿Estás seguro de que agregaste una imagen?" destroy: notice: "La foto fue eliminada." - edit: - editing: "Editando" - new: - back_to_list: "Volver a la lista" - new_photo: "Nueva Foto" - post_it: "¡PublÃcalo!" new_photo: empty: "{file} está vacÃo, por favor omÃtelo y nuevamente selecciona archivos." invalid_ext: "{file} tiene una extensión inválida. Solo se permiten {extensions}." size_error: "{file} es demasiado grande, el tamaño máximo de archivo es {sizeLimit}." new_profile_photo: - or_select_one_existing: "o selecciona una de las %{photos} existentes" upload: "¡Subir una nueva foto de perfil!" - photo: - view_all: "ver todas las fotos de %{name}" show: - collection_permalink: "enlace permanente a la colección" - delete_photo: "Borrar Foto" - edit: "editar" - edit_delete_photo: "Editar la descripción de la foto / eliminar foto" - make_profile_photo: "convertir en foto de perfil" show_original_post: "Mostrar publicación original" - update_photo: "Actualizar Foto" - update: - error: "Error al editar la foto." - notice: "La foto se actualizó exitosamente." - posts: - show: - destroy: "Eliminar" - not_found: "Lo sentimos, no pudimos encontrar esa publicación." - permalink: "enlace permanente" - previous: "anterior" privacy: "Privacidad" - privacy_policy: "PolÃtica de Privacidad" profile: "Perfil" profiles: edit: @@ -430,8 +277,6 @@ es-CO: your_birthday: "Cumpleaños" your_gender: "Género" your_name: "Tu Nombre" - your_private_profile: "Tu Perfil Privado" - your_public_profile: "Tu Perfil Público" your_tags: "DescrÃbete en 5 palabras" your_tags_placeholder: "como #pelÃculas #gatos #viajes #profesor #bogotá" public: "Público" @@ -441,10 +286,4 @@ es-CO: zero: "Ninguna reacción" search: "Buscar" settings: "Configuración" - share_visibilites: - update: - post_hidden_and_muted: "La publicación de %{name} se ha ocultado, asà como las notificaciones." - terms_and_conditions: "Términos y Condiciones" - undo: "¿Deshacer?" - username: "Nombre de usuario" - welcome: "¡Bienvenido!" \ No newline at end of file + username: "Nombre de usuario" \ No newline at end of file diff --git a/config/locales/diaspora/es-MX.yml b/config/locales/diaspora/es-MX.yml index 548e577eef7f5220740d8329035bc7a5895e6a71..3277c4c341353e46eafc73d73c765b400d08586b 100644 --- a/config/locales/diaspora/es-MX.yml +++ b/config/locales/diaspora/es-MX.yml @@ -6,11 +6,8 @@ es-MX: _applications: "Aplicaciones" - _comments: "Comentarios" _contacts: "Contactos" _help: "Ayuda" - _home: "Inicio" - _photos: "Fotos" _services: "Servicios" account: "Cuenta" activerecord: @@ -91,13 +88,7 @@ es-MX: other: "cantidad de usuarios nuevos esta semana: %{count}" zero: "cantidad de usuarios nuevos esta semana: ninguno" current_server: "La fecha actual del servidor es %{date}" - ago: "hace %{time}" all_aspects: "Todos los aspectos" - application: - helper: - unknown_person: "persona desconocida" - video_title: - unknown: "TÃtulo de video desconocido" are_you_sure: "¿Estás seguro?" are_you_sure_delete_account: "¿Estás seguro de que quieres eliminar tu cuenta? ¡Esto no se puede deshacer!" aspect_memberships: @@ -111,18 +102,10 @@ es-MX: success: "Contacto añadido exitosamente al aspecto." aspect_listings: add_an_aspect: "+ Agregar un aspecto" - deselect_all: "Desmarcar todos" - edit_aspect: "Editar %{name}" - select_all: "Marcar todos" aspect_stream: make_something: "Haz algo" stay_updated: "Mantente actualizado" stay_updated_explanation: "Tu entrada principal esta formada por todos tus contactos, las etiquetas que sigues, y publicaciones de algunos miembros creativos de la comunidad." - contacts_not_visible: "Los contactos en este aspecto no podrán verse entre ellos." - contacts_visible: "Los contactos en este aspecto podrán verse entre ellos." - create: - failure: "Error al crear el aspecto." - success: "Tu nuevo aspecto %{name} fue creado" destroy: failure: "%{name} no está vacÃo y no puede ser eliminado." success: "%{name} fue eliminado exitosamente." @@ -130,25 +113,15 @@ es-MX: aspect_list_is_not_visible: "Los contactos en este aspecto no pueden verse entre sÃ." aspect_list_is_visible: "Los contactos en este aspecto pueden verse entre sÃ." confirm_remove_aspect: "¿Estás seguro de que quieres eliminar este aspecto?" - make_aspect_list_visible: "¿Hacer visibles entre ellos a los contactos de este aspecto?" - remove_aspect: "Eliminar este aspecto" rename: "renombrar" - set_visibility: "Establecer visibilidad" update: "actualizar" updating: "actualizando" index: - diaspora_id: - content_1: "Tu ID de Diaspora es:" - content_2: "Dáselo a quien quieras y podrán encontrarte en Diaspora." - heading: "ID de Diaspora" donate: "Donar" - handle_explanation: "Esta es tu dirección de Diaspora. Como una dirección de correo electrónico, puedes dársela a la gente para que te encuentre." help: any_problem: "¿Algún problema?" contact_podmin: "¡Contacta al administrador de tu pod!" do_you: "Tal vez:" - email_feedback: "Si lo prefieres, envÃanos tus opiniones a este %{link}." - email_link: "Correo electrónico" feature_suggestion: "• Sugieras una %{link}." find_a_bug: "• Encontraste un %{link}." have_a_question: "• Tienes una %{link}." @@ -161,31 +134,20 @@ es-MX: tutorial_link_text: "Tutoriales" tutorials_and_wiki: "%{faq},%{tutorial} y %{wiki}: Ayuda en tus primeros pasos." introduce_yourself: "Esta es tu entrada. Adelante, preséntate." - keep_diaspora_running: "¡Haz que el desarrollo de Diaspora siga yendo rápido con una donación mensual!" keep_pod_running: "¡Haz que %{pod} siga yendo rápido, y compra a nuestros servidores su dosis de café, con una donación mensual!" new_here: follow: "¡Sigue %{link} y da la bienvenida a nuevos usuarios de diaspora*!" learn_more: "Aprende más" title: "Da la bienvenida a nuevos usuarios" - no_contacts: "No hay contactos" - no_tags: "+ Encuentra una etiqueta para seguir" - people_sharing_with_you: "Personas que comparten contigo" - post_a_message: "publica un mensaje >>" services: content: "Puedes conectar los siguientes servicios a Diaspora:" heading: "Conectar servicios" - unfollow_tag: "Dejar de seguir #%{tag}" welcome_to_diaspora: "¡Bienvenido/a a Diaspora, %{name}!" - new: - create: "Crear" - name: "Nombre (solo es visible para ti)" no_contacts_message: community_spotlight: "lo más destacado de la comunidad" or_spotlight: "O puedes compartir con %{link}" try_adding_some_more_contacts: "Puedes buscar o invitar a más contactos." you_should_add_some_more_contacts: "¡DeberÃas añadir algunos contactos!" - no_posts_message: - start_talking: "¡Nadie ha dicho nada aún!" seed: acquaintances: "Conocidos" family: "Familia" @@ -194,7 +156,6 @@ es-MX: update: failure: "Tu aspecto, %{name}, tenÃa un nombre muy largo para ser guardado." success: "Tu aspecto, %{name}, fue editado exitosamente." - back: "Atrás" blocks: create: failure: "No pude ignorar a ese usuario. #evasion" @@ -206,21 +167,14 @@ es-MX: explanation: "Publica en Diaspora desde cualquier lugar, agregando a tus marcadores este enlace => %{link}." heading: "Marcador" post_something: "Publica en Diaspora" - post_success: "¡Publicado! ¡Cerrando!" cancel: "Cancelar" comments: new_comment: comment: "Comentar" commenting: "Comentando…" - one: "1 comentario" - other: "%{count} comentarios" - zero: "no hay comentarios" contacts: - create: - failure: "No se pudo crear el contacto" index: add_a_new_aspect: "Añade un nuevo aspecto" - add_to_aspect: "Añade contactos a %{name}" all_contacts: "Todos los contactos" community_spotlight: "Lo más destacado de la comunidad" my_contacts: "Mis contactos" @@ -229,33 +183,20 @@ es-MX: only_sharing_with_me: "Compartiendo solo conmigo" start_a_conversation: "Inicia una conversación" title: "Contactos" - your_contacts: "Tus contactos" - sharing: - people_sharing: "Personas que comparten contigo:" spotlight: community_spotlight: "Lo más destacado de la comunidad" suggest_member: "Sugiere a un miembro" conversations: - conversation: - participants: "Participantes" create: fail: "Mensaje inválido" no_contact: "¡Eh, primero necesitas añadir al contacto!" sent: "Mensaje enviado" - helper: - new_messages: - one: "Un mensaje nuevo" - other: "%{count} mensajes nuevos" - zero: "No hay mensajes nuevos" index: conversations_inbox: "Conversaciones – Bandeja de entrada" - create_a_new_conversation: "iniciar una nueva conversación" inbox: "Bandeja de entrada" new_conversation: "Nueva conversación" - no_conversation_selected: "ninguna conversación seleccionada" no_messages: "no hay mensajes" new: - abandon_changes: "¿Descartar los cambios?" send: "Enviar" sending: "Enviando…" subject: "asunto" @@ -276,10 +217,6 @@ es-MX: error_messages: helper: correct_the_following_errors_and_try_again: "Corrige los siguientes errores e inténtalo de nuevo." - invalid_fields: "Campos inválidos" - login_try_again: "Por favor %{login_link}<a href='%{login_link}'>accede</a> e inténtalo de nuevo." - post_not_public: "¡La publicación que estás tratando de ver no es pública!" - post_not_public_or_not_exist: "¡La publicación que estás intentando ver no es pública, o no existe!" fill_me_out: "Complétame" find_people: "Encuentra gente o #etiquetas" help: @@ -453,45 +390,27 @@ es-MX: tutorial: "tutorial" tutorials: "tutoriales" wiki: "wiki" - hide: "Ocultar" - ignore: "Ignorar" - invitation_codes: - excited: "%{name} está entusiasmado por verte aquÃ." invitations: a_facebook_user: "Un usuario de Facebook" check_token: not_found: "No se encontró la identificación de invitación" create: - already_contacts: "Ya estás conectado con esta persona" - already_sent: "Ya has invitado a esta persona." empty: "Por favor, introduce al menos una dirección de correo electrónico." no_more: "No tienes más invitaciones." note_already_sent: "Ya se han enviado invitaciones a: %{emails}" - own_address: "No puedes enviar una invitación a tu propia dirección." rejected: "Las siguientes direcciones electrónicas tuvieron problemas: " sent: "Las invitaciones se han enviado a: %{emails}" - edit: - accept_your_invitation: "Acepta tu invitación" - your_account_awaits: "¡Tu cuenta te está esperando!" new: - already_invited: "Las siguientes personas no aceptaron tu invitación:" - aspect: "Aspecto" - check_out_diaspora: "¡Echa un vistazo a Diaspora!" codes_left: one: "Una invitación restante con este código" other: "%{count} invitaciones restantes con este código" zero: "No quedan invitaciones restantes con este código" comma_separated_plz: "Puedes introducir múltiples direcciones de correo electrónico, separadas por comas." - if_they_accept_info: "si aceptan, serán añadidos al aspecto al cual los invitaste." invite_someone_to_join: "¡Invita a alguien a unirse a Diaspora!" language: "Idioma" paste_link: "Comparte este enlace con tus amigos para invitarlos a diaspora*, o envÃales directamente el enlace por correo electrónico." - personal_message: "Mensaje personal" - resend: "Reenviar" send_an_invitation: "Enviar una invitación" - send_invitation: "Enviar invitación" sending_invitation: "Enviando invitación…" - to: "Para" layouts: application: back_to_top: "Volver al principio" @@ -500,35 +419,13 @@ es-MX: source_package: "descargar el paquete del código fuente" toggle: "Cambiar a sitio móvil" whats_new: "¿Qué hay de nuevo?" - your_aspects: "tus aspectos" header: - admin: "administrador" - blog: "blog" code: "código" - help: "Ayuda" - login: "Entrar" logout: "Salir" profile: "Perfil" - recent_notifications: "Notificaciones recientes" settings: "Ajustes" - view_all: "Ver todo" - likes: - likes: - people_dislike_this: - one: "A una persona no le gusta" - other: "A %{count} personas no les gusta" - zero: "A nadie le disgusta" - people_like_this: - one: "A una persona le gusta" - other: "A %{count} personas les gusta" - zero: "A nadie le gusta aún" - people_like_this_comment: - one: "A una persona le gusta" - other: "A %{count} personas les gusta" - zero: "A nadie le gusta aún" limited: "Limitado" more: "Más" - next: "siguiente" no_results: "No hay resultados" notifications: also_commented: @@ -543,11 +440,6 @@ es-MX: one: "%{actors} comentó en tu %{post_link}." other: "%{actors} comentaron en tu %{post_link}." zero: "%{actors} comentó en tu %{post_link}." - helper: - new_notifications: - one: "Una nueva notificación" - other: "%{count} nuevas notificaciones" - zero: "No hay notificaciones nuevas" index: and: "y" and_others: @@ -592,7 +484,6 @@ es-MX: zero: "%{actors} comenzó a compartir contigo." notifier: a_post_you_shared: "una publicación." - accept_invite: "¡Acepta tu invitación de diaspora*!" click_here: "Haz clic aquÃ" comment_on_post: reply: "Responder o ver la publicación de %{name} >" @@ -622,7 +513,6 @@ es-MX: liked: "A %{name} le gustó tu publicación" view_post: "Ver publicación >" mentioned: - mentioned: "te mencionó en una publicación:" subject: "%{name} te mencionó en diaspora*" private_message: reply_to_or_view: "Responder o ver esta conversación >" @@ -640,119 +530,55 @@ es-MX: to_change_your_notification_settings: "para cambiar los ajustes de notificación" nsfw: "No apto para todo público" ok: "Aceptar" - or: "o" - password: "Contraseña" - password_confirmation: "Confirmación de contraseña" people: add_contact: invited_by: "fuiste invitado por" - add_contact_small: - add_contact_from_tag: "añadir contacto desde una etiqueta" - aspect_list: - edit_membership: "editar aspecto asociado" - helper: - is_not_sharing: "%{name} no está compartiendo contigo" - is_sharing: "%{name} está compartiendo contigo" - results_for: " resultados para %{params}" index: looking_for: "¿Buscando publicaciones etiquetadas con %{tag_link}?" no_one_found: "…y nadie fue encontrado." no_results: "¡Eh! Necesitas buscar algo." results_for: "buscar resultados para" searching: "buscando, por favor sé paciente…" - one: "1 persona" - other: "%{count} personas" person: - add_contact: "añadir contacto" - already_connected: "Ya estás conectado" - pending_request: "Solicitud pendiente" thats_you: "¡Ese eres tú!" profile_sidebar: bio: "BiografÃa" born: "Cumpleaños" - edit_my_profile: "Editar mi perfil" gender: "Género" - in_aspects: "en aspectos" location: "Ubicación" - photos: "Fotos" - remove_contact: "quitar contacto" - remove_from: "¿Eliminar a %{name} de %{aspect}?" show: closed_account: "Esta cuenta ha sido cerrada." does_not_exist: "¡La persona no existe!" has_not_shared_with_you_yet: "¡%{name} aún no ha compartido ninguna publicación contigo!" - ignoring: "Estás ignorando todas las publicaciones de %{name}." - incoming_request: "%{name} quiere compartir contigo" - mention: "Mención" - message: "Mensaje" - not_connected: "No estás compartiendo con esta persona" - recent_posts: "Publicaciones recientes" - recent_public_posts: "Publicaciónes públicas recientes" - return_to_aspects: "Volver a tu página de aspectos" - see_all: "Ver todo" - start_sharing: "comenzar a compartir" - to_accept_or_ignore: "aceptar o ignorar." - sub_header: - add_some: "agregar algunas" - edit: "editar" - you_have_no_tags: "¡no tienes etiquetas!" - webfinger: - fail: "Perdón, no pudimos encontrar %{handle}." - zero: "ninguna persona" photos: - comment_email_subject: "La foto de %{name}" create: integrity_error: "Error al subir la foto. ¿Estás seguro de que era una imagen?" runtime_error: "Error al subir la foto. ¿Hay alguna restricción de seguridad?" type_error: "Error al subir la foto. ¿Estás seguro de que agregaste una imagen?" destroy: notice: "La foto fue eliminada." - edit: - editing: "Editando" - new: - back_to_list: "Volver a la lista" - new_photo: "Foto nueva" - post_it: "¡PublÃcalo!" new_photo: empty: "{file} está vacÃo, por favor selecciona archivos nuevamente sin este último." invalid_ext: "{file} tiene una extensión inválida. Solo se permiten {extensions}." size_error: "{file} es demasiado grande, el tamaño máximo de un archivo es de {sizeLimit}." new_profile_photo: - or_select_one_existing: "o selecciona una de las %{photos} existentes" upload: "¡Subir una nueva foto de perfil!" - photo: - view_all: "ver todas las fotos de %{name}" show: - collection_permalink: "enlace permanente a la colección" - delete_photo: "Eliminar foto" - edit: "editar" - edit_delete_photo: "Editar la descripción de la foto / eliminar foto" - make_profile_photo: "convertir en foto de perfil" show_original_post: "Mostrar publicación original" - update_photo: "Actualizar foto" - update: - error: "Error al editar la foto." - notice: "La foto se actualizó exitosamente." posts: presenter: title: "Una publicación de %{name}" show: - destroy: "Eliminar" - not_found: "Lo sentimos, no pudimos encontrar esa publicación." - permalink: "enlace permanente" photos_by: one: "Una foto de %{author}" other: "%{count} fotos de %{author}" zero: "Ninguna foto de %{author}" reshare_by: "Vuelto a compartir por %{author}" - previous: "anterior" privacy: "Privacidad" - privacy_policy: "PolÃtica de privacidad" profile: "Perfil" profiles: edit: allow_search: "Permitir que la gente te busque dentro de Diaspora" - edit_profile: "Editar perfil" first_name: "Nombre" last_name: "Apellidos" nsfw_check: "Marcar todo lo que comparto como NSFW (no es seguro/apropiado para el trabajo)" @@ -765,8 +591,6 @@ es-MX: your_location: "Ubicación" your_name: "Tu nombre" your_photo: "Foto" - your_private_profile: "Tu perfil privado" - your_public_profile: "Perfil público" your_tags: "DescrÃbete en 5 palabras" your_tags_placeholder: "como #pelÃculas #gatos #viajes #profesora #méxico" update: @@ -781,60 +605,24 @@ es-MX: closed: "Los registros están cerrados en este servidor de Diaspora." create: success: "¡Te has unido a Diaspora!" - edit: - cancel_my_account: "Cancelar mi cuenta" - edit: "Editar %{name}" - leave_blank: "(déjalo en blanco si no quieres cambiarlo)" - password_to_confirm: "(necesitamos tu contraseña actual para confirmar tus cambios)" - unhappy: "¿Insatisfecho?" - update: "Actualizar" invalid_invite: "¡El enlace de invitación que proporcionaste ya no es válido!" new: - create_my_account: "¡Crear mi cuenta!" email: "CORREO ELECTRÓNICO" enter_email: "Ingresa un correo electrónico" enter_password: "Elige una contraseña (mÃnimo seis caracteres)" enter_password_again: "Ingresa de nuevo la misma contraseña" enter_username: "Elige un nombre de usuario (solo letras, números o guiones bajos)" - join_the_movement: "¡Únete al movimiento!" password: "CONTRASEÑA" password_confirmation: "CONFIRMACIÓN DE CONTRASEÑA" sign_up: "REGISTRARSE" - sign_up_message: "Redes sociales con un ♥" submitting: "Enviando…" username: "NOMBRE DE USUARIO" - requests: - create: - sending: "Enviando" - sent: "Has solicitado compartir con %{name}. DeberÃa verlo la próxima vez que entre a Diaspora." - destroy: - error: "¡Por favor selecciona un aspecto!" - ignore: "Solicitud de contacto ignorada." - success: "Ahora estás compartiendo." - helper: - new_requests: - one: "¡nueva solicitud!" - other: "¡%{count} nuevas solicitudes!" - zero: "no hay solicitudes nuevas" - manage_aspect_contacts: - existing: "Contactos existentes" - manage_within: "Gestionar contactos dentro de" - new_request_to_person: - sent: "¡enviado!" reshares: comment_email_subject: "%{resharer} compartió una pubilcación de %{author}" - create: - failure: "Hubo un error al compartir esta publicación." reshare: deleted: "La publicación original fue eliminada por el autor." - reshare: - one: "Compartido una vez" - other: "Compartido %{count} veces" - zero: "Volver a compartir" reshare_confirmation: "¿Compartir la publicación de %{author}?" - reshare_original: "Compartir el original" reshared_via: "compartido vÃa" - show_original: "Mostrar el original" search: "Buscar" services: create: @@ -846,59 +634,24 @@ es-MX: success: "Autenticación eliminada exitosamente." failure: error: "hubo un error al conectarse a ese servicio" - finder: - fetching_contacts: "Diaspora está importando a tus contactos de %{service}, por favor compruébalo en unos minutos." - no_friends: "No se encontraron contactos de Facebook." - service_friends: "Contactos de %{service}" index: disconnect: "desconectar" edit_services: "Editar servicios" logged_in_as: "conectado como" really_disconnect: "¿Desconectar %{service}?" services_explanation: "Conectar con servicios te ofrece la posibilidad de publicar tus mensajes en estos, a medida que los escribes en Diaspora." - inviter: - click_link_to_accept_invitation: "Sigue este enlace para aceptar tu invitación" - join_me_on_diaspora: "Únete a mà en diaspora*" - remote_friend: - invite: "invitar" - not_on_diaspora: "Aún no está en Diaspora" - resend: "reenviar" settings: "Ajustes" - share_visibilites: - update: - post_hidden_and_muted: "La publicación de %{name} se ha ocultado, y las notificaciones se han silenciado." - see_it_on_their_profile: "Si quieres ver las actualizaciones de esta publicación, visita el perfil de %{name}." shared: - add_contact: - add_new_contact: "Añadir un nuevo contacto" - create_request: "Encontrar por ID de Diaspora" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Ingresa un nombre de usuario de Diaspora:" - know_email: "¿Conoces sus direcciones de correo electrónico? DeberÃas invitarlos" - your_diaspora_username_is: "Tu nombre de usuario de Diaspora es: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Añadir contacto" toggle: one: "En un aspecto" other: "En %{count} aspectos" zero: "Añadir contacto" - contact_list: - all_contacts: "Todos los contactos" - footer: - logged_in_as: "conectado como %{name}" - your_aspects: "tus aspectos" invitations: by_email: "Por correo electrónico" - dont_have_now: "No tienes ninguna invitación ahora, ¡pero pronto llegarán más!" - from_facebook: "De Facebook" - invitations_left: "%{count} restantes" - invite_someone: "Invita a alguien" invite_your_friends: "Invita a tus amigos" invites: "Invitaciones" - invites_closed: "Las invitaciones en este servidor de Diaspora están actualmente cerradas." share_this: "¡Comparte este enlace a través de correo electrónico, blog o tu red social favorita!" - notification: - new: "Nuevo %{type} de %{from}" public_explain: atom_feed: "canal Atom" control_your_audience: "Controla tu audiencia" @@ -910,42 +663,21 @@ es-MX: title: "Configurar los servicios conectados" visibility_dropdown: "Utiliza este menú desplegable para cambiar la visibilidad de tu publicación. (Te sugerimos hacer pública esta primera)." publisher: - all: "todo" - all_contacts: "todos los contactos" discard_post: "Descartar publicación" formatWithMarkdown: "Puedes utilizar %{markdown_link} para dar formato a tu publicación" get_location: "Obtener tu ubicación" - make_public: "hacer público" new_user_prefill: hello: "#%{new_user_tag}, acabo de llegar aquÃ. " i_like: "Tengo interés en %{tags}. " invited_by: "Gracias por la invitación, " newhere: "Hola" - post_a_message_to: "Publicar un mensaje en %{aspect}" posting: "Publicando…" - preview: "Vista previa" - publishing_to: "publicar en: " share: "Comparte" - share_with: "compartir con" upload_photos: "Subir fotos" whats_on_your_mind: "¿Qué tienes en mente?" - reshare: - reshare: "Compartir" stream_element: - connect_to_comment: "Conéctate con este usuario para comentar en su publicación" - currently_unavailable: "los comentarios no están disponibles en este momento" - dislike: "No me gusta" - hide_and_mute: "Ocultar y silenciar la publicación" - ignore_user: "Ignorar a %{name}" - ignore_user_description: "¿Ignorar y quitar al usuario de todos los aspectos?" - like: "Me gusta" - nsfw: "Esta publicación ha sido marcada por su autor como no apta para todo público. %{link}" - shared_with: "Compartido con: %{aspect_names}" - show: "mostrar" - unlike: "No me gusta" via: "vÃa %{link}" via_mobile: "vÃa móvil" - viewable_to_anyone: "Esta publicación puede ser vista por cualquiera en la web" simple_captcha: label: "Introduce el código en la casilla:" message: @@ -956,19 +688,9 @@ es-MX: status_messages: create: success: "Se mencionó exitosamente a: %{names}" - destroy: - failure: "Hubo un error al eliminar la publicación." - helper: - no_message_to_display: "No hay mensaje que mostrar." new: mentioning: "Mencionar a: %{person}" too_long: "{\"one\"=>\"por favor, haz que tu mensaje de estado tenga un carácter menos\", \"other\"=>\"por favor, haz que tu mensaje de estado tenga %{count} caracteres menos\", \"zero\"=>\"por favor, haz que tu mensaje de estado tenga %{count} caracteres menos\"}" - stream_helper: - hide_comments: "Ocultar todos los comentarios" - show_comments: - one: "Mostrar un comentario más" - other: "Mostrar %{count} comentarios más" - zero: "No hay más comentarios" streams: activity: title: "Mi actividad" @@ -994,22 +716,11 @@ es-MX: title: "Actividad pública" tags: title: "Publicaciones etiquetadas: %{tags}" - tag_followings: - create: - failure: "Error al seguir #%{name}. ¿Ya lo estás siguiendo?" - none: "¡No puedes sequir una etiqueta en blanco!" - success: "¡Bien! Ahora estás siguiendo #%{name}." - destroy: - failure: "Error al dejar de sequir a #%{name}. ¿Tal vez ya dejaste de seguirlo?" - success: "¡Ay! Ya no estás siguiendo #%{name}." tags: show: follow: "Seguir #%{tag}" - following: "Siguiendo #%{tag}" none: "¡La etiqueta vacÃa no existe!" stop_following: "Dejar de seguir #%{tag}" - terms_and_conditions: "Términos y condiciones" - undo: "¿Deshacer?" username: "Nombre de usuario" users: confirm_email: @@ -1030,7 +741,6 @@ es-MX: character_minimum_expl: "debe tener al menos seis caracteres" close_account: dont_go: "¡Eh, no te vayas!" - if_you_want_this: "Si realmente es lo que deseas, ingresa tu contraseña debajo y pulsa «Eliminar cuenta»." lock_username: "Esto bloqueará tu nombre de usuario si decides volver a registrarte." locked_out: "Cerrarás tu sesión y tu cuenta será bloqueada." make_diaspora_better: "Queremos que nos ayudes a mejorar Diaspora, asà que deberÃas ayudarnos en vez de marcharte. Si en verdad quieres irte, queremos que sepas lo que sucede después." @@ -1041,12 +751,10 @@ es-MX: comment_on_post: "Alguien comenta en tu publicación." current_password: "Contraseña actual" current_password_expl: "con la que inicias sesión…" - download_photos: "Descargar mis fotos" edit_account: "Editar cuenta" email_awaiting_confirmation: "Te hemos enviado un enlace de activación a %{unconfirmed_email}. Hasta que sigas este enlace y actives la nueva dirección, continuaremos usando tu dirección original %{email}." export_data: "Exportar datos" following: "Ajustes de seguimiento" - getting_started: "Preferencias de nuevo usuario" liked: "A alguien le gusta tu publicación." mentioned: "Te mencionan en una publicación." new_password: "Nueva contraseña" @@ -1066,7 +774,6 @@ es-MX: connect_to_facebook_link: "conectando tu cuenta de Facebook" hashtag_explanation: "Las etiquetas te permiten hablar acerca de tus intereses, asà como seguirlos. Son también una gran forma de encontrar gente en Diaspora." hashtag_suggestions: "Intenta seguir etiquetas como #arte, #pelÃculas, #español, etc." - saved: "¡Guardado!" well_hello_there: "Bueno, ¡hola!" what_are_you_in_to: "¿Qué te gusta hacer?" who_are_you: "¿Quién eres?" @@ -1088,13 +795,6 @@ es-MX: settings_updated: "Ajustes actualizados" unconfirmed_email_changed: "Tu correo electrónico cambió. Se requiere activación." unconfirmed_email_not_changed: "Error al cambiar el correo electrónico" - webfinger: - fetch_failed: "hubo un error al obtener el perfil de webfinger de %{profile_url}" - hcard_fetch_failed: "hubo un error al obtener la hcard de %{account}" - no_person_constructed: "No se pudo crear ninguna persona a partir de esta hcard." - not_enabled: "parece que webfinger no está habilitado para el servidor de %{account}" - xrd_fetch_failed: "hubo un error al obtener el xrd de la cuenta %{account}" - welcome: "¡Bienvenido/a!" will_paginate: next_label: "siguiente »" previous_label: "« anterior" \ No newline at end of file diff --git a/config/locales/diaspora/es.yml b/config/locales/diaspora/es.yml index ee9f6f94ba9e2aa279f3a42e063a4ae852b12943..3409e71e20e17cc8d4b8eee6c7c954d4b6ca7943 100644 --- a/config/locales/diaspora/es.yml +++ b/config/locales/diaspora/es.yml @@ -6,11 +6,8 @@ es: _applications: "Aplicaciones" - _comments: "Comentarios" _contacts: "Contactos" _help: "Ayuda" - _home: "Inicio" - _photos: "Fotos" _services: "Servicios" _statistics: "EstadÃsticas" account: "Cuenta" @@ -52,12 +49,19 @@ es: taken: "está en uso." admins: admin_bar: + dashboard: "Panel de control" pages: "Páginas" + pod_network: "Red POD" pod_stats: "EstadÃsticas del servidor" report: "Informes" sidekiq_monitor: "Monitor Sidekiq" user_search: "Buscar usuario" weekly_user_stats: "EstadÃsticas semanales de usuario" + dashboard: + fetching_diaspora_version: "Averiguando la última versión de diaspora*..." + pod_status: "Estado del pod" + pods: + pod_network: "Red POD" stats: 2weeks: "2 semanas" 50_most: "Las 50 etiquetas más leÃdas." @@ -108,7 +112,10 @@ es: are_you_sure_unlock_account: "¿Estás seguro de que quieres desbloquear esta cuenta?" close_account: "cerrar cuenta" email_to: "Correo electrónico a invitar" + invite: "Invitar" + lock_account: "Bloquear cuenta" under_13: "Mostrar usuarios menores de 13 años (COPPA)" + unlock_account: "Desbloquear cuenta" users: one: "se ha encontrado %{count} usuario" other: "se han encontrado %{count} usuarios" @@ -124,13 +131,45 @@ es: other: "Usuarios nuevos esta semana: %{count}" zero: "Usuarios nuevos esta semana: ninguno" current_server: "La fecha del servidor es %{date}" - ago: "hace %{time}" all_aspects: "Todos los aspectos" - application: - helper: - unknown_person: "Persona desconocida" - video_title: - unknown: "TÃtulo de vÃdeo desconocido" + api: + openid_connect: + authorizations: + destroy: + fail: "Falló el intento de cancelar la autorización con ID %{id}" + new: + access: "%{name} solicita acceso a:" + approve: "Aprobar" + bad_request: "Falta el ID del cliente o URI de redireccionamiento" + client_id_not_found: "Ningún se encontro ningún cliente con el ID de cliente %{client_id} o con la URI de redireccionamiento %{redirect_uri}" + deny: "Denegar" + no_requirement: "%{name} no necesita permisos" + redirection_message: "¿Estás seguro que quieres dar acceso a %{redirect_uri}?" + error_page: + contact_developer: "DeberÃas contactar con el desarrollador de la aplicación y enviarle el siguiente mensaje de error:" + could_not_authorize: "No se pudo autorizar la aplicación" + login_required: "Tienes que identificarte antes de autorizar esta aplicación" + title: "¡Oh! Algo salió mal :(" + scopes: + openid: + description: "Permite que la aplicación lea tu perfil básico" + name: "perfil básico" + read: + description: "Esto permite a la aplicación leer tu portada, tus conversaciones y tu perfil completo" + name: "leer perfil, portada y conversaciones" + write: + description: "Permite a la aplicación enviar nuevos mensajes, escribir conversaciones y enviar reacciones" + name: "enviar mensajes, conversaciones y reacciones" + user_applications: + index: + access: "%{name} tiene acceso a:" + edit_applications: "Aplicaciones" + no_requirement: "%{name} no necesita permisos" + title: "Aplicaciones autorizadas" + no_applications: "No tienes aplicaciones autorizadas" + policy: "Mira las polÃticas de privacidad de la aplicación" + revoke_autorization: "Revocar" + tos: "Ver los Términos de Servicio de la aplicación" are_you_sure: "¿Estás seguro?" are_you_sure_delete_account: "¿Seguro que quieres eliminar tu cuenta? ¡Esto no se podrá deshacer!" aspect_memberships: @@ -146,48 +185,27 @@ es: success: "Contacto añadido con éxito al aspecto." aspect_listings: add_an_aspect: "+ Añade un aspecto" - deselect_all: "Desmarcar todos" - edit_aspect: "Editar %{name}" - select_all: "Marcar todos" aspect_stream: make_something: "Haz algo" stay_updated: "Mantente actualizado" stay_updated_explanation: "Tu página principal la forman todos tus contactos, las etiquetas que sigues, y si lo deseas, las publicaciones de diferentes miembros creativos de la comunidad." - contacts_not_visible: "Los contactos en este aspecto no podrán verse entre ellos." - contacts_visible: "Los contactos de este aspecto podrán verse entre ellos." - create: - failure: "Error creando el aspecto." - success: "Se ha credo tu nuevo aspecto %{name}." destroy: failure: "%{name} no pudo ser borrado." success: "%{name} fue eliminado con éxito." success_auto_follow_back: "Se borró correctamente %{name}. Este aspecto se usaba para seguir automáticamente a los usuarios, revisa tu configuración para seleccionar un nuevo aspecto de autoseguimiento." edit: - aspect_chat_is_enabled: "Los contactos de este grupo pueden chatear contigo." - aspect_chat_is_not_enabled: "Los contactos de este grupo no pueden chatear contigo." aspect_list_is_not_visible: "Los contactos en este aspecto no son capaces de verse entre sÃ." aspect_list_is_visible: "Los contactos en este aspecto son capaces de verse entre sÃ." confirm_remove_aspect: "¿Seguro que quieres eliminar este aspecto?" - grant_contacts_chat_privilege: "¿conceder privilegio a los contactos de este aspecto para poder chatear?" - make_aspect_list_visible: "Permitir que los contactos de este aspecto puedan verse entre ellos?" - remove_aspect: "Eliminar este aspecto" rename: "Renombrar" - set_visibility: "Configurar Visibilidad" update: "Actualizar" updating: "Actualizando" index: - diaspora_id: - content_1: "Tu ID de Diaspora* es:" - content_2: "Compártela con quien quieras y podrán encontrarte en Diaspora*." - heading: "ID de Diaspora*" donate: "Donar" - handle_explanation: "Éste es tu ID de Diaspora*. Como una dirección de correo electrónico, puedes dársela a la gente para que te encuentre." help: any_problem: "¿Algún problema?" contact_podmin: "¡Contacta con el administrador de tu pod!" do_you: "Tal vez:" - email_feedback: "Si lo prefieres, envÃa tus comentarios a este %{link}." - email_link: "Correo Electrónico" feature_suggestion: "... tienes alguna %{link} sugerencia?" find_a_bug: "... encuentras algún %{link}?" have_a_question: "... tienes %{link}?" @@ -200,31 +218,21 @@ es: tutorial_link_text: "Tutoriales" tutorials_and_wiki: "%{faq}, %{tutorial} y %{wiki}: ayuda para dar tus primeros pasos." introduce_yourself: "Ésta es tu página principal. Adelante, preséntate..." - keep_diaspora_running: "¡Haz que el desarrollo de Diaspora vaya más rápido con una donación mensual!" keep_pod_running: "Haz que %{pod} vaya más rápido, ¡invita a café a nuestros servidores con una donación mensual!" new_here: follow: "¡Sigue %{link} y da la bienvenida a los nuevos miembros de Diaspora*!" learn_more: "Más información" title: "Bienvenidos nuevos usuarios" - no_contacts: "No hay contactos" - no_tags: "+ Encuentra una etiqueta a seguir" - people_sharing_with_you: "Personas que comparten contigo" - post_a_message: "Publica un mensaje >>" services: content: "Puedes conectar los siguientes servicios a Diaspora:" heading: "Conectar servicios" - unfollow_tag: "Dejar de seguir a #%{tag}" welcome_to_diaspora: "¡Bienvenido a Diaspora*, %{name}!" - new: - create: "Crear" - name: "Nombre (sólo tu lo puedes ver)" no_contacts_message: community_spotlight: "Destacado en la comunidad" + invite_link_text: "invitar" or_spotlight: "O puedes compartir con %{link}" - try_adding_some_more_contacts: "Puedes buscar o invitar a más contactos." + try_adding_some_more_contacts: "Puedes buscar o %{invite_link} a más contactos." you_should_add_some_more_contacts: "¡DeberÃas añadir algunos contactos más!" - no_posts_message: - start_talking: "¡Nadie ha dicho nada todavÃa!" seed: acquaintances: "Conocidos" family: "Familia" @@ -233,34 +241,26 @@ es: update: failure: "Tu aspecto, %{name}, tenÃa un nombre muy largo para guardarlo." success: "Tu aspecto, %{name}, fue editado con éxito." - back: "Atrás" blocks: create: failure: "No puede ignorar a este usuario. #evasion" success: "Bien, no verás a esa persona en tu entrada otra vez. #silencio!" destroy: - failure: "No podrÃa dejar de ignorar a esa persona. #evasion" + failure: "No podrÃa dejar de ignorar a ese usuario. #evasion" success: "¡Vamos a ver qué tiene que decir! #sayhello" bookmarklet: explanation: "Publica en Diaspora* desde cualquier página agregando a tus marcadores este enlace => %{link}." heading: "Marcador" post_something: "Publica en Diaspora*" - post_success: "¡Publicado! ¡Cerrando!" cancel: "Cancelar" comments: new_comment: comment: "Comentar" commenting: "Comentando..." - one: "1 comentario" - other: "%{count} comentarios" - zero: "No hay comentarios" contacts: - create: - failure: "No se pudo crear el contacto" index: add_a_new_aspect: "Añade un nuevo aspecto" add_contact: "Añadir contacto" - add_to_aspect: "Añadir contactos a %{name}" all_contacts: "Todos los contactos" community_spotlight: "Lo más destacado" my_contacts: "Mis contactos" @@ -268,19 +268,14 @@ es: no_contacts_in_aspect: "TodavÃa no tienes ningún contacto en este aspecto. A continuación puedes ver una lista de tus contactos que puedes agregar a este aspecto." no_contacts_message: "Echa un vistazo a la %{community_spotlight}" only_sharing_with_me: "Solo compartiendo conmigo" - remove_contact: "Eliminar contacto" start_a_conversation: "Inicia una conversación" title: "Contactos" user_search: "Buscar usuarios" - your_contacts: "Tus contactos" - sharing: - people_sharing: "Personas que comparten contigo:" spotlight: community_spotlight: "Lo más destacado" + no_members: "No hay miembros todavÃa." suggest_member: "Sugiere un usuario" conversations: - conversation: - participants: "Participantes" create: fail: "Mensaje no válido" no_contact: "¡Eh, primero tienes que añadir al contacto!" @@ -288,20 +283,13 @@ es: destroy: delete_success: "Conversación correctamente borrada" hide_success: "Conversación correctamente oculta" - helper: - new_messages: - one: "1 mensaje nuevo" - other: "%{count} mensajes nuevos" - zero: "No hay mensajes nuevos" index: conversations_inbox: "Conversaciones – Bandeja de entrada" - create_a_new_conversation: "Empieza una nueva conversación" inbox: "Bandeja de entrada" new_conversation: "Nueva conversación" - no_conversation_selected: "Ninguna conversación seleccionada" no_messages: "Ningún mensaje" new: - abandon_changes: "¿Descartar los cambios?" + message: "Mensaje" send: "Enviar" sending: "Enviando..." subject: "Asunto" @@ -312,6 +300,7 @@ es: show: delete: "Borrar conversación" hide: "ocultar y silenciar la conversación" + last_message: "Último mensaje recibido %{timeago}" reply: "Responder" replying: "Respondiendo..." date: @@ -324,21 +313,18 @@ es: error_messages: helper: correct_the_following_errors_and_try_again: "Corrige los siguientes errores e inténtalo de nuevo." - invalid_fields: "Campos inválidos" - login_try_again: "Por favor, <a href='%{login_link}'>accede</a> e inténtalo de nuevo." - post_not_public: "¡La publicación que intentas ver no es pública!" - post_not_public_or_not_exist: "¡La publicación que estás tratando de abrir no es pública, o no existe!" + need_javascript: "Esta web necesita JavaScript para funcionar correctamente. Si lo desactivaste, por favor actÃvalo y actualiza la página." fill_me_out: "Complétame" find_people: "Encuentra gente o #etiquetas" help: account_and_data_management: - close_account_a: "Vaya a la parte inferior de la página de configuración y haga clic en el botón Cerrar Cuenta." + close_account_a: "Ve al final de la página de configuración y pulsa en el botón \"Cerrar cuenta\". Se te pedirá que metas tu contraseña para completar el proceso. Recuerda, si cierras tu cuenta, <strong>nunca</strong> podrás volver a registrar tu nombre de usuario en este pod." close_account_q: "¿Cómo puedo borrar mi semilla (cuenta)?" data_other_podmins_a: "Cuando esté compartiendo con un contacto alojado en otro servidor (vaina), cualquier publicación que compartas con ese contacto, asà como, una copia de tu perfil, se guardara en ese servidor, estando esta información accesible para el administrador de la base de datos de ese servidor. Cuando borre una publicación o un dato de perfil, esta información será borrada tanto de su servidor como de cuaquier otro en el esté alojada." data_other_podmins_q: "¿Pueden los administradores de otros pods (vainas) ver mi información?" data_visible_to_podmin_a: "La comunicación entre \"pods\" (vainas) siempre está cifrada (usando tanto SSL como el cifrado propio que utiliza diaspora*), pero el almacenamiento de datos en los \"pods\" no está cifrado. Si quisiera, la persona que administra la base de datos en tu \"pod\" (generalmente la persona que dirige la vaina) podrÃa acceder tanto a todos los datos de su perfil como a sus publicaciones (este es el caso de la mayorÃa de los sitios web que almacenan datos de sus usuarios). Poner en marcha su propio \"pod\" proporciona una mayor privacidad al poder usted controlar el nivel de acceso a la base de datos." data_visible_to_podmin_q: "¿Qué parte de mi información puede ver el administrador de mi pod (vaina)?" - download_data_a: "SÃ. En la parte inferior de la página de configuración de su Cuenta hay dos botones para la descarga de sus datos." + download_data_a: "SÃ. Al final de la pestaña Cuenta de tu página de configuración encontrarás dos botones: uno para descargar tus datos y otro para descargar tus fotos." download_data_q: "¿Puedo descargar un copia de todo los datos contenidos en mi semilla (cuenta)?" move_pods_a: "En el futuro será capaz de exportar su cuenta (semilla) de un servidor (vaina) para importarlo en otro, pero esto de momento no es posible. De todas formas puede abrir una nueva cuenta (semilla) y añadir a sus contactos a los aspectos correspondientes y pedirle a ellos que hagan lo mismo con su nueva cuenta." move_pods_q: "¿Cómo puedo mover mi semilla (cuenta) de una vaina (servidor) a otra?" @@ -356,7 +342,7 @@ es: person_multiple_aspects_q: "¿Puedo poner a una misma persona en varios aspectos?" post_multiple_aspects_a: "SÃ. Cuando estas haciendo una nueva publicación, usa el botón de selector de aspecto para seleccionar o deseleccionar aspectos. Tu publicación será visible para todos los aspectos que selecciones. También puedes seleccionar los aspectos a los que quieres publicar desde la barra lateral. Cuando tu publicas, el(los) aspectos que has seleccionado en la lista de la izquierda serán automáticamente seleccionados en el selector de aspectos cuado hagas una nueva publicación." post_multiple_aspects_q: "¿Puedo realizar publicaciones en varios aspectos a la vez?" - remove_notification_a: "No." + remove_notification_a: "No. No serán notificados si les añades en más aspectos cuando ya estás compartiendo con ellos." remove_notification_q: "Si yo elimino alguien de un aspecto, o de todos mis aspectos, ellos son notificados de esto?" rename_aspect_a: "SÃ. En tu lista de aspectos en el lado izquierdo de la pagina principal, apunta tu mouse hacia el aspecto que quieres renombrar. Haz click en el pequeño lapiz \"editar\" que aparece en la derecha. Haz click en la caja \"renombrar\" que aparece." rename_aspect_q: "¿Cómo renombro un aspecto?" @@ -376,7 +362,7 @@ es: foundation_website: "página web de la fundación Diaspora*" getting_help: get_support_a_faq: "Lee nuestra página %{faq} en la wiki" - get_support_a_hashtag: "pregunta en una publicación pública en diaspora* usando el hashtag %{question}" + get_support_a_hashtag: "Pregunta en un mensaje público en diaspora* usando la etiqueta %{question}" get_support_a_irc: "Únete a nosotros en %{irc} (chat en vivo)" get_support_a_tutorials: "Consulta nuestros %{tutorials}" get_support_a_website: "VisÃtanos en %{link}" @@ -409,7 +395,7 @@ es: see_mentions_a: "SÃ, pulsa en \"@menciones\" en la columna izquierda de tu pagina principal." see_mentions_q: "¿Hay alguna forma de ver las publicaciones en las cuales he sido mencionado?" title: "Menciones" - what_is_a_mention_a: "Una mención es un enlace a el perfil de una persona que aparece en una publicación. Cuando alguien es mencionado, recibirá una notificación que llama su atención a la publicación." + what_is_a_mention_a: "Una mención es un enlace a el perfil de una persona que aparece en una publicación. Cuando alguien es mencionado, recibirá una notificación que llamará su atención a la publicación." what_is_a_mention_q: "¿Qué es una \"mención\"?" miscellaneous: back_to_top_a: "SÃ. Después de haberse desplazado hacia abajo en la página, haga click en la flecha gris que aparece en la esquina inferior derecha de la ventana de su navegador." @@ -427,7 +413,7 @@ es: title: "Vainas (Servidores)" use_search_box_a: "Si conoces su ID de diaspora* completo (ej. nombreusuario@nombrevaina.org) puedes encontrales al buscar desde ahÃ. Si estas en su mismo pod, puedes buscarle por su nombre de usuario. Una alternativa es buscar por su nombre de perfil (el nombre que ves en la pantalla). Si una búsqueda no funciona a la primera, inténtalo denuevo." use_search_box_q: "Como uso la caja de búsqueda para encontrar individuos particulares?" - what_is_a_pod_a: "Una vaina es un servidor ejecutanto el software diaspora* y conectado a la red diaspora*. \"Vaina\" es una metafora refiriendose a las vainas (pod en ingles) en las plantas que contienen semillas, en la forma en que un servidor contiene un número de cuentas de usuario. Hay muchos pods diferentes. Puedes agregar amigos de otros pods y comunicarte con ellos. (Puedes pensar en las vainas de diaspora* como un proveedor de e-mail: hay vainas publicas, privadas, y con algún esfuerzo puedes incluso ejecutar la tuya)." + what_is_a_pod_a: "Un pod es un servidor ejecutanto el software diaspora* y conectado a la red diaspora*. \"Pod\" es una metafora refiriendose a las vainas -pod en ingles- de las plantas que contienen semillas, al igual que un servidor contiene un número de cuentas de usuario. Hay muchos pods diferentes. Puedes agregar amigos de otros pods y comunicarte con ellos. Puedes pensar en las vainas de diaspora* como un proveedor de e-mail. Hay pods publicos, privados, y con algún esfuerzo puedes incluso ejecutar el tuyo." what_is_a_pod_q: "¿Qué es una vaina?" posts_and_posting: char_limit_services_a: "En esos casos tu publicación está limitada al menor número de caracteres (140 en el caso de Twitter; 1000 en el caso de Tumblr), y el número de caracteres que tienes restantes para usar es mostrado cuando el icono del servicio esta resaltado. Puedes aún asà publicar para esos servicios si tu publicación sobrepasa el lÃmite, pero el texto sera truncado para aquellos." @@ -547,84 +533,77 @@ es: tutorial: "tutorial" tutorials: "tutoriales" wiki: "wiki" - hide: "Ocultar publicación" - ignore: "Ignorar" + home: + default: + be_who_you_want_to_be: "Sé quien quieras ser" + be_who_you_want_to_be_info: "Muchas redes insisten en que uses tu identiadd real. diaspora* no. Aquà tú puedes elegir quién quieres ser y compartir tanto o tan poco sobre tà mismo como tú quieras. Realmente depende de ti cómo quieres interactuar con otras personas." + byline: "La red social mundial donde tú tienes el control" + choose_your_audience: "Escoge tu público" + choose_your_audience_info: "Los aspectos de diaspora* te permiten compartir sólamente con las personas que quieras. Puedes ser tan público o privado como prefieras. Comparte una foto divertida con el mundo entero, o un oscuro secreto con tus amigos más cercanos. Tú tienes el control." + headline: "Bienvenido a %{pod_name}" + own_your_data: "Sé el dueño de tus datos" + own_your_data_info: "Muchas redes usan tus datos para hacer dinero analizando tus interacciones y usando esa información para mostrarte anuncios. diaspora* no usa tus datos para ningún propósito distinto que permitirte estar en contacto con otros." + podmin: + admin_panel: "panel de administración" + byline: "Estas a punto de cambiar internet. Vamos a configurarlo, ¿de acuerdo?" + configuration_info: "Abre %{database_path} y %{diaspora_path} en tu editor de texto favorito y revisalos cuidadosamente, están comentados al detalle." + configure_your_pod: "Configura tu pod" + contact_irc: "contáctanos en el IRC" + contribute: "Colabora" + contribute_info: "¡Haz diaspora* aún mejor! Si encuentras algún fallo, por favor %{report_bugs}." + create_an_account: "Crear una cuenta" + create_an_account_info: "%{sign_up_link} para crear una cuenta." + faq_for_podmins: "FAQ para los administradores de los pod en nuestra wiki" + getting_help: "Obtener ayuda" + getting_help_info: "Mostramos algunas %{faq} incluyendo algunos consejos adicionales, trucos y soluciones para los problemas más comunes. También puedes probar %{irc}." + headline: "¡Bienvenido!" + make_yourself_an_admin: "Conviértete en administrador" + make_yourself_an_admin_info: "Puedes encontrar instrucciones en la %{wiki}. Esto añadirá un enlace \"Administrador\" a tu menú de usuario en el encabezado cuando inicies sesión. Esto añadirá funciones como búsqueda de usuarios y estadÃsticas de tu pod. Para detalles avanzados en el aspecto operacional, ve al %{admin_panel}" + report_bugs: "repórtalos" + update_instructions: "actualiza las instrucciones en la wiki de diaspora*" + update_your_pod: "Actualiza tu pod" + update_your_pod_info: "Puedes encontrar %{update_instructions}" invitation_codes: - excited: "%{name} está encantado de verte por aquÃ." not_valid: "Ese código de invitación ya no es válido" invitations: a_facebook_user: "Un usuario de Facebook" check_token: not_found: "Identificación de invitación no encontrada" create: - already_contacts: "Ya estás conectado con esta persona" - already_sent: "Ya has invitado a esta persona." empty: "Por favor, introduce al menos una dirección de correo electrónico." no_more: "No tienes más invitaciones." note_already_sent: "Las invitaciones han sido enviadas a: %{emails}" - own_address: "No puedes enviar una invitación a tu propio correo." rejected: "Hubo problemas con las siguientes direcciones de correo: " sent: "Las invitaciones han sido enviadas a: %{emails}" - edit: - accept_your_invitation: "Aceptar tu invitación" - your_account_awaits: "¡Tu cuenta te espera!" new: - already_invited: "La siguiente persona no ha aceptado tu invitación:" - aspect: "Aspecto" - check_out_diaspora: "¡Echa un vistazo a Diaspora!" codes_left: one: "Queda %{count} invitación para este código" other: "Quedan %{count} invitaciones para este código" zero: "No quedan invitaciones para este código" comma_separated_plz: "Puedes introducir múltiples direcciones de correo electrónico separadas por comas." - if_they_accept_info: "Si acepta, se añadirá al aspecto seleccionado." invite_someone_to_join: "¡Invita a alguien a unirse a Diaspora*!" language: "Idioma" paste_link: "¡Comparte este enlace con tus amigos para invitarles a diaspora*, o envÃaselo directamente por correo electrónico!" - personal_message: "Mensaje personal" - resend: "Reenviar" send_an_invitation: "Enviar una invitación" - send_invitation: "Enviar invitación" sending_invitation: "Enviando invitación..." - to: "Para" layouts: application: back_to_top: "Volver arriba" + be_excellent: "¡Sed buenos! ♥" powered_by: "Impulsado por Diaspora*" public_feed: "Canal público de %{name} " source_package: "Descargar el paquete del código fuente" statistics_link: "EstadÃsticas del pod" toggle: "Cambiar a interfaz móvil" whats_new: "Novedades" - your_aspects: "Tus aspectos" header: - admin: "Administrar" - blog: "Blog" code: "Código" - help: "Ayuda" - login: "Acceder" logout: "Salir" profile: "Perfil" - recent_notifications: "Notificaciones recientes" settings: "Ajustes" - view_all: "Ver todo" - likes: - likes: - people_dislike_this: - one: "A 1 persona no le gusta" - other: "A %{count} personas no les gusta" - zero: "A nadie le disgusta" - people_like_this: - one: "Le gusta a %{count} persona" - other: "Le gusta a %{count} personas" - zero: "A nadie le gusta" - people_like_this_comment: - one: "Le gusta a %{count} persona" - other: "Le gusta a %{count} personas" - zero: "A nadie le gusta" + toggle_navigation: "Cambiar navegación" limited: "Limitado" more: "Más" - next: "Siguiente" no_results: "No hay resultados" notifications: also_commented: @@ -639,11 +618,6 @@ es: one: "%{actors} ha comentado tu %{post_link}." other: "%{actors} han comentado tu %{post_link}." zero: "%{actors} comentarios en tu %{post_link}." - helper: - new_notifications: - one: "1 notificación nueva" - other: "%{count} notificaciones nuevas" - zero: "No hay notificaciones nuevas" index: all_notifications: "Todas las Notificaciones" also_commented: "Otros comentarios" @@ -702,7 +676,6 @@ es: a_limited_post_comment: "Hay un nuevo comentario en una publicación limitada en diaspora* para que lo consultes." a_post_you_shared: "una publicación." a_private_message: "Hay un nuevo mensaje privado en diaspora* para que lo consultes." - accept_invite: "¡Acepta tu invitación a diaspora*!" also_commented: limited_subject: "Hay un nuevo comentario en una publicación que comentaste" click_here: "Pulsa aquÃ" @@ -760,16 +733,18 @@ es: message: |- ¡Hola! - ¡Has recibido una invitación para unirte a diaspora*! + ¡Has recibido una invitación para unirte a diaspora* de %{diaspora_id}! Sigue este enlace para comenzar [%{invite_url}][1] + O puedes añadir %{diaspora_id} a tus contactos si ya tienes una cuenta. + Saludos, - ¡El generador de correo automático de Diaspora*! + ¡El generador de correo automático de diaspora*! P.D.: ¡En el caso de que (todavÃa) no sepas qué es diaspora*, [aquÃ][2] está la respuesta! @@ -782,10 +757,10 @@ es: view_post: "Ver comentario >" mentioned: limited_post: "Se te mencionó en un post privado." - mentioned: "te mencionó en una publicación:" subject: "%{name} te mencionó en diaspora*" private_message: reply_to_or_view: "Responder o ver esta conversación >" + subject: "Tienes un nuevo mensaje privado" remove_old_user: body: |- Hola, @@ -836,20 +811,9 @@ es: to_change_your_notification_settings: "para cambiar tus ajustes de notificación" nsfw: "No apto para todos los públicos" ok: "Aceptar" - or: "o" - password: "Contraseña" - password_confirmation: "Confirmación de la contraseña" people: add_contact: invited_by: "Fuiste invitado por" - add_contact_small: - add_contact_from_tag: "Añadir contacto desde una etiqueta" - aspect_list: - edit_membership: "editar aspectos asociados" - helper: - is_not_sharing: "%{name} no está compartiendo contigo" - is_sharing: "%{name} está compartiendo contigo" - results_for: "resultados para %{params}" index: couldnt_find_them: "¿No pudiste encontrarlos?" looking_for: "¿Buscando publicaciones sobre %{tag_link}?" @@ -859,105 +823,66 @@ es: search_handle: "Utiliza su ID de Diaspora* (usuario@pod.tld) para estar seguro de que encontrarás a tus amigos." searching: "Buscando, por favor sé paciente…" send_invite: "¿TodavÃa nadie? ¡EnvÃa una invitación!" - one: "1 persona" - other: "%{count} personas" person: - add_contact: "Añadir contacto" - already_connected: "Ya conectado" - pending_request: "Solicitud pendiente" thats_you: "¡Ese eres tú!" profile_sidebar: bio: "BiografÃa" born: "Fecha de nacimiento" - edit_my_profile: "Editar mi perfil" gender: "Género" - in_aspects: "En los aspectos" location: "Ubicación" - photos: "Fotos" - remove_contact: "Eliminar contacto" - remove_from: "¿Eliminar a %{name} de %{aspect}?" show: closed_account: "Esta cuenta ha sido eliminada." does_not_exist: "¡La persona no existe!" has_not_shared_with_you_yet: "¡%{name} todavÃa no ha compartido ninguna publicación contigo!" - ignoring: "Estás ignorando todas las publicaciones de %{name}." - incoming_request: "%{name} quisiera compartir contigo" - mention: "Mención" - message: "Mensaje" - not_connected: "No estás compartiendo con esta persona." - recent_posts: "Últimas publicaciones" - recent_public_posts: "Últimas publicaciones públicas" - return_to_aspects: "Volver a tu página de aspectos" - see_all: "Ver todos" - start_sharing: "Empezar a compartir" - to_accept_or_ignore: "aceptar o ignorar" - sub_header: - add_some: "Añadir algunos" - edit: "Editar" - you_have_no_tags: "¡No tienes etiquetas!" - webfinger: - fail: "Perdona, no pudimos encontrar %{handle}." - zero: "0 personas" photos: - comment_email_subject: "FotografÃa de %{name}" create: integrity_error: "Error subiendo la foto. ¿Seguro que era una imagen?" runtime_error: "Error subiendo la foto. ¿Alguna restricción de seguridad?" type_error: "Error subiendo la foto. ¿Seguro que añadiste la imagen?" destroy: notice: "Foto eliminada." - edit: - editing: "Editando" - new: - back_to_list: "Volver a la lista" - new_photo: "Nueva fotografÃa" - post_it: "¡PublÃcalo!" new_photo: empty: "{file} está vacÃo, por favor selecciona otros archivos." invalid_ext: "{file} tiene una extensión inválida. Sólo {extensions} están permitidas." size_error: "{file} es demasiado largo, el tamaño máximo por archivo es de {sizeLimit}." new_profile_photo: - or_select_one_existing: "o selecciona alguna de las %{photos} ya existentes" upload: "¡Sube una foto nueva de perfil!" - photo: - view_all: "Ver todas las fotografÃas de %{name}" show: - collection_permalink: "Enlace permanente a la colección" - delete_photo: "Eliminar fotografÃa" - edit: "Editar" - edit_delete_photo: "Editar pie de foto / eliminar foto" - make_profile_photo: "Convertir en foto de perfil" show_original_post: "Mostrar la publicación original" - update_photo: "Actualizar fotografÃa" - update: - error: "Error editando la foto." - notice: "Foto actualizada con éxito." + polls: + votes: + one: "%{count} voto por ahora" + other: "%{count} votos oor ahora" + zero: "Ningún voto por ahora" posts: presenter: title: "Una publicación de %{name}" show: - destroy: "Eliminar" forbidden: "No tienes permiso para hacer eso" - not_found: "Lo sentimos, no podemos encontrar esa publicación." - permalink: "Enlace permanente" + location: "Publicado desde %{location}" photos_by: one: "Una foto por %{author}" other: "%{count} fotos por %{author}" zero: "Ninguna foto por %{author}" reshare_by: "Vuelto a compartir por %{author}" - previous: "Anterior" privacy: "Privacidad" - privacy_policy: "PolÃtica de Privacidad" profile: "Perfil" profiles: edit: allow_search: "Permitir que la gente te busque dentro de Diaspora*" - edit_profile: "Editar perfil" + basic: "Mi perfil básico" + basic_hint: "Cada campo de tu perfil es opcional. Tu perfil básico siempre será visible para todos." + extended: "Mi perfil extendido" + extended_hint: "Pulsa el interruptor para configurar la visibilidad de los datos del perfil extendido. Público significa que es visible en internet, limitado significa que sólo las personas con quien compartes verán esta información." + extended_visibility_text: "Visibilidad de tu perfil extendido" first_name: "Nombre" last_name: "Apellidos" + limited: "Limitado" nsfw_check: "Marcar todo lo que comparto como NSFW ('no es seguro para el trabajo)." nsfw_explanation: "\"No es seguro para el trabajo\" (NSFW-'not safe for work') es un estándar de la comunidad de diaspora autónomo para el contenido que puede no ser adecuado para ver mientras estas trabajando. Si planeas compartir este material con frecuencia, por favor marca esta opción para que todo lo que compartas esté escondido para las personas comunes a menos que ellos elijan verlas." nsfw_explanation2: "Si eliges no marcar esta opción, por favor agrega la etiqueta #nsfw cada vez que compartas un material de este tipo." + public: "Público" + settings: "Configuración del perfil" update_profile: "Actualizar perfil" your_bio: "BiografÃa" your_birthday: "Fecha de nacimiento" @@ -965,8 +890,6 @@ es: your_location: "Ubicación" your_name: "Tu nombre" your_photo: "Foto" - your_private_profile: "Perfil privado" - your_public_profile: "Perfil público" your_tags: "DescrÃbete en 5 palabras" your_tags_placeholder: "Como #pelÃculas #gatitos #viajes #profesor #madrid" update: @@ -981,26 +904,16 @@ es: closed: "Los registros están cerrados en este servidor de Diaspora." create: success: "¡Te has unido a Diaspora*!" - edit: - cancel_my_account: "Cancelar mi cuenta" - edit: "Editar %{name}" - leave_blank: "(déjalo en blanco si no quieres cambiarlo)" - password_to_confirm: "(necesitamos tu contraseña actual para confirmar los cambios)" - unhappy: "¿Triste?" - update: "Actualizar" invalid_invite: "¡El enlace de la invitación ya no es válido!" new: - create_my_account: "¡Crear mi cuenta!" email: "Correo electrónico" enter_email: "Escribe tu correo" enter_password: "Escribe una contraseña (seis caracteres como mÃnimo)" enter_password_again: "Escribe la misma contraseña como antes" enter_username: "Elige un nombre de usuario (letras, números o guiones bajos)" - join_the_movement: "¡Únete al movimiento!" password: "Contraseña" password_confirmation: "Confirmación de contraseña" sign_up: "Registrarse" - sign_up_message: "Redes Sociales con un ♥" submitting: "En proceso..." terms: "Creando una cuenta, usted acepta los %{terms_link}" terms_link: "términos del servicio" @@ -1013,45 +926,18 @@ es: post_label: "<b>Publicación</b>: %{title}" reason_label: "Razón: %{text}" reported_label: "<b>Reportado por</b> %{person}" + reported_user_details: "Detalles del usuario denunciado" review_link: "Marcar como revisado" status: - created: "El informe ha sido creado" destroyed: "La publicación ha sido eliminada" failed: "Algo salió mal" - marked: "El informe ha sido marcado como revisado" title: "Resúmen de Informes" - requests: - create: - sending: "Enviando" - sent: "¿Quieres compartir con %{name}?. Será visible la próxima vez que entre/n en Diaspora*." - destroy: - error: "¡Selecciona un aspecto!" - ignore: "Solicitud de contacto ignorada." - success: "Ahora estás compartiendo." - helper: - new_requests: - one: "¡nueva solicitud!" - other: "¡%{count} solicitudes nuevas!" - zero: "no hay nuevas solicitudes" - manage_aspect_contacts: - existing: "Contactos existentes" - manage_within: "Gestión de contactos" - new_request_to_person: - sent: "¡Enviado!" reshares: comment_email_subject: "%{resharer} compartió la publicación de %{author}" - create: - failure: "Hubo un error al compartir esta publicación." reshare: deleted: "La publicación original fue eliminada por su autor." - reshare: - one: "Se ha compartido 1 vez" - other: "Se ha compartido %{count} veces" - zero: "Compartir" reshare_confirmation: "¿Compartir la publicación de %{author}?" - reshare_original: "Compartir original" reshared_via: "Compartido a través de" - show_original: "Mostrar el original" search: "Buscar" services: create: @@ -1063,10 +949,6 @@ es: success: "Autenticación eliminada con éxito." failure: error: "Hubo un error conectando a ese servicio" - finder: - fetching_contacts: "Diaspora está trasladando tus contactos de %{service}; vuelve a intentarlo en unos minutos." - no_friends: "No se han encontrados contactos en Facebook." - service_friends: "Contactos de %{service}" index: connect: "Conectar" disconnect: "Desconectar" @@ -1075,57 +957,28 @@ es: no_services_available: "No hay servicios disponibles en este pod." not_logged_in: "Usuario no identificado." really_disconnect: "¿Desconectar %{service}?" - services_explanation: "Conectar con servicios te da la posibilidad de publicar tus mensajes en ellos a medida que los escribes en diaspora." - inviter: - click_link_to_accept_invitation: "Sigue este enlace para aceptar tu invitación" - join_me_on_diaspora: "Nos vemos en diaspora*." + services_explanation: "Conectar con servicios de terceros te da la posibilidad de publicar tus mensajes en ellos a medida que los escribes en diaspora*." + share_to: "Compartir con %{provider}" + title: "Administrar servicios conectados" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "Invitar" - not_on_diaspora: "Aún no está en Diaspora" - resend: "Reenviar" settings: "Ajustes" - share_visibilites: - update: - post_hidden_and_muted: "La publicación de %{name} ha sido ocultada, y las notificaciones desactivadas." - see_it_on_their_profile: "Si quieres ver actualizaciones sobre esta publicación, visita el perfil de %{name}." shared: - add_contact: - add_new_contact: "Añade un nuevo contacto" - create_request: "Encontrar por el ID de Diaspora*" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Introduce un nombre de usuario de Diaspora*:" - know_email: "¿Conoces sus direcciones de correo? PodrÃas invitarles" - your_diaspora_username_is: "Tu nombre de usuario Diaspora* es: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Añadir contacto" mobile_row_checked: "%{name} (eliminar)" mobile_row_unchecked: "%{name} (añadir)" toggle: one: "En %{count} aspecto" other: "En %{count} aspectos" zero: "Añadir contacto" - contact_list: - all_contacts: "Todos los contactos" - footer: - logged_in_as: "Conectado como %{name}" - your_aspects: "Tus aspectos" invitations: by_email: "Por correo electrónico" - dont_have_now: "No tienes invitaciones ahora mismo pero, ¡pronto llegarán más!" - from_facebook: "Por Facebook" - invitations_left: "%{count} restantes" - invite_someone: "Invita a alguien" invite_your_friends: "Invita a tus contactos" invites: "Invitaciones" - invites_closed: "Las invitaciones en este servidor diaspora* están cerradas actualmente" share_this: "¡Comparte este enlace a través de correo electrónico, blog o tu red social favorita!" - notification: - new: "Nuevo %{type} de %{from}" public_explain: atom_feed: "canal Atom" control_your_audience: "Controla tu público" @@ -1137,12 +990,9 @@ es: title: "Configurar los servicios conectados" visibility_dropdown: "Usa este menú desplegable para cambiar la visibilidad de tu publicación. (Sugerimos hacerlo público la primera vez.)" publisher: - all: "Todo" - all_contacts: "Todos los contactos" discard_post: "Descartar publicación" formatWithMarkdown: "Puedes usar %{markdown_link} para dar formato al mensaje." get_location: "Obtener tu localización" - make_public: "Hacer público" new_user_prefill: hello: "Hola a todos, soy #%{new_user_tag}. " i_like: "Tengo interés en %{tags}. " @@ -1150,36 +1000,14 @@ es: newhere: "Hola" poll: add_a_poll: "Crear una encuesta" - add_poll_answer: "Añadir opción" - option: "Opción 1" - question: "Pregunta" - remove_poll_answer: "Quitar opción" - post_a_message_to: "Publicar un mensaje en %{aspect}" posting: "Publicando..." - preview: "Vista previa" - publishing_to: "Publicar en: " remove_location: "Eliminar ubicación" share: "Compartir" - share_with: "Compartir con" upload_photos: "Subir fotos" whats_on_your_mind: "¿Qué estás pensando?" - reshare: - reshare: "Compartir" stream_element: - connect_to_comment: "Conecta con esta persona para comentar en su publicación" - currently_unavailable: "Comentarios no disponibles en este momento" - dislike: "No me gusta" - hide_and_mute: "Ignorar la publicación" - ignore_user: "Ignorar a %{name}" - ignore_user_description: "¿Ignorar y quitar a esa persona de todos los aspectos?" - like: "Me gusta" - nsfw: "Esta publicación ha sido calificada por su autor como no apta para todos los públicos. %{link}" - shared_with: "Compartido con: %{aspect_names}" - show: "Mostrar" - unlike: "No me gusta" via: "VÃa %{link}" via_mobile: "VÃa móvil" - viewable_to_anyone: "Esta publicación podrá verla cualquiera en internet" simple_captcha: label: "Ingrese el código en el recuadro." message: @@ -1205,21 +1033,12 @@ es: status_messages: create: success: "Se ha mencionado con éxito a: %{names}" - destroy: - failure: "Hubo un error al eliminar la publicación" - helper: - no_message_to_display: "No hay mensajes que mostrar." new: mentioning: "Menciones: %{person}" too_long: "Por favor, pon un mensaje de estado menor de %{count} caracteres. Actualmente ocupa %{current_length} caracteres." stream_helper: - hide_comments: "Ocultar comentarios" no_more_posts: "Has llegado al final de la página." no_posts_yet: "TodavÃa no hay publicaciones." - show_comments: - one: "Mostrar un comentario más" - other: "Mostrar %{count} comentarios más" - zero: "No hay más comentarios" streams: activity: title: "Mi actividad" @@ -1246,13 +1065,6 @@ es: tags: title: "Publicaciones etiquetadas: %{tags}" tag_followings: - create: - failure: "Error al seguir a #%{name}. ¿Estás siguiéndolo ya?" - none: "¡No puedes seguir una etiqueta vacÃa!" - success: "¡SÃ! Ahora sigues publicaciones sobre: #%{name}." - destroy: - failure: "Error al dejar de seguir #%{name}. ¿Tal vez ya lo hiciste?" - success: "¡Ay! Ya no estás siguiendo #%{name}." manage: no_tags: "No estás suscrito a ninguna etiqueta." title: "Administra las etiquetas suscritas" @@ -1260,15 +1072,12 @@ es: name_too_long: "Por favor haz que tu mensaje de estado tenga menos de %{count} caracteres. En este momento el máximo permitido es de %{current_length} caracteres." show: follow: "Seguir #%{tag}" - following: "Siguiendo #%{tag}" none: "¡La etiqueta vacÃa no existe!" stop_following: "Dejar de seguir #%{tag}" tagged_people: one: "Una persona etiquetada con %{tag}" other: "%{count} personas etiquetadas con %{tag}" zero: "Nadie etiquetado con %{tag}" - terms_and_conditions: "Términos y Condiciones" - undo: "¿Deshacer?" username: "Nombre de usuario" users: confirm_email: @@ -1283,33 +1092,31 @@ es: auto_follow_aspect: "Aspecto para los usuarios seguidos automáticamente:" auto_follow_back: "Seguir automáticamente a los usuarios que te sigan" change: "Cambiar" + change_color_theme: "Cambiar el color del tema" change_email: "Cambiar correo" change_language: "Cambiar idioma" change_password: "Cambiar contraseña" character_minimum_expl: "mÃnimo seis caracteres" close_account: dont_go: "¡Eh, no te vayas!" - if_you_want_this: "Si de verdad quieres hacerlo, teclea tu contraseña debajo y haz click en 'Eliminar Cuenta'" lock_username: "Se bloqueará tu nombre de usuario. No podrás crear una nueva cuenta en este pod con el mismo ID." locked_out: "Serás desconectado y tu cuenta bloqueada hasta que se haya borrado." - make_diaspora_better: "Nos gustarÃa que te quedaras con nosotros y nos ayudaras a hacer de diaspora* un sitio mejor en lugar de dejarnos.. Si quieres irte, queremos que sepas lo que sucede a continuación:" + make_diaspora_better: "Nos gustarÃa que te quedaras con nosotros y nos ayudaras a hacer de diaspora* un sitio mejor en lugar de dejarnos. Si quieres irte, queremos que sepas lo que sucede a continuación:" mr_wiggles: "El TÃo la Vara estará triste si te vas" no_turning_back: "No hay vuelta atrás!. Si estás totalmente seguro, entra tu contraseña a continuación." - what_we_delete: "Eliminaremos todas tus publicaciones y datos del perfil, tan pronto como sea posible. Tus comentarios seguirán en lÃnea, pero asociados a tu dirección Diaspora* en lugar de a tu nombre." + what_we_delete: "Eliminaremos todas tus publicaciones y datos del perfil, tan pronto como sea posible. Tus comentarios en las publicaciones de otros seguirán apareciendo, pero asociados a tu dirección Diaspora* en lugar de a tu nombre." close_account_text: "Eliminar cuenta" comment_on_post: "...alguien comentó en tu publicación" current_password: "Contraseña actual" current_password_expl: "con la que inicias sesión..." download_export: "Descargar mi perfil" download_export_photos: "Descargar mis fotografÃas" - download_photos: "Descargar mis fotografÃas" edit_account: "Editar cuenta" email_awaiting_confirmation: "Te hemos enviado un enlace de activación a %{unconfirmed_email}. Hasta que no sigas este enlace y actives la nueva dirección, continuaremos usando tu dirección original %{email}." export_data: "Exportar datos" export_in_progress: "Actualmente estamos procesando tus datos. Por favor, vuelve en unos minutos." export_photos_in_progress: "En este momento estamos procesando tus fotografÃas. Por favor, vuelva en unos instantes." following: "Ajustes de Seguimiento" - getting_started: "Preferencias del Nuevo Usuario" last_exported_at: "(Última actualización el %{timestamp})" liked: "a alguien le gusta tu publicación" mentioned: "te mencionan en una publicación" @@ -1334,21 +1141,22 @@ es: community_welcome: "¡La comunidad de Diaspora está feliz de tenerte a bordo!" connect_to_facebook: "Podemos acelerar un poquito las cosas al %{link} a Diaspora. Esto permitirá usar tu mismo nombre y foto, además de habilitar la publicación cruzada." connect_to_facebook_link: "Conectando tu cuenta de Facebook" - hashtag_explanation: "Las etiquetas te permiten hablar sobre tus intereses asà como seguirlos. Además es una forma genial de encontrar gente nueva en Diaspora. " + hashtag_explanation: "Las etiquetas te permiten hablar sobre tus intereses asà como seguirlos. Además es una buena forma de encontrar gente nueva en diaspora*." hashtag_suggestions: "Prueba a seguir etiquetas como #arte, #cine, #activismo, #libros, etc." - saved: "¡Guardado!" well_hello_there: "Bueno, ¿qué tal?" what_are_you_in_to: "¿Qué te atrae?" who_are_you: "¿Quién eres?" privacy_settings: ignored_users: "Usuarios ignorados" no_user_ignored_message: "En este momento no estás ignorando a ningún usuario" - stop_ignoring: "dejar de ignorar" + stop_ignoring: "Dejar de ignorar" strip_exif: "Descartar metadatos como la localización, el autor o el modelo de la cámara en las imágenes subidas (recomendado)" title: "Ajustes de privacidad" public: does_not_exist: "¡La persona %{username} no existe!" update: + color_theme_changed: "Se cambió correctamente el color del tema." + color_theme_not_changed: "Ha ocurrido un error cambiando el color del tema." email_notifications_changed: "Las notificaciones por correo han cambiado" follow_settings_changed: "Ajustes de seguimiento modificados" follow_settings_not_changed: "Error al cambiar los ajustes de seguimiento." @@ -1360,13 +1168,6 @@ es: settings_updated: "Ajustes actualizados" unconfirmed_email_changed: "Correo electrónico cambiado. Necesitas activarlo." unconfirmed_email_not_changed: "Error al cambiar el correo." - webfinger: - fetch_failed: "Error al buscar el perfil webfinger de %{profile_url}" - hcard_fetch_failed: "Hubo un problema al buscar el hcard para #{@account}" - no_person_constructed: "Ninguna persona pudo ser creada a partir de este hcard." - not_enabled: "El webfinger parece no estar habilitado para el host de %{account}" - xrd_fetch_failed: "Hubo un error al recibir el xrd desde la cuenta %{account}" - welcome: "Bienvenido!" will_paginate: next_label: "siguiente »" previous_label: "« anterior" \ No newline at end of file diff --git a/config/locales/diaspora/et.yml b/config/locales/diaspora/et.yml index 334b13541a28a615666ab7c080d73d96ae602133..056efcbd84b1e6d6fb4f5139cc533eb9ad34a102 100644 --- a/config/locales/diaspora/et.yml +++ b/config/locales/diaspora/et.yml @@ -6,29 +6,19 @@ et: _applications: "Rakendused" - _photos: "pildid" _services: "Teenused" account: "Konto" - ago: "%{time} tagasi" are_you_sure: "Oled kindel?" are_you_sure_delete_account: "Oled kindel, et soovid oma konto kustutada? Kontot ei saa taastada!" - back: "Tagasi" cancel: "Tühista" delete: "Eemalda" email: "E-mail" find_people: "Otsi inimesi või #silte" - hide: "Peida" limited: "Piiratud" ok: "Oki" - or: "või" - password: "Salasõna" - password_confirmation: "Salasõna kinnitus" privacy: "Privaatsus" - privacy_policy: "Privaatsuspoliis" profile: "Profiil" public: "Avalik" search: "Otsi" settings: "Seaded" - terms_and_conditions: "Kasutajatingimused" - undo: "Võta tagasi?" username: "Kasutajanimi" \ No newline at end of file diff --git a/config/locales/diaspora/eu.yml b/config/locales/diaspora/eu.yml index 48f9dfc2d065ecef1dadfd6ca2f8e046bb14d79e..a86e80cb7bf9cbd3a4de4570fd9079b3d74337ed 100644 --- a/config/locales/diaspora/eu.yml +++ b/config/locales/diaspora/eu.yml @@ -6,10 +6,7 @@ eu: _applications: "Aplikazioak" - _comments: "Iruzkinak" _contacts: "Adiskideak" - _home: "Hasiera" - _photos: "argazkiak" _services: "Zerbitzuak" account: "Kontua" activerecord: @@ -88,13 +85,7 @@ eu: other: "erabiltzaile berriak azken astean: %{count}" zero: "erabiltzaile berririk ez azken astean" current_server: "Uneko zerbitzariaren data %{date} da" - ago: "%{time}" all_aspects: "Arlo guztiak" - application: - helper: - unknown_person: "pertsona ezezaguna" - video_title: - unknown: "Bideo izen ezezaguna" are_you_sure: "Ziur al zaude?" are_you_sure_delete_account: "Ziur zaude zure kontua ezabatu nahi duzunaz? Hayu ezin da desegin!" aspect_memberships: @@ -108,18 +99,10 @@ eu: success: "Adiskidea arrakastaz gehitu da arlora." aspect_listings: add_an_aspect: "+ Arlo berria sortu" - deselect_all: "Guztiak deshautatu" - edit_aspect: "Aldatu %{name}" - select_all: "Guztiak hautatu" aspect_stream: make_something: "Sortu zerbait" stay_updated: "Eguneratuta Mantendu" stay_updated_explanation: "Zure kronologia zure lagunek, jarraitzen dituzun etiketek, eta komunitateko pertsona nabarmenduen mezuek osatzen dute." - contacts_not_visible: "Arlo honetako lagunak nor dagoen bere arloan ezingo dute ikusi." - contacts_visible: "Arlo honetako lagunak jakingo dute nor dagoen arloan." - create: - failure: "Akatsa arloaren sormenean." - success: "Zure arlo berria, %{name}, sortua izan da." destroy: failure: "%{name} ez dago hutsik eta ezin izan da ezabatu." success: "%{name} arrakastaz ezabatu da." @@ -127,22 +110,13 @@ eu: aspect_list_is_not_visible: "arloaren zerrenda ezkutua da arloko besteentzat" aspect_list_is_visible: "arloaren zerrenda ikusgarria da arloko besteengandik" confirm_remove_aspect: "Ziur al zaude arlo hau ezabatu nahi duzunaz?" - make_aspect_list_visible: "arlo honetako lagunak ikusgarriak egin bata bestearekiko?" - remove_aspect: "Arlo hau ezabatu" rename: "berrizendatu" update: "eguneratu" updating: "eguneratzen" index: - diaspora_id: - content_1: "Zure Diaspora ID honakoa da:" - content_2: "Emaiozu edonori eta Diasporan aurkituko zaituzte hura erabiliz." - heading: "Diaspora IDa" donate: "Donatu" - handle_explanation: "Hau da zure Diaspora IDa. E-posta helbidea bezalakoa da, zure lagunei emaiezu zu aurkitzearren." help: do_you: "Zuk:" - email_feedback: "%{link} zure feedbacka, nahiago baduzu" - email_link: "E-posta" feature_suggestion: "... %{link} iradokizun bat duzu?" find_a_bug: "... %{link} bat aurkitu?" have_a_question: "... %{link} bat duzu?" @@ -152,31 +126,20 @@ eu: tag_feature: "funtzioa" tag_question: "galdera" introduce_yourself: "Hau zure kronologia da. Animatu eta zure burua aurkeztu." - keep_diaspora_running: "Diaspoaren garapena azkartu ezazu hilabeteroko donazio batekin!" keep_pod_running: "Mantendu %{pod} azkar izaten hornitzaileari kafe-konponketa ordainduz hilero!" new_here: follow: "Jarraitu %{link} eta emaiezu ongietorria Diasporako erabiltzaile berriei!" learn_more: "Ikasi gehiago" title: "Ongietorri Erabiltzaile Berriak" - no_contacts: "Adiskiderik ez" - no_tags: "+ Aurkitu jarraitzeko etiketa bat" - people_sharing_with_you: "Zurekin harremanetan dagoen jendea" - post_a_message: "mezu bat bidali >>" services: content: "Honako zerbitzuak lotu ditzakezu Diasporara:" heading: "Zerbitzuak Lotu" - unfollow_tag: "#%{tag} jarraitzeari utzi" welcome_to_diaspora: "Ongietorri Diasporara, %{name}!" - new: - create: "Sortu" - name: "Izena (zuk bakarrik ikus dezakezu)" no_contacts_message: community_spotlight: "komunitateko nabarmenena" or_spotlight: "Edo %{link}(e)z partekatu dezakezu" try_adding_some_more_contacts: "Adiskide gehiago bilatu edo gonbidatu ditzakezu." you_should_add_some_more_contacts: "Adiskide gehiago lortu beharko zenituzke!" - no_posts_message: - start_talking: "Oraindik inork ez du ezer esan!" seed: acquaintances: "Ezagunak" family: "Familia" @@ -185,7 +148,6 @@ eu: update: failure: "Zure arloak, %{name}(e)k, izen luzeegia du." success: "Zure arloa, %{name}, eraldatua izan da." - back: "Atzera" blocks: create: failure: "Ezin izan diot erabiltzaile horri muzin egin. #sahiestu" @@ -197,21 +159,14 @@ eu: explanation: "Partekatu zerbait Diasporan laster-markatara gehituz esteka hau => %{link}." heading: "Bookmarkleta" post_something: "Partekatu zerbait Diasporan" - post_success: "Bidalia! Irteten!" cancel: "Ezeztatu" comments: new_comment: comment: "Iruzkindu" commenting: "Iruzkintzen..." - one: "iruzkin 1" - other: "%{count} iruzkin" - zero: "iruzkinik ez" contacts: - create: - failure: "Akatsa lagun berria sortzean" index: add_a_new_aspect: "Arlo berria gehitu" - add_to_aspect: "Adiskideak gehitu %{name}(e)n" all_contacts: "Adiskide Guztiak" community_spotlight: "Komunitateko nabarmenduak" my_contacts: "Nire Adiskideak" @@ -220,29 +175,16 @@ eu: only_sharing_with_me: "Bakarrik nirekin harremanetan" start_a_conversation: "Elkarrizketa bat hasi" title: "Adiskideak" - your_contacts: "Zure Adiskideak" - sharing: - people_sharing: "Zurekin harremanetan daudenak:" spotlight: community_spotlight: "Komunitateko Nabarmenena" conversations: create: fail: "Mezu baliogabea" sent: "Mezua arrakastaz bidali da" - helper: - new_messages: - few: "%{count} mezu pribatu berri" - many: "%{count} mezu pribatu berri" - one: "mezu pribatu berri 1" - other: "%{count} mezu pribatu berri" - two: "%{count} new messages" - zero: "Mezu pribatu berririk ez" index: inbox: "Sarrera-ontzia" - no_conversation_selected: "ez da aukeratu elkarrizketarik" no_messages: "mezurik ez" new: - abandon_changes: "Aldaketak bertan behera utzi?" send: "Bidali" sending: "Bidaltzen..." subject: "gaia" @@ -261,46 +203,26 @@ eu: error_messages: helper: correct_the_following_errors_and_try_again: "Zuzendu honako akatsak eta saiatu berriro." - invalid_fields: "Eremu akasdunak" - login_try_again: "Mesedez <a href='%{login_link}'>sartu</a> eta saiatu berriz." - post_not_public: "Ikusten saiatzen ari zaren mezua ez da publikoa!" fill_me_out: "Bete nazazu" find_people: "Jendea edo #etiketak aurkitu" - hide: "Ezkutatu" - invitation_codes: - excited: "%{name} pozik dago zu ikusteaz" invitations: a_facebook_user: "Facebook erabiltzaile bat" check_token: not_found: "Gonbidapena ez da aurkitu" create: - already_contacts: "Pertsona honekin harremanetan zaude jadanik" - already_sent: "Pertsona hau gonbidatu duzu jada." no_more: "Ez daukazu gonbidapen gehiago." - own_address: "Ezin diozu zeure buruari gonbidapen bat bidali." rejected: "Hurrengo e-posta hauek arazoak sortu dituzte:" sent: "Gonbidapenen jasotzaileak hauek izan dira:" - edit: - accept_your_invitation: "Zure gonbidapena onartu" - your_account_awaits: "Zure kontuak itxaroten du!" new: - already_invited: "Pertsona hauek ez dute zure gonbidapena onartu:" - aspect: "Arloa" - check_out_diaspora: "Probatu Diaspora!" codes_left: one: "Gonbidapen bat geratzen zaizu kode honekin" other: "%{count} gonbidapen geratzen zaizkizu kode honekin" zero: "Ez zaizkizu geratzen gonbidapenak kode honekin" comma_separated_plz: "Email desberdinak jarri ditzakezu, koma batez bereiztuak." - if_they_accept_info: "eskaera onartzen badute, gonbidatutako arlora batuko dira" invite_someone_to_join: "Gonbida ezazu norbait Diasporan izen ematera!" language: "Hizkuntza" paste_link: "Partekatu esteka hau lagunekin Diasporara gonbidatzeko, edo bidali email bidez zuzenean." - personal_message: "Mezu pertsonala" - resend: "Berbidali" send_an_invitation: "Gonbidapen bat bidali" - send_invitation: "Gonbidapena bidali" - to: "Jasotzailea:" layouts: application: back_to_top: "Gora" @@ -308,43 +230,13 @@ eu: public_feed: "%{name}(r)en Diaspora Feed publikoa" toggle: "gaitu mugikorreko orrialdea" whats_new: "zer berri?" - your_aspects: "zure arloak" header: - admin: "kudeatu" - blog: "bloga" code: "kodea" - login: "sartu" logout: "Irten" profile: "Profila" - recent_notifications: "Jakinarazpen berrienak" settings: "Lehentasunak" - view_all: "Guztiak ikusi" - likes: - likes: - people_dislike_this: - few: "%{count} pertsonek ez dute hau gustuko" - many: "%{count} pertsonek ez dute hau gustuko" - one: "%{count}ek ez du hau gustuko" - other: "%{count} pertsonek ez dute hau gustuko" - two: "%{count} dislikes" - zero: "gustuko ez duen pertsonarik ez" - people_like_this: - few: "%{count} pertsonek gustuko dute hau" - many: "%{count} pertsonek gustuko dute hau" - one: "%{count}ek du gustuko" - other: "%{count} pertsonek gustuko dute hau" - two: "%{count}(e)k gustuko dute" - zero: "oraindik ez du inork gustuko" - people_like_this_comment: - few: "%{count}(e)k gustuko dute" - many: "%{count}(e)k gustuko dute" - one: "%{count}ek gustuko du" - other: "%{count}(e)k gustuko dute" - two: "%{count}(e)k gustuko dute" - zero: "inork ez du gustuko" limited: "Mugatua" more: "Gehiago" - next: "hurrengoa" no_results: "Ez Da Ezer Aurkitu" notifications: also_commented: @@ -368,14 +260,6 @@ eu: other: "%{actors}(e)k zure %{post_link} iruzkindu du(te)." two: "%{actors}(e)k zure %{post_link} iruzkindu du(te)." zero: "%{actors}(e)k zure %{post_link} iruzkindu du(te)." - helper: - new_notifications: - few: "%{count} jakinarazpen berri" - many: "%{count} jakinarazpen berri" - one: "jakinarazpen berri 1" - other: "%{count} jakinarazpen berri" - two: "%{count} jakinarazpen berri" - zero: "Jakinarazpen berririk ez" index: and: "eta" and_others: @@ -447,7 +331,6 @@ eu: zero: "%{actors} zurekin harremanetan hasi d(ir)a" notifier: a_post_you_shared: "mezu bat." - accept_invite: "Onartu zure Diaspora* gonbidapena!" click_here: "sakatu hau" comment_on_post: reply: "Erantzun edo ikusi %{name}(r)en mezua >" @@ -477,7 +360,6 @@ eu: liked: "%{name}(e)k zure mezua gustuko du" view_post: "Mezua ikusi >" mentioned: - mentioned: "zu aipatu zaituzte mezu batean:" subject: "%{name}(e)k Diasporan aipatu zaitu" private_message: reply_to_or_view: "Erantzun edo ikusi elkarrizketa hau >" @@ -495,103 +377,45 @@ eu: to_change_your_notification_settings: "zure jakinarazpenen lehentasunak aldatzeko" nsfw: "NSFW" ok: "Onartu" - or: "edo" - password: "Pasahitza" - password_confirmation: "Pasahitz baieztapena" people: add_contact: invited_by: "honek gonbidatu zaitu:" - add_contact_small: - add_contact_from_tag: "gehitu laguna etiketatik abiatuta" - aspect_list: - edit_membership: "aldatu arloaren bazkidetza" - helper: - results_for: " %{params}(r)entzat emaitzak" index: looking_for: "%{tag_link} etiketadun mrezuak bilatzen?" no_one_found: "... ez da inor aurkitu." no_results: "Aizu! Zerbait bilatu behar duzu." results_for: "bilaketa emaitzak hontarako:" searching: "bilatzen, mesedez itxaron pixka bat..." - one: "pertsona 1" - other: "%{count} pertsona" person: - add_contact: "laguna gehitu" - already_connected: "Dagoeneko harremanetan" - pending_request: "Onarpenaren zain" thats_you: "Zu zeu zara!" profile_sidebar: bio: "niri buruz" born: "jaioteguna" - edit_my_profile: "Nire profila aldatu" gender: "sexua" - in_aspects: "arloetan" location: "kokalekua" - remove_contact: "laguna ezabatu" - remove_from: "%{name} ezabatu %{aspect} arlotik?" show: closed_account: "Kontu hau ezabatua izan da." does_not_exist: "Pertsona hau ez dago!" has_not_shared_with_you_yet: "%{name}(e)k ez duzu mezurik partekatu zurekin oraindik!" - ignoring: "%{name}(r)en mezuak sahiesten ari zara." - incoming_request: "%{name}(e)k zure laguna izan nahi du" - mention: "Aipatu" - message: "Mezu pribatua bidali" - not_connected: "Ez zaude harremanetan pertsona honekin" - recent_posts: "Mezu Berrienak" - recent_public_posts: "Azken berri publikoak" - return_to_aspects: "Zure arlo orrialdera itzuli" - see_all: "Guztiak ikusi" - start_sharing: "harremanetan hasi" - to_accept_or_ignore: "onartu edo utzi." - sub_header: - add_some: "gehitu batzuk" - edit: "aldatu" - you_have_no_tags: "etiketarik ez duzu!" - webfinger: - fail: "%{handle} ezin izan dugu aurkitu." - zero: "jenderik ez" photos: - comment_email_subject: "%{name}(r)en argazkia" create: integrity_error: "Argazki igoerak huts egin du. Ziur al zaude irudi bat zela?" runtime_error: "Argazki igoerak huts egin du. Ziur zaude zure uhala azkarra dela?" type_error: "Argazki igoerak huts egin du. Ziur al zaude irudia gehitu duzunaz?" destroy: notice: "Argazkia ezabatu duzu." - edit: - editing: "Aldatzen" - new: - back_to_list: "Zerrendara itzuli" - new_photo: "Argazki Berria" - post_it: "partekatu ezazu!" new_photo: empty: "{file} hutsik dago, mesedez aukera itzazu fitxategiak hura kenduta." invalid_ext: "{file}(r)en luzapena ez da onartu. {extensions} dira onartuak soilik." size_error: "{file} pisutsuegia da, fitxategi baten gehiengo pisua {sizeLimit} da." new_profile_photo: - or_select_one_existing: "edo erabili dagoeneko dituzun %{photos}" upload: "Igo ezazu profil argazki berri bat!" - photo: - view_all: "%{aspect}(r)en argazki guztiak ikusi" show: - collection_permalink: "bildumako permalink" - delete_photo: "Argazkia Ezabatu" - edit: "aldatu" - edit_delete_photo: "Argazkiaren deskribapena aldatu / argazkia ezabatu" - make_profile_photo: "profileko argazki bihurtu" show_original_post: "Jatorrizko mezua erakutsi" - update_photo: "Argazkia Eguneratu" - update: - error: "Huts argazkia aldatzean." - notice: "Argazkia arrakastaz eguneratua." posts: presenter: title: "" show: - destroy: "Ezabatu" - not_found: "Barkatu, baina ezin izan dugu mezu hori aurkitu." - permalink: "permalinka" photos_by: few: "%{count} argazki %{author}(r)en eskutik" many: "%{count} argazki %{author}(r)en eskutik" @@ -600,14 +424,11 @@ eu: two: "Bi argazki %{author}(r)en eskutik" zero: "Argazkirik ez %{author}(r)en eskutik" reshare_by: "Birpartekaketa %{author}(r)en eskutik" - previous: "aurrekoa" privacy: "Pribatutasuna" - privacy_policy: "Pribatutasunaren Politika" profile: "Profila" profiles: edit: allow_search: "Jendea baimendu zu Diasporan bilatzera" - edit_profile: "Profila aldatu" first_name: "Izena" last_name: "Abizena" update_profile: "Profila Eguneratu" @@ -617,8 +438,6 @@ eu: your_location: "Zure kokalekua" your_name: "Zure izena" your_photo: "Zure argazkia" - your_private_profile: "Zure profil pribatua" - your_public_profile: "Zure profil publikoa" your_tags: "Zure burua deskribatu 5 hitzetan" your_tags_placeholder: "#filmak #katakumeak #bidaiak #irakaslea #newyork bezalakoak" update: @@ -636,64 +455,22 @@ eu: closed: "Izen emateak itxirik daude Diaspora zerbitzari hontan." create: success: "Diasporarekin bat egin duzu!" - edit: - cancel_my_account: "Nire kontua ezabatu" - edit: "%{name} aldatu" - leave_blank: "(hutsik utzi aldatu nahi ez baduzu)" - password_to_confirm: "(zure pasahitza behar dugu zure aldaketak gauzatzeko)" - unhappy: "Goibel?" - update: "Eguneratu" invalid_invite: "Eman duzun gonbidapen esteka ez da jada baliagarria!" new: - create_my_account: "Nire kontua sortu!" email: "EMAILA" enter_email: "Idatzi zure e-posta" enter_password: "Pasahitz bat idatzi (sei karaktere gutxienez)" enter_password_again: "Lehengo pasahitz berdina idatzi" enter_username: "Aukeratu erabiltzaile izen bat (hizkiak, zenbakiak eta gidoibaxuak soilik)" - join_the_movement: "Mugimendura batu!" password: "PASAHITZA" sign_up: "IZENA EMAN" - sign_up_message: "Sare Sozialak ♥ batekin" username: "ERABILTZAILE-IZENA" - requests: - create: - sending: "Bidaltzen" - sent: "%{name}(r)ekin harremanetan hasi nahi duzu. Diasporara sartzen diren hurrengo aldian ikusiko dute eskaera." - destroy: - error: "Arlo bat aukeratu, mesedez!" - ignore: "Adiskide eskaera baztertua." - success: "Orain lagun zarete." - helper: - new_requests: - few: "%{count} eskaera berri!" - many: "%{count} eskaera berri!" - one: "eskaera berria!" - other: "%{count} eskaera berri!" - two: "%{count} eskaera berri!" - zero: "eskaera berririk ez" - manage_aspect_contacts: - existing: "Adiskideak" - manage_within: "Adiskideak kudeatu hemen:" - new_request_to_person: - sent: "bidalia!" reshares: comment_email_subject: "%{author}(r)en mezuaren %{resharer}(r)en birpartekaketa" - create: - failure: "Huts mezu hau birpartekatzean." reshare: deleted: "Egileak jatorrizko mezua ezabatu du." - reshare: - few: "%{count} Birpartekaketa" - many: "%{count} Birpartekaketa" - one: "Birpartekaketa 1" - other: "%{count} birpartekaketa " - two: "%{count} birpartekaketa" - zero: "Birpartekatu" reshare_confirmation: "Birpartekatu %{author}(r)en mezua?" - reshare_original: "Birpartekatu jatorrizkoa" reshared_via: "birpartekatuta honen bidez:" - show_original: "Jatorrizkoa erakutsi" search: "Bilatu" services: create: @@ -704,58 +481,23 @@ eu: success: "Egiaztapena arrakastaz ezabatua." failure: error: "huts zerbitzu hori konektatzean" - finder: - fetching_contacts: "Diaspora zure %{service}(e)ko lagunekin betetzen ari da, mesedez saiatu berriz minutu batzuetan." - no_friends: "Ez dira Facebookeko lagunak aurkitu." - service_friends: "%{service}(e)ko Lagunak" index: disconnect: "irten" edit_services: "Aldatu zerbitzuak" logged_in_as: "Lotuta duzun kontua honakoa da:" really_disconnect: "irten %{service}(e)tik?" - inviter: - click_link_to_accept_invitation: "Jarraitu esteka hau zure gonbidapena onartzeko" - join_me_on_diaspora: "Bat egin nirekin DIASPORAN" - remote_friend: - invite: "gonbidapena" - not_on_diaspora: "Diasporan oraindik ez" - resend: "berbidali" settings: "Lehentasunak" - share_visibilites: - update: - post_hidden_and_muted: "%{name}(r)en mezua izkutatu egin da, eta jakinarazpenak isildu egin dira." - see_it_on_their_profile: "Mezu honen eguneraketak ikusi nahi badituzu, ikusi %{name}(r)en profil orrialdea." shared: - add_contact: - add_new_contact: "Adiskide berria gehitu" - create_request: "Diaspora IDaren arabera bilatu" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Diaspora erabiltzaile izena idatzi:" - know_email: "Badakizu beraien e-posta? Gonbida itzazu!" - your_diaspora_username_is: "Zure Diaspora helbidea honakoa da: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Adiskidea gehitu" toggle: one: "Arlo %{count}en" other: "%{count} arlotan" zero: "Adiskidea gehitu" - contact_list: - all_contacts: "Adiskide Guztiak" - footer: - logged_in_as: "%{name} zara" - your_aspects: "zure arloak" invitations: by_email: "Email bidez" - dont_have_now: "Bukatu egin zaizkizu, baina gonbidapen gehiago iritsiko dira laister!" - from_facebook: "Facebooketik" - invitations_left: "(%{count} dauzkazu" - invite_someone: "Norbait gonbidatu" invite_your_friends: "Zure lagunak gonbidatu" invites: "Gonbidapenak" - invites_closed: "Gonbidapenak itxita daude orain Diaspora zerbitzari hontan" share_this: "Partekatu ezazu esteka hau email, blog, edo sare sozial gogokoenen bidez!" - notification: - new: "%{type} berria %{from}(r)en eskutik" public_explain: atom_feed: "Atom feeda" control_your_audience: "Zure Jarraitzalieak kontrolatu" @@ -767,58 +509,25 @@ eu: title: "Zerbitzu konektatuak kudeatu" visibility_dropdown: "Erabili zabalgarri hau zure mezuaren ikusgarritasuna aldatzeko. (Lehenengo publikoa izatea aholkatzen dizugu.)" publisher: - all: "guztiak" - all_contacts: "lagun guztiak" discard_post: "Mezua baztertu" - make_public: "publikoa egin" new_user_prefill: hello: "Kaixo guztioi, #%{new_user_tag} naiz. " i_like: "%{tags} interesatzen zait." invited_by: "Eskerrik asko gonbidapenagatik, " newhere: "Berria" - post_a_message_to: "%{aspect}(e)n mezu bat partekatu" posting: "Partekatzen..." - publishing_to: "hemen partekatzen:" share: "Partekatu" - share_with: "honekin partekatu:" upload_photos: "Argazkiak igo" whats_on_your_mind: "Zer ari zara pentsatzen?" - reshare: - reshare: "Berriz partekatu" stream_element: - connect_to_comment: "Erabiltzaile honekin harremanetan jarri bere mezua iruzkintzeko" - currently_unavailable: "iruzkinak tenporalki desgaituak" - dislike: "Ez dut gustuko" - hide_and_mute: "Ezkutatu eta isildu mezua" - ignore_user: "Sahiestu %{name}" - ignore_user_description: "Sahiestu eta ezabatu erabiltzailea arlo guztietatik?" - like: "Gustoko dut" - nsfw: "Mezu hau NSFW gisa markatu du egileak. %{link}" - shared_with: "%{aspect_names}(r)kin partekatua" - show: "erakutsi" - unlike: "Ez dut gustuko" via: "%{link}(r)en bidez" via_mobile: "mugikorraren bidez" - viewable_to_anyone: "Mezu hau edonork ikusi dezake Interneten" status_messages: create: success: "Arrakastaz aipatu dituzu: %{names}" - destroy: - failure: "Akatsa mezua ezabatzean" - helper: - no_message_to_display: "Erakusteko mezurik ez." new: mentioning: "Aipatzen: %{person}" too_long: "{\"few\"=>\"mesedez, egin itzazu zure mezuak %{count} karaktere baino motzagoak\", \"many\"=>\"mesedez, egin itzazu zure mezuak %{count} karaktere baino motzagoak\", \"one\"=>\"mesedez, egin itzazu zure mezuak karaktere %{count} baino motzagoak\", \"other\"=>\"mesedez, egin itzazu zure mezuak %{count} karaktere baino motzagoak\", \"two\"=>\"mesedez egin itzazu zure mezuak %{count} laraktere baino motzagoak\", \"zero\"=>\"mesedez, egin itzazu zure mezuak %{count} karaktere baino motzagoak\"}" - stream_helper: - hide_comments: "Iruzkin guztiak ezkutatu" - show_comments: - few: "Erakutsi %{count} iruzkin gehiago" - many: "Erakutsi %{count} iruzkin gehiago" - one: "Erakutsi iruzki bat gehiago" - other: "Erakutsi %{count} iruzkin gehiago" - two: "Erakutsi bi iruzkin gehiago" - zero: "Ez dago iruzkin gehiago" streams: activity: title: "Nire Jarduera" @@ -844,22 +553,11 @@ eu: title: "Ekintza Publikoak" tags: title: "Mezu etiketatuak: %{tags}" - tag_followings: - create: - failure: "Huts #%{name} jarraitzean. Jada jarraitzen ari zara?" - none: "Ezin duzu jarraitu etiketa huts bat!" - success: "Aupa! #%{name} jarraitzen ari zara orain." - destroy: - failure: "Huts #%{name} jarraitzeari uztean. Beharbada jarraitzeari utzi diozu jada?" - success: "Arrakastaz #%{name} jarraitzeari utzi duzu." tags: show: follow: "Jarraitu #%{tag}" - following: "#%{tag} jarraitzen" none: "Etiketa hutsik ez dago!" stop_following: "Ez Jarraitu #%{tag}" - terms_and_conditions: "Termino eta Baldintzak" - undo: "Desegin?" username: "Erabiltzailea" users: confirm_email: @@ -880,7 +578,6 @@ eu: character_minimum_expl: "gutxienez sei karakterekoa izan behar da" close_account: dont_go: "Aizu, ez joan mesedez!" - if_you_want_this: "Bentan hau nahi baduzu, idatzi hemen zure pasahitza eta sakatu 'Kontua Ezabatu'" lock_username: "Honek zure erabiltzaile izena giltzapetuko du berriz izena eman nahi baduzu." locked_out: "Atera egingo zara eta zure kontutik botata." make_diaspora_better: "Diaspora hobetu nahi dugu, beraz mesedez lagundu gaitzazu joan ordez. Joaten bazara, egingo duzun hurrengoa jakin nahi dugu." @@ -891,12 +588,10 @@ eu: comment_on_post: "...norbaitek zure mezu bat iruzkintzen duenean?" current_password: "Pasahitz zaharra" current_password_expl: "sartzen zarenarekin..." - download_photos: "nire argazkiak jaitsi" edit_account: "Kontua aldatu" email_awaiting_confirmation: "Aktibaketa esteka bat bidali dizugu %{unconfirmed_email}(e)ra. Esteka hau jarraitzen duzun arte, zure jatorrizko e-postak, %{email}, jarraituko du erabilpenean." export_data: "Datuak esportatu" following: "Jarraipen Ezarpenak" - getting_started: "Erabiltzeile Berriaren Lehentasunak" liked: "...norbaitek zure mezu bat gustuko duenean?" mentioned: "...mezu batean aipatzen zaituztenean?" new_password: "Pasahitz berria" @@ -914,7 +609,6 @@ eu: community_welcome: "Diasporaren komunitatea zu etortzeagatik pozik dago!" hashtag_explanation: "Hashtagek gustuko duen jendea eta gauzak jarraitzea ahalbidetzen dizu. Jende berria ezagutzeko bide on bat dira baita ere." hashtag_suggestions: "Saiatu #artea, #filmak, #gif, etab. bezalako etiketak jarraitzen" - saved: "Gordeta!" well_hello_there: "Beno, kaixo!" what_are_you_in_to: "Zelan zabiltza?" who_are_you: "Zein zara?" @@ -936,13 +630,6 @@ eu: settings_updated: "Lehentasunak eguneratu dira" unconfirmed_email_changed: "E-Posta aldatua. Aktibaketa behar du." unconfirmed_email_not_changed: "E-Posta aldaketak huts egin du" - webfinger: - fetch_failed: "ezin izan da webfinger profila hartu %{profile_url} webgunetik" - hcard_fetch_failed: "%{account} kontutik ezin izan da hcard sortu" - no_person_constructed: "Ezin izan da pertsona sortu hcard erabiliz." - not_enabled: "webfinger ez dago aktibatuta %{account} zerbitzariarengatik" - xrd_fetch_failed: "akatsa sortu da %{account}(e)tik xrd lortzean" - welcome: "Ongietorri!" will_paginate: next_label: "hurrengoa »" previous_label: "« aurrekoa" \ No newline at end of file diff --git a/config/locales/diaspora/fa.yml b/config/locales/diaspora/fa.yml index 605270e1a16d50173524e28f996a9a5aa4dc1767..f488d69e12550707d6048db06708fec19755c9fb 100644 --- a/config/locales/diaspora/fa.yml +++ b/config/locales/diaspora/fa.yml @@ -6,10 +6,7 @@ fa: _applications: "برنامه‌های کاربردی" - _comments: "دیدگاه‌ها" _contacts: "مخاطبین" - _home: "خانه" - _photos: "عکس‌ها" _services: "سرویس‌ها" account: "Øساب کاربری" activerecord: @@ -40,13 +37,7 @@ fa: username: invalid: "نامعتبر است. Ùقط می‌توانید از ØروÙØŒ اعداد، Ùˆ خط تیره استÙاده کنید." taken: "درØال Øاظر گرÙته‌شده." - ago: "‎%{time}‎ پیش" all_aspects: "تمام منظرها" - application: - helper: - unknown_person: "شخص ناشناس" - video_title: - unknown: "عنوان ناشناس ویدئو" are_you_sure: "مطمئن هستید؟" are_you_sure_delete_account: "مطمئن هستید Ú©Ù‡ می‌خواهید Øساب کاربریتان را ببندید؟ این کار غیرقابل بازگشت است!" aspects: @@ -55,16 +46,8 @@ fa: success: "مخاطب با موÙقیت به منظر اضاÙÙ‡ شد." aspect_listings: add_an_aspect: "+اضاÙÙ‡ کردن منظر" - deselect_all: "لغو انتخاب همه" - edit_aspect: "ویرایش ‎%{name}‎" - select_all: "انتخاب همه" aspect_stream: stay_updated: "بروز بمانید" - contacts_not_visible: "مخاطبینی Ú©Ù‡ در این منظر قرار دارند قادرند یکدیگر را ببینند." - contacts_visible: "مخاطبینی Ú©Ù‡ در این منظر قرار دارند قادرند یکدیگر را ببینند." - create: - failure: "خطا در ساخت منظر" - success: "منظر جدید شما، ‎%{name}‎ ساخته شد" destroy: failure: "‎%{name}‎ خالی نیست Ùˆ نمی‌توانید ØØ°ÙØ´ کنید." success: "‎%{name}‎ با موÙقیت Øذ٠شد." @@ -72,21 +55,13 @@ fa: aspect_list_is_not_visible: "لیست منظر برای اÙراد دیگر در این منظر مخÙÛŒ است" aspect_list_is_visible: "لیست منظر برای اÙراد دیگر در این منظر قابل مشاهده است" confirm_remove_aspect: "مطمئن هستید می‌خواهید این منظر را Øذ٠کنید؟" - make_aspect_list_visible: "مخاطبینی Ú©Ù‡ در این منظر هستند برای یکدیگر قابل مشاهده باشند؟" - remove_aspect: "Øذ٠این منظر" rename: "تغییر نام" update: "بروزرسانی" updating: "در Øال بروزرسانی" index: - diaspora_id: - content_1: "آدرس شناسایی دیاسپورای شما:" - content_2: "در اختیار هرکسی Ú©Ù‡ قادر به یاÙتن شما در دیاسپورا هست قرار دهید." - heading: "آدرس شناسایی دیاسپورا" donate: "Ú©Ù…Ú© مالی" - handle_explanation: "این آدرس شناسایی دیاسپورای شماست. مثل تمامی آدرس‌های رایانامه، می‌توانید آن را برای رسیدن به خودتان به مردم بدهید." help: do_you: "آیا شما:" - email_feedback: "اگر ØªØ±Ø¬ÛŒØ Ù…ÛŒâ€ŒØ¯Ù‡ÛŒØ¯ØŒ ‎%{link}‎ پاسخ شما" feature_suggestion: "یک پیشنهاد ‎%{link}‎ دارید؟" find_a_bug: "یک ‎%{link}‎ یاÙتید؟" have_a_question: "یک %{link} دارید؟" @@ -100,25 +75,15 @@ fa: follow: "‎%{link}‎ دبنلا کنید Ùˆ به کاربران جدید دیاسپورا* خوش آمد بگوئید!" learn_more: "بیشتر بدانید" title: "خوش آمد گویی به کاربران جدید" - no_contacts: "بدون مخاطب" - no_tags: "+یاÙتن یک تگ برای دنبال کردن" - people_sharing_with_you: "اÙراد با شما به اشتراک گذاشتن" - post_a_message: "ارسال پیام >>" services: content: "شما می‌توانید سرویس‌های زیر را به دیاسپورا متصل کنید:" heading: "اتصال سرویس‌ها" - unfollow_tag: "لغو دنبال کردن #‎%{tag}‎" welcome_to_diaspora: "%{name}ØŒ به دیاسپورا خوش آمدی!" - new: - create: "ساختن" - name: "نام (Ùقط برای شما قابل مشاهده است)" no_contacts_message: community_spotlight: "کانون توجه جامعه" or_spotlight: "یا Ù…ÛŒ توانید با ‎%{link}‎ به اشترام بگذارید" try_adding_some_more_contacts: "شما می‌توانید مخاطبین بیشتری را جستجو یا دعوت کنید." you_should_add_some_more_contacts: "شما باید مخاطبین بیشتری اضاÙÙ‡ کنید!" - no_posts_message: - start_talking: "هنوز کسی چیطی Ù†Ú¯Ùته!" seed: acquaintances: "آشنایان" family: "خانواده" @@ -127,34 +92,22 @@ fa: update: failure: "منظر ‎%{name}‎، نامش برای ذخیره سازی طولانی هست." success: "منظر ‎%{name}‎، با موÙقیت ویرایش شد." - back: "عقب" cancel: "Ù„ÙÙˆ" delete: "ØØ°Ù" email: "رایانامه" error_messages: helper: correct_the_following_errors_and_try_again: "خطاها را درست کرده Ùˆ دوباره تلاش کنید." - invalid_fields: "Ùیلدهای نامعتبر" fill_me_out: "پر کنید" find_people: "یاÙتن اÙراد یا #تگ‌ها" - hide: "مخÙÛŒ" limited: "Ù…Øدود" more: "بیشتر" - next: "بعدی" no_results: "نتیجه‌ای یاÙت نشد" nsfw: "NSFW" ok: "قبول" - or: "یا" - password: "رمز عبور" - password_confirmation: "تایید رمز عبور" - previous: "قبلی" privacy: "Øریم خصوصی" - privacy_policy: "سیاست ØÙظ Øریم خصوصی" profile: "نمایه" public: "عمومی" search: "جستجو" settings: "تنظیمات" - terms_and_conditions: "شرایط Ùˆ ظوابط" - undo: "برگشت؟" - username: "نام‌کاربری" - welcome: "خوش آمدید!" \ No newline at end of file + username: "نام‌کاربری" \ No newline at end of file diff --git a/config/locales/diaspora/fi.yml b/config/locales/diaspora/fi.yml index 120f288d5d2d067c54ebda929b72f29e03476435..267982531d247840a0c5aed7de67b13c06d35441 100644 --- a/config/locales/diaspora/fi.yml +++ b/config/locales/diaspora/fi.yml @@ -6,11 +6,8 @@ fi: _applications: "Sovellukset" - _comments: "Kommentit" _contacts: "Kontaktit" _help: "Apua" - _home: "Etusivu" - _photos: "Kuvat" _services: "Ulkoiset palvelut" _statistics: "Tilastot" _terms: "Ehdot" @@ -125,13 +122,7 @@ fi: other: "Uusia käyttäjiä tällä viikolla: %{count}" zero: "Ei yhtään uutta käyttäjää tällä viikolla." current_server: "Tämänhetkinen palvelimen päiväys on %{date}" - ago: "%{time} sitten" all_aspects: "Kaikki näkymät" - application: - helper: - unknown_person: "Tuntematon henkilö" - video_title: - unknown: "Tuntematon videon otsikko" are_you_sure: "Oletko varma?" are_you_sure_delete_account: "Haluatko varmasti sulkea tilisi? Tätä ei voi kumota!" aspect_memberships: @@ -147,48 +138,27 @@ fi: success: "Kontaktin lisääminen näkymään onnistui." aspect_listings: add_an_aspect: "+ Lisää näkymä" - deselect_all: "Poista valinnat" - edit_aspect: "Muokkaa näkymää %{name}" - select_all: "Valitse kaikki" aspect_stream: make_something: "Julkaise jotain" stay_updated: "Pysy ajan tasalla" stay_updated_explanation: "Näet päävirrassasi kaikki kontaktiesi ja eräiden yhteisön luovien jäsenten lähettämät sekä seuraamillasi tageillä merkityt julkaisut." - contacts_not_visible: "Tämän näkymän kontaktit eivät voi nähdä toisiaan." - contacts_visible: "Tämän näkymän kontaktit voivat nähdä toisensa." - create: - failure: "Näkymän luominen epäonnistui." - success: "Uusi näkymäsi, %{name}, on luotu" destroy: failure: "%{name} ei ole tyhjä, eikä sitä voitu poistaa." success: "%{name} poistettiin onnistuneesti." success_auto_follow_back: "%{name} poistettiin onnistuneesti. Käytit tätä näkymää seurataksesi käyttäjiä takaisin automaattisesti. Tarkista asetuksesi valitaksesi uuden näkymän, jolla seurataan takaisin automaattisesti." edit: - aspect_chat_is_enabled: "Tämän näkymän kontaktit voivat lähettää sinulle pikaviestejä." - aspect_chat_is_not_enabled: "Tämän näkymän kontaktit eivät voi lähettää sinulle pikaviestejä." aspect_list_is_not_visible: "Tämän näkymän kontaktit eivät voi nähdä toisiaan." aspect_list_is_visible: "Tämän näkymän kontaktit voivat nähdä toisensa." confirm_remove_aspect: "Oletko varma, että haluat poistaa tämän näkymän?" - grant_contacts_chat_privilege: "Salli näkymän kontaktien lähettää pikaviestejä?" - make_aspect_list_visible: "Salli tämän näkymän kontaktien nähdä toisensa?" - remove_aspect: "Poista näkymä" rename: "Nimeä uudelleen" - set_visibility: "Aseta näkyvyys" update: "Päivitä" updating: "Päivittää" index: - diaspora_id: - content_1: "Diaspora-ID:si on:" - content_2: "Anna se kenelle tahansa ja hän löytää sinut Diasporasta." - heading: "Diaspora-ID" donate: "Lahjoita" - handle_explanation: "Tämä on Diaspora-tunnuksesi. Voit antaa sen ihmisille kuten sähköpostiosoitteesi, jotta he voivat sen avulla tavoittaa sinut Diasporasta." help: any_problem: "Ongelmia?" contact_podmin: "Ota yhteyttä podisi ylläpitäjään!" do_you: "Haluatko:" - email_feedback: "Voit halutessasi lähettää palautteesi %{link}" - email_link: "sähköpostilla" feature_suggestion: "... ehdottaa uutta ominaisuutta? %{link}" find_a_bug: "... raportoida ohjelmistovirheen? %{link}" have_a_question: "... kysyä kysymyksen? %{link}" @@ -201,31 +171,20 @@ fi: tutorial_link_text: "Ohjeita" tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: ohjeita alkuun pääsemiseksi." introduce_yourself: "Tämä on virtasi. Hyppää sekaan ja esittele itsesi." - keep_diaspora_running: "Pidä Diasporan kehitys nopeana kuukausittaisten lahjoitusten avulla!" keep_pod_running: "Pidä %{pod} vauhdissa tarjoamalla palvelimille kupponen kahvia kuukausittaisella lahjoituksella!" new_here: follow: "Seuraa tagia %{link} ja toivota uudet käyttäjät tervetulleiksi Diasporaan!" learn_more: "Lue lisää" title: "Tervehdi uusia käyttäjiä" - no_contacts: "Ei kontakteja" - no_tags: "+ Etsi tageja seurattaviksi" - people_sharing_with_you: "Henkiöt, jotka jakavat kanssasi" - post_a_message: "Lähetä viesti >>" services: content: "Voit yhdistää Diasporaan seuraavat palvelut:" heading: "Yhdistä palveluihin" - unfollow_tag: "Lopeta tagin #%{tag} seuraaminen" welcome_to_diaspora: "Tervetuloa Diasporaan, %{name}!" - new: - create: "Luo" - name: "Nimi (näkyy vain sinulle)" no_contacts_message: community_spotlight: "Yhteisön valokeila" or_spotlight: "Voit myös jakaa %{link}n kanssa" try_adding_some_more_contacts: "Voit etsiä tai kutsua lisää kontakteja." you_should_add_some_more_contacts: "Sinun pitäisi lisätä kontakteja!" - no_posts_message: - start_talking: "Kukaan ei ole vielä sanonut mitään!" seed: acquaintances: "Tuttavat" family: "Perhe" @@ -234,7 +193,6 @@ fi: update: failure: "Antamasi näkymän nimi, %{name}, oli liian pitkä tallennettavaksi." success: "Näkymäsi, %{name}, muokkaus onnistui." - back: "Takaisin" blocks: create: failure: "En voinut sivuuttaa käyttäjää. #evasion" @@ -246,22 +204,15 @@ fi: explanation: "Voit julkaista Diasporaan mistä tahansa lisäämällä tämän linkin kirjanmerkkeihisi: %{link}" heading: "Sovelluskirjanmerkki" post_something: "Lähetä julkaisu Diasporaan" - post_success: "Lähetetty! Suljetaan!" cancel: "Peruuta" comments: new_comment: comment: "Kommentoi" commenting: "Kommentoidaan..." - one: "1 kommentti" - other: "%{count} kommenttia" - zero: "Ei kommentteja" contacts: - create: - failure: "Kontaktin luominen epäonnistui" index: add_a_new_aspect: "Lisää näkymä" add_contact: "Lisää kontakti" - add_to_aspect: "Lisää kontakteja näkymään %{name}" all_contacts: "Kaikki kontaktit" community_spotlight: "Yhteisön valokeila" my_contacts: "Kontaktini" @@ -269,19 +220,13 @@ fi: no_contacts_in_aspect: "Tässä näkymässä ei ole vielä yhtään kontaktia. Alla on lista kontakteista joita voit lisätä tähän näkymään." no_contacts_message: "Käy katsomassa %{community_spotlight}" only_sharing_with_me: "Jakaa vain kanssani" - remove_contact: "Poista kontakti" start_a_conversation: "Aloita keskustelu" title: "Kontaktit" user_search: "Käyttäjähaku" - your_contacts: "Kontaktisi" - sharing: - people_sharing: "Henkilöt, jotka jakavat kanssasi:" spotlight: community_spotlight: "Yhteisön valokeila" suggest_member: "Ehdota jäsentä" conversations: - conversation: - participants: "Osallistujat" create: fail: "Virheellinen viesti" no_contact: "Hei, sinun on ensin lisättävä vastaanottaja!" @@ -289,23 +234,12 @@ fi: destroy: delete_success: "Keskustelun poistaminen onnistui" hide_success: "Keskustelun piilottaminen onnistui" - helper: - new_messages: - few: "%{count} uutta viestiä" - many: "%{count} uutta viestiä" - one: "1 uusi viesti" - other: "%{count} uutta viestiä" - two: "%{count} uutta viestiä" - zero: "Ei uusia viestejä" index: conversations_inbox: "Keskustelut - Saapuneet" - create_a_new_conversation: "Aloita uusi keskustelu" inbox: "Uudet viestit" new_conversation: "Uusi keskustelu" - no_conversation_selected: "Yhtäkään keskustelua ei ole valittu" no_messages: "Ei viestejä" new: - abandon_changes: "Hylkää muutokset?" send: "Lähetä" sending: "Lähetetään..." subject: "Aihe" @@ -328,10 +262,6 @@ fi: error_messages: helper: correct_the_following_errors_and_try_again: "Korjaa seuraavat virheet ja yritä uudelleen." - invalid_fields: "Vialliset arvot" - login_try_again: "<a href='%{login_link}'>Kirjaudu sisään</a> ja yritä uudelleen." - post_not_public: "Julkaisu, jota yrität lukea, ei ole julkinen!" - post_not_public_or_not_exist: "Julkaisu, jota yrität katsella, ei ole julkinen tai sitä ei ole olemassa!" fill_me_out: "Täytä tiedot" find_people: "Etsi ihmisiä tai #tageja" help: @@ -550,46 +480,29 @@ fi: tutorial: "Opastus" tutorials: "ohjeita" wiki: "wiki" - hide: "Piilota" - ignore: "Sivuuta" invitation_codes: - excited: "%{name} on innoissaan nähdessään sinut täällä." not_valid: "Kutsukoodi ei ole enää voimassa" invitations: a_facebook_user: "Facebook-käyttäjä" check_token: not_found: "Kutsun tunnusta ei löytynyt" create: - already_contacts: "Olet jo yhteydessä tähän henkilöön" - already_sent: "Olet jo kutsunut tämän henkilön." empty: "Ole hyvä kirjoita vähintään yksi sähköpostiosoite." no_more: "Sinulla ei ole enempää kutsuja." note_already_sent: "Kutsuja on jo lähetetty osoitteisiin: %{emails}" - own_address: "Et voi lähettää kutsua omaan osoitteeseesi." rejected: "Seuraavissa sähköpostiosoitteissa oli ongelmia: " sent: "Kutsut on lähetetty seuraaviin sähköpostiosoitteisiin: %{emails}" - edit: - accept_your_invitation: "Hyväksy kutsu" - your_account_awaits: "Käyttäjätilisi odottaa!" new: - already_invited: "Seuraavat henkilöt eivät ole hyväksyneet kutsuasi:" - aspect: "Näkymä" - check_out_diaspora: "Tule tutustumaan Diasporaan!" codes_left: one: "Tällä koodilla on %{count} kutsu jäljellä." other: "Tällä koodilla on %{count} kutsua jäljellä." zero: "Tällä koodilla ei ole yhtään kutsua jäljellä." comma_separated_plz: "Voit syöttää useita eri sähköpostiosoitteita pilkuilla erotettuna." - if_they_accept_info: "jos he hyväksyvät kutsun, heidät lisätään siihen näkymään, johon heidät kutsuit." invite_someone_to_join: "Kutsu joku Diasporan käyttäjäksi!" language: "Kieli" paste_link: "Jaa tämä linkki ystäviesi kanssa kutsuaksesi heidät diasporaan*, tai sähköpostita se heille suoraan." - personal_message: "Henkilökohtainen viesti" - resend: "Lähetä uudelleen" send_an_invitation: "Lähetä kutsu" - send_invitation: "Lähetä kutsu" sending_invitation: "Lähetetään kutsua..." - to: "Vastaanottaja" layouts: application: back_to_top: "Takaisin ylös" @@ -599,35 +512,13 @@ fi: statistics_link: "Podin tilastot" toggle: "Mobiilisivusto päälle/pois" whats_new: "Uutta" - your_aspects: "Näkymäsi" header: - admin: "Ylläpitäjä" - blog: "Blogi" code: "Lähdekoodi" - help: "Apua" - login: "Kirjaudu sisään" logout: "Kirjaudu ulos" profile: "Profiili" - recent_notifications: "Viimeaikaiset ilmoitukset" settings: "Asetukset" - view_all: "Kaikki" - likes: - likes: - people_dislike_this: - one: "%{count} ei tykkää" - other: "%{count} ei tykkää" - zero: "kukaan ei ole inhonnut tätä" - people_like_this: - one: "%{count} tykkäys" - other: "%{count} tykkäystä" - zero: "Ei tykkäyksiä" - people_like_this_comment: - one: "%{count} tykkäys" - other: "%{count} tykkäystä" - zero: "Ei tykkäyksiä" limited: "Rajoitettu" more: "Lisää" - next: "Seuraava" no_results: "Tuloksia ei löytynyt" notifications: also_commented: @@ -642,14 +533,6 @@ fi: one: "%{actors} kommentoi julkaisuasi %{post_link}" other: "%{actors} kommentoi julkaisuasi %{post_link}" zero: "%{actors} kommentoi julkaisuasi %{post_link}" - helper: - new_notifications: - few: "%{count} uutta ilmoitusta" - many: "%{count} uutta ilmoitusta" - one: "1 uusi ilmoitus" - other: "%{count} uutta ilmoitusta" - two: "%{count} uutta ilmoitusta" - zero: "Ei uusia ilmoituksia" index: all_notifications: "Kaikki ilmoitukset" also_commented: "Myös kommentoidut" @@ -714,7 +597,6 @@ fi: a_limited_post_comment: "Rajoitetulle julkaisullesi on uusi kommentti Diasporassa." a_post_you_shared: "julkaisu" a_private_message: "Diasporassa on sinulle uusi yksityisviesti." - accept_invite: "Hyväksy sinun Diaspora* kutsusi!" also_commented: limited_subject: "Kommentoimassasi julkaisussa on uusi kommentti" click_here: "Klikkaa tästä" @@ -791,7 +673,6 @@ fi: view_post: "Näytä julkaisu >" mentioned: limited_post: "Sinut mainittiin rajatussa julkaisussa." - mentioned: "mainitsi sinut viestissään:" subject: "%{name} on maininnut sinut Diaspora*:ssa" private_message: reply_to_or_view: "Lue tai osallistu keskusteluun >" @@ -845,20 +726,9 @@ fi: to_change_your_notification_settings: "muuttaaksesi ilmoitusasetuksia" nsfw: "NSFW" ok: "OK" - or: "tai" - password: "Salasana" - password_confirmation: "Salasanan vahvistus" people: add_contact: invited_by: "Sinut kutsui" - add_contact_small: - add_contact_from_tag: "Lisää kontakti tagista" - aspect_list: - edit_membership: "Muokkaa näkymän jäsenyyttä" - helper: - is_not_sharing: "%{name} ei jaa kanssasi" - is_sharing: "%{name} jakaa kanssasi" - results_for: " tulokset kyselylle %{params}" index: couldnt_find_them: "Etkö löytänyt etsimääsi henkilöä?" looking_for: "Etsitkö tagilla %{tag_link} merkittyjä viestejä?" @@ -868,100 +738,47 @@ fi: search_handle: "Löydät ystäväsi parhaiten käyttämällä heidän Diaspora-ID:itään (käyttäjänimi@pod.tld)." searching: "etsitään, pieni hetki..." send_invite: "Ei edelleenkään mitään? Lähetä kutsu!" - one: "1 henkilö" - other: "%{count} henkilöä" person: - add_contact: "Lisää kontakti" - already_connected: "Yhteys jo olemassa" - pending_request: "Jonossa oleva pyyntö" thats_you: "Se olet sinä!" profile_sidebar: bio: "Elämäkerta" born: "Syntymäpäivä" - edit_my_profile: "Muokkaa profiiliani" gender: "Sukupuoli" - in_aspects: "Näkymissä" location: "Sijainti" - photos: "Kuvat" - remove_contact: "Poista kontakti" - remove_from: "Poista %{name} näkymästä %{aspect}?" show: closed_account: "Tämä käyttäjätili on suljettu." does_not_exist: "Henkilöä ei ole olemassa!" has_not_shared_with_you_yet: "%{name} ei ole jakanut vielä yhtään julkaisua kanssasi!" - ignoring: "Sivuutat nyt kaikki julkaisut, jotka %{name} lähettää." - incoming_request: "%{name} haluaisi jakaa kanssasi" - mention: "Mainitse" - message: "Viesti" - not_connected: "Et ole yhteydessä tähän henkilöön " - recent_posts: "Viimeisimmät tapahtumat" - recent_public_posts: "Viimeisimmät julkiset julkaisut" - return_to_aspects: "Palaa näkymiin" - see_all: "Näytä kaikki" - start_sharing: "Aloita jakamaan" - to_accept_or_ignore: "hyväksyäksesi tai hylätäksesi sen." - sub_header: - add_some: "Lisää niitä" - edit: "Muokkaa" - you_have_no_tags: "Sinulla ei ole tageja!" - webfinger: - fail: "Valitettavasti tunnusta %{handle} ei löytynyt." - zero: "Ei henkilöitä" photos: - comment_email_subject: "Kuva käyttäjältä %{name}" create: integrity_error: "Kuvan lataus epäonnistui. Oletko varma, että se oli kuva?" runtime_error: "Kuvan lataus epäonnistui. Onhan turvavyösi kiinni?" type_error: "Kuvan lataus epäonnistui. Lisäsitkö varmasti kuvan?" destroy: notice: "Kuva poistettu." - edit: - editing: "Muokkaa" - new: - back_to_list: "Takaisin listaan" - new_photo: "Uusi kuva" - post_it: "Lähetä!" new_photo: empty: "{file} on tyhjä, valitse tiedostot uudelleen ilman kyseistä tiedostoa." invalid_ext: "{file} sisältää viallisen tiedostopäätteen. Tuetut muodot ovat {extensions}." size_error: "{file} on liian suuri, suurin tiedostokoko on {sizeLimit}." new_profile_photo: - or_select_one_existing: "tai valitse joku jo lisäämistäsi kuvista: %{photos}" upload: "Lisää uusi profiilikuva!" - photo: - view_all: "Näytä kaikki käyttäjän %{name} kuvat" show: - collection_permalink: "Tallenna pysyvä linkki" - delete_photo: "Poista kuva" - edit: "Muokkaa" - edit_delete_photo: "Muokkaa kuvan kuvausta / poista kuva" - make_profile_photo: "Aseta profiilikuvaksi" show_original_post: "Näytä alkuperäinen julkaisu" - update_photo: "Päivitä kuva" - update: - error: "Kuvan muokkaus epäonnistui." - notice: "Kuva päivitettiin onnistuneesti." posts: presenter: title: "Julkaisu käyttäjältä %{name}" show: - destroy: "Poista" forbidden: "Et saa tehdä noin" - not_found: "Valitettavasti tätä julkaisua ei löytynyt." - permalink: "Pysyvä linkki" photos_by: one: "Yksi kuva käyttäjältä %{author}" other: "%{count} kuvaa käyttäjältä %{author}" zero: "Ei kuvia käyttäjältä %{author}" reshare_by: "Uudelleenjaettu käyttäjältä %{author}" - previous: "Edellinen" privacy: "Yksityisyys" - privacy_policy: "Tietosuojakäytäntö" profile: "Profiili" profiles: edit: allow_search: "Salli ihmisten etsiä sinua Diasporassa" - edit_profile: "Muokkaa profiilia" first_name: "Etunimi" last_name: "Sukunimi" nsfw_check: "Merkitse kaikki jakamani sisältö NSFW:ksi" @@ -974,8 +791,6 @@ fi: your_location: "Sijaintisi" your_name: "Nimesi" your_photo: "Profiilikuvasi" - your_private_profile: "Yksityinen profiilisi" - your_public_profile: "Julkinen profiilisi" your_tags: "Kuvaile itseäsi viidellä sanalla" your_tags_placeholder: "Esim. #elokuvat #kissat #matkailu #opettaja #turku" update: @@ -990,26 +805,16 @@ fi: closed: "Rekisteröityminen on suljettu tässä Diaspora-podissa." create: success: "Olet liittynyt Diasporaan!" - edit: - cancel_my_account: "Poista käyttäjätilini" - edit: "Muokkaa %{name}" - leave_blank: "(jätä tyhjäksi, mikäli et halua muuttaa sitä)" - password_to_confirm: "(tarvitsemme nykyisen salasanasi muutosten varmistusta varten)" - unhappy: "Tyytymätön?" - update: "Päivitä" invalid_invite: "Antamasi kutsulinkki ei ole enää voimassa!" new: - create_my_account: "Luo käyttäjätili!" email: "Sähköposti" enter_email: "Syötä sähköpostiosoitteesi" enter_password: "Syötä salasana (vähintään kuusi merkkiä)" enter_password_again: "Syötä sama salasana kuin edellä" enter_username: "Valitse käyttäjänimi (vain kirjaimet, numerot ja alaviivat sallittuja)" - join_the_movement: "Liity joukkoon!" password: "Salasana" password_confirmation: "Salasana uudestaan" sign_up: "Rekisteröidy" - sign_up_message: "Yhteisöpalvelu suurella ♥:llä" submitting: "Lähettää..." terms: "Luomalla tilin hyväksyt %{terms_link}" terms_link: "palvelun käyttöehdot" @@ -1024,43 +829,15 @@ fi: reported_label: "<b>Ilmoituksen teki</b> %{person}" review_link: "Merkitse tarkistetuksi" status: - created: "Ilmoitus on luotu" destroyed: "Julkaisu on poistettu" failed: "Jotain meni vikaan" - marked: "Ilmoitus merkittiin tarkistetuksi" title: "Merkittyjen Ilmoitusten Yleiskatsaus" - requests: - create: - sending: "Lähetetään" - sent: "Olet lähettänyt käyttäjälle %{name} pyynnön jakaa kanssasi. Hänen pitäisi nähdä se kirjautuessaan seuraavan kerran Diasporaan." - destroy: - error: "Valitse joku näkymä!" - ignore: "Hylätty kontaktipyyntö." - success: "Olet nyt jakamassa." - helper: - new_requests: - one: "Uusi pyyntö!" - other: "%{count} uutta pyyntöä!" - zero: "Ei uusia pyyntöjä" - manage_aspect_contacts: - existing: "Olemassa olevat kontaktit" - manage_within: "Muokkaa kontakteja näkymässä" - new_request_to_person: - sent: "Lähetetty!" reshares: comment_email_subject: "Käyttäjän %{resharer} uudelleenjako käyttäjän %{author} julkaisusta." - create: - failure: "Julkaisun uudelleen jakamisessa tapahtui virhe." reshare: deleted: "Kirjoittaja on poistanut alkuperäisen julkaisun." - reshare: - one: "jaettu uudelleen %{count} kerran" - other: "jaettu uudelleen %{count} kertaa" - zero: "Jaa uudelleen" reshare_confirmation: "Jaetaanko käyttäjän %{author} julkaisu uudelleen?" - reshare_original: "Jaa alkuperäinen uudelleen" reshared_via: "Jaettu uudelleen" - show_original: "Näytä alkuperäinen" search: "Haku" services: create: @@ -1072,10 +849,6 @@ fi: success: "Tunnistuksen poisto onnistui." failure: error: "Palveluun yhdistämisessä tapahtui virhe" - finder: - fetching_contacts: "Diaspora etsii %{service}-ystäviäsi. Katso uudelleen muutaman minuutin kuluttua." - no_friends: "Facebook-kavereita ei löytynyt." - service_friends: "%{service}-kaverit" index: connect: "Yhdistä" disconnect: "Katkaise yhteys" @@ -1085,56 +858,25 @@ fi: not_logged_in: "Et ole kirjautunut sisään." really_disconnect: "Katkaistaanko yhteys palveluun %{service}?" services_explanation: "Palveluihin yhdistäminen antaa sinulle mahdollisuuden julkaista Diasporaan lähettämäsi julkaisut myös niissä." - inviter: - click_link_to_accept_invitation: "Paina tätä linkkiä hyväksyäksesi kutsun" - join_me_on_diaspora: "Liity seuraani Diasporaan*" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "Kutsu" - not_on_diaspora: "Ei vielä Diasporassa" - resend: "Lähetä uudelleen" settings: "Asetukset" - share_visibilites: - update: - post_hidden_and_muted: "Käyttäjän %{name} julkaisu on piilotettu, ja ilmoitukset on vaimennettu." - see_it_on_their_profile: "Jos haluat nähdä päivitykset tälle julkaisulle, mene käyttäjän %{name} profiilisivulle." shared: - add_contact: - add_new_contact: "Lisää uusi kontakti" - create_request: "Etsi Diaspora-ID:llä" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Anna Diaspora-käyttäjätunnus:" - know_email: "Tiedätkö heidän sähköpostiosoitteitansa? Kutsu heidät!" - your_diaspora_username_is: "Diaspora-käyttäjätunnuksesi on: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Lisää kontakti" mobile_row_checked: "%{name} (poista)" mobile_row_unchecked: "%{name} (lisää)" toggle: one: "%{count} näkymässä" other: "%{count} näkymässä" zero: "Lisää kontakti" - contact_list: - all_contacts: "Kaikki kontaktit" - footer: - logged_in_as: "Kirjauduttu sisään käyttäjänä %{name}" - your_aspects: "Näkymäsi" invitations: by_email: "Sähköpostilla" - dont_have_now: "Sinulla ei ole yhtään kutsua jäljellä, mutta lisää tulee pian!" - from_facebook: "Facebookista" - invitations_left: "%{count} jäljellä" - invite_someone: "Kutsu joku" invite_your_friends: "Kutsu kavereitasi" invites: "Kutsut" - invites_closed: "Kutsut on toistaiseksi suljettu tällä Diaspora-palvelimella" share_this: "Jaa tämä linkki sähköpostilla, blogissa tai haluamassasi yhteisöpalvelussa!" - notification: - new: "Uusi %{type} henkilöltä %{from}" public_explain: atom_feed: "Atom-syöte" control_your_audience: "Hallitse yleisöäsi" @@ -1146,12 +888,9 @@ fi: title: "Yhdistä ulkoisia palveluita" visibility_dropdown: "Muuta tästä pudotusvalikosta julkaisusi näkyvyyttä. (Suosittelemme, että teet tästä ensimmäisestä julkaisustasi julkisen.)" publisher: - all: "Kaikki" - all_contacts: "Kaikki kontaktit" discard_post: "Hylkää julkaisu" formatWithMarkdown: "Voit käyttää %{markdown_link}-merkintäkieltä muotoillaksesi julkaisuasi" get_location: "Nouda sijaintisi" - make_public: "tee julkiseksi" new_user_prefill: hello: "Hei kaikki, olen #%{new_user_tag}. " i_like: "Kiinnostukseni kohteita ovat %{tags}." @@ -1159,36 +898,14 @@ fi: newhere: "uusitäällä" poll: add_a_poll: "Lisää kysely" - add_poll_answer: "Lisää vastausvaihtoehto" - option: "Vaihtoehto 1" - question: "Kysymys" - remove_poll_answer: "Poista vastausvaihtoehto" - post_a_message_to: "Lähetä julkaisu näkymään %{aspect}" posting: "Lähetetään..." - preview: "Esikatselu" - publishing_to: "Julkaistaan: " remove_location: "Poista sijainti" share: "Jaa" - share_with: "Jaa" upload_photos: "Lisää kuvia" whats_on_your_mind: "Mitä mielessä?" - reshare: - reshare: "Jaa uudelleen" stream_element: - connect_to_comment: "Yhdistä tähän käyttäjään kommentoidaksesi hänen julkaisuaan" - currently_unavailable: "Kommentointi ei ole tällä hetkellä mahdollista" - dislike: "En tykkää" - hide_and_mute: "Piilota ja vaimenna julkaisu" - ignore_user: "Sivuuta %{name}" - ignore_user_description: "Sivuuta käyttäjä ja poista hänet kaikista näkymistä?" - like: "Tykkää" - nsfw: "Tämän julkaisun lähettäjä on merkinnyt sen ei-työturvalliseksi. %{link}" - shared_with: "Jaettu heidän kanssaan: %{aspect_names}" - show: "Näytä" - unlike: "Peru tykkäys" via: "%{link} kautta" via_mobile: "Mobiililaitteen kautta" - viewable_to_anyone: "Kuka tahansa verkossa näkee tämän julkaisun" simple_captcha: label: "Kirjoita kentässä oleva koodi:" message: @@ -1214,24 +931,12 @@ fi: status_messages: create: success: "Onnistuneesti mainittu: %{names}" - destroy: - failure: "Julkaisun poisto epäonnistui" - helper: - no_message_to_display: "Ei näytettäviä viestejä." new: mentioning: "Mainitse: %{person}" too_long: "Sinun täytyy lyhentää tilapäivitystäsi, sillä se voi sisältää enimmillään %{count} merkkiä. Tällä hetkellä päivityksessäsi on %{current_length} merkkiä." stream_helper: - hide_comments: "Piilota kaikki kommentit" no_more_posts: "Olet saavuttanut virran päätepisteen." no_posts_yet: "Julkaisuja ei vielä ole." - show_comments: - few: "Näytä %{count} muuta kommenttia" - many: "Näytä %{count} muuta kommenttia" - one: "Näytä yksi muu kommentti" - other: "Näytä %{count} muuta kommenttia" - two: "Näytä kaksi muuta kommenttia" - zero: "Ei enempää kommentteja" streams: activity: title: "Oma toimintani" @@ -1258,13 +963,6 @@ fi: tags: title: "%{tags} merkityt julkaisut" tag_followings: - create: - failure: "Tagin #%{name} seuraamisen aloittaminen epäonnistui. Seuraatko sitä jo?" - none: "Et voi seurata tyhjää tagia!" - success: "Hiphei! Seuraat nyt tagia #%{name}." - destroy: - failure: "Tagin #%{name} seuraamisen lopettaminen epäonnistui. Oletko jo lopettanut sen seuraamisen?" - success: "Noin! Et seuraa enää tagia #%{name}." manage: no_tags: "Et seuraa yhtään tagia." title: "Hallitse seurattuja tageja" @@ -1272,15 +970,12 @@ fi: name_too_long: "Tee tagin nimestä lyhyempi kuin %{count} merkkiä. Tällä hetkellä se on %{current_length} merkkiä pitkä." show: follow: "Seuraa tagia #%{tag} " - following: "Seurataan tagia #%{tag}" none: "Tyhjää tagia ei ole olemassa!" stop_following: "Lopeta tagin #%{tag} seuraaminen" tagged_people: one: "1 henkilö merkitty tagilla %{tag}" other: "%{count} henkilöä merkitty tagilla %{tag}" zero: "Ketään ei ole merkitty tagilla %{tag}" - terms_and_conditions: "Käyttöehdot" - undo: "Peruuta?" username: "Käyttäjätunnus" users: confirm_email: @@ -1301,7 +996,6 @@ fi: character_minimum_expl: "täytyy olla vähintään kuusi merkkiä" close_account: dont_go: "Hei, älä lähde!" - if_you_want_this: "Jos todella haluat tämän tapahtuvan, kirjoita salasanasi alle ja napsauta 'Sulje käyttäjätili'" lock_username: "Käyttäjänimesi lukitaan. Et pysty luomaan uutta tiliä tälle podille samalla ID:llä." locked_out: "Sinut kirjataan ulos ja käyttäjätilisi lukitaan, kunnes tilisi on poistettu." make_diaspora_better: "Näkisimme mielelläme sinun jäävän ja auttavan Diasporan parantamisessa lähtemisen sijaan. Jos kuitenkin haluat varmasti lähteä, käyttäjätilillesi suoritetaan seuraavat toimenpiteet:" @@ -1314,14 +1008,12 @@ fi: current_password_expl: "se, jolla kirjaudut sisään..." download_export: "Lataa profiilini" download_export_photos: "Lataa kaikki kuvat" - download_photos: "Lataa kaikki kuvat" edit_account: "Muokkaa käyttäjätiliä" email_awaiting_confirmation: "Olemme lähettäneet sinulle aktivointilinkin osoitteeseen %{unconfirmed_email}. Jatkamme alkuperäisen osoitteesi %{email} käyttämistä siihen saakka, kunnes aktivoit uuden osoitteesi kyseisen linkin kautta." export_data: "Vie tietoja" export_in_progress: "Profiilidataasi käsitellään parhaillaan. Tarkista käsittelyn tila hetken kuluttua uudelleen." export_photos_in_progress: "Kuvatiedostojasi käsitellään parhaillaan. Tarkista tilanne uudelleen hetken kuluttua." following: "Jakamisen asetukset" - getting_started: "Uudet käyttäjäasetukset" last_exported_at: "(Viimeksi päivitetty %{timestamp})" liked: "joku tykkää julkaisustasi" mentioned: "sinut mainitaan julkaisussa" @@ -1348,7 +1040,6 @@ fi: connect_to_facebook_link: "yhdistämällä Facebook-tilisi" hashtag_explanation: "Hashtagien avulla voit keskustella ja seurata keskusteluja kiinnostuksen kohteistasi. Ne ovat myös hyvä keino löytää ihmisiä Diasporassa." hashtag_suggestions: "Voit seurata tageja kuten #taide, #elokuvat, #gif jne." - saved: "Tallennettu!" well_hello_there: "No, mutta hei!" what_are_you_in_to: "Mistä olet kiinnostunut?" who_are_you: "Kuka olet?" @@ -1372,13 +1063,6 @@ fi: settings_updated: "Asetukset päivitetty" unconfirmed_email_changed: "Sähköpostiosoite muutettu. Se täytyy aktivoida." unconfirmed_email_not_changed: "Sähköpostiosoitteen vaihto epäonnistui" - webfinger: - fetch_failed: "webfinger-profiilin %{profile_url} haku epäonnistui" - hcard_fetch_failed: "tapahtui virhe haettaessa hcard:ia tilille %{account}" - no_person_constructed: "Yhtäkään henkilöä ei pystytty kokoamaan tältä hcardilta." - not_enabled: "webfinger-palvelua ei ilmeisesti ole aktivoitu tilin, %{account}, isännälle" - xrd_fetch_failed: "tapahtui virhe haettaessa xrd:tä käyttäjätilille %{account}" - welcome: "Tervetuloa!" will_paginate: next_label: "seuraava »" previous_label: "« edellinen" \ No newline at end of file diff --git a/config/locales/diaspora/fil.yml b/config/locales/diaspora/fil.yml index 72c16429d6c9e56b358b9fe70deec5c0446e1762..3f1f0a23ba4c1b71628ce8fb0ba5ce0925868ad0 100644 --- a/config/locales/diaspora/fil.yml +++ b/config/locales/diaspora/fil.yml @@ -6,10 +6,7 @@ fil: _applications: "Mga Applikasyon" - _comments: "Mga Kumento" _contacts: "Mga Kakilala" - _home: "Home Port" - _photos: "Mga Larawan" _services: "Mga Serbisyo" account: "Pag-aari" activerecord: @@ -40,13 +37,7 @@ fil: username: invalid: "ay hindi tama. Pinapahintulutan lamang namin ang mga letra ng alpabeto, numero, at salungguhit." taken: "ay mayroon ng nagmamay-ari." - ago: "%{time} ang nakalipas" all_aspects: "Lahat ng aspeto" - application: - helper: - unknown_person: "hindi kilala" - video_title: - unknown: "Hindi kilalang Titulo" are_you_sure: "Sigurado ka ba?" aspect_memberships: destroy: @@ -59,27 +50,16 @@ fil: success: "Successfully added contact to crew." aspect_listings: add_an_aspect: "+ Add a crew" - contacts_not_visible: "Contacts in this crew will not be able to see each other." - contacts_visible: "Contacts in this crew will be able to see each other." - create: - failure: "Crew creation failed." - success: "Your new crew %{name} was created" edit: aspect_list_is_not_visible: "crew list is hidden to others in crew" aspect_list_is_visible: "crew list is visible to others in crew" confirm_remove_aspect: "Are you sure you want to delete this crew?" - make_aspect_list_visible: "make crew list visible?" - remove_aspect: "Fire this crew" index: - handle_explanation: "This is your diaspora id. Like an email address, you can give this to people to reach you." help: here_to_help: "Diaspora community is here to help!" tag_bug: "#bug" tag_feature: "#feature" tag_question: "#question" - no_contacts: "No mateys" - new: - name: "Pangalan" no_contacts_message: try_adding_some_more_contacts: "You can search (top) or invite (right) more contacts." seed: @@ -89,20 +69,9 @@ fil: work: "Shipmates" contacts: index: - add_to_aspect: "Add contacts to %{name}" all_contacts: "All yer mateys" no_contacts: "No contacts." title: "Mateys" - your_contacts: "Yer Mateys" - conversations: - helper: - new_messages: - few: "%{count} new messages" - many: "%{count} new messages" - one: "1 new messages" - other: "%{count} new messages" - two: "%{count} new messages" - zero: "No new messages" layouts: application: toggle: "toggle mobile site" @@ -110,29 +79,6 @@ fil: logout: "abandon ship" profile: "profile" settings: "settings" - likes: - likes: - people_dislike_this: - few: "%{count} dislikes" - many: "%{count} dislikes" - one: "%{count} dislike" - other: "%{count} dislikes" - two: "%{count} dislikes" - zero: "no dislikes" - people_like_this: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" - people_like_this_comment: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" limited: "Limitado" notifications: also_commented: @@ -156,14 +102,6 @@ fil: other: "%{actors} commented on your %{post_link}." two: "%{actors} commented on your %{post_link}." zero: "%{actors} commented on your %{post_link}." - helper: - new_notifications: - few: "%{count} new notifications" - many: "%{count} new notifications" - one: "1 new notifications" - other: "%{count} new notifications" - two: "%{count} new notifications" - zero: "No new notifications" index: and_others: few: "and %{count} others" @@ -236,27 +174,10 @@ fil: reshared: reshared: "%{name} just reshared your post" people: - add_contact_small: - add_contact_from_tag: "magdagdag ng kakilala mula sa tag" - helper: - results_for: " mga resulta para sa %{params}" - one: "1 person" - other: "%{count} people" person: - add_contact: "magdagdag ng mga kakilala" - already_connected: "Konektado ka na" - pending_request: "Nakabinbin na kahilingan" thats_you: "Ikaw yan!" profile_sidebar: born: "date o' birth" - sub_header: - add_some: "magdagdag ng ilan" - edit: "baguhin" - you_have_no_tags: "wala ka pang mga tag!" - zero: "no people" - photos: - new: - new_photo: "New Portrait" posts: show: photos_by: @@ -276,34 +197,8 @@ fil: other: "%{count} reactions" two: "%{count} reactions" zero: "0 reactions" - registrations: - new: - create_my_account: "Create my account" - sign_up_message: "Social Networking with a <3" - requests: - helper: - new_requests: - few: "%{count} new requests!" - many: "%{count} new requests!" - one: "new request!" - other: "%{count} new requests!" - two: "%{count} new requests!" - zero: "no new requests" - reshares: - reshare: - reshare: - few: "%{count} reshares" - many: "%{count} reshares" - one: "1 reshare" - other: "%{count} reshares" - two: "%{count} reshares" - zero: "Reshare" - services: - inviter: - click_link_to_accept_invitation: "Click this link to accept your invitation" shared: aspect_dropdown: - add_to_aspect: "Add to aspect" toggle: few: "In %{count} aspects" many: "In %{count} aspects" @@ -316,39 +211,15 @@ fil: i_like: "I'm interested in %{tags}." share: "Fire!" whats_on_your_mind: "What be botherin' you?" - stream_element: - hide_and_mute: "Hide and Mute" - shared_with: "Fired at: %{aspect_names}" status_messages: too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: aspects: title: "Your Aspects" mentions: title: "Your Mentions" - tag_followings: - create: - failure: "Failed to follow: #%{name}" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" users: edit: close_account: what_we_delete: "We delete all of your posts, profile data, as soon as humanly possible. Your comments will hang around, but be associated with your Diaspora Handle." - your_handle: "Your diaspora id" - webfinger: - fetch_failed: "hindi nakuha ang webfinger profile para sa %{profile_url}" - hcard_fetch_failed: "nagkaroon ng problema sa pagkuha ng hcard ni %{account}" - no_person_constructed: "Walang taong magagawa mula sa hcard na ito." - not_enabled: "ang webfinger ay hindi gumagana sa host ni %{account}" - xrd_fetch_failed: "nagkaroon ng pagkakamali sa pagkuha ng xrd mula sa pag-aari %{account}" \ No newline at end of file + your_handle: "Your diaspora id" \ No newline at end of file diff --git a/config/locales/diaspora/fr.yml b/config/locales/diaspora/fr.yml index bb9aa0e376aea6fa3cd102bbf9daabd4495c7834..137627b4f747ad4665c4c222f3b62dc6e3c0a1bf 100644 --- a/config/locales/diaspora/fr.yml +++ b/config/locales/diaspora/fr.yml @@ -6,11 +6,8 @@ fr: _applications: "Applications" - _comments: "Commentaires" _contacts: "Contacts" _help: "Aide" - _home: "Accueil" - _photos: "Photos" _services: "Services" _statistics: "Statistiques" _terms: "conditions d'utilisation" @@ -53,12 +50,19 @@ fr: taken: "est déjà pris." admins: admin_bar: + dashboard: "Tableau de bord" pages: "Pages" + pod_network: "Réseau du pod" pod_stats: "Statistiques du pod" report: "Signalements" sidekiq_monitor: "Moniteur Sidekiq" user_search: "Chercher un utilisateur" weekly_user_stats: "Statistiques utilisateur hebdomadaires" + dashboard: + fetching_diaspora_version: "Entrain de déterminer la dernière version de diaspora*..." + pod_status: "État du pod" + pods: + pod_network: "Réseau du pod" stats: 2weeks: "Deux semaines" 50_most: "50 tags les plus populaires" @@ -92,6 +96,7 @@ fr: email: "E-mail" guid: "GUID" id: "ID" + invite_token: "Jeton d'invitation" last_seen: "Dernière connexion" ? "no" : Non @@ -109,7 +114,10 @@ fr: are_you_sure_unlock_account: "Êtes-vous sûr de vouloir déverrouiller ce compte ?" close_account: "Fermer ce compte" email_to: "Adresse électronique de la personne à inviter" + invite: "Inviter" + lock_account: "Verrouiller le compte" under_13: "Afficher les utilisateurs de moins de 13 ans" + unlock_account: "Déverrouiller le compte" users: one: "%{count} utilisateur trouvé" other: "%{count} utilisateurs trouvés" @@ -125,13 +133,59 @@ fr: other: "%{count} nouveaux utilisateurs cette semaine." zero: "Aucun nouvel utilisateur cette semaine." current_server: "La date actuelle du serveur est %{date}" - ago: "Il y a %{time}" all_aspects: "Tous les aspects" - application: - helper: - unknown_person: "Personne inconnue" - video_title: - unknown: "Titre de vidéo inconnu" + api: + openid_connect: + authorizations: + destroy: + fail: "La tentative de révoquer l'autorisation avec ID %{id} a échoué" + new: + access: "%{name} a besoin d'accéder à :" + approve: "Autoriser" + bad_request: "ID client manquant ou URL de redirection" + client_id_not_found: "Pas de client avec client_id %{client_id} avec URL de redirection %{redirect_uri} trouvé" + deny: "Refuser" + no_requirement: "%{name} n'a pas besoin de permissions" + redirection_message: "Voulez-vous vraiment donner accès à %{redirect_uri} ?" + error_page: + contact_developer: "Vous devriez contacter le développeur de l'application et inclure le message d'erreur détaillé suivant :" + could_not_authorize: "L'application n'a pas pu être autorisée" + login_required: "Vous devez d'abord vous connecter afin de pouvoir autoriser cette application" + title: "Oups ! Quelque-chose n'a pas marché :(" + scopes: + name: + name: "nom" + nickname: + description: "Cela donne les permissions liées au surnom à l'application" + name: "Surnom" + openid: + description: "Ceci permet à l'application de voir votre profil basique" + name: "profil basique" + picture: + description: "Cela donne les permissions liées aux images à l'application" + name: "image" + profile: + description: "Ceci autorise l'application à lire votre profil complet" + name: "profil complet" + read: + description: "Ceci permet à l'application de voir votre flux, vos conversations et votre profil complet" + name: "voir profil, flux et conversations" + sub: + description: "Ceci octroie des sous-permissions à l'application" + name: "sous" + write: + description: "Ceci permet à l'application d'envoyer de nouvelles publications, écrire des conversations et publier des réactions" + name: "envoyer publications, conversations et réactions" + user_applications: + index: + access: "%{name} a accès à :" + edit_applications: "Applications" + no_requirement: "%{name} n'as pas besoin d'autorisations." + title: "Applications autorisées" + no_applications: "Vous n'avez pas d'applications autorisées" + policy: "Voir la politique de confidentialité de l'application" + revoke_autorization: "Révoquer" + tos: "Voir les conditions d'utilisation de l'application" are_you_sure: "Êtes-vous certain ?" are_you_sure_delete_account: "Souhaitez-vous vraiment supprimer votre compte ? Cette action est définitive !" aspect_memberships: @@ -147,48 +201,27 @@ fr: success: "Le contact a été ajouté à l'aspect avec succès." aspect_listings: add_an_aspect: "+ Ajouter un aspect" - deselect_all: "Tout désélectionner" - edit_aspect: "Éditer %{name}" - select_all: "Tout sélectionner" aspect_stream: make_something: "Faites quelque chose" stay_updated: "Restez informé(e)" stay_updated_explanation: "Votre flux principal est complété par vos contacts, vos tags suivis, et les messages de certains membres de la communauté." - contacts_not_visible: "Les contacts dans cet aspect ne se verront pas les uns les autres." - contacts_visible: "Les contacts dans cet aspect pourront se voir entre eux." - create: - failure: "La création de l'aspect a échoué." - success: "Votre nouvel aspect %{name} a été créé" destroy: failure: "%{name} n'a pas pu être supprimé." success: "%{name} a été supprimé avec succès." success_auto_follow_back: "%{name} a été supprimé avec succès. Vous utilisiez cet aspect pour suivre automatiquement les utilisateurs qui vous suivent. Vérifiez vos paramètres utilisateurs pour sélectionner un nouvel aspect pour le suivi automatique." edit: - aspect_chat_is_enabled: "Les contacts de cet aspect peuvent chatter avec vous." - aspect_chat_is_not_enabled: "Les contacts de cet aspect ne peuvent pas chatter avec vous." aspect_list_is_not_visible: "Les contacts dans cet aspect ne peuvent pas se voir entre eux." aspect_list_is_visible: "Les contacts dans cet aspect peuvent se voir entre eux." confirm_remove_aspect: "Voulez-vous vraiment supprimer cet aspect ?" - grant_contacts_chat_privilege: "permettre aux contacts de cet aspect de chatter avec vous ?" - make_aspect_list_visible: "Permettre aux contacts de cet aspect de se voir entre eux ?" - remove_aspect: "Supprimer cet aspect" rename: "Renommer" - set_visibility: "Régler la visibilité" update: "Mettre à jour" updating: "En cours de mise à jour" index: - diaspora_id: - content_1: "Votre identifiant diaspora* est :" - content_2: "Communiquez-le à quelqu'un pour qu'il vous trouve sur diaspora*." - heading: "Identifiant diaspora*" donate: "Faire un don" - handle_explanation: "Ceci est votre identifiant diaspora*. Comme une adresse de courrier électronique, communiquez-le à d'autres personnes pour leur permettre de vous contacter." help: any_problem: "Un problème ?" contact_podmin: "Contacter l'administrateur de votre pod !" do_you: "Avez-vous :" - email_feedback: "Envoyez vos impressions par %{link} , si vous préférez." - email_link: "Courriel" feature_suggestion: "... une %{link} ?" find_a_bug: "... trouvé un %{link} ?" have_a_question: "... une %{link} ?" @@ -201,31 +234,21 @@ fr: tutorial_link_text: "Tutoriels" tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki} : Aide pour les débutants." introduce_yourself: "Ceci est votre flux. Rejoignez-nous et présentez-vous." - keep_diaspora_running: "Participez à un développement rapide de diaspora* par un don mensuel !" keep_pod_running: "Permettez à %{pod} de fonctionner rapidement et offrez une dose de café mensuelle à nos serveurs !" new_here: follow: "Suivez %{link} et souhaitez la bienvenue aux nouveaux utilisateurs de diaspora* !" learn_more: "En savoir plus" - title: "Accueillir des nouveaux utilisateurs" - no_contacts: "Aucun contact" - no_tags: "+ Trouver un tag à suivre" - people_sharing_with_you: "Personnes partageant avec vous" - post_a_message: "Publier un message >>" + title: "Accueillir les nouveaux venus" services: content: "Vous pouvez connecter les services suivants à diaspora* :" heading: "Connecter des services" - unfollow_tag: "Ne plus suivre #%{tag}" welcome_to_diaspora: "Bienvenue sur diaspora*, %{name} !" - new: - create: "Créer" - name: "Nom (uniquement visible par vous)" no_contacts_message: community_spotlight: "Actualités de la communauté" + invite_link_text: "inviter" or_spotlight: "Ou vous pouvez partager avec %{link}" - try_adding_some_more_contacts: "Vous pouvez rechercher ou inviter plus de contacts." + try_adding_some_more_contacts: "Vous pouvez rechercher ou %{invite_link} plus de contacts." you_should_add_some_more_contacts: "Vous devez ajouter un peu plus de contacts !" - no_posts_message: - start_talking: "Personne n’a encore rien dit !" seed: acquaintances: "Connaissances" family: "Famille" @@ -234,7 +257,6 @@ fr: update: failure: "Votre aspect %{name} a un nom trop long pour être enregistré." success: "Votre aspect %{name} a été modifié avec succès." - back: "Retour" blocks: create: failure: "Je n'ai pas pu ignorer cet utilisateur. #évasion" @@ -246,22 +268,15 @@ fr: explanation: "Publiez sur diaspora* depuis n'importe où en ajoutant %{link} à vos marque-pages." heading: "Bookmarklet" post_something: "Publiez sur diaspora*" - post_success: "Publié ! Fermeture !" cancel: "Annuler" comments: new_comment: comment: "Commenter" commenting: "Commentaire en cours d'envoi..." - one: "1 commentaire" - other: "%{count} commentaires" - zero: "Aucun commentaire" contacts: - create: - failure: "Impossible de créer le contact" index: add_a_new_aspect: "Ajouter un nouvel aspect" add_contact: "Ajouter ce contact" - add_to_aspect: "Ajouter les contacts à %{name}" all_contacts: "Tous les contacts" community_spotlight: "Actualités de la communauté" my_contacts: "Mes contacts" @@ -269,19 +284,14 @@ fr: no_contacts_in_aspect: "Vous n'avez pas encore de contacts dans cet aspect. Voici une liste des contacts existants que vous pouvez ajouter à cet aspect." no_contacts_message: "Consultez %{community_spotlight}" only_sharing_with_me: "Partage uniquement avec moi" - remove_contact: "Retirer ce contact" start_a_conversation: "Démarrer une conversation" title: "Contacts" user_search: "Checher un contact" - your_contacts: "Vos contacts" - sharing: - people_sharing: "Personnes partageant avec vous :" spotlight: community_spotlight: "Actualités de la communauté" + no_members: "Il n'y a encore aucun membre." suggest_member: "Suggérer un membre" conversations: - conversation: - participants: "Participants" create: fail: "Message invalide" no_contact: "Hé, vous avez besoin d'ajouter le contact d'abord !" @@ -289,23 +299,13 @@ fr: destroy: delete_success: "Conversation effacée avec succès" hide_success: "Conversation masquée avec succès" - helper: - new_messages: - few: "%{count} nouveaux messages" - many: "%{count} nouveaux messages" - one: "1 nouveau message" - other: "%{count} nouveaux messages" - two: "%{count} nouveaux messages" - zero: "Aucun nouveau message" index: conversations_inbox: "Discussions - Boîte de réception" - create_a_new_conversation: "commencer une nouvelle discussion" inbox: "Boîte de réception" new_conversation: "Nouvelle discussion" - no_conversation_selected: "Aucune conversation sélectionnée" no_messages: "Aucun message" new: - abandon_changes: "Abandonner les changements ?" + message: "Message" send: "Envoyer" sending: "Envoi…" subject: "Sujet" @@ -316,6 +316,7 @@ fr: show: delete: "Supprimer la conversation" hide: "masquer et mettre en muet la conversation" + last_message: "Dernier message reçu %{timeago}" reply: "Répondre" replying: "Réponse en cours d'envoi..." date: @@ -328,10 +329,7 @@ fr: error_messages: helper: correct_the_following_errors_and_try_again: "Corrigez les erreurs suivantes, puis réessayez." - invalid_fields: "Champs invalides" - login_try_again: "Merci de vous <a href='%{login_link}'>connecter</a> et d'essayer de nouveau." - post_not_public: "Le message que vous essayez de voir n'est pas public !" - post_not_public_or_not_exist: "Le message que vous essayez de voir n'est pas public, ou n'existe pas !" + need_javascript: "Ce site web nécessite JavaScript pour fonctionner correctement. Si vous avez désactivé JavaScript, veuillez le réactiver et actualiser cette page." fill_me_out: "Écrire ici" find_people: "Rechercher des personnes ou des #tags" help: @@ -553,87 +551,77 @@ fr: tutorial: "tutoriel" tutorials: "tutoriels" wiki: "wiki" - hide: "Masquer" - ignore: "Ignorer" + home: + default: + be_who_you_want_to_be: "Soyez celui que vous voulez" + be_who_you_want_to_be_info: "De nombreux réseaux vous incitent à utiliser votre véritable identité. Pas diaspora*. Ici, vous pouvez choisir qui vous voulez être et partager autant ou aussi peu que vous le souhaitez. C'est vraiment vous qui décidez de la façon dont vous interagissez avec les autres." + byline: "Le réseau social où vous gardez le contrôle." + choose_your_audience: "Choisissez votre public" + choose_your_audience_info: "Les aspects de diaspora* vous permettent de partager seulement avec les personnes que vous choisissez. Vous demeurez aussi ouvert ou aussi restreint que vous le souhaitez. Partagez des photos amusantes avec le monde entier, ou un grand secret avec vos amis les plus proches. C'est vous qui avez le contrôle." + headline: "Bienvenue sur %{pod_name}" + own_your_data: "Soyez propriétaire de vos données" + own_your_data_info: "De nombreux réseaux utilisent vos données pour gagner de l'argent en analysant vos interactions et en utilisant ces informations pour vous proposer des publicités ciblées. Vos données sur diaspora* ne servent qu'à vous mettre en relation et à partager avec d'autres personnes." + podmin: + admin_panel: "panneau d'administrateur" + byline: "Vous êtes sur le point de changer la face d'Internet. Prêt à vous lancer ?" + configuration_info: "Ouvrez %{database_path} et %{diaspora_path} dans votre éditeur de texte favori et relisez-les soigneusement, ils sont abondamment commentés." + configure_your_pod: "Configurez votre pod" + contact_irc: "nous contacter sur IRC" + contribute: "Contribuez" + contribute_info: "Rendez diaspora* encore meilleur ! Si vous rencontrez des bugs, %{report_bugs} s'il vous plaît." + create_an_account: "Créez un compte" + create_an_account_info: "%{sign_up_link} pour un nouveau compte." + faq_for_podmins: "FAQ pour les podmins sur notre wiki" + getting_help: "Obtenez de l'aide" + getting_help_info: "Nous avons listé quelques %{faq} incluant des trucs et astuces supplémentaires ainsi que des solutions aux problèmes les plus communs. N'hésitez pas à %{irc}." + headline: "Bienvenue, l'ami." + make_yourself_an_admin: "Devenez administrateur" + make_yourself_an_admin_info: "Vous trouverez des renseignements sur le %{wiki}. Cela devrait ajouter un lien « Administrateur » à l'entête de votre menu utilisateur lorsque vous êtes connecté. Cela vous donne accès à des rubriques telles que la recherche d'utilisateur ou les statistiques de votre pod. Pour une description détaillée des aspects opérationnels de votre pod, allez sur le %{admin_panel}." + report_bugs: "reportez-les" + update_instructions: "des instructions de mise à jour sur le wiki de diaspora*" + update_your_pod: "Maintenez votre pod à jour" + update_your_pod_info: "Vous trouverez %{update_instructions}." invitation_codes: - excited: "%{name} est content de vous voir ici." not_valid: "Ce code d'invitation n'est plus valide." invitations: a_facebook_user: "Un utilisateur de Facebook" check_token: not_found: "Jeton d'invitation introuvable" create: - already_contacts: "Vous avez déjà établi une connexion avec cette personne" - already_sent: "Vous avez déjà invité cette personne." empty: "Veuillez fournir au moins une adresse de courrier électronique." no_more: "Vous n’avez plus d’invitation." note_already_sent: "Une invitation a déjà été envoyée aux e-mails %{emails}" - own_address: "Vous ne pouvez pas envoyer une invitation à votre propre adresse." rejected: "Les adresses de courrier électronique suivantes ont rencontré des problèmes :" sent: "Les invitations ont été envoyées à : %{emails}" - edit: - accept_your_invitation: "Accepter l'invitation" - your_account_awaits: "Votre compte vous attend !" new: - already_invited: "Les personnes suivantes n'ont pas accepté votre invitation :" - aspect: "Aspect" - check_out_diaspora: "Essayez diaspora* !" codes_left: one: "Plus qu'une invitation disponible avec ce code." other: "Encore %{count} invitations disponibles avec ce code." zero: "Plus d'invitation disponible avec ce code." comma_separated_plz: "Vous pouvez entrer plusieurs adresses de courrier électronique séparées par des virgules." - if_they_accept_info: "s'ils acceptent, ils seront ajoutés à l'aspect auquel vous les avez invités." invite_someone_to_join: "Invitez quelqu'un à rejoindre diaspora* !" language: "Langue" paste_link: "Partagez ce lien auprès de vos amis pour les inviter sur diaspora*, ou bien envoyez-leur directement le lien par courriel." - personal_message: "Message personnel" - resend: "Envoyer à nouveau" send_an_invitation: "Envoyer une invitation" - send_invitation: "Envoyer l'invitation" sending_invitation: "Invitation en cours ..." - to: "À" layouts: application: back_to_top: "Retour en haut" + be_excellent: "Soyez bienveillant envers chacun ! ♥" powered_by: "Propulsé par diaspora*" public_feed: "Flux diaspora* public de %{name}" source_package: "Téléchargez le code source" statistics_link: "Statistiques du pod" toggle: "Activer/désactiver la version mobile" whats_new: "Quoi de neuf ?" - your_aspects: "Vos aspects" header: - admin: "Admin" - blog: "Blog" code: "Code" - help: "Aide" - login: "Connexion" logout: "Déconnexion" profile: "Profil" - recent_notifications: "Notifications" settings: "Paramètres" - view_all: "Tout afficher" - likes: - likes: - people_dislike_this: - few: "%{count} personnes n'aiment pas" - many: "%{count} personnes n'aiment pas" - one: "%{count} personne n'aime pas" - other: "%{count} personnes n'aiment pas" - two: "%{count} n'aiment pas" - zero: "Personne n'aime pas" - people_like_this: - one: "%{count} personne aime" - other: "%{count} personnes aiment" - zero: "Personne n'aime" - people_like_this_comment: - one: "%{count} personne aime" - other: "%{count} personnes aiment" - zero: "Personne n'aime ça" + toggle_navigation: "Afficher/cacher le menu" limited: "Limité" more: "Plus" - next: "Suivant" no_results: "Aucun résultat trouvé" notifications: also_commented: @@ -648,14 +636,6 @@ fr: one: "%{actors} a commenté votre message %{post_link}." other: "%{actors} ont commenté votre message %{post_link}." zero: "%{actors} n'a commenté sur votre message %{post_link}." - helper: - new_notifications: - few: "%{count} nouvelles notifications" - many: "%{count} nouvelles notifications" - one: "1 nouvelle notification" - other: "%{count} nouvelles notifications" - two: "%{count} nouvelles notifications" - zero: "Aucune nouvelle notification" index: all_notifications: "Toutes les notifications" also_commented: "Aussi commenté" @@ -717,7 +697,6 @@ fr: a_limited_post_comment: "Vous avez un nouveau commentaire sur un message à visibilité limitée." a_post_you_shared: "un message." a_private_message: "Vous avez un nouveau message privé à consulter sur diaspora*." - accept_invite: "Acceptez votre invitation sur diaspora* !" also_commented: limited_subject: "Il y a un nouveau commentaire sur un message que vous avez commenté" click_here: "Cliquez ici" @@ -775,21 +754,22 @@ fr: message: |- Bonjour ! - Vous avez été invité(e) à rejoindre diaspora* ! + Vous avez été invité-e par %{diaspora_id} à rejoindre diaspora* ! Cliquez sur ce lien pour vous lancer dans l'aventure : [%{invite_url}][1] + Ou si vous avez déjà un compte, vous pouvez ajouter %{diaspora_id} à vos contacts. - Bien le bonjour chez vous, + Amicalement, Le messager automatique de diaspora* PS : Au cas où vous ne sauriez pas (encore) ce qu'est diaspora*, la réponse est [ici][2] ! [1] : %{invite_url} - [2]: %{diasporafoundation_url} + [2] : %{diasporafoundation_url} invited_you: "%{name} vous a invité(e) sur diaspora*" liked: liked: "%{name} a aimé votre message" @@ -797,10 +777,10 @@ fr: view_post: "Voir le message >" mentioned: limited_post: "Vous avez été mentionné dans une publication restreinte." - mentioned: "vous a mentionné(e) dans un message :" subject: "%{name} vous a mentionné(e) sur diaspora*" private_message: reply_to_or_view: "Répondre ou voir cette conversation >" + subject: "Vous avez un nouveau message privé" remove_old_user: body: |- Bonjour, @@ -834,10 +814,10 @@ fr: Le messager automatique de diaspora* [1]: %{url} - subject: "Un nouveau %{type} a été marqué comme offensant." + subject: "Un nouveau %{type} a été marqué comme offensant" type: comment: "commentaire" - post: "Message" + post: "message" reshared: reshared: "%{name} a repartagé votre message" view_post: "Voir le message >" @@ -852,20 +832,9 @@ fr: to_change_your_notification_settings: "pour changer vos paramètres de notification" nsfw: "NSFW" ok: "OK" - or: "ou" - password: "Mot de passe" - password_confirmation: "Confirmation du mot de passe" people: add_contact: invited_by: "Vous avez été invité(e) par" - add_contact_small: - add_contact_from_tag: "Ajouter ce contact à partir de ce tag" - aspect_list: - edit_membership: "Modifier l'appartenance à vos aspects" - helper: - is_not_sharing: "%{name} ne partage pas avec vous" - is_sharing: "%{name} partage avec vous" - results_for: "résultats pour %{params}" index: couldnt_find_them: "Vous ne les trouvez pas ?" looking_for: "Rechercher des commentaires taggés %{tag_link}?" @@ -873,107 +842,68 @@ fr: no_results: "Hé ! Vous devez rechercher quelque chose." results_for: "Utilisateurs correspondant à %{search_term}" search_handle: "Utilisez leur identifiant diaspora* (nomutilisateur@urldupod) pour être sûr de trouver vos amis." - searching: "Recherche en cours, veuillez patienter ..." + searching: "Recherche en cours, veuillez patienter…" send_invite: "Toujours rien ? Envoyez leur une invitation !" - one: "1 personne" - other: "%{count} personnes" person: - add_contact: "Ajouter un contact" - already_connected: "Déjà connecté" - pending_request: "Requête en attente" thats_you: "C'est vous !" profile_sidebar: bio: "Bio" born: "Anniversaire" - edit_my_profile: "Modifier mon profil" gender: "Genre" - in_aspects: "Dans les aspects" location: "Localisation" - photos: "Photos" - remove_contact: "Supprimer ce contact" - remove_from: "Supprimer %{name} de %{aspect} ?" show: closed_account: "Ce compte a été fermé." does_not_exist: "Cette personne n'existe pas !" has_not_shared_with_you_yet: "%{name} n'a pas encore partagé de messages avec vous !" - ignoring: "Vous ignorez tous les messages de %{name}." - incoming_request: "%{name} désire partager avec vous" - mention: "Mentionner" - message: "Écrire" - not_connected: "Vous n'êtes pas connecté(e) avec cette personne" - recent_posts: "Messages récents" - recent_public_posts: "Messages publics récents" - return_to_aspects: "Retourner à la page de vos aspects" - see_all: "Tout afficher" - start_sharing: "Commencer à partager" - to_accept_or_ignore: "accepter ou ignorer ceci" - sub_header: - add_some: "En ajouter quelques-uns" - edit: "Modifier" - you_have_no_tags: "Vous n'avez pas de tags !" - webfinger: - fail: "Impossible de trouver %{handle}." - zero: "Personne" photos: - comment_email_subject: "photo de %{name}" create: integrity_error: "Impossible d'envoyer la photo. S'agit-il réellement d'une image ?" runtime_error: "L'envoi de la photo a échoué. Avez-vous attaché votre ceinture ?" type_error: "L'envoi de la photo a échoué. Vérifiez qu'une photo a bien été ajoutée ?" destroy: notice: "La photo a été supprimée." - edit: - editing: "Modification" - new: - back_to_list: "Retourner à la liste" - new_photo: "Nouvelle photo" - post_it: "Publiez-le !" new_photo: empty: "{file} est vide, merci de sélectionner d'autres fichiers." invalid_ext: "{file} a une extension invalide. Seules {extensions} sont autorisées." size_error: "{file} est trop grand, la taille maximum pour un fichier est {sizeLimit}." new_profile_photo: - or_select_one_existing: "ou choisissez parmi vos photos existantes %{photos}" upload: "Mettre une nouvelle photo de profil !" - photo: - view_all: "Voir toutes les photos de %{name}" show: - collection_permalink: "Lien permanent à la collection" - delete_photo: "Supprimer la photo" - edit: "Modifier" - edit_delete_photo: "Modifier la description de la photo / supprimer la photo" - make_profile_photo: "Choisir comme photo de profil" show_original_post: "Montrer le message original" - update_photo: "Mettre à jour la photo" - update: - error: "La modification de la photo a échoué." - notice: "La photo a été mise à jour." + polls: + votes: + one: "%{count} vote pour l'instant" + other: "%{count} votes pour l'instant" + zero: "%{count} votes pour l'instant" posts: presenter: title: "Un message de %{name}" show: - destroy: "Supprimer" forbidden: "Vous n'êtes pas autorisé à faire cela" - not_found: "Désolés, nous n'avons pas pu trouver ce message." - permalink: "Lien permanent" + location: "Publié depuis : %{location}" photos_by: one: "Une photo par %{author}" other: "%{count} photos par %{author}" zero: "Pas de photo par %{author}" reshare_by: "Repartagé par %{author}" - previous: "Précédent" privacy: "Vie privée" - privacy_policy: "Règles de confidentialité" profile: "Profil" profiles: edit: allow_search: "Permettre à tous de vous rechercher dans diaspora*" - edit_profile: "Modifier le profil" + basic: "Mon profil basique" + basic_hint: "Tous les éléments de votre profil sont optionnels. Votre profil basique sera toujours visible publiquement." + extended: "Mon profil complet" + extended_hint: "Cliquez sur l'interrupteur pour choisir la visibilité de votre profil complet. « Public » signifie qu'il sera visible sur tout Internet, « limité » signifie qu'uniquement les personnes avec qui vous partagez pourront voir cette information." + extended_visibility_text: "Visibilité de votre profil complet :" first_name: "Prénom" last_name: "Nom de famille" + limited: "Limité" nsfw_check: "Marquer tout ce que je poste comme #NSFW" nsfw_explanation: "NSFW ('Not Safe For Work') est une convention pour le contenu qui n'est pas visualisable au travail. Si vous prévoyez de partager ce genre de contenu fréquemment, vous pouvez cocher cette option pour que tous vos messages soient masqués aux autres utilisateurs jusqu'à ce qu'ils les affichent manuellement." nsfw_explanation2: "Si vous choisissez de ne pas cocher cette option, veuillez ajouter le tag #nsfw à chaque fois que vous postez du contenu choquant." + public: "Public" + settings: "Paramètres du profil" update_profile: "Mettre à jour le profil" your_bio: "Votre biographie" your_birthday: "Votre anniversaire" @@ -981,8 +911,6 @@ fr: your_location: "Votre localisation" your_name: "Votre nom" your_photo: "Votre photo" - your_private_profile: "Votre profil privé" - your_public_profile: "Votre profil public" your_tags: "Décrivez-vous en 5 mots" your_tags_placeholder: "comme #films #repassage #voyage #professeur #paris" update: @@ -997,30 +925,20 @@ fr: closed: "Les inscriptions sont fermées sur ce pod diaspora*." create: success: "Vous avez rejoint diaspora* !" - edit: - cancel_my_account: "Clôturer mon compte" - edit: "Modifier %{name}" - leave_blank: "(laissez vide si vous ne souhaitez pas modifier)" - password_to_confirm: "(nous avons besoin de votre mot de passe actuel pour confirmer vos changements)" - unhappy: "Insatisfait(e) ?" - update: "Mettre à jour" invalid_invite: "Le lien d'invitation que vous avez fourni n'est plus valide !" new: - create_my_account: "Créer mon compte !" - email: "COURRIEL" + email: "Adresse électronique" enter_email: "Saisissez une adresse de courrier électronique" enter_password: "Saisissez un mot de passe (d'au moins six caractères)" enter_password_again: "Saisissez à nouveau le même mot de passe" enter_username: "Choisissez un nom d'utilisateur (uniquement des lettres, chiffres et caractères de soulignement)" - join_the_movement: "Rejoignez le mouvement !" - password: "MOT DE PASSE" - password_confirmation: "CONFIRMATION DU MOT DE PASSE" - sign_up: "INSCRIVEZ-VOUS" - sign_up_message: "Le réseau social avec un ♥" - submitting: "Envoi en cours..." + password: "Mot de passe" + password_confirmation: "Confirmation du mot de passe" + sign_up: "Inscrivez-vous" + submitting: "Envoi en cours…" terms: "En créant un compte, vous acceptez les %{terms_link}" terms_link: "conditions d'utilisation" - username: "NOM D'UTILISATEUR" + username: "Nom d’utilisateur" report: comment_label: "<b>Commentaire</b>:<br>%{data}" confirm_deletion: "Etes vous vraiment sur de vouloir supprimer cet élément ?" @@ -1029,45 +947,18 @@ fr: post_label: "<b>Message</b>: %{title}" reason_label: "Raison : %{text}" reported_label: "<b>Signalé par</b> %{person}" + reported_user_details: "Détails sur l'utilisateur signalé" review_link: "Marqué comme revu." status: - created: "Un signalement a été créé" destroyed: "Le message a été détruit" failed: "Il y a eu un problème." - marked: "Ce signalement a été marqué comme revu" title: "Vue d'ensemble des signalements." - requests: - create: - sending: "En cours d'envoi" - sent: "Vous avez demandé à partager avec %{name}. Il devrait le voir lors de sa prochaine connexion à diaspora*." - destroy: - error: "Veuillez sélectionner un aspect !" - ignore: "Requête de contact ignorée." - success: "Vous êtes à présent ami(e)s." - helper: - new_requests: - one: "Nouvelle requête !" - other: "%{count} nouvelles requêtes !" - zero: "Aucune nouvelle requête" - manage_aspect_contacts: - existing: "Contacts existants" - manage_within: "Gérer les contacts de" - new_request_to_person: - sent: "Envoyée !" reshares: comment_email_subject: "Partage par %{resharer} d'un message de %{author}" - create: - failure: "Une erreur a été rencontrée lors du repartage de ce message." reshare: deleted: "Le message original a été supprimé par l'auteur." - reshare: - one: "1 repartage" - other: "%{count} repartages" - zero: "Repartager" reshare_confirmation: "Repartager le message de %{author} ?" - reshare_original: "Repartager l'original" reshared_via: "Repartagé par" - show_original: "Afficher l'original" search: "Rechercher" services: create: @@ -1079,10 +970,6 @@ fr: success: "Authentification supprimée." failure: error: "Une erreur s'est produite lors de la connexion avec ce service" - finder: - fetching_contacts: "Diaspora* est en train d'importer vos amis %{service}. Revenez dans quelques minutes." - no_friends: "Aucun ami Facebook trouvé." - service_friends: "Amis %{service}" index: connect: "Se connecter" disconnect: "Déconnecter" @@ -1092,56 +979,27 @@ fr: not_logged_in: "Vous n'êtes pas connecté actuellement." really_disconnect: "Déconnecter %{service} ?" services_explanation: "Se connecter à des services vous donne la possibilité d'y publier vos messages depuis diaspora*." - inviter: - click_link_to_accept_invitation: "Suivez ce lien pour accepter l'invitation" - join_me_on_diaspora: "Rejoignez-moi sur diaspora*" + share_to: "Partager avec %{provider}" + title: "Gérer les services connectés" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "Wordpress" - remote_friend: - invite: "Inviter" - not_on_diaspora: "Pas encore sur diaspora*" - resend: "Envoyer à nouveau" settings: "Paramètres" - share_visibilites: - update: - post_hidden_and_muted: "La publication de %{name} a été masquée et vous ne serez plus notifié." - see_it_on_their_profile: "Si vous souhaitez voir des mises à jour de ce message, visitez la page de profil de %{name}." shared: - add_contact: - add_new_contact: "Ajouter un nouveau contact" - create_request: "Rechercher par identifiant diaspora*" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Entrez un nom d'utilisateur diaspora* :" - know_email: "Connaissez-vous leur adresse de courrier électronique ? Vous devriez les inviter" - your_diaspora_username_is: "Votre nom d'utilisateur diaspora* est : %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Ajouter le contact" mobile_row_checked: "%{name} (retirer)" mobile_row_unchecked: "%{name} (ajouter)" toggle: one: "Dans %{count} aspect" other: "Dans %{count} aspects" zero: "Ajouter le contact" - contact_list: - all_contacts: "Tous les contacts" - footer: - logged_in_as: "Connecté en tant que %{name}" - your_aspects: "Vos aspects" invitations: by_email: "Par courriel" - dont_have_now: "Vous n'en avez aucune pour l'instant, mais d'autres invitations arriveront bientôt !" - from_facebook: "Depuis Facebook" - invitations_left: "il vous en reste %{count}" - invite_someone: "Inviter quelqu'un" invite_your_friends: "Invitez vos amis" invites: "Invitations" - invites_closed: "Les invitations sont actuellement fermées sur ce pod diaspora*" share_this: "Partagez ce lien par courriel, sur un blog ou via votre réseau social favori !" - notification: - new: "Nouveau/nouvelle %{type} de %{from}" public_explain: atom_feed: "Flux Atom" control_your_audience: "Contrôlez votre audience" @@ -1153,12 +1011,9 @@ fr: title: "Mettre en place des services connectés" visibility_dropdown: "Utilisez ce menu déroulant pour modifier la visibilité de votre message. (Nous vous conseillons de rendre public ce premier message.)" publisher: - all: "Tous" - all_contacts: "Tous les contacts" discard_post: "Supprimer la publication" formatWithMarkdown: "Utilisez la syntaxe %{markdown_link} pour mettre en forme votre message" get_location: "Ajouter votre emplacement" - make_public: "Rendre public" new_user_prefill: hello: "Bonjour tout le monde, je suis #%{new_user_tag}. " i_like: "Mes centres d'intérêt sont %{tags}. " @@ -1166,36 +1021,14 @@ fr: newhere: "nouveauici" poll: add_a_poll: "Ajouter un sondage" - add_poll_answer: "Ajouter un choix" - option: "Option 1" - question: "Question" - remove_poll_answer: "Enlever ce choix" - post_a_message_to: "Publier un message dans %{aspect}" posting: "Publication…" - preview: "Aperçu" - publishing_to: "Publication vers : " remove_location: "Supprimer l'emplacement" share: "Partager" - share_with: "Partager avec" upload_photos: "Envoyer des photos" whats_on_your_mind: "Exprimez-vous..." - reshare: - reshare: "Repartager" stream_element: - connect_to_comment: "Ajoutez cet utilisateur pour commenter son message" - currently_unavailable: "Les commentaires sont actuellement indisponibles" - dislike: "Je n'aime pas" - hide_and_mute: "Masquer et mettre le message en sourdine" - ignore_user: "Ignorez %{name}" - ignore_user_description: "Ignorer et supprimer l'utilisateur de tous les aspects ?" - like: "J'aime" - nsfw: "Le message a été marqué par son auteur comme étant EXPLICITE. %{link}" - shared_with: "Partagé avec : %{aspect_names}" - show: "Montrer" - unlike: "Je n'aime plus" via: "Via %{link}" - via_mobile: "Envoyé d'un mobile" - viewable_to_anyone: "Publication visible par n'importe qui sur le web" + via_mobile: "Envoyé depuis un mobile" simple_captcha: label: "Entrez le code dans le champ" message: @@ -1221,21 +1054,12 @@ fr: status_messages: create: success: "Mention de : %{names}" - destroy: - failure: "Impossible de supprimer le message" - helper: - no_message_to_display: "Aucun message à afficher." new: mentioning: "Mentionne : %{person}" too_long: "Veillez à écrire un message de statut de %{count} caractères maximum. Il compte actuellement %{current_length} caractères." stream_helper: - hide_comments: "Masquer tous les commentaires" no_more_posts: "Vous avez atteint la fin de ce flux." no_posts_yet: "Il n'y a pas encore de message ici." - show_comments: - one: "Montrer un commentaire supplémentaire" - other: "Montrer %{count} commentaires supplémentaires" - zero: "Plus de commentaire." streams: activity: title: "Mon activité" @@ -1262,13 +1086,6 @@ fr: tags: title: "Messages tagués : %{tags}" tag_followings: - create: - failure: "Impossible de suivre #%{name}. Le suivez-vous déjà ?" - none: "Vous ne pouvez pas suivre de tag vide !" - success: "Hourra ! Maintenant vous suivez #%{name}." - destroy: - failure: "Impossible de ne plus suivre #%{name}. Peut-être ne le suivez-vous déjà plus?" - success: "Dommage ! Vous ne suivez plus #%{name}." manage: no_tags: "Vous ne suivez aucun tag." title: "Gérer les tags suivis." @@ -1276,15 +1093,12 @@ fr: name_too_long: "Votre tag doit faire moins de %{count} caractères (actuellement, %{current_length})" show: follow: "Suivre #%{tag}" - following: "Suivre #%{tag}" none: "Le tag vide n'existe pas !" stop_following: "Arrêter de suivre #%{tag}" tagged_people: one: "1 personne marquée avec %{tag}" other: "%{count} personnes marquées avec %{tag}" zero: "Personne n'est marqué avec %{tag}" - terms_and_conditions: "Conditions d'utilisation" - undo: "Annuler ?" username: "Nom d'utilisateur" users: confirm_email: @@ -1299,13 +1113,13 @@ fr: auto_follow_aspect: "Aspect pour les utilisateurs que vous suivez automatiquement :" auto_follow_back: "Suivre automatiquement en retour ceux qui vous suivent" change: "Modifier" + change_color_theme: "Changer le thème de couleur" change_email: "Changer d'adresse électronique" change_language: "Changer la langue" change_password: "Changer le mot de passe" character_minimum_expl: "doit comporter au moins six caractères" close_account: dont_go: "Hé, s'il vous plaît, ne partez pas !" - if_you_want_this: "Si vous êtes sûr de vous, saisissez votre mot de passe ci-dessous et cliquez sur 'Supprimer le compte'" lock_username: "Votre nom d'utilisateur sera bloqué. Vous ne pourrez pas créer un nouveau compte sur ce pod avec le même identifiant." locked_out: "Vous serez déconnecté et votre compte sera inaccessible jusqu'à sa suppression." make_diaspora_better: "Nous aimerions beaucoup que vous restiez pour nous aider à améliorer diaspora* plutôt que de nous quitter. Toutefois, si c'est vraiment ce que vous souhaitez, voilà ce qui va se passer :" @@ -1318,14 +1132,12 @@ fr: current_password_expl: "Celui avec lequel vous vous connectez ..." download_export: "Télécharger mon profil" download_export_photos: "Télécharger mes photos" - download_photos: "Télécharger mes photos" edit_account: "Modifier le compte" email_awaiting_confirmation: "Nous vous avons envoyé un lien d'activation à %{unconfirmed_email}. Jusqu'à ce que vous suiviez ce lien et activiez la nouvelle adresse, nous allons continuer à utiliser votre adresse originale %{email}." export_data: "Exporter des données" export_in_progress: "Nous sommes en train de traiter vos données. Veuillez vérifier à nouveau l'avancement dans un moment." export_photos_in_progress: "Nous sommes en train de traiter vos photos. Merci de revenir ici dans quelques instants." following: "Paramètres de partage" - getting_started: "Préférences de nouvel utilisateur" last_exported_at: "(Dernière mise à jour à %{timestamp})" liked: "…quelqu'un a aimé votre message." mentioned: "…l'on vous mentionne dans un message." @@ -1352,7 +1164,6 @@ fr: connect_to_facebook_link: "Connexion avec votre compte Facebook en cours" hashtag_explanation: "Les tags vous permettent de parler de vos centres d'intérêt et de suivre ce qui s'en dit. Ils sont aussi un excellent moyen de rencontrer de nouvelles personnes sur diaspora*." hashtag_suggestions: "Essayez de suivre des tags comme #art, #films, #french, etc." - saved: "Sauvé !" well_hello_there: "Bienvenue !" what_are_you_in_to: "Qu'aimez-vous faire ?" who_are_you: "Qui êtes-vous ?" @@ -1365,6 +1176,8 @@ fr: public: does_not_exist: "L'utilisateur %{username} n'existe pas !" update: + color_theme_changed: "Thème de couleur changé." + color_theme_not_changed: "Une erreur s'est produite pendant le changement de thème de couleur." email_notifications_changed: "Notifications par courriel modifiées" follow_settings_changed: "Les paramètres de suivi ont été modifiés" follow_settings_not_changed: "Échec de la modification des paramètres de suivi." @@ -1376,13 +1189,6 @@ fr: settings_updated: "Mise à jour des paramètres" unconfirmed_email_changed: "Adresse électronique changée. Activation nécessaire." unconfirmed_email_not_changed: "Le changement d'adresse électronique a échoué" - webfinger: - fetch_failed: "Impossible de télécharger le profil webfinger pour %{profile_url}" - hcard_fetch_failed: "Une erreur est survenue lors du téléchargement de la hcard de %{account}" - no_person_constructed: "Cette hcard semble être invalide." - not_enabled: "webfinger ne semble pas être activé sur l'hôte de %{account}" - xrd_fetch_failed: "Une erreur est survenue lors de la récupération du xrd du compte %{account}" - welcome: "Bienvenue !" will_paginate: next_label: "suivant »" previous_label: "« précédent" \ No newline at end of file diff --git a/config/locales/diaspora/fy.yml b/config/locales/diaspora/fy.yml index 934f9794c52da118d9cb21f597ff3e7d8aa12edf..bd41dd90504663163b1841951ca8bce696b7ae04 100644 --- a/config/locales/diaspora/fy.yml +++ b/config/locales/diaspora/fy.yml @@ -6,20 +6,14 @@ fy: _applications: "Tapassingen" - _comments: "Reaksjes" _contacts: "Kontakten" - _home: "Thús" - _photos: "foto's" account: "Akkount" - ago: "%{time} lyn" are_you_sure: "Bisto wis?" aspects: edit: update: "fernij" updating: "fernije" index: - diaspora_id: - content_1: "Dyn Diaspora ID is:" help: find_a_bug: "... in %{link} fine?" have_a_question: "... in %{link} hawwe?" @@ -27,37 +21,24 @@ fy: new_here: learn_more: "Lês mear" title: "Wolkom Nije Brûkers" - no_contacts: "Gjin kontakten" - post_a_message: "stjoer in berjocht >>" welcome_to_diaspora: "Wolkom by Diaspora, %{name}!" - new: - create: "Oanmeitsje" seed: acquaintances: "Bekenden" family: "Famylje" friends: "Freonen" work: "Wurk" - back: "Tebek" cancel: "Annulearje" comments: new_comment: comment: "Reaksje" commenting: "Reagearje..." contacts: - create: - failure: "Koe gjin kontakt oanmeitsje" index: all_contacts: "Alle Kontakten" title: "Kontakten" - your_contacts: "Dyn Kontakten" conversations: create: sent: "Berjocht ferstjoerd" - helper: - new_messages: - one: "1 nij berjocht" - other: "%{count} nije berjochten" - zero: "Gjin nije berjochten" index: inbox: "Ynbox" no_messages: "gjin berjochten" @@ -77,32 +58,21 @@ fy: delete: "Fuortsmite" email: "E-mail" find_people: "Minsken of #labels Sykje" - hide: "Ferbergje" invitations: a_facebook_user: "In Facebook brûker" new: invite_someone_to_join: "Immen útnoadigje foar Diaspora!" language: "Taal" - personal_message: "Persoanlik berjocht" - resend: "Opnij ferstjoere" send_an_invitation: "In útnoeging ferstjoere" - send_invitation: "Útnoeging ferstjoerd" - to: "Oan" layouts: application: powered_by: "MEA MOOGLIK MAKKE TROCH DIASPORA*" header: - admin: "behearder" - blog: "bloch" code: "koade" - login: "ynlogge" logout: "Útlogge" profile: "Profyl" - recent_notifications: "Resinte notifikaasjes" settings: "Ynstellingen" - view_all: "Toan alle" more: "Mear" - next: "folgjende" no_results: "Gjin Risseltaten Fûn" notifications: post: "berjocht" @@ -115,20 +85,9 @@ fy: thanks: "Tige Tank," nsfw: "Net Feilich Foar Wurk" ok: "Okee" - or: "of" - password: "Wachtwurd" - password_confirmation: "Wachtwurd konfirmaasje" - people: - one: "1 persoan" - zero: "gjin minsken" - previous: "foarrige" privacy: "Privacy" - privacy_policy: "Privacybelied" profile: "Profyl" public: "Iepenbier" search: "Sykje" settings: "Ynstellingen" - terms_and_conditions: "Algemiene Betingsten" - undo: "Ûngedien meitsje?" - username: "Brûkersnamme" - welcome: "Wolkom!" \ No newline at end of file + username: "Brûkersnamme" \ No newline at end of file diff --git a/config/locales/diaspora/ga.yml b/config/locales/diaspora/ga.yml index 1f568c2ca21853ff9fa769bf47cf28a60d136dc9..175a66f7d47a03728543797b45b0eb72bd3e02a6 100644 --- a/config/locales/diaspora/ga.yml +++ b/config/locales/diaspora/ga.yml @@ -6,10 +6,7 @@ ga: _applications: "Feidhmchláir" - _comments: "Tráchtanna" _contacts: "Teagmhálacha" - _home: "Baile" - _photos: "griangraif" _services: "SeirbhÃsÃ" account: "Cuntas" activerecord: @@ -28,34 +25,25 @@ ga: username: invalid: "neamhbhailÃ. Tá ach litreacha, uimhreacha agus béim ceadaithe." taken: "glacadh cheana." - ago: "%{time} ó shin" all_aspects: "Gach gnéithe" are_you_sure: "An bhfuil tú cinnte?" are_you_sure_delete_account: "An bhfuil tú cinnte go dteastaÃonn uait do chuntas a dhúnadh? Nà féidir é seo a chealaigh!" aspects: - aspect_listings: - edit_aspect: "%{name} a chur in eagar" edit: rename: "athainmnigh" update: "uasdátaigh" updating: "nuashonrú" index: - diaspora_id: - heading: "ID Diaspora" help: - email_link: "RÃomhphoist" need_help: "Cabhair?" tag_bug: "fabht" tag_feature: "gné" new_here: learn_more: "Breis eolais" - new: - create: "Cruthaigh" seed: family: "Gaolmhara" friends: "Cháirde" work: "Obair" - back: "Ar ais" cancel: "Cealaigh" contacts: index: @@ -63,7 +51,6 @@ ga: community_spotlight: "Spotsolas Pobail" my_contacts: "Mo Theagmhálacha" title: "Teagmhálacha" - your_contacts: "Do Theagmhálacha" spotlight: community_spotlight: "Spotsolas Pobail" conversations: @@ -78,27 +65,19 @@ ga: delete: "Scrios" email: "RÃomhphoist" fill_me_out: "LÃon amach" - hide: "Folaigh" invitations: a_facebook_user: "Úsáideoir Facebook" new: - aspect: "Gné" language: "Teanga" - personal_message: "Teachtaireacht pearsanta" - to: "Le" layouts: application: back_to_top: "Barr" - your_aspects: "do ghnéithe" header: - blog: "blag" code: "cód" - login: "logáil isteach" logout: "Logáil amach" settings: "Sainroghanna" limited: "Teoranta" more: "NÃos mó" - next: "chugainn" no_results: "NÃl Torthaà Aimsithe" notifications: index: @@ -122,40 +101,20 @@ ga: thanks: "Maith agat," nsfw: "NSFW" ok: "OK" - or: "nó" - password: "Pasfhocal" - password_confirmation: "Deimhniú pásfhocal" people: - one: "duine amháin" - other: "%{count} daoine" person: thats_you: "Is leatsa!" profile_sidebar: born: "Breithlá" gender: "Inscne" location: "SuÃomh" - show: - message: "Teachtaireacht" - zero: "gan duine" photos: destroy: notice: "Griangraf scriosta." - new: - back_to_list: "Ar ais go dtà an liosta" - new_photo: "Griangraf Nua" - show: - delete_photo: "Scrios an Ghriangraf" - edit: "cur in eagar" - posts: - show: - destroy: "Scrios" - previous: "roimhe" privacy: "PrÃobháideachas" - privacy_policy: "Polasaà PrÃobháideachta" profile: "PróifÃl" profiles: edit: - edit_profile: "Cur do phróifÃl in eagar" first_name: "Ainm baiste" last_name: "Sloinne" your_birthday: "Do bhreithlá" @@ -164,10 +123,7 @@ ga: your_photo: "Do ghriangraf" public: "PoiblÃ" registrations: - edit: - unhappy: "MÃshona?" new: - create_my_account: "Cruthaigh mo chuntas!" email: "RÃOMHPHOIST" enter_email: "Seoladh rÃomhphoist" password: "PASFHOCAL" @@ -176,10 +132,7 @@ ga: username: "AINM ÚSAIDEOIR" search: "Cuardaigh" settings: "Sainroghanna" - terms_and_conditions: "Téarmaà agus CoinnÃollacha" - undo: "Cealaigh?" username: "Ainm úsáideora" users: edit: - your_email: "Do rÃomhphoist" - welcome: "Fáilte!" \ No newline at end of file + your_email: "Do rÃomhphoist" \ No newline at end of file diff --git a/config/locales/diaspora/gd.yml b/config/locales/diaspora/gd.yml index d4f06be2ac41c3c48ef4dede14a7adb1a48867fb..87be78cd8d165f69309f4b9916235e9aa2f602d5 100644 --- a/config/locales/diaspora/gd.yml +++ b/config/locales/diaspora/gd.yml @@ -6,11 +6,8 @@ gd: _applications: "Aplacaidean" - _comments: "Beachdan" _contacts: "Luchd-aithne" _help: "Cuideachadh" - _home: "Dachaigh" - _photos: "Dealbhan" _services: "Seirbheisean" account: "Cunntas" activerecord: @@ -50,27 +47,14 @@ gd: month: "Mìos" usage_statistic: "Staitistigs Cleachdaidh" week: "Seachdain" - ago: "o chionn %{time}" are_you_sure: "A bheil thu cinnteach?" are_you_sure_delete_account: "A bheil thu cinnteach gu bheil thu airson an cunntas agad a dhùnadh? Chan urrainn dhut seo a neo-dhèanamh!" aspects: - aspect_listings: - deselect_all: "Na tagh na h-uile" - edit_aspect: "Deasaich %{name}" - select_all: "Tagh na h-uile" - contacts_not_visible: "Chan fhaic daoine anns an roinn seo a chèile." - contacts_visible: "Chì daoine anns an roinn seo a chèile." edit: - make_aspect_list_visible: "A bheil thu ag iarraidh gum faic daoine san roinn seo a chèile?" update: "ùraich" updating: "ag ùrachadh" index: - diaspora_id: - content_1: "'S e seo an ID diaspora* agad:" - content_2: "Ma bheireas tu do chuideigin e, faodaidh iad gad lorg air diaspora*." - heading: "ID diaspora*" help: - email_link: "Post-d" feature_suggestion: "... a bheil thu airson %{link} a mholadh?" find_a_bug: "... an do lorg thu %{link}?" have_a_question: "... a bheil %{link} agad?" @@ -81,36 +65,24 @@ gd: content: "Faodaidh tu ceangal a dhèanamh eadar diaspora* agus na sèirbheisean na leanas." heading: "Dèan ceangal ri Sèirbheis" welcome_to_diaspora: "Fà ilte gu diaspora*, a %{name}!" - new: - create: "Cruthaich" seed: acquaintances: "Muinntireachd" family: "Teaghlach" friends: "Cà irdean" - back: "Air ais" cancel: "Sguir dheth" comments: new_comment: comment: "Thoir beachd air" commenting: "a' toirt beachd air..." - one: "1 bheachd" - other: "%{count} beachdan" - zero: "Gun bheachd" contacts: index: all_contacts: "Cà irdean gu lèir" my_contacts: "Mo Chà irdean" no_contacts_message: "Thoir sùil air %{community_spotlight}" title: "Cà irdean" - your_contacts: "Do Chà irdean" conversations: create: fail: "Teachdaireachd neo-bhrìgheil" - helper: - new_messages: - one: "1 theachdaireachd ùr" - other: "%{count} teachdaireachdan ùra" - zero: "0 teachdaireachd ùr" new: send: "Cuir" sending: "a' cur..." @@ -129,7 +101,6 @@ gd: error_messages: helper: correct_the_following_errors_and_try_again: "Cuir ceart na mearachdan a leanas is feuch ris a-rithist." - invalid_fields: "Raointean mì-dhligheach" fill_me_out: "Lìon a-steach" find_people: "Lorg daoine no #tagaichean" help: @@ -140,26 +111,19 @@ gd: public_posts: title: "Brathan poblach" wiki: "" - hide: "Falaich" invitations: new: language: "Cà nan" - resend: "Cuir a-rithist" - to: "Gu" layouts: application: powered_by: "a' ruith air diaspora*" whats_new: "dè tha dol?" header: - admin: "riaghladh" - blog: "blog" - login: "log a-steach" logout: "Log a-mach" profile: "Profaidhl" settings: "Roghainnean" limited: "Cuingichte" more: "Barrachd" - next: "Air adhart" no_results: "Cha deach toradh a lorg" notifications: index: @@ -195,7 +159,6 @@ gd: liked: "Tha do brath còrdadh ri %{name}" view_post: "Seall air a' bhrath >" mentioned: - mentioned: "air iomradh a thoirt ort ann am brath:" subject: "Thug %{name} iomradh ort air diaspora*" private_message: reply_to_or_view: "Seall air a' bhrath seo no cuir freagairt ris >" @@ -206,46 +169,21 @@ gd: view_profile: "Thoir sùil air profaidhl %{name}" thanks: "Tapadh leat," ok: "Ceart ma-thà " - or: "no" - password: "Facal-faire" - password_confirmation: "Dearbhadh an fhacail-fhaire" people: index: no_results: "Haidh! Feumaidh tu rannsachadh airson rudeigin." - one: "duine" person: - already_connected: "Ceangailte mar-thà " - pending_request: "Iarrtas a' feitheamh ri dearbhadh" thats_you: "'S tusa a th' ann!" profile_sidebar: born: "Co-là -breith" - edit_my_profile: "Deasaich mo phrofaidhl" gender: "Gnè" - photos: "Dealbhan" show: closed_account: "Tha an cunntas seo dùinte." - mention: "Thoir iomradh air" - message: "Cuir brath" - sub_header: - edit: "deasaich" - photos: - edit: - editing: "Deasachadh" - new: - new_photo: "Dealbh ùr" - show: - edit: "deasaich" - posts: - show: - destroy: "Dubh à s" - previous: "Air ais" privacy: "Prìobhaideachd" - privacy_policy: "Am poileasaidh prìobhaideachd" profile: "Pròifil" profiles: edit: allow_search: "Am faod daoine rannsachadh air do shon air diaspora*" - edit_profile: "Deasaich profaidhl" first_name: "D' ainm-baistidh" last_name: "Do sloinneadh" update_profile: "Ùraich profaidhl" @@ -261,47 +199,26 @@ gd: updated: "Profaidhl air ùrachadh" public: "Poblach" registrations: - edit: - cancel_my_account: "Dùin mo chunntas" - edit: "Deasaich %{name}" - unhappy: "Mì-thoilichte?" - update: "Ùraich" new: - create_my_account: "Cruthaich mo chunntas!" email: "POST-D" enter_email: "Cuir a-steach seòladh post-d" enter_password: "Tagh facal-faire (co-dhiù sia litrichean)" enter_password_again: "Sgrìobh am facal-faire a-rithist" enter_username: "Tagh ainm-cleachdadh (a-u, 0-9 agus _ a-mhà in)" - join_the_movement: "Gabh anns an iomairt!" password: "FACAL-FAIRE" sign_up: "CLÀRAICH" username: "AINM-CLEACHDAIDH" - requests: - create: - sending: "a' cur" - new_request_to_person: - sent: "air a chur!" search: "Lorg" services: index: edit_services: "Deasaich sèirbheisean" - remote_friend: - resend: "cuir a-rithist" settings: "Roghainnean" shared: - add_contact: - diaspora_handle: "" public_explain: atom_feed: "" share: "Sgaoil" publisher: - preview: "Ro-shealladh" share: "Sgaoil" - reshare: - reshare: "Sgaoil" - terms_and_conditions: "Teirmichean is cumhaichean" - undo: "Neo-dhèan?" username: "Ainm-cleachdaiche" users: edit: @@ -311,5 +228,4 @@ gd: your_email: "Do phost-d" your_handle: "ID diaspora* agad" privacy_settings: - title: "Roghainnean Prìobhaideachd" - welcome: "Fà ilte!" \ No newline at end of file + title: "Roghainnean Prìobhaideachd" \ No newline at end of file diff --git a/config/locales/diaspora/he.yml b/config/locales/diaspora/he.yml index df89e9cb2dcdd74e75727c0d2ab9c8a279a9363e..dbb57ea3428e6f7e1acf0102ebec4069ddc47368 100644 --- a/config/locales/diaspora/he.yml +++ b/config/locales/diaspora/he.yml @@ -6,11 +6,8 @@ he: _applications: "יישומי×" - _comments: "תגובות" _contacts: "×× ×©×™ קשר" _help: "עזרה" - _home: "בית" - _photos: "×ª×ž×•× ×•×ª" _services: "שירותי×" account: "חשבון" activerecord: @@ -101,13 +98,7 @@ he: other: "מספר ×ž×©×ª×ž×©×™× ×—×“×©×™× ×”×©×‘×•×¢: %{count}" zero: "מספר ×ž×©×ª×ž×©×™× ×—×“×©×™× ×”×©×‘×•×¢: ×פס" current_server: "השעה עכשיו בצד השרת ×”×™× %{date}" - ago: "%{time}" all_aspects: "כל ההיבטי×" - application: - helper: - unknown_person: "××“× ×œ× ×™×“×•×¢" - video_title: - unknown: "כותרת הוויד×ו ××™× ×” ידועה" are_you_sure: "×”×× ××ª× ×‘×˜×•×—×™×?" are_you_sure_delete_account: "×”×× ××ª× ×‘×˜×•×—×™× ×©×‘×¨×¦×•× ×›× ×œ×¡×’×•×¨ ×ת החשבון? ×œ× ×™×”×™×” × ×™×ª×Ÿ לשחזרו!" aspect_memberships: @@ -121,18 +112,10 @@ he: success: "×יש הקשר × ×•×¡×£ בהצלחה להיבט." aspect_listings: add_an_aspect: "+ הוספת היבט" - deselect_all: "ביטול בחירה" - edit_aspect: "עריכת %{name}" - select_all: "בחירת הכל" aspect_stream: make_something: "בו×ו ×œ×©× ×•×ª" stay_updated: "היש×רו ×ž×¢×•×“×›× ×™×" stay_updated_explanation: "החדשות המרכזיות שלך כוללות ×ת כל ×× ×©×™ הקשר שלך, תגיות × ×¢×§×‘×•×ª והודעות מחברי קהילה יצירתיי×." - contacts_not_visible: "×× ×©×™ הקשר בהיבט ×–×” ×œ× ×™×•×›×œ×• לר×ות ×–×” ×ת ×–×”." - contacts_visible: "×× ×©×™ הקשר בהיבט ×–×” יוכלו לר×ות ×–×” ×ת ×–×”." - create: - failure: "יצירת ההיבט × ×›×©×œ×”." - success: "ההיבט החדש שלך %{name} × ×•×¦×¨" destroy: failure: "%{name} ××™× ×• ריק ×•×œ× × ×™×ª×Ÿ להסירו" success: "%{name} הוסר בהצלחה." @@ -140,25 +123,15 @@ he: aspect_list_is_not_visible: "×× ×©×™ הקשר בהיבט ×–×” ××™× × ×™×›×•×œ×™× ×œ×¨×ות ×–×” ×ת ×–×”." aspect_list_is_visible: "×× ×©×™ הקשר בהיבט ×–×” ×™×›×•×œ×™× ×œ×¨×ות ×–×” ×ת ×–×”." confirm_remove_aspect: "×”×× ××ª× ×‘×˜×•×—×™× ×©×‘×¨×¦×•× ×›× ×œ×ž×—×•×§ היבט ×–×”?" - make_aspect_list_visible: "ל×פשר ל×× ×©×™ הקשר בהיבט ×–×” לר×ות ×–×” ×ת ×–×”?" - remove_aspect: "מחיקת היבט ×–×”" rename: "×©×™× ×•×™ ש×" - set_visibility: "קביעת × ×¨×ות" update: "עדכון" updating: "בעדכון" index: - diaspora_id: - content_1: "המזהה שלך בדי×ספורה* הו×:" - content_2: "ב×מצעות מזהה ×–×” כל ×חד יוכל ×œ×ž×¦×•× ×ותך בדי×ספורה*." - heading: "מזהה די×ספורה*" donate: "תרומה" - handle_explanation: "זהו המזהה שלך בדי×ספורה (Diaspora ID). בדומה לכתובת דו×\"ל, × ×™×ª×Ÿ לחלוק ×ותו ×¢× ×× ×©×™× ××—×¨×™× ×‘×›×“×™ ×©×”× ×™×ž×¦×ו ×ותך." help: any_problem: "×”×× ×™×© בעיה כלשהי?" contact_podmin: "צור קשר ×¢× ×ž× ×”×œ הפוד שלך!" do_you: "×”××:" - email_feedback: "× ×™×ª×Ÿ לשלוח ×ת המשוב ב%{link}, ×× ×ª×¢×“×™×¤×•" - email_link: דו×"ל feature_suggestion: "... יש לך הצעה ל%{link} חדשה?" find_a_bug: "מצ×ת %{link}?" have_a_question: "...יש לך %{link}?" @@ -171,31 +144,20 @@ he: tutorial_link_text: "מדריכי×" tutorials_and_wiki: "%{faq}, %{tutorial} ו-%{wiki}: עזרה ×‘×¦×¢×“×™×›× ×”×¨××©×•× ×™×.." introduce_yourself: "זוהי תצוגת החדשות שלכ×. תרגישו חופשי להציג ×ת עצמיכ×." - keep_diaspora_running: "עזרו לפיתוח של די×ספורה* על ידי מתן תרומה חודשית!" keep_pod_running: "ד×גו לפעילות ×ª×§×™× ×” של ×”×תר והביעו ×ת ×ª×ž×™×›×ª×›× ×‘-%{pod} ב×מצעות תרומה חודשית!" new_here: follow: "עקבו ×חר %{link} וקבלו ×ת ×¤× ×™×”× ×©×œ ×ž×©×ª×ž×©×™× ×—×“×©×™× ×‘×“×™×ספורה*!" learn_more: "למדו עוד" title: "ברכו ×ž×©×ª×ž×©×™× ×—×“×©×™×" - no_contacts: "×ין ×× ×©×™ קשר" - no_tags: "+ חיפוש תגית לעקיבה" - people_sharing_with_you: "×× ×©×™× ×”×ž×©×ª×¤×™× ×יתך" - post_a_message: "×¤×¨×¡×•× ×”×•×“×¢×” >>" services: content: "× ×™×ª×Ÿ לקשר ×ת ×”×©×™×¨×•×ª×™× ×”×‘××™× ×œ×“×™×ספורה*:" heading: "קישור שירותי×" - unfollow_tag: "הפסקת עקיבה ×חרי #%{tag}" welcome_to_diaspora: "ברוך בו×ך לדי×ספורה*, %{name}!" - new: - create: "יצירה" - name: "×©× (מופיע ×‘×¤× ×™×š בלבד)" no_contacts_message: community_spotlight: "×¤×¨×¡×•×ž×™× ×—×©×•×‘×™× ×‘×§×”×™×œ×”" or_spotlight: "×ו ×©× ×™×ª×Ÿ לשתף ×¢× %{link}" try_adding_some_more_contacts: "× ×™×ª×Ÿ לחפש ×ו להזמין ×× ×©×™ קשר × ×•×¡×¤×™×" you_should_add_some_more_contacts: "כד××™ להוסיף כמה ×× ×©×™ קשר!" - no_posts_message: - start_talking: "××£ ×חד ×œ× ×›×ª×‘ הודעה עדיין!" seed: acquaintances: "מכרי×" family: "משפחה" @@ -204,7 +166,6 @@ he: update: failure: "ההיבט שלך, %{name}, ×œ× × ×©×ž×¨ מכיוון ×©×”×©× ×©×œ×• ×”×™×” ×רוך מדי." success: "ההיבט שלך, %{name}, × ×¢×¨×š בהצלחה." - back: "חזרה" blocks: create: failure: "×œ× × ×™×ª×Ÿ ×œ×”×ª×¢×œ× ×ž×”×ž×©×ª×ž×© ×”×–×”. #evasion" @@ -216,21 +177,14 @@ he: explanation: "×¤×¨×¡×•× ×ž×›×œ ×ž×§×•× ×™×©×™×¨×•×ª לדי×ספורה* על ידי הוספת הקישור ×”×‘× ×œ×¡×™×ž× ×™×•×ª הדפדפן : %{link}" heading: "×¡×™×ž× ×™×™×”" post_something: "×¤×¨×¡×•× ×œ×“×™×ספורה*" - post_success: "פורס×! × ×¡×’×¨!" cancel: "ביטול" comments: new_comment: comment: "תגובה" commenting: "התגובה × ×©×œ×—×ª..." - one: "תגובה ×חת" - other: "%{count} תגובות" - zero: "×ין תגובות" contacts: - create: - failure: "×ירע כשל ביצירת ×יש קשר" index: add_a_new_aspect: "הוספת היבט חדש" - add_to_aspect: "הוספת ×× ×©×™ קשר ל-%{name}" all_contacts: "כל ×× ×©×™ הקשר" community_spotlight: "×¤×¨×¡×•×ž×™× ×—×©×•×‘×™× ×‘×§×”×™×œ×”" my_contacts: "×× ×©×™ הקשר שלי" @@ -239,36 +193,20 @@ he: only_sharing_with_me: "רק ×לו ×”×ž×©×ª×¤×™× ×תי" start_a_conversation: "התחלת שיחה" title: "×× ×©×™ קשר" - your_contacts: "×× ×©×™ הקשר שלך" - sharing: - people_sharing: "×× ×©×™× ×”×ž×©×ª×¤×™× ×יתך:" spotlight: community_spotlight: "×¤×¨×¡×•×ž×™× ×—×©×•×‘×™× ×‘×§×”×™×œ×”" suggest_member: "המלצה על חבר" conversations: - conversation: - participants: "משתתפי×" create: fail: "הודעה שגויה" no_contact: "×”×™, יש להוסיף ×ת ×יש הקשר קוד×!" sent: "ההודעה × ×©×œ×—×”" - helper: - new_messages: - few: "%{count} הודעות חדשות" - many: "%{count} הודעות חדשות" - one: "הודעה חדשה ×חת" - other: "%{count} הודעות חדשות" - two: "%{count} ×ž×¡×¨×™× ×—×“×©×™×" - zero: "×ין הודעות חדשות" index: conversations_inbox: "שיחות - דו×ר × ×›× ×¡" - create_a_new_conversation: "התחלת שיחה חדשה" inbox: "דו×ר × ×›× ×¡" new_conversation: "שיחה חדשה" - no_conversation_selected: "×œ× × ×‘×—×¨ דיון" no_messages: "×ין הודעות" new: - abandon_changes: "×”×× ×œ×”×ª×¢×œ× ×ž×”×©×™× ×•×™×™×?" send: "שליחה" sending: "בשליחה..." subject: "× ×•×©×" @@ -289,10 +227,6 @@ he: error_messages: helper: correct_the_following_errors_and_try_again: "יש לתקן ×ת השגי×ות הב×ות ×•×œ× ×¡×•×ª שוב." - invalid_fields: "שדות שגויי×" - login_try_again: "×× × <a href='%{login_link}'>התחברו</a> ×•× ×¡×• שוב." - post_not_public: "ההודעה ××™× ×” פומבית!" - post_not_public_or_not_exist: "ההודעה שבה ××ª× ×ž× ×¡×™× ×œ×¦×¤×•×ª ××™× ×” ציבורית, ×ו ש××™× ×” קיימת!" fill_me_out: "× × ×œ×ž×œ× ×ותי" find_people: "חיפוש ×× ×©×™× ×ו #תגיות" help: @@ -329,45 +263,27 @@ he: tutorial: "מדריך" tutorials: "מדריכי×" wiki: "ויקי" - hide: "הסתרה" - ignore: "התעלמות" - invitation_codes: - excited: "%{name} שמח/×” לר×ות ×ותך ×›×ן." invitations: a_facebook_user: "משתמש פייסבוק" check_token: not_found: "×סימון ×”×”×–×ž× ×” ×œ× × ×ž×¦×" create: - already_contacts: "כבר יש לך קשר ×¢× ××“× ×–×”." - already_sent: "כבר ×”×–×ž× ×ª ××“× ×–×”." empty: "× × ×œ×”×–×™×Ÿ לפחות כתובת דו×\"ל ×חת." no_more: "×ין לך עוד ×”×–×ž× ×•×ª." note_already_sent: "×”×–×ž× ×•×ª כבר × ×©×œ×—×• ל: %{emails}" - own_address: "×œ× × ×™×ª×Ÿ לשלוח ×”×–×ž× ×•×ª לכתובת שלך." rejected: "בכתובות הדו×״ל הב××” התגלו שגי×ות: " sent: "×”×–×ž× ×•×ª × ×©×œ×—×• ×ל: %{emails}" - edit: - accept_your_invitation: "קבלת ×”×”×–×ž× ×” שלך" - your_account_awaits: "החשבון שלך ממתין!" new: - already_invited: "×”×× ×©×™× ×”×‘××™× ×œ× × ×¢× ×• ×œ×”×–×ž× ×” שלך:" - aspect: "היבט" - check_out_diaspora: "× ×¡×• ×ת די×ספורה*!" codes_left: one: "× ×•×ª×¨×• ×”×–×ž× ×” ×חת עבור קוד ×–×”" other: "× ×•×ª×¨×• %{count} ×”×–×ž× ×•×ª עבור קוד ×–×”" zero: "×œ× × ×•×ª×¨×• ×”×–×ž× ×•×ª עבור קוד ×–×”" comma_separated_plz: "× ×™×ª×Ÿ להזין מספר כתובות דו×\"ל מופרדות בפסיקי×." - if_they_accept_info: "×× ×”× ×™×שרו, ×”× ×™×ª×•×•×¡×¤×• להיבט ש×ליו ×”×–×ž× ×ª ×ות×." invite_someone_to_join: "×”×–×ž×™× ×• ×—×‘×¨×™× ×œ×”×¦×˜×¨×£ לדי×ספורה*!" language: "שפה" paste_link: "שתפו ×ת הקישור ×”×–×” ×¢× ×—×‘×¨×™× ×¢×œ ×ž× ×ª להזמין ××•×ª× ×œ×“×™×ספורה*, ×ו שלחו ×œ×”× ×“×•×\"ל ×¢× ×”×§×™×©×•×¨ ישירות מכ×ן." - personal_message: "הודעה ×ישית" - resend: "שליחה חוזרת" send_an_invitation: "שליחת ×”×–×ž× ×”" - send_invitation: "שליחת ×”×–×ž× ×”" sending_invitation: "×”×”×–×ž× ×” × ×©×œ×—×ª..." - to: "×ל" layouts: application: back_to_top: "חזרה למעלה" @@ -376,38 +292,13 @@ he: source_package: "הורדת חבילת קוד המקור" toggle: "הפעלה/כיבוי תצוגת מכשיר × ×™×™×“" whats_new: "מה חדש?" - your_aspects: "×”×”×™×‘×˜×™× ×©×œ×š" header: - admin: "× ×™×”×•×œ" - blog: "בלוג" code: "קוד" - help: "עזרה" - login: "התחברות" logout: "×”×ª× ×ª×§×•×ª" profile: "פרופיל" - recent_notifications: "התר×ות ××—×¨×•× ×•×ª" settings: "הגדרות" - view_all: "הצגת הכל" - likes: - likes: - people_dislike_this: - one: "%{count} ×œ× ×הב/×”" - other: "%{count} ×× ×©×™× ×œ× ×הבו" - zero: "×ין ×× ×©×™× ×©×œ× ×הבו" - people_like_this: - one: "מישהו ×חד ×הב ×ת ×–×”" - other: "%{count} ×× ×©×™× ×הבו ×ת ×–×”" - zero: "××£ ×חד ×œ× ×הב ×ת ×–×”" - people_like_this_comment: - few: "%{count} ×הבו ×–×ת" - many: "%{count} ×הבו ×–×ת" - one: "%{count} ×הב/×”" - other: "%{count} ×הבו" - two: "%{count} ×ž×ª×¢× ×™×™×Ÿ" - zero: "××£ ×חד ×œ× ×הב" limited: "מוגבל" more: "עוד" - next: "הב××”" no_results: "×œ× × ×ž×¦×ו תוצ×ות" notifications: also_commented: @@ -422,11 +313,6 @@ he: one: "%{actors} הגיב/×” על ×”%{post_link} שלך." other: "%{actors} הגיב/×” על ×”%{post_link} שלך." zero: "%{actors} הגיבו על ×”%{post_link} שלך." - helper: - new_notifications: - one: "התר××” חדשה ×חת" - other: "%{count} התר×ות חדשות" - zero: "×ין התר×ות חדשות" index: all_notifications: "כל ההתר×ות" also_commented: "×’× ×”×’×™×‘/×”" @@ -481,7 +367,6 @@ he: zero: "%{actors} החלו לשתף ×יתך." notifier: a_post_you_shared: "הודעה." - accept_invite: "קבלת ×”×”×–×ž× ×” שלך לדי×ספורה*!" click_here: "יש ללחוץ ×›×ן" comment_on_post: reply: "שליחת תגובה ×ו צפייה בהודעה של %{name} >" @@ -506,7 +391,6 @@ he: liked: "%{name} ×הב/×” ×ת ההודעה שלך" view_post: "צפייה בהודעה >" mentioned: - mentioned: "הזכיר/×” ×ותך בהודעה" subject: "%{name} הזכיר/×” ×ותך בדי×ספורה*" private_message: reply_to_or_view: "שליחת תגובה ×ו צפייה בשיחה זו >" @@ -524,20 +408,9 @@ he: to_change_your_notification_settings: "כדי ×œ×©× ×•×ª ×ת הגדרות ההתר×ות שלך" nsfw: "×œ× ×ž×ª××™× ×œ×¦×¤×™×™×” בציבור" ok: "×ישור" - or: "×ו" - password: "סיסמה" - password_confirmation: "×ישור סיסמה" people: add_contact: invited_by: "×”×•×–×ž× ×ª על ידי" - add_contact_small: - add_contact_from_tag: "הוספת ×יש קשר מתגית" - aspect_list: - edit_membership: "עריכת חברות בהיבט" - helper: - is_not_sharing: "%{name} ×œ× ×ž×©×ª×£/ת ×יתך" - is_sharing: "%{name} משתף/ת ×יתך" - results_for: " תוצ×ות עבור %{params}" index: couldnt_find_them: "×œ× ×”×¦×œ×—×ª× ×œ×ž×¦×•× ×ות×?" looking_for: "×”×× ×”×ª×›×•×•× ×ª לחפש הודעות שתויגו %{tag_link}?" @@ -547,99 +420,46 @@ he: search_handle: "השתמשו במזהה די×ספורה* (username@pod.tld) כדי להיות ×‘×˜×•×—×™× ×©×ª×ž×¦×ו ×ת חבריכ×." searching: "החיפוש מתבצע, × × ×œ×”×ž×ª×™×Ÿ ×‘×¡×‘×œ× ×•×ª..." send_invite: "עדיין ×œ× ×ž×¦×ת×? שלחו ×”×–×ž× ×”!" - one: "××“× ×חד" - other: "%{count} ×× ×©×™×" person: - add_contact: "הוספת ×יש קשר" - already_connected: "××ª× ×›×‘×¨ מקושרי×" - pending_request: "בקשה ×ž×ž×ª×™× ×”" thats_you: "×–×” הפרופיל שלך!" profile_sidebar: bio: "×ודות" born: "ת×ריך לידה" - edit_my_profile: "עריכת הפרופיל שלי" gender: "מין" - in_aspects: "בהיבטי×" location: "מיקו×" - photos: "×ª×ž×•× ×•×ª" - remove_contact: "הסרת ×יש קשר" - remove_from: "×”×× ×œ×”×¡×™×¨ ×ת %{name} מההיבט %{aspect}?" show: closed_account: "חשבון ×–×” × ×¡×’×¨." does_not_exist: "××“× ×–×” ××™× ×• קיי×!" has_not_shared_with_you_yet: "%{name} ×˜×¨× ×©×™×ª×£ ×יתך הודעה כלשהי!" - ignoring: "××ª× ×ž×ª×¢×œ×ž×™× ×ž×›×œ הההודעות של %{name}." - incoming_request: "%{name} רוצה לשתף ×יתך" - mention: "×זכור" - message: "הודעה" - not_connected: "××™× ×›× ×ž×©×ª×¤×™× ×¢× ××“× ×–×”" - recent_posts: "הודעות שפורסמו ל××—×¨×•× ×”" - recent_public_posts: "הודעות ציבוריות שפורסמו ל××—×¨×•× ×”" - return_to_aspects: "חזרה לעמוד ×”×”×™×‘×˜×™× ×©×œ×š" - see_all: "צפייה בהכול" - start_sharing: "התחלת שיתוף" - to_accept_or_ignore: "כדי לקבל ×ו לדחות." - sub_header: - add_some: "הוספת כמה" - edit: "עריכה" - you_have_no_tags: "×ין לך תגיות כלל!" - webfinger: - fail: "מצטערי×, ×œ× × ×™×ª×Ÿ ×œ×ž×¦×•× ×ת %{handle}." - zero: "×ין ×× ×©×™×" photos: - comment_email_subject: "×”×ª×ž×•× ×” של %{name}" create: integrity_error: "העל×ת ×”×ª×ž×•× ×” × ×›×©×œ×”. ×”×× ×”×§×•×‘×¥ ×כן ×”×™×” ×ª×ž×•× ×”?" runtime_error: "העל×ת ×”×ª×ž×•× ×” × ×›×©×œ×” עקב שגי×ת שרת ×¤× ×™×ž×™×ª." type_error: "העל×ת ×”×ª×ž×•× ×” × ×›×©×œ×”. ×”×× ×ª×ž×•× ×” ×כן × ×•×¡×¤×”?" destroy: notice: "×”×ª×ž×•× ×” × ×ž×—×§×”." - edit: - editing: "עריכה" - new: - back_to_list: "חזרה לרשימה" - new_photo: "×ª×ž×•× ×” חדשה" - post_it: "פרסו×" new_photo: empty: "הקובץ {file} ריק, × × ×œ×‘×—×•×¨ ×§×‘×¦×™× ×‘×©× ×™×ª בלעדיו" invalid_ext: "לקובץ {file} יש סיומת ×œ× ×—×•×§×™×ª. רק הסיומות הב×ות מ×ופשרות: {extensions}." size_error: "הקובץ {file} גדול מדי. הגודל המירבי ×”×•× {sizeLimit}." new_profile_photo: - or_select_one_existing: "×ו שיש לבחור ×חת מבין ×”%{photos} הקיימות." upload: "העל×ת ×ª×ž×•× ×ª פרופיל חדשה" - photo: - view_all: "הצגת כל ×”×ª×ž×•× ×•×ª של %{name}" show: - collection_permalink: "קישור קבוע ל×וסף" - delete_photo: "מחיקת ×ª×ž×•× ×”" - edit: "עריכה" - edit_delete_photo: "עריכת תי×ור ×ª×ž×•× ×” / מחיקת ×ª×ž×•× ×”" - make_profile_photo: "יצירת ×ª×ž×•× ×ª פרופיל" show_original_post: "הצגת ההודעה המקורית" - update_photo: "עדכון ×ª×ž×•× ×”" - update: - error: "×ירע כשל בעריכת ×”×ª×ž×•× ×”." - notice: "×”×ª×ž×•× ×” ×¢×•×“×›× ×” בהצלחה." posts: presenter: title: "הודעה מ×ת %{name}" show: - destroy: "מחיקה" - not_found: "מצטערי×, ×œ× × ×™×ª×Ÿ ×œ×ž×¦×•× ×”×•×“×¢×” זו." - permalink: "קישור קבוע" photos_by: one: "×ª×ž×•× ×•×ª ×חת מ×ת %{author}" other: "%{count} ×ª×ž×•× ×•×ª מ×ת %{author}" zero: "×ין ×ª×ž×•× ×•×ª מ×ת %{author}" reshare_by: "שותף מחדש על ידי %{author}" - previous: "הקודמת" privacy: "פרטיות" - privacy_policy: "×ž×“×™× ×™×•×ª פרטיות" profile: "פרופיל" profiles: edit: allow_search: "מתן ×ישור ל×× ×©×™× ×œ×—×¤×© ×חריך בדי×ספורה*" - edit_profile: "עריכת פרופיל" first_name: "×©× ×¤×¨×˜×™" last_name: "×©× ×ž×©×¤×—×”" nsfw_check: "סמן ×ת כל ×”×¤×¨×¡×•×ž×™× ×©×œ×™ ×›×œ× ×ž×ª××™×ž×™× ×œ×¦×¤×™×” בציבור" @@ -652,8 +472,6 @@ he: your_location: "×”×ž×™×§×•× ×©×œ×š" your_name: "שמך" your_photo: "×”×ª×ž×•× ×” שלך" - your_private_profile: "הפרופיל הפרטי שלך" - your_public_profile: "הפרופיל הציבורי שלך" your_tags: "ת×ר/×™ ×ת עצמך ב־5 מילי×" your_tags_placeholder: "כגון #×¡×¨×˜×™× #×—×ª×œ×ª×•×œ×™× #×˜×™×•×œ×™× #מורה #כרמי×ל" update: @@ -668,63 +486,24 @@ he: closed: "ההרשמה סגורה בפוד ×–×” של די×ספורה*." create: success: "הצטרפת לדי×ספורה*!" - edit: - cancel_my_account: "ביטול החשבון שלי" - edit: "עריכת %{name}" - leave_blank: "(יש להש×יר ריק ×× ×ין ×‘×¨×¦×•× ×š ×œ×©× ×•×ª ×–×ת)" - password_to_confirm: "(× ×–×“×§×§ לסיסמה ×”× ×•×›×—×™×ª שלך בכדי ל×מת ×ת ×”×©×™× ×•×™×™× ×©×‘×™×¦×¢×ª)" - unhappy: "×œ× ×ž×¨×•×¦×”?" - update: "עדכון" invalid_invite: "הקישור ×œ×”×–×ž× ×” שסיפקת ××™× ×• תקף יותר!" new: - create_my_account: "יצירת החשבון שלי" email: דו×"ל enter_email: "× × ×œ×”×–×™×Ÿ כתובת דו×״ל" enter_password: "×”×–×™× ×• סיסמה (שישה ×ª×•×•×™× ×œ×¤×—×•×ª)" enter_password_again: "יש להזין ×ת ×ותה הסיסמה כמקוד×" enter_username: "× × ×œ×‘×—×•×¨ ×©× ×ž×©×ª×ž×© (×ותיות, ×ž×¡×¤×¨×™× ×•×§×•×•×™× ×ª×—×ª×•× ×™× ×‘×œ×‘×“)" - join_the_movement: "צרפו ×ותי!" password: "סיסמה" password_confirmation: "×ימות סיסמה" sign_up: "הרשמה" - sign_up_message: "רשת חברתית ×¢× â™¥" submitting: "המידע בשליחה..." username: "×©× ×ž×©×ª×ž×©" - requests: - create: - sending: "בשליחה" - sent: "ביקשת לשתף ×¢× %{name}. ×”× ××ž×•×¨×™× ×œ×¨×ות ×–×ת ×‘×¤×¢× ×”×‘××” שיתחברו לדי×ספורה*." - destroy: - error: "× × ×œ×‘×—×•×¨ היבט!" - ignore: "התעלמת מבקשת ×יש הקשר." - success: "××ª× ×ž×©×ª×¤×™× ×›×¢×ª." - helper: - new_requests: - few: "%{count} בקשות חדשות!" - many: "%{count} בקשות חדשות!" - one: "בקשה חדשה!" - other: "%{count} בקשות חדשות!" - two: "%{count} בקשות חדשות" - zero: "×ין בקשות חדשות" - manage_aspect_contacts: - existing: "×× ×©×™ קשר קיימי×" - manage_within: "× ×™×”×•×œ ×× ×©×™ קשר בתוך" - new_request_to_person: - sent: "הבקשה × ×©×œ×—×”!" reshares: comment_email_subject: "שיתוף מחדש של %{resharer} להודעה של %{author}" - create: - failure: "×רעה שגי××” ×‘× ×¡×™×•×Ÿ לשתף מחדש הודעה זו." reshare: deleted: "ההודעה המקורית × ×ž×—×§×” על ידי הכותב/ת." - reshare: - one: "שיתוף מחדש ×חד" - other: "%{count} ×©×™×ª×•×¤×™× ×ž×—×“×©" - zero: "שיתוף מחדש" reshare_confirmation: "×”×× ×œ×©×ª×£ מחדש ×ת ההודעה של %{author}?" - reshare_original: "שיתוף מחדש של המקור" reshared_via: "שיתף מחדש ב×מצעות" - show_original: "הצגת המקור" search: "חיפוש" services: create: @@ -736,59 +515,24 @@ he: success: "×”×ימות × ×ž×—×§ בהצלחה." failure: error: "×ירעה שגי××” בעת ההתחברות לשירות ×–×”." - finder: - fetching_contacts: "די×ספורה* מוסיפה ×ת ×—×‘×¨×™×›× ×‘-%{service}, ×× × ×‘×“×§×• שוב בעוד מספר דקות." - no_friends: "×œ× × ×ž×¦×ו חברי פייסבוק." - service_friends: "×—×‘×¨×™× ×‘Ö¾%{service}" index: disconnect: "×”×ª× ×ª×§×•×ª" edit_services: "עריכת שירותי×" logged_in_as: "התחברת בש×" really_disconnect: "×”×× ×œ× ×ª×§ ×ת %{service}?" services_explanation: "התחברות ×œ×©×™×¨×•×ª×™× × ×•×¡×¤×™× ×ž×פשרת לך ×œ×¤×¨×¡× ×”×•×“×¢×•×ª ×”× ×›×ª×‘×•×ª בדי×ספורה* ×’× ×‘×©×™×¨×•×ª×™× ×לו." - inviter: - click_link_to_accept_invitation: "יש לעקוב ×חר הקישור ×”×‘× ×‘×›×“×™ לקבל ×ת ×”×”×–×ž× ×” שלך" - join_me_on_diaspora: "הצטרפו ×לי בדי×ספורה*" - remote_friend: - invite: "×”×–×ž× ×”" - not_on_diaspora: "עדיין ×œ× ×‘×“×™×ספורה*" - resend: "שליחה מחדש" settings: "הגדרות" - share_visibilites: - update: - post_hidden_and_muted: "ההודעה של %{name} הוסתרה, וההתר×ות הושתקו." - see_it_on_their_profile: "×× ×‘×¨×¦×•× ×š לר×ות ×¢×“×›×•× ×™× ×‘×”×•×“×¢×” זו בקר בדף הפרופיל של %{name}." shared: - add_contact: - add_new_contact: "הוספת ×יש קשר חדש" - create_request: "חיפוש לפי מזהה די×ספורה*" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "× × ×œ×”×–×™×Ÿ ×©× ×ž×©×ª×ž×© בדי×ספורה*" - know_email: "כתובת הדו×״ל ×©×œ×”× ×™×“×•×¢×” לך? כד××™ להזמין ×ות×" - your_diaspora_username_is: "×©× ×”×ž×©×ª×ž×© שלך בדי×ספורה* הו×: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "הוספת ×יש קשר" toggle: one: "ב×חד מההיבטי×" other: "ב־%{count} היבטי×" zero: "הוספת ×יש קשר" - contact_list: - all_contacts: "כל ×× ×©×™ הקשר" - footer: - logged_in_as: "מחובר ×›-%{name}" - your_aspects: "×”×”×™×‘×˜×™× ×©×œ×š" invitations: by_email: "בדו×״ל" - dont_have_now: "×ין לך כרגע, ×ך יתווספו לך ×”×–×ž× ×•×ª בקרוב!" - from_facebook: "מפייסבוק" - invitations_left: "× ×•×ª×¨×• %{count}" - invite_someone: "שליחת ×”×–×ž× ×”" invite_your_friends: "×”×–×ž× ×ª ×”×—×‘×¨×™× ×©×œ×š" invites: "×”×–×ž× ×•×ª" - invites_closed: "×”×”×–×ž× ×•×ª לפוד ×–×” של די×ספורה* סגורות כרגע." share_this: "שתפו ×ת הקישור ×”×–×” בדו×\"ל, בבלוג ×ו ברשת חברתית ×חרת!" - notification: - new: "%{type} חדשה מ×ת %{from}" public_explain: atom_feed: "פיד Atom" control_your_audience: "היו בשליטה על קהל היעד שלכ×" @@ -802,12 +546,9 @@ he: title: "הגדרת ×©×™×¨×•×ª×™× ×ž×§×•×©×¨×™×" visibility_dropdown: "השתמשו בתיבה × ×¤×ª×—×ª ×–×ת כדי לבחור מי יר××” ×ת ×”×•×“×¢×ª×›× (×× ×—× ×• ×ž×¦×™×¢×™× ×©×”×•×“×¢×ª×›× ×”×¨××©×•× ×” תהיה ציבורית)." publisher: - all: "הכל" - all_contacts: "כל ×× ×©×™ הקשר" discard_post: "מחיקת ההודעה" formatWithMarkdown: "× ×™×ª×Ÿ להשתמש ב %{markdown_link} כדי לעצב ×ת הודעתך" get_location: "קבלת ×”×ž×™×§×•× ×©×œ×š" - make_public: "הפיכה לציבורי" new_user_prefill: hello: "×©×œ×•× ×œ×›×•×œ×, ×× ×™ #%{new_user_tag}. " i_like: "×× ×™ ×ž×ª×¢× ×™×™×Ÿ/ת ב%{tags}. " @@ -815,36 +556,14 @@ he: newhere: "חדשכ×ן" poll: add_a_poll: "הוספת סקר" - add_poll_answer: "הוספת ×פשרות" - option: "×פשרות 1" - question: "ש×לה" - remove_poll_answer: "הסרת ×פשרות" - post_a_message_to: "×¤×¨×¡×•× ×”×•×“×¢×” ל-%{aspect}" posting: "בפרסו×..." - preview: "תצוגה מקדימה" - publishing_to: "×¤×¨×¡×•× ×ל: " remove_location: "הסרת מיקו×" share: "שיתוף" - share_with: "שיתוף ×¢×" upload_photos: "העל×ת ×ª×ž×•× ×•×ª" whats_on_your_mind: "על מה ××ª× ×—×•×©×‘×™×?" - reshare: - reshare: "שיתוף מחדש" stream_element: - connect_to_comment: "התחבר למשתמש ×”×–×” על ×ž× ×ª להגיב על הודעתו" - currently_unavailable: "×œ× × ×™×ª×Ÿ להגיב כרגע" - dislike: "×œ× ×הבתי" - hide_and_mute: "הסתרה והשתקת ההודעה" - ignore_user: "התעלמות מ%{name}" - ignore_user_description: "×œ×”×ª×¢×œ× ×ž×”×ž×©×ª×ž×© ולהסיר ×ותו מכל ההיבטי×?" - like: "×הבתי" - nsfw: "הודעה זו ×¡×•×ž× ×” ×›-NSFW על ידי הכותב: %{link}" - shared_with: "משותף ×¢×: %{aspect_names}" - show: "הצגה" - unlike: "ביטול '×הבתי'" via: "ב×מצעות %{link}" via_mobile: "דרך ×”× ×™×™×“" - viewable_to_anyone: "הודעה זו × ×™×ª× ×ª לצפייה על ידי כל גולשי הרשת" simple_captcha: label: "×”×–×™× ×• ×ת הקוד שבתיבה:" message: @@ -855,19 +574,9 @@ he: status_messages: create: success: "×וזכרו בהצלחה: %{names}" - destroy: - failure: "×ירע כשל במחיקת ההודעה" - helper: - no_message_to_display: "×ין הודעה להצגה." new: mentioning: "×זכור: %{person}" too_long: "{\"one\"=>\"× × ×œ×§×¦×¨ ×ת הודעות הסטטוס שלך לפחות מתו ×חד\", \"other\"=>\"× × ×œ×§×¦×¨ ×ת הודעות הסטטוס שלך לפחות מ-%{count} תווי×\", \"zero\"=>\"× × ×œ×§×¦×¨ ×ת הודעות הסטטוס שלך לפחות מ-%{count} תווי×\"}" - stream_helper: - hide_comments: "הסתרת כל התגובות" - show_comments: - one: "הצגת תגובה × ×•×¡×¤×ª" - other: "הצגת %{count} תגובות × ×•×¡×¤×•×ª" - zero: "×ין תגובות × ×•×¡×¤×•×ª" streams: activity: title: "הפעילות שלי" @@ -893,22 +602,11 @@ he: title: "פעילות ציבורית" tags: title: "הודעות שתויגו: %{tags}" - tag_followings: - create: - failure: "המעקב ×חרי #%{name} × ×›×©×œ. ×”×× ××ª× ×›×‘×¨ ×¢×•×§×‘×™× ×חרי תגית זו?" - none: "××ª× ×œ× ×™×›×•×œ×™× ×œ×¢×§×•×‘ ×חרי תגית ריקה!" - success: "הידד! ××ª× ×¢×•×§×‘×™× ×›×¢×ª ×חרי #%{name}" - destroy: - failure: "×ירע כשל בהפסקת העקיבה ×חרי %{name}. ×ולי כבר ×”×¤×¡×§×ª× ×œ×¢×§×•×‘ ×חרי תגית זו בעבר?" - success: "×בוי! ××ª× ×›×‘×¨ ×œ× ×¢×•×§×‘×™× ×חרי #%{name}." tags: show: follow: "עקיבה ×חר #%{tag}" - following: "במעקב ×חר #%{tag}" none: "התגית הריקה ×œ× ×§×™×™×ž×ª!" stop_following: "הפסקת עקיבה ×חר #%{tag}" - terms_and_conditions: "×ª× ××™ שימוש" - undo: "×”×× ×œ×‘×˜×œ?" username: "×©× ×ž×©×ª×ž×©" users: confirm_email: @@ -931,7 +629,6 @@ he: character_minimum_expl: "חובה לכלול לפחות 6 תווי×" close_account: dont_go: "בבקשה ×ל תלכו!" - if_you_want_this: "×× ××ª× ×‘×מת ×¨×•×¦×™× ×–×ת, הקלידו ×ת ×¡×™×¡×ž×ª×›× ×œ×ž×˜×” ולחצו על \"סגירת חשבון\"." lock_username: "×”×פשרות ×ª× ×¢×œ ×ת ×©× ×”×ž×©×ª×ž×© ×©×œ×›× ×œ×ž×§×¨×” שתחליטו ×œ×”×¨×©× ×ž×—×“×©." locked_out: "××ª× ×ª× ×•×ª×§×• ×•×—×©×‘×•× ×›× ×™× ×¢×œ." make_diaspora_better: "×‘×ž×§×•× ×œ×¢×–×•×‘, ×”×™×™× ×• ×¨×•×¦×™× ×©×ª×¢×–×¨×• ×œ× ×• לשפר ×ת די×ספורה*. ×× ×ª×¢×“×™×¤×• לעזוב בכל ×–×ת, ×”×™×™× ×• ×¨×•×¦×™× ×œ×™×™×“×¢ ××ª×›× ×¢×œ מה שקורה בהמשך." @@ -942,12 +639,10 @@ he: comment_on_post: "...מישהו הגיב על הודעה שלך?" current_password: "סיסמה × ×•×›×—×™×ª" current_password_expl: "×–×ת המשמשת ×œ×›× ×™×¡×”..." - download_photos: "הורדת ×”×ª×ž×•× ×•×ª שלי" edit_account: "עריכת חשבון" email_awaiting_confirmation: "×©×œ×—× ×• קישור הפעלה לכתובת %{unconfirmed_email}. עד שתעקבו ×חר קישור ×–×” ותפעילו ×ת הכתובת החדשה, ×× ×• × ×ž×©×™×š להשתמש בכתובת המקורית: %{email}." export_data: "×™×¦×•× ×”×ž×™×“×¢ שלך" following: "הגדרות מעקב" - getting_started: "העדפות ×ž×©×ª×ž×©×™× ×—×“×©×™×" liked: "...מישהו ×הב הודעה שלך?" mentioned: "...מישהו הזכיר ×ותך בהודעה?" new_password: "סיסמה חדשה" @@ -967,7 +662,6 @@ he: connect_to_facebook_link: "התחברות לחשבון הפייסבוק שלך" hashtag_explanation: "תגיות מ×פשרות לך לשוחח על תחומי ×”×¢× ×™×™×Ÿ שלך ולעקוב ×חריה×. הן ×’× ×“×¨×š ×ž×¦×•×™× ×ª להכיר ×× ×©×™× ×—×“×©×™× ×‘×“×™×ספורה*." hashtag_suggestions: "× ×¡×• לעקוב ×חרי תגיות כגון #××ž× ×•×ª, #סרטי×, #×¦×™×œ×•× ×•×›×“×•×ž×”." - saved: "× ×©×ž×¨!" well_hello_there: "×©×œ×•× ×œ×š!" what_are_you_in_to: "מה ×ž×¢× ×™×™×Ÿ ×תכ×?" who_are_you: "מי ×ת×?" @@ -989,13 +683,6 @@ he: settings_updated: "ההגדרות ×¢×•×“×›× ×•" unconfirmed_email_changed: "כתובת הדו×״ל ×©×•× ×ª×”. × ×“×¨×©×ª הפעלה." unconfirmed_email_not_changed: "×©×™× ×•×™ כתובת הדו×״ל × ×›×©×œ" - webfinger: - fetch_failed: "×ירע כשל בקבלת פרופיל ×”Ö¾webfinger עבור %{profile_url}" - hcard_fetch_failed: "הייתה בעיה בקבלת ×”-hcard עבור %{account}" - no_person_constructed: "×œ× × ×™×ª×Ÿ ×œ×‘× ×•×ª ×יש קשר מה-hcard ×”×–×”." - not_enabled: "× ×¨××” ש-webfinger ××™× ×• פעיל עבור המ×רח של %{account}" - xrd_fetch_failed: "×ירעה שגי××” בקבלת ×”Ö¾xrd מהחשבון %{account}" - welcome: "ברוך בו×ך!" will_paginate: next_label: "×”×‘× Â»" previous_label: "« הקוד×" \ No newline at end of file diff --git a/config/locales/diaspora/hi.yml b/config/locales/diaspora/hi.yml index 87b13a9e4e9e8919475b403f015abea2b9cdce4e..9f20a67268bf6f02808c4a3924821e79a79b82a2 100644 --- a/config/locales/diaspora/hi.yml +++ b/config/locales/diaspora/hi.yml @@ -5,13 +5,8 @@ hi: - _photos: "तसà¥à¤µà¥€à¤°à¥‡à¤‚" _services: "सेवाà¤à¤‚" account: "खाता" - ago: "%{time} पूरà¥à¤µ" - application: - helper: - unknown_person: "अजनबी" are_you_sure: "कà¥à¤¯à¤¾ आपको यकीन है?" aspects: index: @@ -20,14 +15,8 @@ hi: cancel: "रदà¥à¤¦ करें" delete: "मिटाओ" email: "ईमेल" - hide: "छà¥à¤ªà¤¾à¤à¤" ok: "ठीक" - or: "अथवा" privacy: "गोपनीयता" - privacy_policy: "गोपनीयता नीति" profile: "पà¥à¤°à¥‹à¤«à¤¼à¤¾à¤‡à¤²" settings: "विनà¥à¤¯à¤¾à¤¸" - terms_and_conditions: "नियम और शरà¥à¤¤à¥‡à¤‚" - undo: "पूरà¥à¤µà¤µà¤¤?" - username: "उपयोगकरà¥à¤¤à¤¾ नाम" - welcome: "आपका सà¥à¤µà¤¾à¤—त है!" \ No newline at end of file + username: "उपयोगकरà¥à¤¤à¤¾ नाम" \ No newline at end of file diff --git a/config/locales/diaspora/hu.yml b/config/locales/diaspora/hu.yml index b3f8ab62ead0e5880b69e1ce020567d6c63423df..5d45caf8f415c8547d7b4d61da716d209e127143 100644 --- a/config/locales/diaspora/hu.yml +++ b/config/locales/diaspora/hu.yml @@ -6,11 +6,8 @@ hu: _applications: "Alkalmazások" - _comments: "Hozzászólások" _contacts: "IsmerÅ‘sök" _help: "Súgó" - _home: "KezdÅ‘lap" - _photos: "képeidbÅ‘l" _services: "Szolgáltatások" account: "Felhasználói fiók" activerecord: @@ -107,13 +104,7 @@ hu: other: "az új felhasználók száma ezen a héten: %{count}" zero: "az új felhasználók száma ezen a héten: %{count}" current_server: "A jelenlegi szerverdátum: %{date}" - ago: "ezelÅ‘tt" all_aspects: "Összes csoport" - application: - helper: - unknown_person: "ismeretlen személy" - video_title: - unknown: "ismeretlen videó cÃm" are_you_sure: "Biztos vagy benne?" are_you_sure_delete_account: "Biztos, hogy törölni akarod a fiókodat? A törlés nem vonható vissza!" aspect_memberships: @@ -127,47 +118,26 @@ hu: success: "A kapcsolat hozzáadva a csoporthoz." aspect_listings: add_an_aspect: "+ Új csoport" - deselect_all: "Kijelölések törlése" - edit_aspect: "Szerkesztés %{name}" - select_all: "Mindent kijelöl" aspect_stream: make_something: "Kezdj bele" stay_updated: "Légy naprakész!" stay_updated_explanation: "A HÃrfolyamodban megjelennek az ismerÅ‘seid bejegyzései, követett cÃmkéid és a Reflektorfényben szereplÅ‘ személyek bejegyzései." - contacts_not_visible: "A csoporttagok nem láthatják egymást." - contacts_visible: "A csoport tagjai láthatják egymást." - create: - failure: "Csoport létrehozása sikertelen." - success: "Új csoport létrehozva: %{name}" destroy: failure: "%{name} nem üres, Ãgy nem lehet törölni." success: "%{name} csoport sikeresen törölve." edit: - aspect_chat_is_enabled: "A csoport tagjai beszélgethetnek veled." - aspect_chat_is_not_enabled: "A csoport tagjai nem beszélgethetnek veled." aspect_list_is_not_visible: "csoportlista rejtett a csoporttagok számára" aspect_list_is_visible: "csoportlista látható a csoporttagok számára" confirm_remove_aspect: "Biztos, hogy törölni akarod a csoportot?" - grant_contacts_chat_privilege: "feljogosÃtod a csoport tagjait, hogy beszélgethessenek veled?" - make_aspect_list_visible: "a csoporttagok láthatják egymást" - remove_aspect: "Csoport törlése" rename: "átnevezés" - set_visibility: "Láthatóság beállÃtása" update: "frissÃtés" updating: "frissÃtés" index: - diaspora_id: - content_1: "A te diaspora* azonosÃtód:" - content_2: "Add meg bárkinek és ez alapján meg tud találni a diaspora*-n." - heading: "diaspora* azonosÃtó" donate: "Adományozás" - handle_explanation: "Ez a Te diaspora* azonosÃtód. Megadhatod elérhetÅ‘ségként, mint egy email cÃmet." help: any_problem: "Gondod támadt?" contact_podmin: "Vedd fel a kapcsolatot a kiszolgálód karbantartójával!" do_you: "Mit szeretnél?" - email_feedback: "Küldd el %{link}-ben a visszajelzésed" - email_link: "E-mail" feature_suggestion: "...felötlött benned egy fejlesztési %{link}?" find_a_bug: "...feltűnt egy %{link}?" have_a_question: "...eszedbe jutott egy %{link}?" @@ -180,31 +150,20 @@ hu: tutorial_link_text: "Útmutatók" tutorials_and_wiki: "A kezdÅ‘ lépéseidben segÃthet még a %{faq}, az %{tutorial} és a %{wiki}" introduce_yourself: "Ez a te HÃrfolyamod. Kezdd is el gyorsan egy bemutatkozással!" - keep_diaspora_running: "Támogasd a diaspora* gyorsabb fejlesztését havi adományoddal!" keep_pod_running: "Hogy gyors maradhasson ez a kiszolgáló (%{pod}), adományozz havonta egy kis kávéra valót a szervereknek ;)" new_here: follow: "Kövesd az %{link} cÃmkét és üdvözöld az új Diaspora* felhasználókat!" learn_more: "Tudj meg többet" title: "Sziasztok új felhasználók" - no_contacts: "Nincs ismerÅ‘s" - no_tags: "+ #cÃmke keresése" - people_sharing_with_you: "IsmerÅ‘seid" - post_a_message: "üzenet küldése >>" services: content: "A következÅ‘ szolgáltatásokhoz tudsz kapcsolódni:" heading: "Szolgáltatások összekapcsolása" - unfollow_tag: "Követés leállÃtása #%{tag}" welcome_to_diaspora: "Ãœdv a diaspora* közösségi oldalon, %{name}!" - new: - create: "Létrehoz" - name: "Név" no_contacts_message: community_spotlight: "a figyelem középpontjában" or_spotlight: "Vagy körülnézhetsz a kiemelt tagok között is, lásd: %{link}" try_adding_some_more_contacts: "IsmerÅ‘söket kereshetsz vagy hÃvhatsz meg." you_should_add_some_more_contacts: "Adj hozzá még néhány ismerÅ‘st." - no_posts_message: - start_talking: "Mindenki hallgat. Kezdd el te a beszélgetést." seed: acquaintances: "IsmerÅ‘sök" family: "Család" @@ -213,7 +172,6 @@ hu: update: failure: "A %{name} nevű csoportodnak túl hosszú a neve." success: "%{name} csoport szerkesztve." - back: "Vissza" blocks: create: failure: "Nem sikerült figyelmen kÃvül hagyni a felhasználót. #megkerülés" @@ -225,62 +183,38 @@ hu: explanation: "Küldj bejegyzést a diaspora*-ra bárhonnan, csak mentsd el könyvjelzÅ‘ként a következÅ‘ hivatkozást => %{link}." heading: "KönyvjelzÅ‘" post_something: "Ãœzenj a diaspora*-ra" - post_success: "Elküldve! Bezárás!" cancel: "Mégsem" comments: new_comment: comment: "Hozzászólás" commenting: "Hozzászólok.." - one: "1 hozzászólás" - other: "%{count} hozzászólás" - zero: "nincs hozzászólás" contacts: - create: - failure: "Kapcsolat létrehozása sikertelen" index: add_a_new_aspect: "Új csoport" add_contact: "IsmerÅ‘s hozzáadása" - add_to_aspect: "Kapcsolatok hozzáadása %{name}" all_contacts: "Összes ismerÅ‘s" community_spotlight: "A figyelem középpontjában" my_contacts: "Kapcsolataim" no_contacts: "Nincs ismerÅ‘söd." no_contacts_message: "Tekintsd meg %{community_spotlight} álló népszerű tagokat" only_sharing_with_me: "KövetÅ‘k" - remove_contact: "IsmerÅ‘s eltávolÃtása" start_a_conversation: "Beszélgetés indÃtása" title: "IsmerÅ‘sök" user_search: "Felhasználó keresése" - your_contacts: "IsmerÅ‘seid" - sharing: - people_sharing: "IsmerÅ‘seid:" spotlight: community_spotlight: "A figyelem középpontjában" suggest_member: "Javasolj egy tagot" conversations: - conversation: - participants: "RésztvevÅ‘k" create: fail: "Érvénytelen üzenet" no_contact: "Hé, elÅ‘ször kapcsolatot kell hozzáadnod!" sent: "Ãœzenet elküldve" - helper: - new_messages: - few: "%{count} új üzenet" - many: "%{count} új üzenet" - one: "1 új üzenet" - other: "%{count} új üzenet" - two: "%{count} új üzenet" - zero: "nincs új üzenet" index: conversations_inbox: "Beszélgetések - levelesláda" - create_a_new_conversation: "új beszélgetés indÃtása" inbox: "BejövÅ‘" new_conversation: "Új beszélgetés" - no_conversation_selected: "nincs beszélgetés kiválasztva" no_messages: "nincs üzenet" new: - abandon_changes: "Elveted a változtatásokat?" send: "Küldés" sending: "Küldés ..." subject: "tárgy" @@ -301,10 +235,6 @@ hu: error_messages: helper: correct_the_following_errors_and_try_again: "JavÃtsd a következÅ‘ hibákat és próbáld újra." - invalid_fields: "Érvénytelen adatok" - login_try_again: "Kérlek <a href='%{login_link}'>jelentkezz be</a> és próbáld meg újra." - post_not_public: "A megtekinteni kÃvánt bejegyzés nem nyilvános!" - post_not_public_or_not_exist: "A megtekinteni kÃvánt bejegyzés nem nyilvános vagy nem létezik!" fill_me_out: "Töltsd ki" find_people: "Emberek vagy #cÃmkék keresése" help: @@ -443,44 +373,26 @@ hu: tutorial: "útmutató" tutorials: "útmutatók" wiki: "wiki" - hide: "Elrejt" - ignore: "MellÅ‘zés" - invitation_codes: - excited: "%{name} alig várja, hogy üdvözölhessen nálunk." invitations: a_facebook_user: "Egy Facebook felhazsnáló" check_token: not_found: "MeghÃvó azonosÃtó nem található" create: - already_contacts: "Már ismerÅ‘söd ez a személy" - already_sent: "Már meghÃvtad ezt a személyt." empty: "Kérlek adj meg legalább egy e-mail cÃmet." no_more: "Nincs több felkérésed." note_already_sent: "A meghÃvókat már kiküldtük a következÅ‘ cÃm(ek)re: %{emails}" - own_address: "Nem küldhetsz meghÃvót a saját cÃmedre." rejected: "Az alábbi e-mail cÃmmel voltak problémák:" sent: "MeghÃvók elküldve ide: %{emails}" - edit: - accept_your_invitation: "MeghÃvás elfogadása" - your_account_awaits: "A fiókod vár!" new: - already_invited: "A következÅ‘ személy nem fogadta el a meghÃvásod:" - aspect: "Csoport" - check_out_diaspora: "Próbáld ki a diaspora*-t!" codes_left: other: "%{count} meghÃvó maradt még ezen a kódon" zero: "Nem maradt több meghÃvó ezen a kódon" comma_separated_plz: "Megadhatsz több e-mail cÃmet is vesszÅ‘vel elválasztva." - if_they_accept_info: "Ha elfogadják felkérésed, akkor belekerülnek abba a csoportba amelyikbe meghÃvtad Å‘ket." invite_someone_to_join: "HÃvj meg valakit, hogy csatlakozzon a diaspora*-hoz!" language: "Nyelv" paste_link: "Ha szeretnéd meghÃvni a barátaidat a Diaspora-ra, oszd meg velük ezt a hivatkozást vagy küldd el nekik közvetlenül levélben." - personal_message: "Személyes üzenet" - resend: "Újraküld" send_an_invitation: "Küldj egy meghÃvót" - send_invitation: "MeghÃvás küldése" sending_invitation: "MeghÃvó küldése folyamatban..." - to: "CÃmzett" layouts: application: back_to_top: "Vissza az elejére" @@ -489,32 +401,13 @@ hu: source_package: "forráskódcsomag letöltése" toggle: "mobil változat" whats_new: "Mik az újdonságok?" - your_aspects: "csoportjaid" header: - admin: "rendszergazda" - blog: "blog" code: "kód" - help: "Súgó" - login: "bejelentkezés" logout: "Kijelentkezés" profile: "Adatlap" - recent_notifications: "Legújabb jelzések" settings: "BeállÃtások" - view_all: "Az összes megtekintése" - likes: - likes: - people_dislike_this: - other: "%{count} ember nem kedveli" - zero: "nincs negatÃv visszajelzés" - people_like_this: - other: "%{count} ember kedveli" - zero: "senki nem kedveli" - people_like_this_comment: - other: "%{count} embernek tetszik" - zero: "még senki nem kedvelte" limited: "Korlátozott" more: "BÅ‘vebben" - next: "következÅ‘" no_results: "Nincs eredmény" notifications: also_commented: @@ -534,10 +427,6 @@ hu: comment_on_post: other: "%{actors} hozzászólt a bejegyzésedhez (%{post_link})." zero: "%{actors} hozzászólt a bejegyzésedhez (%{post_link})." - helper: - new_notifications: - other: "%{count} új értesÃtés" - zero: "nincs új értesÃtés" index: all_notifications: "Minden értesÃtés" also_commented: "Szintén hozzászólt" @@ -603,7 +492,6 @@ hu: zero: "%{actors} mostantól megoszt veled." notifier: a_post_you_shared: "egy bejegyzés." - accept_invite: "Fogadd el a diaspora* meghÃvódat!" click_here: "kattints ide" comment_on_post: reply: "Válaszolok vagy megnézem %{name} bejegyzését >" @@ -653,7 +541,6 @@ hu: liked: "%{name} kedveli a bejegyzésedet" view_post: "Bejegyzés megtekintése >" mentioned: - mentioned: "megemlÃtett téged egy bejegyzésében:" subject: "%{name} megemlÃtett téged a Diaspora* közösségi oldalon." private_message: reply_to_or_view: "Beszélgetés folytatása vagy megtekintése >" @@ -691,20 +578,9 @@ hu: to_change_your_notification_settings: "hogy megváltoztasd az értesÃtési beállÃtásaidat." nsfw: "NSFW (munkahelyen nem illÅ‘ tartalom)" ok: "Rendben" - or: "vagy" - password: "Jelszó" - password_confirmation: "Jelszó megerÅ‘sÃtése" people: add_contact: invited_by: "Å‘ hÃvott meg téged:" - add_contact_small: - add_contact_from_tag: "ismerÅ‘s hozzáadása cÃmkébÅ‘l" - aspect_list: - edit_membership: "csoport tagság szerkesztése" - helper: - is_not_sharing: "%{name} nem oszt meg veled tartalmakat" - is_sharing: "%{name} megoszt veled" - results_for: "eredmények %{params}" index: couldnt_find_them: "Nem találod Å‘ket?" looking_for: "%{tag_link} cÃmkéjű bejegyzéseket keresel?" @@ -714,86 +590,36 @@ hu: search_handle: "Hogy biztosan megtaláld a barátaidat, használd a diaspora azonosÃtójukat (felhasználónév@pod.tld)." searching: "keresés folyamatban, légy türelmes..." send_invite: "Még mindig semmi? Küldj meghÃvót!" - one: "1 személy" - other: "%{count} személy" person: - add_contact: "Kapcsolat hozzáadása" - already_connected: "Már csatlakozott" - pending_request: "Folyamatban lévÅ‘ kérelem" thats_you: "Ez vagy Te!" profile_sidebar: bio: "személyes" born: "születésnap" - edit_my_profile: "Adatlapom szerkesztése" gender: "nem" - in_aspects: "csoportokban" location: "lakóhely" - photos: "képek" - remove_contact: "kapcsolat törlése" - remove_from: "Törlöd %{name}-t a %{aspect} csoportból?" show: closed_account: "Ez a fiók zárolva lett." does_not_exist: "Személy nem létezik!" has_not_shared_with_you_yet: "%{name} még nem oszt meg veled semmit." - ignoring: "Figyelmen kÃvül hagyod az összes bejegyzést tÅ‘le: %{name}." - incoming_request: "%{name} megosztást kezdeményezett veled." - mention: "MegemlÃt" - message: "Ãœzenet" - not_connected: "Nem az ismerÅ‘söd" - recent_posts: "Legutóbbi bejegyzések" - recent_public_posts: "Legutóbbi nyilvános bejegyzések" - return_to_aspects: "Menj vissza a csoportokhoz" - see_all: "Összes" - start_sharing: "Megosztás indÃtása" - to_accept_or_ignore: "hogy elfogadd vagy figyelmen kÃvül hagyd." - sub_header: - add_some: "adj hozzá néhányat" - edit: "szerkesztés" - you_have_no_tags: "nincs cÃmkéd!" - webfinger: - fail: "Sajnáljuk, de nem találjuk Å‘t: %{handle}." - zero: "senki" photos: - comment_email_subject: "%{name} fényképe" create: integrity_error: "Kép feltöltése nem sikerült. Biztos vagy benne, hogy ez egy kép?" runtime_error: "Kép feltöltése nem sikerült. Szerver nem válaszol!" type_error: "Kép feltöltése nem sikerült. Biztos vagy benne, hogy jelöltél ki képet?" destroy: notice: "Kép törölve." - edit: - editing: "Szerkesztés" - new: - back_to_list: "Vissza a listához" - new_photo: "Új kép" - post_it: "Elküld!" new_photo: empty: "{file} egy üres fájl, válaszd ki újra a fájlokat {file} kivételéve!" invalid_ext: "{file} érvénytelen kiterjesztés. Csak {extensions} kiterjesztések megengedettek." size_error: "{file} túl nagy, maximum fájlméret {sizeLimit}." new_profile_photo: - or_select_one_existing: "vagy válassz egyet a már meglévÅ‘k közül %{photos}" upload: "Tölts fel új önarcképet!" - photo: - view_all: "%{name} összes képének megtekintése" show: - collection_permalink: "Galéria permalink" - delete_photo: "Kép törlése" - edit: "szerkesztés" - edit_delete_photo: "Kép leÃrás szerkesztése / kép törlése" - make_profile_photo: "beállÃtás önarcképnek" show_original_post: "Eredeti bejegyzés megtekintése" - update_photo: "Kép frissÃtése" - update: - error: "Nem sikerült szerkeszteni a képet." - notice: "Kép szerkesztése sikerült." posts: presenter: title: "%{name} bejegyzése" show: - destroy: "Töröl" - not_found: "Ez a bejegyzés sajnos nem található." - permalink: "permalink" photos_by: few: "%{count} fénykép tÅ‘le: %{author}" many: "%{count} fénykép tÅ‘le: %{author}" @@ -802,14 +628,11 @@ hu: two: "Két fénykép tÅ‘le: %{author}" zero: "Nincs fénykép tÅ‘le: %{author}" reshare_by: "forrás: %{author}" - previous: "elÅ‘zÅ‘" privacy: "Magántér" - privacy_policy: "Adatvédelem" profile: "Adatlap" profiles: edit: allow_search: "megtalálható legyek a diaspora* keresÅ‘ben" - edit_profile: "Adatlap szerkesztése" first_name: "Keresztnév" last_name: "Vezetéknév" nsfw_check: "Minden megosztásom megjelölése NSFW tartalomként" @@ -822,8 +645,6 @@ hu: your_location: "Lakóhelyed" your_name: "Neved" your_photo: "Fényképed" - your_private_profile: "Személyes adatlapod" - your_public_profile: "Nyilvános adatlapod" your_tags: "5 tulajdonság (#cÃmke) rólad:" your_tags_placeholder: "pl: #film #kultúra #utazás #fényképezés" update: @@ -837,26 +658,16 @@ hu: closed: "A feliratkozási lehetÅ‘ség zárolva van ezen a diaspora* kiszolgálón." create: success: "Csatlakoztál a diaspora* közösségi oldalra!" - edit: - cancel_my_account: "Fiókom törlése" - edit: "%{name} szerkesztése" - leave_blank: "(hagyd üresen, ha nem akarod megváltoztatni)" - password_to_confirm: "(Szükségünk van a jelenlegi jelszavadra, hogy jóváhagyd a változást)" - unhappy: "Elégedetlen vagy?" - update: "FrissÃtés" invalid_invite: "Ez a meghÃvó többé nem érvényes!" new: - create_my_account: "Fiók létrehozása!" email: "E-MAIL" enter_email: "Ãrd be az e-mail cÃmed" enter_password: "Adj meg egy jelszót (legalább hat karakterbÅ‘l álljon)" enter_password_again: "Ugyanazt a jelszót Ãrd amit az elÅ‘bb" enter_username: "Válassz egy felhasználónevet (csak angol betű, szám és aláhúzás megengedett)" - join_the_movement: "Csatlakozz!" password: "JELSZÓ" password_confirmation: "Jelszó megerÅ‘sÃtése" sign_up: "Feliratkozás" - sign_up_message: "Közösségi Hálózat <3" submitting: "Feldolgozás folyamatban..." terms: "A fiók létrehozásával elfogadod a %{terms_link}." terms_link: "felhasználási feltételeket" @@ -871,49 +682,15 @@ hu: reported_label: "<b>Jelentette:</b> %{person}" review_link: "Ãtnézettnek jelöl" status: - created: "Jelentés létrehozva" destroyed: "A bejegyzés megsemmisÃtve" failed: "Valami hiba történt" - marked: "A jelentés átnézettként lett megjelölve" title: "Jelentések áttekintése" - requests: - create: - sending: "Küldés" - sent: "Jelezted %{name} felhasználónak, hogy szeretnél megosztani vele. Ezt a felhÃvást következÅ‘ bejelentkezésekor fogja látni." - destroy: - error: "Kérlek válassz egy csoportot!" - ignore: "Kapcsolati felkérés figyelmen kÃvül hagyva." - success: "Mostantól ismerÅ‘sök vagytok." - helper: - new_requests: - few: "%{count} új felkérés!" - many: "%{count} új felkérés!" - one: "új felkérések!" - other: "%{count} új felkérés!" - two: "%{count} új kérés" - zero: "nincs új felkérés" - manage_aspect_contacts: - existing: "MeglévÅ‘ kapcsolatok" - manage_within: "Kapcsolatok kezelése" - new_request_to_person: - sent: "elküldve!" reshares: comment_email_subject: "%{resharer} újraosztotta %{author} bejegyzését" - create: - failure: "Hiba történt a bejegyzés újraosztásakor." reshare: deleted: "Eredeti bejegyzés törölve szerzÅ‘ által." - reshare: - few: "%{count} Å‘jraosztás" - many: "%{count} újraosztás" - one: "1 újraosztás" - other: "%{count} újraosztás" - two: "%{count} megosztás" - zero: "Újraosztás" reshare_confirmation: "Újraosztod %{author} - %{text}?" - reshare_original: "Eredeti újraosztása" reshared_via: "forrás" - show_original: "Eredeti megjelenÃtése" search: "Keresés" services: create: @@ -925,10 +702,6 @@ hu: success: "Sikeresen megszakÃtottad a kapcsolódást." failure: error: "Hiba történt a szolgáltatáshoz való kapcsolódás során" - finder: - fetching_contacts: "A diaspora* keresi a %{service} ismerÅ‘seidet, nézz vissza néhány perc múlva." - no_friends: "Nincs Facebook ismerÅ‘söd" - service_friends: "%{service} ismerÅ‘sök" index: connect: "Kapcsolódás" disconnect: "megszakÃt" @@ -937,28 +710,9 @@ hu: not_logged_in: "Jelenleg nem vagy bejelentkezve." really_disconnect: "MegszakÃtod a kapcsolatot ezzel: %{service}?" services_explanation: "Ha kapcsolódsz más szolgáltatásokhoz, lehetÅ‘séged lesz bejegyzéseket küldeni a felületükre, amint azokat a diaspora* rendszerén belül megÃrod." - inviter: - click_link_to_accept_invitation: "Kattints a linkre, hogy elfogadd a meghÃvást." - join_me_on_diaspora: "Találkozzunk a DIASPORA*-n" - remote_friend: - invite: "meghÃv" - not_on_diaspora: "Még nincs diaspora* fiókja" - resend: "újraküld" settings: "BeállÃtások" - share_visibilites: - update: - post_hidden_and_muted: "%{name} bejegyzései és értesÃtései el lettek rejtve." - see_it_on_their_profile: "Ha szeretnéd látni a frissÃtéseket ezen a bejegyzésen, látogasd meg %{name} adatlapját." shared: - add_contact: - add_new_contact: "Új ismerÅ‘s" - create_request: "Keresés diaspora* azonosÃtó alapján" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "diaspora* felhasználónév:" - know_email: "Tudod az e-mail cÃmüket? HÃvd meg Å‘ket!" - your_diaspora_username_is: "diaspora* felhasználóneved: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "IsmerÅ‘s hozzáadása" toggle: few: "%{count} csoportban" many: "%{count} csoportban" @@ -966,23 +720,11 @@ hu: other: "%{count} csoportban" two: "%{count} nézetben" zero: "IsmerÅ‘s hozzáadása" - contact_list: - all_contacts: "Összes kapcsolat" - footer: - logged_in_as: "bejelentkezve, mint %{name}" - your_aspects: "csoportjaid" invitations: by_email: "emailben" - dont_have_now: "Nincs több meghÃvód, de hamarosan kapsz még!" - from_facebook: "Facebook-ról" - invitations_left: "%{count} maradt" - invite_someone: "HÃvj meg valakit" invite_your_friends: "HÃvd meg a barátaidat" invites: "MeghÃvók" - invites_closed: "A meghÃvás jelenleg szünetel erre a diaspora* kiszolgálóra." share_this: "Oszd meg ezt a hivatkozást levélben, blogon vagy közösségi hálón!" - notification: - new: "Új %{type} %{from}-tól/tÅ‘l" public_explain: atom_feed: "Atom hÃrfolyamod (feed)" control_your_audience: "Válassz célközönséget!" @@ -996,12 +738,9 @@ hu: title: "Kapcsolódó szolgáltatások beállÃtása" visibility_dropdown: "Használd ezt a legördülÅ‘ menüt, hogy módosÃtsd a bejegyzésed láthatóságát." publisher: - all: "összes" - all_contacts: "összes kapcsolat" discard_post: "Bejegyzés elvetése" formatWithMarkdown: "%{markdown_link} jelek használatával formázni is tudod a bejegyzésedet" get_location: "Helyzetmeghatározás" - make_public: "nyilvánossá tesz" new_user_prefill: hello: "Sziasztok, én #%{new_user_tag} vagyok. " i_like: "Engem ezek érdekelnek: %{tags}." @@ -1009,36 +748,14 @@ hu: newhere: "újonc" poll: add_a_poll: "Körkérdés hozzáadása" - add_poll_answer: "Válasz hozzáadása" - option: "1. válasz" - question: "Kérdés" - remove_poll_answer: "Válasz törlése" - post_a_message_to: "Bejegyzés küldése ennek a csoportnak: %{aspect}" posting: "Küldés..." - preview: "ElÅ‘nézet" - publishing_to: "Publikálás:" remove_location: "Tartózkodási hely eltávolÃtása" share: "Megosztás" - share_with: "megosztás vele" upload_photos: "Képek feltöltése" whats_on_your_mind: "Mi jár a fejedben?" - reshare: - reshare: "Újraosztás" stream_element: - connect_to_comment: "Csatlakozz ehhez a személyhez, hogy hozzászólhass a bejegyzéseihez" - currently_unavailable: "a hozzászólási lehetÅ‘ség felfüggesztve" - dislike: "Nem tetszik" - hide_and_mute: "Bejegyzés elrejtése és némÃtása" - ignore_user: "MellÅ‘z: %{name}" - ignore_user_description: "A felhasználó mellÅ‘zése és eltávolÃtása az összes csoportból?" - like: "Tetszik" - nsfw: "Ez a bejegyzés \"nem biztonságos\" jelölést kapott a szerzÅ‘jétÅ‘l. %{link}" - shared_with: "Megosztva vele: %{aspect_names}" - show: "megmutat" - unlike: "Nem tetszik" via: "ezen keresztül: %{link}" via_mobile: "mobilon keresztül" - viewable_to_anyone: "Ez a bejegyzés bárki számára megtekinthetÅ‘ az interneten." simple_captcha: label: "Ãrd be a jelet a mezÅ‘be:" message: @@ -1049,24 +766,12 @@ hu: status_messages: create: success: "MegemlÃtetted: %{names}" - destroy: - failure: "Bejegyzés törlése sikertelen" - helper: - no_message_to_display: "Nincs üzenet." new: mentioning: "MegemlÃt: %{person}" too_long: "RövidÃts. Az állapotfrissÃtésed nem lehet hosszabb %{count} leütésnél. Jelenleg %{current_length} karakterbÅ‘l áll" stream_helper: - hide_comments: "hozzászólások elrejtése" no_more_posts: "Elérted a hÃrfolyam végét." no_posts_yet: "Még nincsenek bejegyzések." - show_comments: - few: "Még %{count} hozzászólás megtekintése" - many: "Még %{count} hozzászólás megtekintése" - one: "Még egy hozzászólás megtekintése" - other: "Még %{count} hozzászólás megtekintése" - two: "Még két hozzászólás megtekintése" - zero: "Nincs több hozzászólás" streams: activity: title: "Tevékenységeim" @@ -1092,22 +797,11 @@ hu: title: "Nyilvános tevékenység" tags: title: "Bejegyzés megjelölve: %{tags}" - tag_followings: - create: - failure: "#%{name} követése nem sikerült. Talán már eddig is követted?" - none: "Nem követhetsz egy üres cÃmkét!" - success: "Hurrá! Figyelemmel követed #%{name} dolgait." - destroy: - failure: "Hiba #%{name} követésének leállÃtásakor. Talán már nem is követed Å‘t? " - success: "Már nem követed Å‘t: #%{name}" tags: show: follow: "CÃmke követése" - following: "#%{tag} követve" none: "Az üres cÃmke nem létezik!" stop_following: "CÃmke-követés leállÃtása #%{tag}" - terms_and_conditions: "Felhasználási feltételek" - undo: "Visszavonod?" username: "Felhasználónév" users: confirm_email: @@ -1128,7 +822,6 @@ hu: character_minimum_expl: "legalább hat karakter legyen" close_account: dont_go: "Hé, kérlek ne menj!" - if_you_want_this: "Ha tényleg ezt akarod, Ãrd be a jelszavad a lenti mezÅ‘be és kattints a \"Fiók törlése\" gombra." lock_username: "A felhasználóneved foglalt marad. Nem lesz lehetÅ‘séged ezen a kiszolgálón új fiókot létrehozni ugyanezzel a névvel." locked_out: "Ki fogunk léptetni és kizárunk a fiókodból, amÃg végleg el nem távolÃtjuk." make_diaspora_better: "Azt szeretnénk, ha segÃtenél, hogy jobbá tehessük a diaspora*-t. A távozásod helyett ezért szÃvesebben vennénk, ha közreműködnél. Ãm ha úgy döntesz, hogy elhagyod az oldalt, a következÅ‘ fog történni:" @@ -1140,13 +833,11 @@ hu: current_password: "Jelenlegi jelszó" current_password_expl: "amelyikkel bejelentkezel..." download_export_photos: "Képeim letöltése" - download_photos: "Képeim letöltése" edit_account: "Fiók szerkesztése" email_awaiting_confirmation: "Aktivációs link elküldve ide: %{unconfirmed_email}. AmÃg nem erÅ‘sÃted meg az új cÃmed, addig a régit használjuk: %{email}." export_data: "Adatok kivitele" export_photos_in_progress: "Jelenleg folyamatban van a képeid feldolgozása. Kérlek nézz vissza késÅ‘bb." following: "Követési beállÃtások" - getting_started: "Új felhasználó beállÃtásai" liked: "valakinek tetszik a bejegyzésed?" mentioned: "megemlÃtettek téged egy bejegyzésben?" new_password: "Új jelszó" @@ -1168,7 +859,6 @@ hu: connect_to_facebook_link: "összekapcsolod Facebook fiókodat" hashtag_explanation: "A #cÃmkék segÃtenek egy bizonyos téma megtalálásában és ezáltal akár új kapcsolatokra is szert tehetsz." hashtag_suggestions: "Kövess pár téged érdeklÅ‘ cÃmkét. Például: #művészet, #fényképezés, #webdesign, #filozófia" - saved: "Mentve!" well_hello_there: "Nos, üdv nálunk!" what_are_you_in_to: "Mi érdekel?" who_are_you: "Ki is vagy?" @@ -1191,13 +881,6 @@ hu: settings_updated: "BeállÃtások frissÃtve" unconfirmed_email_changed: "Email megváltozott, aktiváció szükséges." unconfirmed_email_not_changed: "Email módosÃtás sikertelen" - webfinger: - fetch_failed: "Nem sikerült lekérni webfinger profilt %{profile_url} számára" - hcard_fetch_failed: "nem sikerült lekérni a hCard-ot #{@account} számára" - no_person_constructed: "EbbÅ‘l a hCard névjegybÅ‘l nem lehet személyt létrehozni." - not_enabled: "a webfinger nincs engedélyezve %{account} kiszolgálóján" - xrd_fetch_failed: "%{account} fiókjából nem sikerült az XRD kiolvasása" - welcome: "Ãœdv!" will_paginate: next_label: "következÅ‘ »" previous_label: "« elÅ‘zÅ‘" \ No newline at end of file diff --git a/config/locales/diaspora/hy.yml b/config/locales/diaspora/hy.yml index f927b26c0d7f5e03cd525488da03e1b5789661c3..c307fa3f6bbe4e9d0d6a30b637ca15d673260d68 100644 --- a/config/locales/diaspora/hy.yml +++ b/config/locales/diaspora/hy.yml @@ -6,11 +6,8 @@ hy: _applications: "Õ€Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¶Õ¥Ö€" - _comments: "Õ„Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€" _contacts: "Õ„Õ¡Ö€Õ¤Õ«Õ¯" _help: "Õ•Õ£Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - _home: "Ô³Õ¬ÕÕ¡Õ¾Õ¸Ö€ Õ§Õ»" - _photos: "Õ†Õ¯Õ¡Ö€Õ¶Õ¥Ö€" _services: "Ô¾Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€" _statistics: "ÕŽÕ«Õ³Õ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" _terms: "ÕŠÕ¡ÕµÕ´Õ¡Õ¶Õ¶Õ¥Ö€" @@ -53,12 +50,19 @@ hy: taken: "Õ¡Ö€Õ¤Õ¥Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¸Ö‚Õ´ Õ§Ö‰" admins: admin_bar: + dashboard: "ÕŽÕ¡Õ°Õ¡Õ¶Õ¡Õ¯" pages: "Ô·Õ»Õ¥Ö€" + pod_network: "Õ“Õ¸Õ¤Õ« ÖÕ¡Õ¶Ö" pod_stats: "Õ“Õ¸Õ¤Õ« Õ¾Õ«Õ³Õ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" report: "Ô²Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€" sidekiq_monitor: "ÕÕ¡ÕµÕ¤Õ¯Õ«Ö„Õ« Õ°Õ½Õ¯Õ¸Ö‚Õ´" user_search: "Õ•Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´" weekly_user_stats: "Õ•Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ« Õ·Õ¡Õ¢Õ¡Õ©Õ¡Õ¯Õ¡Õ¶ Õ¾Õ«Õ³Õ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" + dashboard: + fetching_diaspora_version: "ÕˆÖ€Õ¸Õ·Õ¾Õ¸Ö‚Õ´ Õ§ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ¡Õ´Õ¥Õ¶Õ¡Õ©Õ¡Ö€Õ´ վարկածը․․․" + pod_status: "Õ“Õ¸Õ¤Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯Õ¨" + pods: + pod_network: "Õ“Õ¸Õ¤Õ« ÖÕ¡Õ¶Ö" stats: 2weeks: "2 Õ·Õ¡Õ¢Õ¡Õ©" 50_most: "Ô±Õ´Õ¥Õ¶Õ¡Õ¿Õ¡Ö€Õ¡Õ®Õ¾Õ¡Õ® 50 ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ¨" @@ -109,7 +113,10 @@ hy: are_you_sure_unlock_account: "Õ€Õ¡Õ´Õ¸Õ¦Õ¾Õ¡ÕžÕ® Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ¡ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ¡ÕµÕ½ Õ°Õ¡Õ·Õ«Õ¾Õ¨Ö‰" close_account: "Õ“Õ¡Õ¯Õ¥Õ¬ Õ°Õ¡Õ·Õ«Õ¾Õ¨" email_to: "Ô·Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ¶` Õ°Ö€Õ¡Õ¾Õ¥Ö€ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€" + invite: "Õ€Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬" + lock_account: "Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ°Õ¡Õ·Õ«Õ¾Õ¨" under_13: "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ 13-Õ«Ö ÖƒÕ¸Ö„Ö€ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ«Õ¶ (COPPA)" + unlock_account: "Ô±ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ°Õ¡Õ·Õ«Õ¾Õ¨" users: one: "Õ£Õ¿Õ¶Õ¾Õ¥Ö %{count} Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€" other: "Õ£Õ¿Õ¶Õ¾Õ¥Ö %{count} Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€" @@ -125,13 +132,41 @@ hy: other: "Ô±ÕµÕ½ Õ·Õ¡Õ¢Õ¡Õ©Õ¾Õ¡ Õ¶Õ¸Ö€ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ« Ö„Õ¡Õ¶Õ¡Õ¯Õ¨Õ %{count}" zero: "Ô±ÕµÕ½ Õ·Õ¡Õ¢Õ¡Õ©Õ¾Õ¡ Õ¶Õ¸Ö€ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ« Ö„Õ¡Õ¶Õ¡Õ¯Õ¨Õ 0" current_server: "ÕÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¹Õ« Õ¡Õ´Õ½Õ¡Õ©Õ«Õ¾Õ¨` %{date}" - ago: "%{time} Õ¡Õ¼Õ¡Õ»" all_aspects: "Ô²Õ¸Õ¬Õ¸Ö€ ÕÕ´Õ¢Õ¥Ö€Õ¨" - application: - helper: - unknown_person: "Ô±Õ¶Õ°Õ¡ÕµÕ¿ Õ¡Õ¶Õ±" - video_title: - unknown: "ÕÕ¥Õ½Õ¡Õ¶ÕµÕ¸Ö‚Õ©Õ« Õ¡Õ¶Õ°Õ¡ÕµÕ¿ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Õ«Ö€" + api: + openid_connect: + authorizations: + new: + access: "%{name} Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¨ Õ´Õ¡Õ¿Õ¹Õ¸Ö‚Õ´ Õ§ Õ°Õ¡ÕµÖÕ¸Ö‚Õ´ Õ°Õ¥Õ¿Õ¥Ö‚ÕµÕ¡Õ¬Õ«Õ¶Õ" + approve: "Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬" + bad_request: "ÕÕºÕ¡Õ½Õ¡Õ¼Õ¸Ö‚Õ« Õ¡ÕµÕ¤Õ«Õ¶ Õ¯Õ¡Õ´ Õ¾Õ¥Ö€Õ¡Õ¸Ö‚Õ²Õ²Õ¸Ö€Õ¤Õ´Õ¡Õ¶ Õ…Õ¸Ö‚Ô±Ö€Ô±Õµ-Õ¨ Õ¢Õ¡ÖÕ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ´ Õ¥Õ¶Ö‰" + client_id_not_found: "ÕˆÕ¹ Õ´Õ« Õ½ÕºÕ¡Õ½Õ¡Õ¼Õ¸Ö‚ %{client_id} Õ½ÕºÕ¡Õ½Õ¡Õ¼Õ¸Ö‚Õ« Õ¡ÕµÕ¤Õ«Õ¸Õ¾ %{redirect_uri} Õ¾Õ¥Ö€Õ¡Õ¸Ö‚Õ²Õ²Õ¸Ö€Õ¤Õ´Õ¡Õ¶ Õ…Õ¸Ö‚Ô±Ö€Ô±Õµ-Õ¸Õ¾ Õ¹Õ£Õ¿Õ¶Õ¾Õ¥ÖÖ‰" + deny: "Õ„Õ¥Ö€ÕªÕ¥Õ¬" + no_requirement: "%{name} Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¨ Õ¸Õ¹ Õ´Õ« Õ©Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ« ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¸Ö‚Õ´" + redirection_message: "ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ´Õ¡Õ¿Õ¹Õ¸Ö‚Õ´ Õ¿Õ¡Õ¬ %{redirect_uri}-Õ«Õ¶Ö‰" + error_page: + contact_developer: "ÕŠÕ¥Õ¿Ö„ Õ§ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨ Õ´Õ·Õ¡Õ¯Õ¸Õ²Õ«Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ½ Õ°Õ¥Õ¿Õ¥Ö‚ÕµÕ¡Õ¬ Õ½ÕÕ¡Õ¬Õ« Õ´Õ¡Õ¶Ö€Õ¡Õ´Õ¡Õ½Õ¶ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨`" + title: "Õ•Õ°, Õ«Õ¶Õ¹-Õ¸Ö€ Õ¢Õ¡Õ¶ Õ½ÕÕ¡Õ¬ Õ£Õ¶Õ¡Ö Ö‰Õ‰" + scopes: + openid: + description: "ÕÕ¡ Õ¯Õ©Õ¸Õ²Õ¶Õ« Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ«Õ¶ Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Ö„Õ¸ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¨" + name: "Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¨" + read: + description: "ÕÕ¡ Õ¯Õ©Õ¸Õ²Õ¶Õ« Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ«Õ¶ Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Ö„Õ¸ Õ¬Ö€Õ¡Õ°Õ¸Õ½Õ¨, Ö„Õ¸ Õ¦Ö€Õ¸Ö‚ÕµÖÕ¶Õ¥Ö€Õ¨ Õ¸Ö‚ Ö„Õ¸ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¨" + name: "Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¨, Õ¬Ö€Õ¡Õ°Õ¸Õ½Õ¶ Õ¸Ö‚ Õ¦Ö€Õ¸Ö‚ÕµÖÕ¶Õ¥Ö€Õ¨" + write: + description: "ÕÕ¡ Õ¯Õ©Õ¸Õ²Õ¶Õ« Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ«Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¶Õ¸Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨, Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¶Õ¸Ö€ Õ¦Ö€Õ¸Ö‚ÕµÖÕ¶Õ¥Ö€ Õ¸Ö‚ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¡Ö€Õ±Õ¡Õ£Õ¡Õ¶Ö„Õ¶Õ¥Ö€Õ¨" + name: "Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨, Õ¦Ö€Õ¸Ö‚ÕµÖÕ¶Õ¥Ö€Õ¶ Õ¸Ö‚ Õ¡Ö€Õ±Õ¡Õ£Õ¡Õ¶Ö„Õ¶Õ¥Ö€Õ¨" + user_applications: + index: + access: "%{name} Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¨ Õ´Õ¡Õ¿Õ¹Õ¸Ö‚Õ´ Õ¸Ö‚Õ¶Õ« Õ°Õ¥Õ¿Õ¥Ö‚ÕµÕ¡Õ¬Õ«Õ¶Õ" + edit_applications: "Õ€Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¶Õ¥Ö€" + no_requirement: "%{name} Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¨ Õ¸Õ¹ Õ´Õ« Õ©Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ« ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¸Ö‚Õ´" + title: "Ô±Ö€Õ¿Õ¸Õ¶Õ¾Õ¡Õ® Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¶Õ¥Ö€" + no_applications: "ÕˆÕ¹ Õ´Õ« Õ¡Ö€Õ¿Õ¸Õ¶Õ¾Õ¡Õ® Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ® Õ¹Õ¸Ö‚Õ¶Õ¥Õ½" + policy: "ÕÕ¥Õ½ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ« Õ£Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨" + revoke_autorization: "Õ‰Õ¥Õ²ÕµÕ¡Õ¬ Õ°Õ¡Õ´Õ¡Ö€Õ¥Õ¬" + tos: "ÕÕ¥Õ½ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ´Õ¡Õ¶ ÕºÕ¡ÕµÕ´Õ¡Õ¶Õ¶Õ¥Ö€Õ¨" are_you_sure: "Õ€Õ¡Õ´Õ¸Õ¦Õ¾Õ¡ÕžÕ® Õ¥Õ½" are_you_sure_delete_account: "Õ€Õ¡Õ´Õ¸Õ¦Õ¾Õ¡ÕžÕ® Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ ÖƒÕ¡Õ¯Õ¥Õ¬ Õ°Õ¡Õ·Õ«Õ¾Õ¤Ö‰ Ô·Õ¬ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬ Õ¹Õ« Õ¬Õ«Õ¶Õ«Ö‰" aspect_memberships: @@ -147,48 +182,27 @@ hy: success: "Ô²Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¾Õ¥Ö ÕÕ´Õ¢Õ«Õ¶Ö‰" aspect_listings: add_an_aspect: "+ ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¶Õ¸Ö€ ÕÕ¸Ö‚Õ´Õ¢" - deselect_all: "Ô±ÕºÕ¡Õ¶Õ·Õ¥Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¨" - edit_aspect: "Õ“Õ¸ÕÕ¥Õ¬ %{name}" - select_all: "Õ†Õ·Õ¥Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¨" aspect_stream: make_something: "ÕÕ¿Õ¥Õ²Õ®Õ«Ö€" stay_updated: "ÔµÕ²Õ«Õ›Ö€ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡ÖÕ¾Õ¡Õ®" stay_updated_explanation: "Ô¼Ö€Õ¡Õ°Õ¸Õ½Õ¸Ö‚Õ´Õ¤ Õ¬Õ«Õ¶Õ¥Õ¬Õ¸Ö‚ Õ¥Õ¶ Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¤ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨, Õ¡ÕµÕ¶ ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ¸Õ¾ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨, Õ¸Ö€Õ¸Õ¶Ö Õ°Õ¥Õ¿Ö‡Õ¸Ö‚Õ´ Õ¥Õ½, Ö‡ Õ°Õ¡Õ´Õ¡ÕµÕ¶Ö„Õ« Õ¸Ö€Õ¸Õ· «ընտրված» Õ¡Õ¶Õ¤Õ¡Õ´Õ¶Õ¥Ö€Õ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰" - contacts_not_visible: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¹Õ¥Õ¶ Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ´Õ«Õ´ÕµÕ¡Õ¶ÖÖ‰" - contacts_visible: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¯Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Õ¶ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ´Õ«Õ´ÕµÕ¡Õ¶ÖÖ‰" - create: - failure: "Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬ ÕÕ¸Ö‚Õ´Õ¢Õ¨Ö‰" - success: "Õ”Õ¸ Õ¶Õ¸Ö€ %{name} ÕÕ¸Ö‚Õ´Õ¢Õ¨ ÕºÕ¡Õ¿Ö€Õ¡Õ½Õ¿ Õ§Ö‰" destroy: failure: "%{name} ÕÕ¸Ö‚Õ´Õ¢Õ¤ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ»Õ¶Õ»Õ¾Õ¥Õ¬Ö‰" success: "%{name} ÕÕ¸Ö‚Õ´Õ¢Õ¤ Õ¢Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² Õ»Õ¶Õ»Õ¾Õ¥ÖÖ‰" success_auto_follow_back: "%{name} ÕÕ¸Ö‚Õ´Õ¢Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ»Õ¶Õ»Õ¾Õ¥ÖÖ‰ Ô±ÕµÕ¤ ÕÕ¸Ö‚Õ´Õ¢ Õ«Õ¶Ö„Õ¶Õ¡Õ¢Õ¥Ö€Õ¡Õ¢Õ¡Ö€ Õ¡Õ¾Õ¥Õ¬Õ¡Õ¶Õ¸Ö‚Õ´ Õ§Õ«Õ¶ Ö„Õ¥Õ¦ Õ°Õ¥Õ¿ Õ¯Õ«Õ½Õ¾Õ¥Õ¬ Õ½Õ¯Õ½Õ¡Õ® Õ´Õ¡Ö€Õ¤Õ«Õ¯Ö‰ ÕÕ¿Õ¸Ö‚Õ£Õ«Ö€ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¤ Õ¸Ö‚ Õ¶Õ¸Ö€ ÕÕ¸Ö‚Õ´Õ¢ Õ¨Õ¶Õ¿Ö€Õ«Ö€, Õ¸Ö‚Ö€ Õ¯Õ¡Õ¾Õ¥Õ¬Õ¡Õ¶Õ¡Õ¶ Õ«Õ¶Ö„Õ¶Õ¡Õ¢Õ¥Ö€Õ¡Õ¢Õ¡Ö€ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¾Õ¸Õ² Õ´Õ¡Ö€Õ¤Õ«Õ¯Ö‰" edit: - aspect_chat_is_enabled: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¹Õ¡Õ©Õ¾Õ¥Õ¬ Ö„Õ¸ Õ°Õ¥Õ¿Ö‰" - aspect_chat_is_not_enabled: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¹Õ¥Õ¶ Õ¯Õ¡Ö€Õ¸Õ² Õ¹Õ¡Õ©Õ¾Õ¥Õ¬ Ö„Õ¸ Õ°Õ¥Õ¿Ö‰" aspect_list_is_not_visible: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¹Õ¥Õ¶ Õ¯Õ¡Ö€Õ¸Õ² Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ´Õ«Õ´ÕµÕ¡Õ¶ÖÖ‰" aspect_list_is_visible: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ´Õ«Õ´ÕµÕ¡Õ¶ÖÖ‰" confirm_remove_aspect: "ÕŽÕ½Õ¿Õ¡ÕžÕ° Õ¥Õ½, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ»Õ¶Õ»Õ¥Õ¬ Õ¡ÕµÕ½ ÕÕ¸Ö‚Õ´Õ¢Õ¨Ö‰" - grant_contacts_chat_privilege: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¶ Õ¿Õ¡ÕžÕ¬ Ö„Õ¸ Õ°Õ¥Õ¿ Õ¹Õ¡Õ©Õ¾Õ¥Õ¬Õ¸Ö‚ ÕºÕ¡Õ¿Õ«Õ¾ Õ¸Ö‚ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Ö‰" - make_aspect_list_visible: "Ô´Õ¡Ö€Õ±Õ¶Õ¥ÕžÕ¬ Õ¡ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ´Õ«Õ´ÕµÕ¡Õ¶Ö Õ°Õ¡Õ´Õ¡Ö€Ö‰" - remove_aspect: "Õ‹Õ¶Õ»Õ¥Õ¬ Õ¡ÕµÕ½ ÕÕ¸Ö‚Õ´Õ¢Õ¨" rename: "ÕŽÕ¥Ö€Õ¡Õ¶Õ¾Õ¡Õ¶Õ¥Õ¬" - set_visibility: "Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¥Õ¬ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨" update: "Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬" updating: "Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¾Õ¸Ö‚Õ´ Õ§" index: - diaspora_id: - content_1: "Õ”Õ¸ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Ô±ÕµÔ´Õ«-Õ¶Õ" - content_2: "Õ“Õ¸ÕÕ¡Õ¶ÖÕ«Ö€ Õ½Õ¡ ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® Õ´Õ¥Õ¯Õ«Õ¶, Ö‡ Õ¶Õ¡ Õ¯Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡ Õ£Õ¿Õ¶Õ¥Õ¬ Ö„Õ¥Õ¦ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ¸Ö‚Õ´Ö‰" - heading: "Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Ô±ÕµÔ´Õ«" donate: "Õ†Õ¾Õ«Ö€Õ¡Õ¢Õ¥Ö€Õ¥Õ¬" - handle_explanation: "ÕÕ¡ Ö„Õ¸ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Ô±ÕµÔ´Õ«-Õ¶ Õ§Ö‰ ÕÖ€Õ¡ Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾ Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ£Õ¿Õ¶Õ¥Õ¬ Ö„Õ¥Õ¦, Õ«Õ¶Õ¹ÕºÕ¥Õ½ Ö…Ö€Õ«Õ¶Õ¡Õ¯ էլ․հասÖÕ¥Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾Ö‰" help: any_problem: "Ô½Õ¶Õ¤Õ«ÕžÖ€ Õ¸Ö‚Õ¶Õ¥Õ½" contact_podmin: "Ô¿Õ¡ÕºÕ¾Õ«Ö€ Ö„Õ¸ ÖƒÕ¸Õ¤Õ« Õ¡Õ¤Õ´Õ«Õ¶Õ« Õ°Õ¥Õ¿Ö‰" do_you: "Ô±Ö€Õ¤ÕµÕ¸ÕžÖ„." - email_feedback: "Õ†Õ¡Ö‡ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¯Õ¡Ö€Õ®Õ«Ö„Õ¤ %{link}Õ¸Õ¾Ö‰" - email_link: "էլ․փոստ" feature_suggestion: "… %{link} Õ¸Ö‚Õ¶Õ¥Õ½Ö‰" find_a_bug: "… %{link} Õ¥Õ½ Õ£Õ¿Õ¥Õ¬Ö‰" have_a_question: "… %{link} Õ¸Ö‚Õ¶Õ¥Õ½Ö‰" @@ -201,31 +215,21 @@ hy: tutorial_link_text: "Õ¸Ö‚Õ½Õ¸Ö‚ÖÕ¡Õ¶Õ¸Õ² Õ¶ÕµÕ¸Ö‚Õ©Õ¥Ö€" tutorials_and_wiki: "%{faq}, %{tutorial} Ö‡ %{wiki}Õ Õ¡Õ¼Õ¡Õ»Õ«Õ¶ Ö„Õ¡ÕµÕ¬Õ¥Ö€Õ«Õ¤ Õ°Õ¡Õ´Õ¡Ö€Ö‰" introduce_yourself: "ÕÕ¡ Ö„Õ¸ Õ¬Ö€Õ¡Õ°Õ¸Õ½Õ¶ է։  Ընկղմվիր Õ¸Ö‚ Õ¶Õ¥Ö€Õ¯Õ¡ÕµÕ¡ÖÖ€Õ¸Ö‚ Õ«Õ¶Ö„Õ¤ Ö„Õ¥Õ¦Ö‰" - keep_diaspora_running: "Õ†ÕºÕ¡Õ½Õ¿Õ«Õ›Ö€ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ¡Ö€Õ¡Õ£ Õ¦Õ¡Ö€Õ£Õ¡ÖÕ´Õ¡Õ¶Õ¨ Õ¡Õ´Õ½Õ¡Õ¯Õ¡Õ¶ Õ¶Õ¾Õ«Ö€Õ¡Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢Ö‰" keep_pod_running: "Õ“Õ¸Õ² Ö„ÖÕ¾Õ¥Õ¶Ö„ %{pod}-Õ« Õ¡Õ¼Õ¸Õ²Õ»Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€Ö‰" new_here: follow: "Õ€Õ¥Õ¿Ö‡Õ«Ö€ %{link} ÕºÕ«Õ¿Õ¡Õ¯Õ¨ Ö‡ Õ¸Õ²Õ»Õ¸Ö‚Õ¶Õ«Ö€ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ¶Õ¸Ö€ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ«Õ¶Ö‰" learn_more: "Ô»Õ´Õ¡Õ¶Õ¡Õ¬ Õ¡Õ¾Õ¥Õ¬Õ«Õ¶" title: "ÕˆÕ²Õ»Õ¸Ö‚Õ¶Õ«Õ›Ö€ Õ¶Õ¸Ö€Õ¥Õ¯Õ¶Õ¥Ö€Õ«Õ¶" - no_contacts: "ÕˆÕ¹ Õ¸Ö„ Õ¹Õ¯Õ¡" - no_tags: "+ Õ€Õ¥Õ¿Ö‡Õ¥Õ¬Õ¸Ö‚ ÕºÕ«Õ¿Õ¡Õ¯ Õ£Õ¿Õ¶Õ¥Õ¬" - people_sharing_with_you: "Õ”Õ¥Õ¦ Õ°Õ¥Õ¿ Õ¯Õ«Õ½Õ¾Õ¸Õ² Õ´Õ¡Ö€Õ¤Õ«Õ¯" - post_a_message: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´ Õ¡Õ¶Õ¥Õ¬ >>" services: content: "Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ´Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¥Õ¿Ö‡ÕµÕ¡Õ¬ Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ«Õ¶Õ" heading: "Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨" - unfollow_tag: "Ô´Õ¡Õ¤Õ¡Ö€Õ¥Õ¬ Õ°Õ¥Õ¿Ö‡Õ¥Õ¬ #%{tag}" welcome_to_diaspora: "Ô²Õ¡Ö€Õ« Õ£Õ¡Õ¬Õ¸Ö‚Õ½Õ¿ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*, %{name} Õ»Õ¡Õ¶Ö‰" - new: - create: "ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬" - name: "Ô±Õ¶Õ¸Ö‚Õ¶Õ¨ (Õ´Õ«Õ¡ÕµÕ¶ Ö„Õ¥Õ¦ Õ§ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ«)" no_contacts_message: community_spotlight: "Õ°Õ¡Õ´Õ¡ÕµÕ¶Ö„Õ« Õ¡Õ¯Õ¶Õ¡Õ¼Õ¸Ö‚ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ«" + invite_link_text: "Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬" or_spotlight: "Ô¿Õ¡Õ´ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¯Õ«Õ½Õ¾Õ¥Õ¬ %{link} Õ°Õ¥Õ¿Ö‰" - try_adding_some_more_contacts: "Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ§Õ¬Õ« Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö ÖƒÕ¶Õ¿Ö€Õ¥Õ¬ Õ¯Õ¡Õ´ Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬Ö‰" + try_adding_some_more_contacts: "Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ§Õ¬Õ« Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö ÖƒÕ¶Õ¿Ö€Õ¥Õ¬ Õ¯Õ¡Õ´ %{invite_link}Ö‰" you_should_add_some_more_contacts: "Ô¼Õ¡Õ¾ Õ¯Õ¬Õ«Õ¶Õ«Õ Õ´Õ« Ö„Õ¡Õ¶Õ« Õ´Õ¡Ö€Õ¤ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ½Ö‰" - no_posts_message: - start_talking: "Ô²Õ¸Õ¬Õ¸Ö€Õ¨ Õ¤Õ¥Õ¼ Õ¤Õ¡Õ¾Õ¡Õ¤Ö€Õ¡Õ¢Õ¡Ö€ Õ¬Õ¼Õ¸Ö‚Õ´ Õ¥Õ¶" seed: acquaintances: "Ô¾Õ¡Õ¶Õ¸Õ©Õ¶Õ¥Ö€" family: "Ô¸Õ¶Õ¿Õ¡Õ¶Õ«Ö„" @@ -234,85 +238,65 @@ hy: update: failure: "Õ”Õ¸ %{name} ÕÕ´Õ¢Õ« Õ¡Õ¶Õ¸Ö‚Õ¶Õ¨ Õ·Õ¡Õ¿ Õ¥Ö€Õ¯Õ¡Ö€ Õ§ Ö‡ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ¾Õ¥Õ¬Ö‰" success: "%{name} ÕÕ¸Ö‚Õ´Õ¢Õ¤ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ ÖƒÕ¸ÖƒÕ¸ÕÕ¾Õ¥ÖÖ‰" - back: "Õ€Õ¥Õ¿" blocks: create: - failure: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬ Õ¡ÕµÕ¤ օգտատիրոջը։  #evasion" + failure: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬ Õ¡ÕµÕ¤ օգտատիրոջը։  #ÕÕ¸Ö‚Õ½Õ¡ÖƒÕ¡Õ¶Ö„" success: "Ô²Õ¡Ö€Õ«, Õ¡ÕµÕ¬Ö‡Õ½ Õ¹Õ¥Õ½ Õ¿Õ¥Õ½Õ¶Õ« Õ¡ÕµÕ¤ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ«Õ¶ Ö„Õ¸ Õ¬Ö€Õ¡Õ°Õ¸Õ½Õ¸Ö‚Õ´Ö‰ #silencio!" destroy: - failure: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ¤Õ¡Õ¤Õ¡Ö€Õ¥ÖÕ¶Õ¥Õ¬ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬ Õ¡ÕµÕ¤ օգտատիրոջը։  #evasion" + failure: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ¤Õ¡Õ¤Õ¡Ö€Õ¥Õ¬ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬ Õ¡ÕµÕ¤ օգտատիրոջը։  #ÕÕ¸Ö‚Õ½Õ¡ÖƒÕ¡Õ¶Ö„" success: "ÔµÕ¯ Õ¿Õ¥Õ½Õ¶Õ¥Õ¶Ö„Õ Õ«Õ¶Õ¹ Õ¸Ö‚Õ¶Õ¥Õ¶ Õ¶Ö€Õ¡Õ¶Ö„ Õ¡Õ½Õ¥Õ¬Õ¸Ö‚Ö‰ #sayhello" bookmarklet: explanation: "Ô³Ö€Õ¡Õ¼Õ«Ö€ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ¸Ö‚Õ´ ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® Õ¿Õ¥Õ²Õ«Ö` Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬Õ¸Õ¾ Õ¡ÕµÕ½ Õ°Õ²Õ¸Ö‚Õ´Õ¨ => %{link}" heading: "Õ†Õ·Õ¡Õ£Ö€Õ¸Ö‚Õ´ (Bookmarklet)" post_something: "Ô³Ö€Õ¡Õ¼Õ¥Õ¬ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ¸Ö‚Õ´" - post_success: "Ô³Ö€Õ¡Õ¼Õ¾Õ¥ÖÖ‰ Õ“Õ¡Õ¯Õ¾Õ¸Ö‚Õ´ Õ¥Õ´ Ö‰Õƒ" cancel: "Õ‰Õ¥Õ²Õ¡Ö€Õ¯Õ¥Õ¬" comments: new_comment: comment: "Õ„Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¥Õ¬" commenting: "Õ„Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¾Õ¸Ö‚Õ´ է…" - one: "1 Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - other: "%{count} Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - zero: "Õ„Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ¯Õ¡" contacts: - create: - failure: "Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ¯Õ¡Õº Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬" index: add_a_new_aspect: "Õ†Õ¸Ö€ ÕÕ¸Ö‚Õ´Õ¢ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬" add_contact: "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬" - add_to_aspect: "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ %{name} ÕÕ¸Ö‚Õ´Õ¢" all_contacts: "Ô²Õ¸Õ¬Õ¸Ö€Õ¨" community_spotlight: "Õ€Õ¡Õ´Õ¡ÕµÕ¶Ö„Õ« Õ¡Õ¯Õ¶Õ¡Õ¼Õ¸Ö‚ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€" my_contacts: "Ô»Õ´ Õ¯Õ¡ÕºÕ¥Ö€Õ¨" no_contacts: "ÔµÖ€Ö‡Õ¸Ö‚Õ´ Õ§Õ Õ¶Õ¸Ö€ Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ« Õ¯Õ¡Ö€Õ«Ö„ Õ¸Ö‚Õ¶Õ¥Õ½Ö‰" no_contacts_in_aspect: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ¸Ö‚Õ´ Õ¤Õ¥Õ¼ Õ¸Õ¹ Õ´Õ¥Õ¯Õ«Õ¶ Õ¹Õ¥Õ½ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÖ€Õ¥Õ¬Ö‰ Õ†Õ¥Ö€Ö„Ö‡Õ¸Ö‚Õ´ Õ¡ÕµÕ½ ÕºÕ¡Õ°Õ« Ö„Õ¸ Õ¢Õ¸Õ¬Õ¸Ö€ Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ« ÖÕ¸Ö‚ÖÕ¡Õ¯Õ¶ Õ§, Õ¸Ö‚Õ´ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¡ÕµÕ½ ÕÕ´Õ¢Õ«Õ¶Ö‰" - no_contacts_message: "Ô±Õ¶ÖÕ«Õ›Ö€ %{community_spotlight} ÖÕ¸Ö‚ÖÕ¡Õ¯Õ¸Õ¾Ö‰" + no_contacts_message: "Ô±Õ¶ÖÕ«Õ›Ö€ %{community_spotlight}Õ« ÖÕ¸Ö‚ÖÕ¡Õ¯Õ¸Õ¾Ö‰" only_sharing_with_me: "Ô»Õ¶Õ± Õ°Õ¥Õ¿ Õ´Õ«Õ¡Õ¯Õ¸Õ²Õ´Õ¡Õ¶Õ« Õ¯Õ«Õ½Õ¾Õ¸Õ²Õ¶Õ¥Ö€Õ¨" - remove_contact: "Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬" start_a_conversation: "Ô½Õ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ½Õ¯Õ½Õ¥Õ¬" title: "Õ„Õ¡Ö€Õ¤Õ«Õ¯" user_search: "ÕˆÖ€Õ¸Õ¶Õ¸Ö‚Õ´ Õ¯Õ¡ÕºÕ¥Ö€Õ«Õ¤ Õ´Õ¥Õ»" - your_contacts: "Õ”Õ¸ Õ¯Õ¡ÕºÕ¥Ö€Õ¨" - sharing: - people_sharing: "Õ”Õ¥Õ¦ Õ°Õ¥Õ¿ Õ¯Õ«Õ½Õ¾Õ¸Õ² Õ´Õ¡Ö€Õ¤Õ«Õ¯" spotlight: community_spotlight: "Õ€Õ¡Õ´Õ¡ÕµÕ¶Ö„Õ« Õ¡Õ¯Õ¶Õ¡Õ¼Õ¸Ö‚ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€" suggest_member: "Ô±Õ¶Õ¤Õ¡Õ´ Õ¡Õ¼Õ¡Õ»Õ¡Ö€Õ¯Õ¥Õ¬" conversations: - conversation: - participants: "Õ„Õ¡Õ½Õ¶Õ¡Õ¯Õ«ÖÕ¶Õ¥Ö€Õ¨" create: - fail: "Ô±Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" + fail: "Ô±Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Ö‰" no_contact: "Õ€Õ¥Õµ, Õ¢Õ¡ Õ°Õ¡Õ½ÖÕ¥Õ¡Õ¿Õ¥ÕžÖ€Õ¨Ö‰" - sent: "Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¡Õ® Õ§" + sent: "Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¡Õ® Õ§Ö‰" destroy: - delete_success: "Ô½Õ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ»Õ¶Õ»Õ¾Õ¥Ö" - hide_success: "Ô½Õ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ©Õ¡Ö„ÖÕ¾Õ¥Ö" - helper: - new_messages: - one: "1 Õ¶Õ¸Ö€ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - other: "%{count} Õ¶Õ¸Ö€ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - zero: "Õ†Õ¸Ö€ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ¯Õ¡" + delete_success: "Ô½Õ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ»Õ¶Õ»Õ¾Õ¥ÖÖ‰" + hide_success: "Ô½Õ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ©Õ¡Ö„ÖÕ¾Õ¥ÖÖ‰" index: conversations_inbox: "Ô½Õ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€ - Õ´Õ¸Ö‚Õ¿Ö„Õ¡ÕµÕ«Õ¶" - create_a_new_conversation: "Õ†Õ¸Ö€ ÕÕ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ½Õ¯Õ½Õ¥Õ¬" inbox: "Õ„Õ¸Ö‚Õ¿Ö„Õ¡ÕµÕ«Õ¶" new_conversation: "Õ†Õ¸Ö€ ÕÕ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - no_conversation_selected: "ÕˆÖ€Ö‡Õ§ Õ¦Ö€Õ¸Ö‚ÕµÖ Õ¨Õ¶Õ¿Ö€Õ¾Õ¡Õ® Õ¹Õ§" no_messages: "Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€ Õ¹Õ¯Õ¡Õ¶, Õ¤Õ¥Õ¼ ;Õƒ" new: - abandon_changes: "Õ‰Õ¥Õ²Õ¡Ö€Õ¯Õ¥ÕžÕ¬ ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨Ö‰" + message: "Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" send: "ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬" sending: "ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¾Õ¸Ö‚Õ´ է․․․" subject: "Ô¹Õ¥Õ´Õ¡" subject_default: "Ô±Õ¼Õ¡Õ¶Ö Õ©Õ¥Õ´Õ¡ÕµÕ«" to: "ÕˆÕžÖ‚Õ´" new_conversation: - fail: "Ô±Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" + fail: "Ô±Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Ö‰" show: delete: "Õ‹Õ¶Õ»Õ¥Õ¬ ÕÕ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨" - hide: "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Ö‡ Õ±Õ¡ÕµÕ¶Õ¡Õ¦Ö€Õ¯Õ¥Õ¬ ÕÕ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨" + hide: "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¸Ö‚ Õ±Õ¡ÕµÕ¶Õ¡Õ¦Ö€Õ¯Õ¥Õ¬ ÕÕ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨" + last_message: "ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ¶Õ¡Õ´Õ¡Õ¯Õ¨ Õ½Õ¿Õ¡ÖÕ¾Õ¥Õ¬ Õ§ %{timeago}" reply: "ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Õ¬" replying: "ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¸Ö‚Õ´ Õ§..." date: @@ -325,11 +309,8 @@ hy: error_messages: helper: correct_the_following_errors_and_try_again: "ÕˆÖ‚Õ²Õ²Õ«Ö€ Õ¶Õ·Õ¾Õ¡Õ® Õ¾Ö€Õ«ÕºÕ¡Õ¯Õ¶Õ¥Ö€Õ¨ Ö‡ Õ¯Ö€Õ¯Õ«Õ¶ ÖƒÕ¸Ö€Õ±Õ«Ö€Ö‰" - invalid_fields: "Ô±Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ¤Õ¡Õ·Õ¿Õ¥Ö€" - login_try_again: "<a href='%{login_link}'>Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ«Ö€</a> Ö‡ ÖƒÕ¸Ö€Õ±Õ«Ö€ Õ¶Õ¸Ö€Õ«Ö:" - post_not_public: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨, Õ¸Ö€ ÖƒÕ¸Ö€Õ±Õ¸Ö‚Õ´ Õ¥Õ½ Õ¤Õ«Õ¿Õ¥Õ¬, Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ¹Õ§Ö‰" - post_not_public_or_not_exist: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨, Õ¸Ö€ ÖƒÕ¸Ö€Õ±Õ¸Ö‚Õ´ Õ¥Õ½ Õ¤Õ«Õ¿Õ¥Õ¬, Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ¹Õ§ Õ¯Õ¡Õ´ Õ£Õ¸ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ«Ö‰" - fill_me_out: "Ô¼Ö€Õ¡ÖÖ€Õ¸Ö‚Õ› Õ«Õ¶Õ±" + need_javascript: "Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ«Õ¶ Õ‹Õ¡Õ¾Õ¡ÕÖ„Ö€Õ«ÖƒÕ© Õ§ Õ¡Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ ÕºÕ¡Õ¿Õ·Õ¡Õ³ Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ ÔµÕ©Õ¥ Õ¡Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ Õ¥Õ½ Õ¡ÕµÕ¶, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¡Õ¯Õ¿Õ«Õ¡Õ¾ÖÕ¶Õ¥Õ½ Õ¸Ö‚ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ½ Õ§Õ»Õ¨Ö‰" + fill_me_out: "Ô¼Ö€Õ¡ÖÖ€Õ¸Õ›Ö‚ Õ«Õ¶Õ±" find_people: "Ô³Õ¿Õ¶Õ¥Õ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ¯Õ¡Õ´ #ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€" help: account_and_data_management: @@ -554,84 +535,76 @@ hy: tutorial: "Õ¸Ö‚Õ½Õ¸Ö‚ÖÕ¡Õ¶Õ¸Õ² Õ¶ÕµÕ¸Ö‚Õ©" tutorials: "Õ¸Ö‚Õ½Õ¸Ö‚ÖÕ¡Õ¶Õ¸Õ² Õ¶ÕµÕ¸Ö‚Õ©Õ¥Ö€Õ¨" wiki: "Õ¾Õ«Ö„Õ«" - hide: "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬" - ignore: "Ô±Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬" + home: + default: + be_who_you_want_to_be: "ÔµÕ²Õ«Õ›Ö€Õ Õ¸Õ¾ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½" + be_who_you_want_to_be_info: "Õ‡Õ¡Õ¿ ÖÕ¡Õ¶ÖÕ¥Ö€ ÕºÕ¶Õ¤Õ¸Ö‚Õ´ Õ¥Õ¶, Õ¸Ö€ Õ¤Õ¸Ö‚ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ½ Ö„Õ¸ Õ«Ö€Õ¡Õ¯Õ¡Õ¶ Õ«Õ¶Ö„Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨Ö‰ Ô²Õ¡ÕµÖ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*Õ¶Õ Õ¸Õ¹Ö‰ Ô±ÕµÕ½Õ¿Õ¥Õ² Õ¤Õ¸Ö‚ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬, Õ©Õ¥ Õ¸Õ¾ Õ¥Õ½ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¬Õ«Õ¶Õ¥Õ¬ Õ¥Ö‚ Õ¯Õ«Õ½Õ¾Õ¥Õ¬ Ö„Õ¸ Õ´Õ¡Õ½Õ«Õ¶ Õ¡ÕµÕ¶Ö„Õ¡Õ¶ Ö„Õ«Õ¹ Õ¯Õ¡Õ´ Õ¡ÕµÕ¶Ö„Õ¡Õ¶ Õ·Õ¡Õ¿, Õ«Õ¶Õ¹Ö„Õ¡Õ¶ Õ¸Ö‚Õ¦Õ¥Õ¶Õ¡Õ½Ö‰ Ô´Õ¡ Õ«Ö€Õ¸Ö„ Ö„Õ¸ Õ°Õ¡ÕµÕ¥ÖÕ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ§, Õ©Õ¥ Õ«Õ¶Õ¹ÕºÕ¥Õ½ Õ¥Õ½ Õ¤Õ¸Ö‚ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ ÖƒÕ¸ÕÕ¡Õ¦Õ¤Õ¥Õ¬ Õ´ÕµÕ¸Ö‚Õ½Õ¶Õ¥Ö€Õ« Õ°Õ¥Õ¿Ö‰" + byline: "Ô±Õ¼ÖÕ¡Õ¶Ö Õ½Õ¸ÖÕ«Õ¡Õ¬Õ¡Õ¯Õ¡Õ¶ Õ¡Õ·ÕÕ¡Ö€Õ°, Õ¸Ö€Õ¿Õ¥Õ² Õ¾Õ¥Ö€Õ¡Õ°Õ½Õ¯Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Ö„Õ¸ Õ±Õ¥Õ¼Ö„Õ¥Ö€Õ¸Ö‚Õ´ Õ§" + choose_your_audience: "Ô¸Õ¶Õ¿Ö€Õ«Õ›Ö€ Ö„Õ¸ Õ¬Õ½Õ¡Ö€Õ¡Õ¶Õ¨" + choose_your_audience_info: "Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« ÕÕ´Õ¢Õ¥Ö€Õ¨ Õ©Õ¸Ö‚ÕµÕ¬ Õ¥Õ¶ Õ¿Õ¡Õ¬Õ«Õ½ Õ¯Õ«Õ½Õ¾Õ¥Õ¬ Õ´Õ«Õ¡ÕµÕ¶ Õ¡ÕµÕ¶ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ°Õ¥Õ¿, Õ¸Ö‚Õ´ Õ°Õ¥Õ¿ Õ¸Ö€ Õ¤Õ¸Ö‚ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½Ö‰ Ô´Õ¸Ö‚ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¬Õ«Õ¶Õ¥Õ¬ Õ¡ÕµÕ¶Ö„Õ¡Õ¶ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ¸Ö‚ Õ¡ÕµÕ¶Ö„Õ¡Õ¶ ÖƒÕ¡Õ¯, Õ«Õ¶Õ¹Ö„Õ¡Õ¶ Õ¯Õ¡Õ´Õ¥Õ¶Õ¡Õ½Ö‰ Ô¿Õ«Õ½Õ¾Õ«Ö€ Õ¦Õ¾Õ¡Ö€Õ³Õ¡Õ¬Õ« Õ¶Õ¯Õ¡Ö€Õ¸Õ¾ Õ¡Õ´Õ¢Õ¸Õ²Õ» Õ¡Õ·ÕÕ¡Ö€Õ°Õ« Õ°Õ¥Õ¿, Õ«Õ½Õ¯ Õ¬Õ¸Ö‚Ö€Õ» Õ£Õ¡Õ²Õ¿Õ¶Õ«Ö„Õ¶Õ¥Ö€Õ¤Õ Õ¡Õ´Õ¥Õ¶Õ¡Õ´Õ¸Õ¿Õ«Õ¯ Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¤Ö‰ ÕŽÕ¥Ö€Õ¡Õ°Õ½Õ¯Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Ö„Õ¸Õ› Õ±Õ¥Õ¼Ö„Õ¥Ö€Õ¸Ö‚Õ´ Õ§Ö‰" + headline: "Ô²Õ¡Ö€Õ« գալո՜ւստ %{pod_name}" + own_your_data: "ÔµÕ²Õ«Õ›Ö€ Ö„Õ¸ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¿Õ¥Ö€Õ¨" + own_your_data_info: "Õ‡Õ¡Õ¿ ÖÕ¡Õ¶ÖÕ¥Ö€ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Õ¶ Ö„Õ¸ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ£Õ¸Ö‚Õ´Õ¡Ö€ Õ¾Õ¡Õ½Õ¿Õ¡Õ¯Õ¥Õ¬Õ¸Ö‚ Õ¶ÕºÕ¡Õ¿Õ¡Õ¯Õ¸Õ¾Õ Õ¾Õ¥Ö€Õ¬Õ¸Ö‚Õ®Õ¥Õ¬Õ¸Õ¾ Ö„Õ¸ ÖƒÕ¸ÕÕ¡Õ¦Õ¤Õ¥Õ®Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¶ Õ¸Ö‚ Õ¡ÕµÕ¤ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ«Õ´Õ¡Õ¶ Õ¾Ö€Õ¡ Ö„Õ¥Õ¦ Õ«Ö€Õ¥Ö€ Õ£Õ¸Õ¾Õ¡Õ¦Õ¤Õ¥Õ¬Õ¸Õ¾Ö‰ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*Õ¶ Õ¹Õ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Ö„Õ¸ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¸Ö€Õ¥Ö‚Õ§ Õ¶ÕºÕ¡Õ¿Õ¡Õ¯Õ« Õ°Õ¡Õ´Õ¡Ö€, Õ¢Õ¡ÖÕ« Ö„Õ¥Õ¦ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¿Õ¡Õ¬Õ¸Ö‚ÖÕ Õ¯Õ¡Õº Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ Õ¸Ö‚ Õ¯Õ«Õ½Õ¾Õ¥Õ¬ Õ¸Ö‚Ö€Õ«Õ·Õ¶Õ¥Ö€Õ« Õ°Õ¥Õ¿Ö‰" + podmin: + admin_panel: "Õ¡Õ¤Õ´Õ«Õ¶Õ« Õ¾Õ¡Õ°Õ¡Õ¶Õ¡Õ¯" + byline: "Ô´Õ¸Ö‚ Õ´Õ¸Õ¿ Õ¥Õ½ Õ€Õ¡Õ´Õ¡ÖÕ¡Õ¶ÖÕ¨ ÖƒÕ¸ÕÕ¥Õ¬Õ¸Ö‚Õ¶Ö‰ Ô±Ö€Õ«, Õ¶Õ¡ÕÕ¡ÕºÕ¡Õ¿Ö€Õ¡Õ½Õ¿Õ¥Õ¶Ö„ Ö„Õ¥Õ¦, Õ°Õ¨ÕžÕ´Ö‰" + configuration_info: "Ô²Õ¡ÖÕ«Ö€ %{database_path} Õ¸Ö‚ %{diaspora_path} Ö„Õ¸ Õ¶Õ¡ÕÕ¨Õ¶Õ¿Ö€Õ¡Õ® Õ¿Õ¥Ö„Õ½Õ¿Õ¡ÕµÕ«Õ¶ ÕÕ´Õ¢Õ¡Õ£Ö€Õ«Õ¹Õ« Õ´Õ¥Õ» Õ¸Ö‚ Õ¸Ö‚Õ·Õ¡Õ¤Õ«Ö€ Õ¸Ö‚Õ½Õ¸Ö‚Õ´Õ¶Õ¡Õ½Õ«Ö€Õ«Ö€ Õ¡ÕµÕ¶Ö‰ Ô´Ö€Õ¡Õ¶Ö„ Õ´Õ¡Õ¶Ö€Õ¡Õ´Õ¡Õ½Õ¶ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¾Õ¡Õ® Õ¥Õ¶Ö‰" + configure_your_pod: "Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ«Õ›Ö€ Ö„Õ¸ ÖƒÕ¸Õ¤Õ¨" + contact_irc: "Õ¯Õ¡ÕºÕ¾Õ¥Õ¬ Õ´Õ¥Õ¦ Õ°Õ¥Õ¿ Ô±ÕµÔ±Ö€ÕÕ«ÖŠÕ¸Ö‚Õ´" + contribute: "Õ†Õ¥Ö€Õ¤Ö€Õ¸Õ›Ö‚Õ´ Õ¸Ö‚Õ¶Õ¥ÖÕ«Ö€" + contribute_info: "Ô´Õ¡Ö€Õ±Ö€Õ¸Õ›Ö‚ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*Õ¶ Õ¡Õ¾Õ¥Õ¬Õ« Õ¬Õ¡Õ¾Õ¨Ö‰ ÔµÕ©Õ¥ Õ¾Ö€Õ¥ÕºÕ¶Õ¥Ö€ Õ£Õ¿Õ¶Õ¥Õ½, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ %{report_bugs}Ö‰" + create_an_account: "Õ€Õ¡Õ·Õ«Õ›Õ¾ Õ½Õ¿Õ¥Õ²Õ®Õ«Ö€" + create_an_account_info: "%{sign_up_link} Õ¶Õ¸Ö€ Õ°Õ¡Õ·Õ¾Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰" + faq_for_podmins: "Õ´Õ¥Ö€ Õ¾Õ«Ö„Õ«Õ¸Ö‚Õ´ ÖƒÕ¸Õ¤Õ¥Ö€Õ¨ Õ½ÕºÕ¡Õ½Õ¡Ö€Õ¯Õ¸Õ²Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€ Õ€ÕÕ€" + getting_help: "Õ•Õ£Õ¶Õ¸Ö‚Õ©ÕµÕ¸Õ›Ö‚Õ¶ Õ½Õ¿Õ¡ÖÕ«Ö€" + getting_help_info: "Õ„Õ¥Õ¶Ö„ %{faq} Õ¥Õ¶Ö„ Õ¯Õ¡Õ¦Õ´Õ¥Õ¬Õ Õ¶Õ¥Ö€Õ¡Õ¼ÕµÕ¡Õ¬ Õ¸Ö€Õ¸Õ· Õ¬Ö€Õ¡ÖÕ¸Ö‚ÖÕ«Õ¹ ÕÕ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤Õ¶Õ¥Ö€, Õ°Õ¶Õ¡Ö€Ö„Õ¶Õ¥Ö€ Õ¸Ö‚ Õ¬Õ¸Ö‚Õ®Õ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ¡Õ´Õ¥Õ¶Õ¡Õ°Õ¡Õ³Õ¡ÕÕ¡Õ¯Õ« Õ°Õ¡Õ¶Õ¤Õ«ÕºÕ¸Õ² ÕÕ¶Õ¤Õ«Ö€Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰ Õ†Õ¡Õ¥Ö‚ Ö„Õ¥Õ¦ Õ¡Õ¦Õ¡Õ¿ Õ¦Õ£Õ¡Õ %{irc}Ö‰" + headline: "Ô²Õ¡Ö€Õ« գալո՜ւստ, Õ¨Õ¶Õ¯Õ¥Ö€Ö‰" + make_yourself_an_admin: "Õ”Õ¥Õ¦ Õ¡Õ¤Õ´Õ«Õ›Õ¶ Õ¤Õ¡Ö€Õ±Ö€Õ¸Ö‚" + make_yourself_an_admin_info: "Õ‘Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ£Õ¿Õ¶Õ¥Õ¬ %{wiki}Õ¸Ö‚Õ´Ö‰ ÕÖ€Õ¡ Õ¡Ö€Õ¤ÕµÕ¸Ö‚Õ¶Ö„Õ¸Ö‚Õ´ «Ադմին» Õ°Õ²Õ¸Ö‚Õ´ Õ¯Õ¡Õ¾Õ¥Õ¬Õ¡Õ¶Õ¡ Ö„Õ¸ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ´Õ¥Õ¶ÕµÕ¸Ö‚Õ¸Ö‚Õ´, Õ¥Ö€Õ¢ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¡Õ® Õ¬Õ«Õ¶Õ¥Õ½Ö‰ Ô´Õ¡ Ö„Õ¥Õ¦ Õ´Õ« Õ·Õ¡Ö€Ö„ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€ Õ¯Õ¿Õ¡, Õ«Õ¶Õ¹ÕºÕ¥Õ½ Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€Õ« Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´ Õ¯Õ¡Õ´ Ö„Õ¸ ÖƒÕ¸Õ¤Õ« Õ¾Õ«Õ³Õ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨Ö‰ Õ”Õ¸ ÖƒÕ¸Õ¤Õ« Õ£Õ¸Ö€Õ®Õ´Õ¡Õ¶ Õ¯Õ¸Õ²Õ´Õ¥Ö€Õ« Õ¾Õ¥Ö€Õ¡Õ¢Õ¥Ö€ÕµÕ¡Õ¬ Õ¡Õ¼Õ¡Õ¾Õ¥Õ¬ Õ·Õ¡Õ¿ Õ´Õ¡Õ¶Ö€Õ¡Õ´Õ¡Õ½Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€ Õ¡Õ¶ÖÕ«Ö€ %{admin_panel}Ö‰" + report_bugs: "Õ¿Õ¥Õ²Õ¥Õ¯Õ¡ÖÖ€Õ¸Ö‚ Õ¤Ö€Õ¡Õ¶Ö Õ´Õ¡Õ½Õ«Õ¶" + update_instructions: "Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ¾Õ«Ö„Õ«Õ¸Ö‚Õ´" + update_your_pod: "Ô¹Õ¡Ö€Õ´Õ¡ÖÖ€Õ¸Õ›Ö‚ Ö„Õ¸ ÖƒÕ¸Õ¤Õ¨" + update_your_pod_info: "Ô¹Õ¡Ö€Õ´Õ¡ÖÕ´Õ¡Õ¶ ÖÕ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ£Õ¿Õ¶Õ¥Õ¬ %{update_instructions}Ö‰" invitation_codes: - excited: "%{name} Õ¸Ö‚Ö€Õ¡Õ Õ§ Ö„Õ¥Õ¦ Õ¡ÕµÕ½Õ¿Õ¥Õ² Õ¿Õ¥Õ½Õ¶Õ¥Õ¬Ö‰" not_valid: "Õ€Ö€Õ¡Õ¾Õ¥Ö€Õ« Õ¡ÕµÕ½ Õ¯Õ¸Õ¤Õ¶ Õ¡ÕµÕ¬Õ¥Ö‚Õ½ Õ¡Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ§" invitations: a_facebook_user: "Õ–Õ¥ÕµÕ½Õ¢Õ¸Ö‚Ö„ÕµÕ¡Õ¶ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€" check_token: not_found: "Õ€Ö€Õ¡Õ¾Õ¥Ö€Õ« Õ¯Õ¸Õ¤Õ¡Õ¶Õ·Õ¡Õ¶Õ¨ Õ¹Õ£Õ¿Õ¶Õ¾Õ¥ÖÖ‰" create: - already_contacts: "Ô±ÕµÕ½ Õ´Õ¡Ö€Õ¤Õ¸Ö‚ Õ°Õ¥Õ¿ Õ¡Ö€Õ¤Õ¥Õ¶ Õ¯Õ¡Õº Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ Õ¥Õ½" - already_sent: "Ô±ÕµÕ½ Õ´Õ¡Ö€Õ¤Õ¸Ö‚Õ¶ Õ¡Ö€Õ¤Õ¥Õ¶ Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬ Õ¥Õ½Ö‰" empty: "ÕŠÕ¥Õ¿Ö„ Õ§ Õ¡Õ¼Õ¶Õ¾Õ¡Õ¦Õ¶ Õ´Õ¥Õ¯ էլ․հասÖÕ¥ Õ¶Õ·Õ¥Õ½Ö‰" no_more: "Ô±ÕµÕ¬Ö‡Õ½ Õ°Ö€Õ¡Õ¾Õ¥Ö€ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬Õ¸Ö‚ Õ«Ö€Õ¡Õ¾Õ¸Ö‚Õ¶Ö„ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½Ö‰" note_already_sent: "Õ€Ö€Õ¡Õ¾Õ¥Ö€Õ¶Õ¥Ö€Õ¨ Õ¡Ö€Õ¤Õ¥Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¥Õ¬ Õ¥Õ¶ Õ°Õ¥Õ¿Ö‡ÕµÕ¡Õ¬ Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€Õ«Õ¶Õ %{emails}" - own_address: "Ô´Õ¸Ö‚ Õ¹Õ¥Õ½ Õ¯Õ¡Ö€Õ¸Õ² Õ°Ö€Õ¡Õ¾Õ¥Ö€ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Ö„Õ¸ Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ½ÖÕ¥Õ«Õ¶Ö‰" rejected: "Õ€Õ¥Õ¿Ö‡ÕµÕ¡Õ¬ Õ§Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€Õ« Õ°Õ¥Õ¿ Õ¯Õ¡ÕºÕ¾Õ¡Õ® ÕÕ¶Õ¤Õ«Ö€Õ¶Õ¥Ö€ Õ¯Õ¡Õ¶Õ " sent: "Õ€Ö€Õ¡Õ¾Õ¥Ö€Õ¶Õ¥Ö€Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¥ÖÕ«Õ¶ Õ°Õ¥Õ¿Ö‡ÕµÕ¡Õ¬ Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€Õ¸Õ¾Õ %{emails}" - edit: - accept_your_invitation: "Ô¸Õ¶Õ¤Õ¸Ö‚Õ¶Õ«Õ›Ö€ Õ°Ö€Õ¡Õ¾Õ¥Ö€Õ¤" - your_account_awaits: "Õ€Õ¡Õ·Õ«Õ¾Õ¤ Ö„Õ¥Õ›Õ¦ Õ§ Õ½ÕºÕ¡Õ½Õ¸Ö‚Õ´Ö‰" new: - already_invited: "Õ€Õ¥Õ¿Ö‡ÕµÕ¡Õ¬ Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¹Õ¥Õ¶ Õ¨Õ¶Õ¤Õ¸Ö‚Õ¶Õ¥Õ¬ Õ°Ö€Õ¡Õ¾Õ¥Ö€Õ¤Õ" - aspect: "Ô½Õ¸Ö‚Õ´Õ¢" - check_out_diaspora: "Համտեսի՜ր Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*Õ¶Ö‰" codes_left: one: "Ô±ÕµÕ½ Õ°Õ²Õ¸Ö‚Õ´Õ¨ Õ£Õ¸Ö€Õ®Õ¸Õ² Õ§ Õ´Õ¥Õ¯ Õ°Ö€Õ¡Õ¾Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰" other: "Ô±ÕµÕ½ Õ°Õ²Õ¸Ö‚Õ´Õ¨ Õ£Õ¸Ö€Õ®Õ¸Õ² Õ§ %{count} Õ°Ö€Õ¡Õ¾Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰" zero: "Ô±ÕµÕ½ Õ°Õ²Õ´Õ¡Õ´Õ¢ Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬ Õ¡ÕµÕ¬Ö‡Õ½ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ§Ö‰" comma_separated_plz: "Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ´Õ« Ö„Õ¡Õ¶Õ« Õ§Õ¬.Õ°Õ¡Õ½ÖÕ¥ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Õ¬ Õ Õ¢Õ¡ÕªÕ¡Õ¶Õ¥Õ¬Õ¸Õ¾ Õ¤Ö€Õ¡Õ¶Ö„ Õ½Õ¿Õ¸Ö€Õ¡Õ¯Õ¥Õ¿Õ¶Õ¥Ö€Õ¸Õ¾Ö‰" - if_they_accept_info: "Õ¥Õ©Õ¥ Õ¶Ö€Õ¡Õ¶Ö„ Õ¨Õ¶Õ¤Õ¸Ö‚Õ¶Õ¥Õ¶, Õ¡ÕºÕ¡ Õ¯Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¾Õ¥Õ¶ Õ¡ÕµÕ¶ ÕÕ¸Ö‚Õ´Õ¢, Õ¸Ö€Õ¿Õ¥Õ² Õ¶Ö€Õ¡Õ¶Ö Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬ Õ¥Õ½Ö‰" invite_someone_to_join: "Õ€Ö€Õ¡Õ¾Õ«Ö€Õ«Õ›Ö€ Õ¸Ö€Ö‡Õ«ÖÕ¥ Õ´Õ¥Õ¯Õ«Õ¶Õ Õ´Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ«Õ¶Ö‰" language: "Ô¼Õ¥Õ¦Õ¸Ö‚" paste_link: "Ô¿Õ«Õ½Õ¾Õ«Ö€ Õ¡ÕµÕ½ Õ°Õ²Õ¸Ö‚Õ´Õ¸Õ¾ Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¤ Õ°Õ¥Õ¿, Õ¸Ö€ÕºÕ¥Õ½Õ¦Õ« Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ½ Õ¶Ö€Õ¡Õ¶Ö Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*, Õ¯Õ¡Õ´ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ«Ö€ Õ¡ÕµÕ¶ Õ¡Õ¶Õ´Õ«Õ»Õ¡ÕºÕ¥Õ½ Õ¶Ö€Õ¡Õ¶Ö Õ§Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€Õ«Õ¶Ö‰" - personal_message: "Ô±Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - resend: "Ô¿Ö€Õ¯Õ«Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬" send_an_invitation: "Õ€Ö€Õ¡Õ¾Õ¥Ö€ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬" - send_invitation: "ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ°Ö€Õ¡Õ¾Õ¥Ö€Õ¨" sending_invitation: "Õ€Ö€Õ¡Õ¾Õ¥Ö€Õ¨ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¸Ö‚Õ´ է․․․" - to: "ÕˆÕžÖ‚Õ´" layouts: application: back_to_top: "Ô¹Õ¼Õ¶Õ¥Õ¬ Õ¾Õ¥Ö€Ö‡" + be_excellent: "Հարգե՜նք Õ¦Õ´Õ«Õ´ÕµÕ¡Õ¶Õ½ ♥" powered_by: "Ô³Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ§ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Ö…Õ£Õ¶Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢" public_feed: "%{name}-Õ«` Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ°Õ¸Õ½Ö„Õ¨" source_package: "Õ†Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ½Õ¯Õ¦Õ¢Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¯Õ¸Õ¤Õ« ÖƒÕ¡Õ©Õ¥Õ©Õ¨" statistics_link: "Õ€Õ¡Õ¶Õ£Õ¸Ö‚ÕµÖÕ« Õ¾Õ«Õ³Õ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" toggle: "Ô´ÕµÕ¸Ö‚Ö€Õ¡Õ¯Õ«Ö€ Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ¨" whats_new: "Ô»ÕžÕ¶Õ¹ Õ¯Õ¡" - your_aspects: "Õ”Õ¸ ÕÕ´Õ¢Õ¥Ö€Õ¨" header: - admin: "Ô±Õ¤Õ´Õ«Õ¶" - blog: "Ô²Õ¬Õ¸Õ£" code: "Ô¿Õ¸Õ¤" - help: "Õ•Õ£Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - login: "Õ„Õ¸Ö‚Õ¿Ö„" logout: "Ô´Õ¸Ö‚Ö€Õ½ Õ£Õ¡Õ¬" profile: "Ô»Õ´ Õ§Õ»Õ¨" - recent_notifications: "ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨" settings: "Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€" - view_all: "Ô´Õ«Õ¿Õ¥Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ»Õ¨" - likes: - likes: - people_dislike_this: - one: "%{count} Õ°Õ¸Õ£Õ« Õ¹Õ« Õ°Õ¡Õ¾Õ¡Õ¶Õ¸Ö‚Õ´" - other: "%{count} Õ°Õ¸Õ£Õ« Õ¹Õ« Õ°Õ¡Õ¾Õ¡Õ¶Õ¸Ö‚Õ´" - zero: "Õ¹Õ°Õ¡Õ¾Õ¡Õ¶Õ¸Õ² Õ¹Õ¯Õ¡" - people_like_this: - one: "%{count} Õ°Õ¸Õ£Õ« Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬ Õ§" - other: "%{count} Õ°Õ¸Õ£Õ« Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬ Õ¥Õ¶" - zero: "Õ¸Õ¹ Õ¸Ö„ Õ¹Õ« Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬" - people_like_this_comment: - one: "%{count} Õ°Õ¸Õ£Õ« Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬ Õ§" - other: "%{count} Õ°Õ¸Õ£Õ« Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬ Õ¥Õ¶" - zero: "Õ¸Õ¹ Õ¸Ö„ Õ¹Õ« Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬" limited: "Õ“Õ¡Õ¯" more: "Ô±Õ¾Õ¥Õ¬Õ«Õ¶" - next: "Õ€Õ¡Õ»Õ¸Ö€Õ¤" no_results: "ÕˆÕ¹Õ«Õ¶Õ¹ Õ¹Õ£Õ¿Õ¶Õ¾Õ¥Ö" notifications: also_commented: @@ -646,11 +619,6 @@ hy: one: "%{actors} Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¥Ö Ö„Õ¸ %{post_link} Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨Ö‰" other: "%{actors} Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¥ÖÕ«Õ¶ Ö„Õ¸ %{post_link} Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨Ö‰" zero: "%{actors} Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¥Ö Ö„Õ¸ %{post_link} Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨Ö‰" - helper: - new_notifications: - one: "1 Õ¶Õ¸Ö€ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´" - other: "%{count} Õ¶Õ¸Ö€ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´" - zero: "Õ†Õ¸Ö€ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´ Õ¹Õ¯Õ¡" index: all_notifications: "Ô²Õ¸Õ¬Õ¸Ö€ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨" also_commented: "Õ†Õ¸Ö‚ÕµÕ¶ÕºÕ¥Õ½ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¥Õ¬ Õ¥Õ¶" @@ -681,9 +649,9 @@ hy: other: "%{actors} Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬ Õ¥Õ¶ Õ»Õ¶Õ»Õ¾Õ¡Õ® Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¤Ö‰" zero: "%{actors} Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬ Õ§ Õ»Õ¶Õ»Õ¾Õ¡Õ® Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¤Ö‰" mentioned: - one: "%{actors} Õ¶Õ·Õ¥Ö Ö„Õ¥Õ¦ %{post_link} Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥Õ»Ö‰" - other: "%{actors} Õ¶Õ·Õ¥ÖÕ«Õ¶ Ö„Õ¥Õ¦ %{post_link} Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥Õ»Ö‰" - zero: "%{actors} Õ¶Õ·Õ¥Ö Ö„Õ¥Õ¦ %{post_link} Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥Õ»Ö‰" + one: "%{actors} Õ¶Õ·Õ¥Õ¬ Õ§ Ö„Õ¥Õ¦ %{post_link} Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥Õ»Ö‰" + other: "%{actors} Õ¶Õ·Õ¥Õ¬ Õ¥Õ¶ Ö„Õ¥Õ¦ %{post_link} Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥Õ»Ö‰" + zero: "%{actors} Õ¶Õ·Õ¥Õ¬ Õ§ Ö„Õ¥Õ¦ %{post_link} Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥Õ»Ö‰" mentioned_deleted: one: "%{actors} Õ¶Õ·Õ¥Õ¬ Õ§ Ö„Õ¥Õ¦ Õ»Õ¶Õ»Õ¾Õ¡Õ® Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥Õ»Ö‰" other: "%{actors} Õ¶Õ·Õ¥Õ¬ Õ¥Õ¶ Ö„Õ¥Õ¦ Õ»Õ¶Õ»Õ¾Õ¡Õ® Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥Õ»Ö‰" @@ -709,7 +677,6 @@ hy: a_limited_post_comment: "Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ¸Ö‚Õ´ Õ¶Õ¸Ö€ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¸Ö‚Õ¶Õ¥Õ½ ÖƒÕ¡Õ¯ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ տակ․ Õ½Õ¿Õ¸Ö‚Õ£Õ«Ö€Ö‰" a_post_you_shared: "Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨Ö‰" a_private_message: "Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ¸Ö‚Õ´ Õ¶Õ¸Ö€ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ ունես․ Õ¡Õ¹Ö„Õ« Õ¡Õ¶ÖÕ¯Õ¡ÖÖ€Õ¸Ö‚Ö‰" - accept_invite: "Ô¸Õ¶Õ¤Õ¸Ö‚Õ¶Õ«Õ›Ö€ Ö„Õ¸Õ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ°Ö€Õ¡Õ¾Õ¥Ö€Õ¨Ö‰" also_commented: limited_subject: "Õ„Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¡Õ®Õ¤ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ Õ¶Õ¸Ö€ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¸Ö‚Õ¶Õ«" click_here: "ÕÕ¥Õ²Õ´Õ«Ö€ Õ¡ÕµÕ½Õ¿Õ¥Õ²" @@ -763,13 +730,15 @@ hy: message: |- Ողջո՜ւյն։ - Õ”Õ¥Õ¦ Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬ Õ¥Õ¶Õ Õ´Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ«Õ¶Ö‰ + Õ”Õ¥Õ¦ %{diaspora_id} Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬ Õ§Õ Õ´Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ«Õ¶Ö‰ Ô±Õ¶ÖÕ«Ö€ Õ¡ÕµÕ½ Õ°Õ²Õ¸Ö‚Õ´Õ¸Õ¾ Õ½Õ¯Õ½Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Õ - [%{invite_url}][1] - - + [%{invite_url}][1] +  + Ô¿Õ¡Õ´ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ %{diaspora_id}ÖŠÕ«Õ¶ Õ¯Õ¡ÕºÕ¥Ö€Õ«Õ¤ Õ´Õ¥Õ», Õ¥Õ©Õ¥ Õ¡Ö€Õ¤Õ¥Õ¶ Õ°Õ¡Õ·Õ«Õ¾ Õ¸Ö‚Õ¶Õ¥Õ½Ö‰ +  +  ÕÕ«Ö€Õ¸Õ¾Õ դիասպորա*ÕµÕ« Õ§Õ¬.ÖƒÕ¸Õ½Õ¿Õ¡ÕµÕ«Õ¶ ÕªÖ€Õ¡Õ»Õ¡Õ¶ ռոբոտ։  @@ -784,7 +753,6 @@ hy: view_post: "Ô´Õ«Õ¿Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ >" mentioned: limited_post: "Õ”Õ¥Õ¦ Õ¶Õ·Õ¥Õ¬ Õ¥Õ¶ ÖƒÕ¡Õ¯ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥Õ»Ö‰" - mentioned: "Õ¶Õ·Õ¥Õ¬ Õ§ Ö„Õ¥Õ¦ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ մեջ․" subject: "%{name} Õ¶Õ·Õ¥Õ¬ Õ§ Ö„Õ¥Õ¦ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥Õ» Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ¸Ö‚Õ´" private_message: reply_to_or_view: "ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ«Ö€ Õ¯Õ¡Õ´ Õ¿Õ¥Õ½ Õ¡ÕµÕ½ ÕÕ¸Õ½Õ¡Õ¯ÖÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ >" @@ -808,7 +776,9 @@ hy: ÕˆÕ²Õ»Õ¸Ö‚ÕµÕ¶Ö‰ %{id} Ô±ÕµÔ´Õ«-Õ¸Õ¾ %{type}Õ¨ Õ¶Õ·Õ¾Õ¥Õ¬ Õ§ Õ¸Ö€ÕºÕ¥Õ½ Õ¾Õ«Ö€Õ¡Õ¾Õ¸Ö€Õ¡Õ¯Õ¡Õ¶Ö‰ - +  + ÕŠÕ¡Õ¿Õ³Õ¡Õ¼Õ¨Õ %{reason} +  [%{url}][1] Խնդրում Õ¥Õ¶Ö„` Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€Õ«Õ¶Õ½ Õ·Õ¸Ö‚Õ¿ Õ¡Õ¹Ö„Õ« Õ¡Õ¶ÖÕ¯Õ¡ÖÖ€Õ¸Ö‚Ö‰ @@ -836,20 +806,9 @@ hy: to_change_your_notification_settings: "Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ ÖƒÕ¸ÕÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€" nsfw: "Õ”Ô¸Ô½" ok: "Ô¼Õ¡Õ¾" - or: "Õ¯Õ¡Õ´" - password: "Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼" - password_confirmation: "Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´" people: add_contact: invited_by: "Õ”Õ¥Õ¦ Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬ Õ§Õ" - add_contact_small: - add_contact_from_tag: "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ´Õ¥Õ¯Õ«Õ¶ ÕºÕ«Õ¿Õ¡Õ¯Õ«Ö" - aspect_list: - edit_membership: "Õ“Õ¸ÕÕ¥Õ¬ ÕÕ´Õ¢Õ« Õ¡Õ¶Õ¤Õ¡Õ´Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨" - helper: - is_not_sharing: "%{name} Õ¹Õ« Õ¯Õ«Õ½Õ¾Õ¸Ö‚Õ´ Ö„Õ¸ Õ°Õ¥Õ¿" - is_sharing: "%{name} Õ½Õ¯Õ½Õ¥Ö Õ¯Õ«Õ½Õ¾Õ¥Õ¬ Ö„Õ¸ Õ°Õ¥Õ¿" - results_for: " Õ¡Ö€Õ¤ÕµÕ¸Ö‚Õ¶Ö„Õ¶Õ¥Ö€ %{params}-Õ« Õ°Õ¡Õ´Õ¡Ö€" index: couldnt_find_them: "Õ‰Õ£Õ¿Õ¡ÕžÖ€ Õ¶Ö€Õ¡Õ¶ÖÖ‰" looking_for: "Õ”Õ¥Õ¦ %{tag_link} ÕºÕ«Õ¿Õ¡Õ¯Õ¸Õ¾ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥ÕžÖ€ Õ¥Õ¶ ÕºÕ¥Õ¿Ö„Ö‰" @@ -859,107 +818,68 @@ hy: search_handle: "Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ«Ö€ Õ¶Ö€Õ¡Õ¶Ö Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Ô±ÕµÔ´Õ«-Õ¶ (username@pod.am), Õ¸Ö€ Õ°Õ¡Õ½Õ¿Õ¡Õ¿ Õ£Õ¿Õ¶Õ¥Õ½ Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¤Ö‰" searching: "Õ“Õ¶Õ¿Ö€Õ¾Õ¸Ö‚Õ´ Õ§, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¬Õ«Õ¶Õ¥Õ¬ Õ°Õ¡Õ´Õ¢Õ¥Ö€Õ¡Õ¿Õ¡Ö€..." send_invite: "ÕˆÕ¹ Õ´Õ« Õ¡Ö€Õ¤ÕµÕ¸ÕžÖ‚Õ¶Ö„Ö‰ Õ€Ö€Õ¡Õ¾Õ¥Õ›Ö€ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ«Ö€Ö‰" - one: "1 Õ°Õ¸Õ£Õ«" - other: "%{count} Õ°Õ¸Õ£Õ«" person: - add_contact: "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬" - already_connected: "Ô±Ö€Õ¤Õ¥Õ¶ Õ¯Õ¡ÕºÕ¾Õ¡Õ® Õ¥Ö„" - pending_request: "ÕÕºÕ¡Õ½Õ¸Ö‚Õ´ Õ§ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ´Õ¡Õ¶" thats_you: "Ô´Õ¡ Õ¤Õ¸Ö‚Õ› Õ¥Õ½Ö‰" profile_sidebar: bio: "Ô¿Õ¥Õ¶Õ½Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" born: "Ô¾Õ¶Õ¶Õ¤ÕµÕ¡Õ¶ Õ¡Õ´Õ½Õ¡Õ©Õ«Õ¾" - edit_my_profile: "Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ Õ«Õ´ Õ§Õ»Õ¨" gender: "ÕÕ¥Õ¼" - in_aspects: "Ô½Õ´Õ¢Õ¥Ö€Õ¸Ö‚Õ´" location: "ÕÕ¥Õ²Õ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - photos: "Õ†Õ¯Õ¡Ö€Õ¶Õ¥Ö€" - remove_contact: "Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬" - remove_from: "Õ‹Õ¶Õ»Õ¥ÕžÕ¬ %{name}-Õ«Õ¶ %{aspect} ÕÕ´Õ¢Õ«ÖÖ‰" show: closed_account: "Ô±ÕµÕ½ Õ°Õ¡Õ·Õ«Õ¾Õ¨ ÖƒÕ¡Õ¯Õ¾Õ¥Õ¬ Õ§Ö‰" does_not_exist: "Ô±ÕµÕ½ Õ¡Õ¶Õ±Õ¨ Õ£Õ¸ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ«Ö‰ Õ€Õ¡Õ´Õ¥Õ¶Õ¡ÕµÕ¶ Õ¤Õ¥ÕºÕ½ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ¸Ö‚Õ´Ö‰" has_not_shared_with_you_yet: "%{name} Õ¤Õ¥Õ¼ Õ¹Õ« Õ¯Õ«Õ½Õ¾Õ¥Õ¬ Ö„Õ¸ Õ°Õ¥Õ¿ Õ¸Ö€Ö‡Õ§ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ´Õ¢Ö‰" - ignoring: "Ô´Õ¸Ö‚ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¸Ö‚Õ´ Õ¥Õ½ %{name}-Õ« Õ¢Õ¸Õ¬Õ¸Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰" - incoming_request: "%{name} ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ§ Õ¯Õ«Õ½Õ¾Õ¥Õ¬ Ö„Õ¥Õ¦ Õ°Õ¥Õ¿" - mention: "Õ†Õ·Õ¥Õ¬" - message: "Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - not_connected: "Ô±ÕµÕ½ Õ´Õ¡Ö€Õ¤Õ¸Ö‚ Õ°Õ¥Õ¿ Õ¹Õ¥Õ½ Õ¯Õ«Õ½Õ¾Õ¸Ö‚Õ´Ö‰" - recent_posts: "ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨" - recent_public_posts: "ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨" - return_to_aspects: "ÕŽÕ¥Ö€Õ¡Õ¤Õ¡Õ¼Õ¶Õ¡Õ¬ Ö„Õ¸ ÕÕ´Õ¢Õ¥Ö€Õ« Õ§Õ»Õ«Õ¶" - see_all: "ÕÕ¥Õ½Õ¶Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€Õ«Õ¶" - start_sharing: "ÕÕ¯Õ½Õ¥Õ¬ Õ¯Õ«Õ½Õ¾Õ¥Õ¬" - to_accept_or_ignore: "Õ Õ¨Õ¶Õ¤Õ¸Ö‚Õ¶Õ¥Õ¬Õ¸Ö‚ Õ¯Õ¡Õ´ Õ´Õ¥Ö€ÕªÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰" - sub_header: - add_some: "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥ÕžÕ¬" - edit: "Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬" - you_have_no_tags: "ÕˆÖ€Ö‡Õ§ ÕºÕ«Õ¿Õ¡Õ¯Õ¸Õ¾ Õ¹Õ¥Õ½ Õ¶Õ·Õ¥Õ¬ Ö„Õ¥Õ¦Ö‰" - webfinger: - fail: "Ô¿Õ¶Õ¥Ö€Õ¥Õ½, Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡ÖÕ¡Õ¶Ö„ Õ£Õ¿Õ¶Õ¥Õ¬ %{handle}Ö‰" - zero: "Õ„Õ¡Ö€Õ¤ Õ¹Õ¯Õ¡" photos: - comment_email_subject: "%{name}-Õ« Õ¶Õ¯Õ¡Ö€Õ«Õ¶" create: integrity_error: "Õ†Õ¯Õ¡Ö€ Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬Õ¨ Õ¿Õ¡ÕºÕ¡Õ¬Õ¾Õ¥Ö։  Համոզվա՞ծ Õ¥Õ½, Õ¸Ö€ Õ¤Õ¡ Õ¶Õ¯Õ¡Ö€ Õ§Ö€Ö‰" runtime_error: "Õ†Õ¯Õ¡Ö€ Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬Õ¨ Õ¿Õ¡ÕºÕ¡Õ¬Õ¾Õ¥ÖÖ‰ Õ€Õ¡Õ´Õ¸Õ¦Õ¾Õ¡ÕžÕ® Õ¥Õ½, Õ¸Ö€ Õ¡Õ´Ö€Õ¡Õ£Õ¸Õ¿Õ«Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡ÕºÕ¥Õ¬ Õ§Õ«Ö€Ö‰" type_error: "Õ†Õ¯Õ¡Ö€ Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬Õ¨ Õ¿Õ¡ÕºÕ¡Õ¬Õ¾Õ¥Ö։  Համոզված Õ¥ÕžÕ½, Õ¸Ö€ Õ°Õ¥Õ¶Ö Õ¶Õ¯Õ¡Ö€ Õ§Õ«Ö€ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÖ€Õ¥Õ¬Ö‰" destroy: notice: "Õ†Õ¯Õ¡Ö€Õ¨ Õ»Õ¶Õ»Õ¾Õ¡Õ® Õ§Ö‰" - edit: - editing: "Õ“Õ¸ÖƒÕ¸ÕÕ¾Õ¸Ö‚Õ´ Õ§" - new: - back_to_list: "Õ€Õ¥Õ¿Õ ÖÕ¸Ö‚ÖÕ¡Õ¯Õ«Õ¶" - new_photo: "Õ†Õ¸Ö€ Õ¶Õ¯Õ¡Ö€" - post_it: "Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¥Õ¬" new_photo: empty: "{file}-Õ¨ Õ¤Õ¡Õ¿Õ¡Ö€Õ¯ Õ§, Õ¯Ö€Õ¯Õ«Õ¶ Õ¨Õ¶Õ¿Ö€Õ«Ö€ Ö†Õ¡ÕµÕ¬Õ¥Ö€Õ¨ Õ¡Õ¼Õ¡Õ¶Ö Õ¤Ö€Õ¡Ö‰" invalid_ext: "{file}-Õ¨ Õ¡Õ¶Õ°Õ¡Õ´Õ¡ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶ Õ¨Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ´Õ¡Õ¶ Õ§Ö‰ Õ„Õ«Õ¡ÕµÕ¶ {extensions} Õ¥Õ¶ Õ©Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Ö€Õ¾Õ¸Ö‚Õ´Ö‰" size_error: "{file}-Õ¨ Õ¹Õ¡ÖƒÕ«Ö Õ¤Õ¸Ö‚Ö€Õ½ Õ´Õ¥Õ® Õ§, Õ¡Õ¼Õ¡Õ¾Õ¥Õ¬Õ¡Õ£Õ¸Ö‚ÕµÕ¶ Õ¹Õ¡ÖƒÕ¶ Õ§Õ {sizeLimit}Ö‰" new_profile_photo: - or_select_one_existing: "Õ¯Õ¡Õ´ Õ¨Õ¶Õ¿Ö€Õ«Ö€ Õ¡Ö€Õ¤Õ¥Õ¶ Õ£Õ¸ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¸Ö‚Õ¶Õ¥ÖÕ¸Õ² Õ¶Õ¯Õ¡Ö€Õ¶Õ¥Ö€Õ«ÖÕ¤ Õ´Õ¥Õ¯Õ¨Õ %{photos}" upload: "Նո՜րը Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬" - photo: - view_all: "Ô´Õ«Õ¿Õ¥Õ¬ %{name}-Õ« Õ¢Õ¸Õ¬Õ¸Ö€ Õ¶Õ¯Õ¡Ö€Õ¶Õ¥Ö€Õ¨" show: - collection_permalink: "Õ€Õ¡Õ¾Õ¡Ö„Õ¡Õ®Õ¸Ö‚Õ« Õ°Õ²Õ¸Ö‚Õ´Õ¨" - delete_photo: "Õ‹Õ¶Õ»Õ¥Õ¬ Õ¶Õ¯Õ¡Ö€Õ¨" - edit: "Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬" - edit_delete_photo: "Õ“Õ¸ÕÕ¥Õ¬ Õ¶Õ¯Õ¡Ö€Õ« Õ¶Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ¯Õ¡Õ´ Õ»Õ¶Õ»Õ¥Õ¬ Õ¡ÕµÕ¶" - make_profile_photo: "Ô´Õ¡Ö€Õ±Õ¶Õ¥Õ¬ Õ£Õ¬ÕÕ¡Õ¾Õ¸Ö€ Õ¶Õ¯Õ¡Ö€" show_original_post: "Õ‘Õ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬ Õ½Õ¯Õ¦Õ¢Õ¶Õ¡Õ¯Õ¡Õ¶ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨" - update_photo: "Õ“Õ¸ÕÕ¥Õ¬ Õ¶Õ¯Õ¡Ö€Õ¨" - update: - error: "Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö ÕÕ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ Õ¶Õ¯Õ¡Ö€Õ¨Ö‰" - notice: "Õ†Õ¯Õ¡Ö€Õ¤ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ ÖƒÕ¸ÕÕ¾Õ¥ÖÖ‰" + polls: + votes: + one: "Õ¡Õ¼Õ¡ÕµÕªÕ´ %{count} Õ±Õ¡ÕµÕ¶" + other: "Õ¡Õ¼Õ¡ÕµÕªÕ´ %{count} Õ±Õ¡ÕµÕ¶" + zero: "Õ¤Õ¥Õ¼Õ¥Ö‚Õ½ Ö„Õ¾Õ¥Õ¡Ö€Õ¯Õ¸Õ² Õ¹Õ« Õ¥Õ²Õ¥Õ¬" posts: presenter: title: "%{name}-Õ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨" show: - destroy: "Õ‹Õ¶Õ»Õ¥Õ¬" forbidden: "Ô´Õ¸Ö‚ Õ©Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½ Õ¡Õ¶Õ¥Õ¬ Õ¤Õ¡Ö‰" - not_found: "Õ‘Õ¡Õ¾Õ¸Ö„ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ Õ¹Õ£Õ¿Õ¶Õ¾Õ¥ÖÖ‰" - permalink: "ÕÕ¯Õ¦Õ¢Õ¶Õ¡Õ²Õ¢ÕµÕ¸Ö‚Ö€" + location: "Ô³Ö€Õ¡Õ¼Õ¾Õ¡Õ® Õ§ %{location}Õ«Ö" photos_by: one: "Õ„Õ¥Õ¯ Õ¶Õ¯Õ¡Ö€ %{author}-Õ«Ö" other: "%{count} Õ¶Õ¯Õ¡Ö€ %{author}-Õ«Ö" zero: "%{author}-Õ¨ Õ¶Õ¯Õ¡Ö€ Õ¹Õ¸Ö‚Õ¶Õ«" reshare_by: "%{author}-Õ« Õ¿Õ¡Ö€Õ¡Õ®Õ¡Õ®Õ¨" - previous: "Õ†Õ¡ÕÕ¸Ö€Õ¤" privacy: "Ô³Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - privacy_policy: "Ô³Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" profile: "Ô»Õ´ Õ§Õ»Õ¨" profiles: edit: allow_search: "Ô¹Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö ÖƒÕ¶Õ¿Ö€Õ¥Õ¬ Ö„Õ¥Õ¦ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¶Õ¥Ö€Õ¸Ö‚Õ´" - edit_profile: "Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ Õ«Õ´ Õ§Õ»Õ¨" + basic: "Ô»Õ´ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»" + basic_hint: "Õ”Õ¸ Õ§Õ»Õ« Õ¡Õ´Õ¥Õ¶ Õ´Õ« Õ¿Õ¾ÕµÕ¡Õ¬ Õ¯Õ¡Õ´Õ¨Õ¶Õ¿Õ«Ö€ Õ§Ö‰ Õ€Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¤ Õ´Õ«Õ·Õ¿ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ¶Õ¸Ö€Õ¥Õ¶ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¯Õ¬Õ«Õ¶Õ«Ö‰" + extended: "Ô»Õ´ Õ¨Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ¾Õ¡Õ® Õ§Õ»" + extended_hint: "ÕÕ¥Õ²Õ´Õ«Ö€, Õ¸Ö€ ÖƒÕ¸ÕÕ¥Õ½ Ö„Õ¸ Õ¨Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ¾Õ¡Õ® Õ§Õ»Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨Ö‰ Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ¶Õ·Õ¡Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§, Õ¸Ö€ Õ¡ÕµÕ¶ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§ Õ¡Õ´Õ¢Õ¸Õ²Õ» Õ°Õ¡Õ´Õ¡ÖÕ¡Õ¶ÖÕ«Õ¶, ÖƒÕ¡Õ¯Õ Õ´Õ«Õ¡ÕµÕ¶ Õ¡ÕµÕ¶ Õ´Õ¡Ö€Õ¤Õ«Õ¯, Õ¸Ö‚Õ´ Õ°Õ¥Õ¿ Õ¯Õ«Õ½Õ¾Õ¸Ö‚Õ´ Õ¥Õ½, Õ¯Õ¿Õ¥Õ½Õ¶Õ¥Õ¶ Õ¡ÕµÕ¤ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨Ö‰" + extended_visibility_text: "Ô¸Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ¾Õ¡Õ® Õ§Õ»Õ«Õ¤ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨Õ" first_name: "Ô±Õ¶Õ¸Ö‚Õ¶" last_name: "Ô±Õ¦Õ£Õ¡Õ¶Õ¸Ö‚Õ¶" + limited: "Õ“Õ¡Õ¯" nsfw_check: "Õ†Õ·Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Õ«Õ´ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¸Ö€ÕºÕ¥Õ½ Õ”Ô¸Ô½" nsfw_explanation: |- Ô¼Õ¡Õ¿Õ«Õ¶Õ¡Õ¿Õ¡Õ¼ NSFW («not safe for work»` Õ¸Õ¹ Õ¡ÕºÕ¡Õ°Õ¸Õ¾ Õ¡Õ·ÕÕ¡Õ¿Õ¡Õ¶Ö„Õ« Õ°Õ¡Õ´Õ¡Ö€) ÕºÕ«Õ¿Õ¡Õ¯Õ¨ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ«Õ¶Ö„Õ¶Õ¡Õ¾Õ¡Ö€ Õ°Õ¡Õ´Õ¡ÕµÕ¶Ö„Õ« Õ½Õ¿Õ¡Õ¶Õ¤Õ¡Ö€Õ¿Õ¶ Õ§ Õ¡ÕµÕ¶ÕºÕ«Õ½Õ« Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€, Õ¸Ö€ Õ¡Õ¶Õ°Õ¡Ö€Õ´Õ¡Ö€ Õ¯Õ¬Õ«Õ¶Õ« Õ¤Õ«Õ¿Õ¥Õ¬ Õ¡Õ·ÕÕ¡Õ¿Õ¡Õ¾Õ¡ÕµÖ€Õ¸Ö‚Õ´Ö‰ ÔµÕ©Õ¥ Õ¶Õ¡ÕÕ¡Õ¿Õ¥Õ½Õ¸Ö‚Õ´ Õ¥Õ½ Õ¶Õ´Õ¡Õ¶Õ¡Õ¿Õ«Õº Õ¶ÕµÕ¸Ö‚Õ©Õ¥Ö€ Õ°Õ¡Õ³Õ¡Õ Õ¤Õ¶Õ¥Õ¬, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¶Õ·Õ¥Õ¬ Õ¡ÕµÕ½ Õ¯Õ¥Õ¿Õ¨, Õ¸Ö€ÕºÕ¥Õ½Õ¦Õ« Ö„Õ¸ Õ¢Õ¸Õ¬Õ¸Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ©Õ¡Ö„ÖÕ¾Õ¥Õ¶ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ¬Ö€Õ¡Õ°Õ¸Õ½Õ¶Õ¥Ö€Õ«Ö, Õ¥Õ©Õ¥ Õ¶Ö€Õ¡Õ¶Ö„ Õ¹Õ¥Õ¶ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬ Õ¤Õ«Õ¿Õ¥Õ¬ Õ¤Ö€Õ¡Õ¶Ö„Ö‰ Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶Õ¸Ö‚Õ´ Õ¯Õ«Ö€Õ¡Õ¼Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¶Õ¡Ö‡ #Ö„Õ¨Õ ÕºÕ«Õ¿Õ¡Õ¯Õ¨Ö‰ nsfw_explanation2: "ÔµÕ©Õ¥ Õ¡ÕµÕ½ Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ¨ Ö„Õ¥Õ¦ Õ°Õ¡Ö€Õ´Õ¡Ö€ Õ¹Õ§, ÕÕ¶Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ #nsfw ÕºÕ«Õ¿Õ¡Õ¯Õ¨ Õ¡Õ´Õ¥Õ¶ Õ¡Õ¶Õ£Õ¡Õ´, Õ¥Ö€Õ¢ Õ¶Õ´Õ¡Õ¶ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´ Õ¯Õ¡Õ¶Õ¥Õ½Ö‰ (Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶Õ¸Ö‚Õ´ «նման բովանդակության» Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¸Õ¹Õ¥Õ¬ Õ¥Õ¶Ö„ Õ”Ô¸Ô½, Õ½Õ¡Õ¯Õ¡ÕµÕ¶ Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¤Õ¡ Õ¹Õ« Õ©Õ¡Ö„ÖÕ¶Õ¸Ö‚Õ´ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨, Õ¡ÕºÕ¡ ÕºÕ¥Õ¿Ö„ Õ§ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ¬Õ¡Õ¿Õ«Õ¶Õ¡Õ¿Õ¡Õ¼ ÕºÕ«Õ¿Õ¡Õ¯Õ¨, Õ¸Ö€ÕºÕ¥Õ½Õ¦Õ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ Õ«Ö€Õ¸Ö„ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ¾Õ« Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ¯Õ¸Õ²Õ´Õ«Ö Õ¸Ö€ÕºÕ¥Õ½ Õ”Ô¸Ô½)Ö‰" + public: "Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶" + settings: "Ô·Õ»Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€" update_profile: "Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Õ«Õ´ Õ§Õ»Õ¨" your_bio: "Ô¿Õ¥Õ¶Õ½Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" your_birthday: "Ô¾Õ¶Õ¶Õ¤ÕµÕ¡Õ¶ Õ¡Õ´Õ½Õ¡Õ©Õ«Õ¾" @@ -967,8 +887,6 @@ hy: your_location: "ÕˆÖ€Õ¿Õ¥ÕžÕ² Õ¥Õ½" your_name: "Ô±Õ¶Õ¸Ö‚Õ¶Õ¤" your_photo: "Õ†Õ¯Õ¡Ö€Õ¤" - your_private_profile: "Õ”Õ¸ ÖƒÕ¡Õ¯ Õ§Õ»Õ¨" - your_public_profile: "Õ”Õ¸ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ§Õ»Õ¨" your_tags: "Õ†Õ¯Õ¡Ö€Õ¡Õ£Ö€Õ«Ö€ Ö„Õ¥Õ¦ 5 Õ¢Õ¡Õ¼Õ¸Õ¾" your_tags_placeholder: "Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ #Õ¯Õ«Õ¶Õ¸ #Õ¯Õ¡Õ¿Õ¸Ö‚ #ÔµÖ€Ö‡Õ¡Õ¶" update: @@ -983,26 +901,16 @@ hy: closed: "Ô³Ö€Õ¡Õ¶ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ¥Õ¶ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ¡ÕµÕ½ ÖƒÕ¸Õ¤Õ¸Ö‚Õ´Ö‰" create: success: "Ô´Õ¸Ö‚ Õ´Õ«Õ¡ÖÕ¡Ö€ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*յի՜ն։" - edit: - cancel_my_account: "Õ‰Õ¥Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ°Õ¡Õ·Õ«Õ¾Õ½" - edit: "Õ“Õ¸ÖƒÕ¸ÕÕ¥Õ¬ %{name}-Õ¨" - leave_blank: "(Õ©Õ¸Õ² Õ¤Õ¡Õ¿Õ¡Ö€Õ¯, Õ¥Õ©Õ¥ Õ¹Õ¥Õ½ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ ÖƒÕ¸ÕÕ¥Õ¬ Õ¤Õ¡)" - password_to_confirm: "(ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ°Õ¡Ö€Õ¯Õ¡Õ¾Õ¸Ö€ Õ§ Ö„Õ¸ Õ¶Õ¥Ö€Õ¯Õ¡ÕµÕ«Õ½ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨)" - unhappy: "ÕÕÕ¸Ö‚ÕžÖ€ Õ¥Õ½" - update: "Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬" - invalid_invite: "Õ€Ö€Õ¡Õ¾Õ¥Ö€Õ« Õ°Õ²Õ¸Ö‚Õ´Õ¨, Õ¸Ö€ Õ¿Õ¾Õ¥Õ¬ Õ¥Õ½, Õ¡ÕµÕ¬Ö‡Õ½ Õ¾Õ¡Õ¾Õ¥Ö€ Õ¹Õ§Ö‰" + invalid_invite: "Õ€Ö€Õ¡Õ¾Õ¥Ö€Õ« Õ°Õ²Õ¸Ö‚Õ´Õ¨, Õ¸Ö€ Õ¿Õ¾Õ¥Õ¬ Õ¥Õ½, Õ¡ÕµÕ¬Õ¥Ö‚Õ½ Õ¾Õ¡Õ¾Õ¥Ö€ Õ¹Õ§Ö‰" new: - create_my_account: "Õտեղծե՜լ Õ«Õ´ Õ°Õ¡Õ·Õ«Õ¾Õ¨" email: "Էլ․հասÖÕ¥" enter_email: "Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ«Ö€ Õ§Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ¤" enter_password: "Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ«Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼ (Õ¡Õ¼Õ¶Õ¾Õ¡Õ¦Õ¶ Õ¾Õ¥Ö Õ¶Õ«Õ·)" enter_password_again: "Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ«Ö€ Õ¶Õ¸Ö‚ÕµÕ¶ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨" enter_username: "Ô¸Õ¶Õ¿Ö€Õ«Ö€ Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶ (Õ´Õ«Õ¡ÕµÕ¶ Õ¿Õ¡Õ¼Õ¥Ö€, Õ©Õ¾Õ¥Ö€ Ö‡ _)" - join_the_movement: "Õ„Õ«Õ¡Öի՜ր Õ·Õ¡Ö€ÕªÕ´Õ¡Õ¶Õ¨Ö‰" password: "Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼" password_confirmation: "Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´" - sign_up: "Ô³Ö€Õ¡Õ¶ÖÕ¾Õ¥Õ¬" - sign_up_message: "♥-Õ¸Õ¾ Õ¬Õ« Õ½Õ¸ÖÕ«Õ¡Õ¬Õ¡Õ¯Õ¡Õ¶ ÖÕ¡Õ¶Ö" + sign_up: "Õ€Õ¡Õ·Õ«Õ¾ Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬" submitting: "ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¾Õ¸Ö‚Õ´ է․․․" terms: "ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬Õ¸Õ¾ Õ°Õ¡Õ·Õ«Õ¾` Õ¨Õ¶Õ¤Õ¸Ö‚Õ¶Õ¸Ö‚Õ´ Õ¥Õ½ %{terms_link}Ö‰" terms_link: "Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ´Õ¡Õ¶ ÕºÕ¡ÕµÕ´Õ¡Õ¶Õ¶Õ¥Ö€Õ¨" @@ -1017,43 +925,15 @@ hy: reported_label: "<b>Ô²Õ¸Õ²Õ¸Ö„Õ¸Õ²Õ¨Õ</b> %{person}" review_link: "Õ†Õ·Õ¥Õ¬ Õ¸Ö€ÕºÕ¥Õ½ Õ½Õ¿Õ¸Ö‚Õ£Õ¾Õ¡Õ®" status: - created: "Ô²Õ¸Õ²Õ¸Ö„ Õ§ Õ½Õ¿Õ¥Õ²Õ®Õ¾Õ¥Õ¬" destroyed: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ Õ¸Õ¹Õ¶Õ¹Õ¡ÖÕ¾Õ¥Õ¬ Õ§" failed: "Ô»Õ¶Õ¹-Õ¸Ö€ Õ¢Õ¡Õ¶ Õ½ÕÕ¡Õ¬ Õ£Õ¶Õ¡Ö" - marked: "Ô²Õ¸Õ²Õ¸Ö„Õ¨ Õ¶Õ·Õ¾Õ¥Õ¬ Õ§ Õ¸Ö€ÕºÕ¥Õ½ Õ½Õ¿Õ¸Ö‚Õ£Õ¾Õ¡Õ®" title: "Ô²Õ¸Õ²Õ¸Ö„Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Õ¼Õ¸Õ¿Õ¡Õ£Õ«Ö€" - requests: - create: - sending: "ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¾Õ¸Ö‚Õ´ Õ§" - sent: "%{name}-Õ«Õ¶ Õ¡Õ¼Õ¡Õ»Õ¡Ö€Õ¯Õ¥Õ¬ Õ¥Õ½ Õ¯Õ«Õ½Õ¾Õ¥Õ¬Ö‰ Ô±Õ¼Õ¡Õ»Õ¡Ö€Õ¯Õ¤ Õ¯Õ¿Õ¥Õ½Õ¶Õ«, Õ¥Ö€Õ¢ Õ°Õ¡Õ»Õ¸Ö€Õ¤ Õ¡Õ¶Õ£Õ¡Õ´ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡* Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ«Ö‰" - destroy: - error: "ÕŠÕ¥Õ¿Ö„ Õ§ ÕÕ¸Ö‚Õ´Õ¢ Õ¨Õ¶Õ¿Ö€Õ¥Õ½Ö‰" - ignore: "Ô±Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¾Õ¡Õ® Õ¨Õ¶Õ¯Õ¥Ö€Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡ÕµÕ¿Ö‰" - success: "Ô´Õ¸Ö‚ Õ¡Ö€Õ¤Õ¥Õ¶ Õ¯Õ«Õ½Õ¾Õ¸Ö‚Õ´ Õ¥Õ½Ö‰" - helper: - new_requests: - one: "Õ†Õ¸Ö€ Õ°Õ¡ÕµÕ¿" - other: "%{count} Õ¶Õ¸Ö€ Õ°Õ¡ÕµÕ¿" - zero: "ÕˆÕ¹ Õ´Õ« Õ¶Õ¸Ö€ Õ°Õ¡ÕµÕ¿" - manage_aspect_contacts: - existing: "Õ†Õ¥Ö€Õ¯Õ¡ Õ¯Õ¡ÕºÕ¥Ö€" - manage_within: "Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¥Õ¬ Õ¯Õ¡ÕºÕ¥Ö€Õ¤" - new_request_to_person: - sent: "ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¾Õ¥Ö" reshares: comment_email_subject: "%{author}-Õ« Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ %{resharer}-Õ« Õ¿Õ¡Ö€Õ¡Õ®Õ´Õ¡Õ¶Õ¨" - create: - failure: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ Õ¿Õ¡Ö€Õ¡Õ®Õ¥Õ¬Õ«Õ½ ÕÕ¶Õ¤Õ«Ö€ Õ¡Õ¼Õ¡Õ»Õ¡ÖÕ¡Õ¾Ö‰" reshare: deleted: "Õ•Ö€Õ«Õ£Õ«Õ¶Õ¡Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ Õ»Õ¶Õ»Õ¾Õ¥Õ¬ Õ§ Õ°Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ« Õ¯Õ¸Õ²Õ´Õ«ÖÖ‰" - reshare: - one: "1 Õ¿Õ¡Ö€Õ¡Õ®Õ¸Ö‚Õ´" - other: "%{count} Õ¿Õ¡Ö€Õ¡Õ®Õ¸Ö‚Õ´" - zero: "ÕˆÕ¹ Õ´Õ« Õ¿Õ¡Ö€Õ¡Õ®Õ¸Ö‚Õ´" reshare_confirmation: "ÕÕ¡Ö€Õ¡Õ®Õ¥ÕžÕ¬ %{author}-Õ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨Ö‰" - reshare_original: "ÕÕ¡Ö€Õ¡Õ®Õ¥Õ¬ Õ¢Õ¶Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ¨" reshared_via: "ÕÕ¡Ö€Õ¡Õ®Õ¾Õ¥Õ¬ Õ§ Õ«Ö€Õ¥Õ¶Õ«Ö`" - show_original: "Õ‘Õ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬ Õ¢Õ¶Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ¨" search: "ÕˆÖ€Õ¸Õ¶Õ¸Ö‚Õ´" services: create: @@ -1065,10 +945,6 @@ hy: success: "Õ†Õ¸Ö‚ÕµÕ¶Õ¡Õ¯Õ¡Õ¶Õ¡ÖÕ¸Ö‚Õ´Õ¨ Õ¢Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² Õ»Õ¶Õ»Õ¾Õ¥ÖÖ‰" failure: error: "Ô±ÕµÕ¤ Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ´Õ«Õ¡ÖÕ¶Õ¥Õ¬Õ«Õ½ ÕÕ¶Õ¤Õ«Ö€ Õ¡Õ¼Õ¡Õ»Õ¡ÖÕ¡Õ¾Ö‰" - finder: - fetching_contacts: "Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*Õ¶ Õ¢Õ¥Ö€Õ¸Ö‚Õ´ Õ§ %{service}Õ« Ö„Õ¸ Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¶Ö‰ Õ„Õ« Ö„Õ¡Õ¶Õ« Ö€Õ¸ÕºÕ¥Õ«Ö Õ°Õ¥Õ¿ Õ¡Ö€Õ«Ö‰" - no_friends: "Õ–Õ¥ÕµÕ½Õ¢Õ¸Ö‚Ö„Õ«Ö Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€ Õ¹Õ£Õ¿Õ¶Õ¾Õ¥ÖÕ«Õ¶Ö‰" - service_friends: "%{service}Õ« Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ¨" index: connect: "Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬" disconnect: "Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬" @@ -1077,57 +953,28 @@ hy: no_services_available: "Ô±ÕµÕ½ ÖƒÕ¸Õ¤Õ« Õ¾Ö€Õ¡ Õ¸Õ¹ Õ´Õ« Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ§ Õ¯Õ¡ÕºÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰" not_logged_in: "Ô´Õ¥Õ¼Ö‡Õ½ Õ¹Õ¥Õ½ Õ´Õ«Õ¡ÖÖ€Õ¥Õ¬Ö‰" really_disconnect: "Ô±Õ¶Õ»Õ¡Õ¿Õ¥ÕžÕ¬ %{service}Õ¨Ö‰" - services_explanation: "Ô¾Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ´Õ«Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ¤Õ¥ÕºÖ„Õ¸Ö‚Õ´ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¤ Õ¡ÕµÕ¶Õ¿Õ¥Õ² Ö‡Õ½ Õ¡Õ¶Õ´Õ«Õ»Õ¡ÕºÕ¥Õ½ Õ¯Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¾Õ¥Õ¶Ö‰" - inviter: - click_link_to_accept_invitation: "Ô±Õ¶ÖÕ«Ö€ Õ¡ÕµÕ½ Õ°Õ²Õ¸Ö‚Õ´Õ¸Õ¾, Õ¸Ö€ Õ¨Õ¶Õ¤Õ¸Ö‚Õ¶Õ¥Õ½ Ö„Õ¸ Õ°Ö€Õ¡Õ¾Õ¥Ö€Õ¨" - join_me_on_diaspora: "Õ„Õ«Õ¡ÖÕ«Õ›Ö€ Õ«Õ¶Õ± Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ¸Ö‚Õ´" + services_explanation: "Ô¿Õ«Õ½Õ¾Õ¥Õ¬Õ¸Ö‚ Õ¥Ö€Ö€Õ¸Ö€Õ¤ Õ¯Õ¸Õ²Õ´Õ« Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ´Õ«Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ¤Õ¥ÕºÖ„Õ¸Ö‚Õ´ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¤ Õ¡ÕµÕ¶Õ¿Õ¥Õ² Õ¥Ö‚Õ½ Õ¡Õ¶Õ´Õ«Õ»Õ¡ÕºÕ¥Õ½ Õ¯Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¾Õ¥Õ¶Ö‰" + share_to: "Ô¿Õ«Õ½Õ¾Õ¥Õ¬ %{provider}Õ¸Ö‚Õ´" + title: "Ô¿Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¥Õ¬ Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨" provider: facebook: "Õ–Õ¥ÕµÕ½Õ¢Õ¸Ö‚Ö„" tumblr: "Ô¹Õ¡Õ´Õ¢Õ¬Õ¨Ö€" twitter: "Ô¹Õ¸Ö‚Õ«Õ©Õ¥Ö€" wordpress: "ÕˆÖ‚Õ¸Ö€Õ¤Õ“Ö€Õ¥Õ½Õ½" - remote_friend: - invite: "Õ€Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬" - not_on_diaspora: "Ô´Õ¥Õ¼ Õ¹Õ¯Õ¡ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ¸Ö‚Õ´" - resend: "Ô¿Ö€Õ¯Õ«Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬" settings: "Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€" - share_visibilites: - update: - post_hidden_and_muted: "%{name}-Õ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ Õ©Õ¡Ö„ÖÕ¾Õ¥Õ¬ Õ§, Õ«Õ½Õ¯ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Õ Õ¡Õ¶Õ»Õ¡Õ¿Õ¾Õ¥Õ¬Ö‰" - see_it_on_their_profile: "ÔµÕ©Õ¥ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ¡ÕµÕ½ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬, Õ¡ÕµÖÕ¥Õ¬Õ«Ö€ %{name}-Õ« Õ§Õ»Õ¨Ö‰" shared: - add_contact: - add_new_contact: "Õ†Õ¸Ö€ Õ´Õ¡Ö€Õ¤ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬" - create_request: "Ô³Õ¿Õ¶Õ¥Õ¬ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Ô±ÕµÔ´Õ«-Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ«Ö€ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶" - know_email: "Ô³Õ«Õ¿Õ¥Õ½ Õ¶Ö€Õ¡Õ¶Ö Õ§Õ¬. Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥ÕžÖ€Õ¨Ö‰ Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬ Õ¶Ö€Õ¡Õ¶ÖÖ‰" - your_diaspora_username_is: "Õ”Õ¸ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶ Õ§Õ %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬" mobile_row_checked: "%{name} (Õ»Õ¶Õ»Õ¥Õ¬)" mobile_row_unchecked: "%{name} (Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬)" toggle: - one: "%{count} ÕÕ¸Ö‚Õ´Õ¢" - other: "%{count} ÕÕ¸Ö‚Õ´Õ¢" + one: "%{count} ÕÕ´Õ¢Õ¸Ö‚Õ´" + other: "%{count} ÕÕ´Õ¢Õ¸Ö‚Õ´" zero: "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ " - contact_list: - all_contacts: "Ô²Õ¸Õ¬Õ¸Ö€ Õ¯Õ¡ÕºÕ¥Ö€Õ¨" - footer: - logged_in_as: "Õ€Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¸Ö‚Õ´ Õ¥Õ½ Õ¸Ö€ÕºÕ¥Õ½ %{name}" - your_aspects: "Õ”Õ¸ ÕÕ´Õ¢Õ¥Ö€Õ¨" invitations: by_email: "Ô·Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ¸Õ¾" - dont_have_now: "Ô±ÕµÕ¬Ö‡Õ½ Õ°Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬Õ¸Ö‚ Õ«Ö€Õ¡Õ¾Õ¸Ö‚Õ¶Ö„ Õ¹Õ¸Ö‚Õ¶Õ¥Õ½, Õ¢Õ¡ÕµÖ Õ·Õ¸Ö‚Õ¿Õ¸Õ¾ Õ¯Õ£Õ¡Õ¶ Õ¶Õ¸Ö€ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Ö‰" - from_facebook: "Õ–Õ¥ÕµÕ½Õ¢Õ¸Ö‚Ö„Õ«Ö" - invitations_left: "Õ´Õ¶Õ¡Ö %{count} Õ°Õ¡Õ¿" - invite_someone: "Õ€Ö€Õ¡Õ¾Õ«Ö€Õ¥Õ¬ Õ¸Ö€Ö‡Õ§ Õ´Õ¥Õ¯Õ«Õ¶" invite_your_friends: "Ô¿Õ¡Õ¶Õ¹Õ«Õ›Ö€ Õ¨Õ¶Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ«Õ¤" invites: "Õ€Ö€Õ¡Õ¾Õ¥Ö€Õ¶Õ¥Ö€" - invites_closed: "Õ†Õ¥Ö€Õ¯Õ¡ ÕºÕ¡Õ°Õ«Õ¶ Õ°Ö€Õ¡Õ¾Õ¥Ö€Õ¶Õ¥Ö€Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ¥Õ¶ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ¡ÕµÕ½ ÖƒÕ¸Õ¤Õ¸Ö‚Õ´Ö‰" share_this: "ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ«Ö€ Õ¡ÕµÕ½ Õ°Õ²Õ¸Ö‚Õ´Õ¨ Õ§Õ¬.ÖƒÕ¸Õ½Õ¿Õ«, Õ¢Õ¬Õ¸Õ£Õ« Õ¯Õ¡Õ´ Õ¡ÕµÕ¬ Õ½Õ¸ÖÕ«Õ¡Õ¬Õ¡Õ¯Õ¡Õ¶ ÖÕ¡Õ¶ÖÕ¥Ö€Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾Ö‰" - notification: - new: "Õ†Õ¸Ö€ %{type} %{from}-Õ«Ö" public_explain: atom_feed: "Ô±Õ¿Õ¸Õ´ Õ°Õ¸Õ½Ö„Õ¨" control_your_audience: "ÕŽÕ¥Ö€Õ¡Õ°Õ½Õ¯Õ«Õ›Ö€ Õ¬Õ½Õ¡Ö€Õ¡Õ¶Õ¤" @@ -1139,12 +986,9 @@ hy: title: "Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¥Õ¬ Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨" visibility_dropdown: "Ô±ÕµÕ½Õ¿Õ¥Õ² Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬ Ö„Õ¸ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ«Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ (ÕÕ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¯Õ¿Õ¡Õ¶Ö„Õ Õ¡ÕµÕ½ Õ¡Õ¼Õ¡Õ»Õ«Õ¶Õ¨ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶ Õ¶Õ·Õ¥Õ½)Ö‰" publisher: - all: "Ô²Õ¸Õ¬Õ¸Ö€Õ¨" - all_contacts: "Ô²Õ¸Õ¬Õ¸Ö€ Õ¯Õ¡ÕºÕ¥Ö€Õ«Õ¶" discard_post: "Õ‰Õ¥Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨" formatWithMarkdown: "Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ %{markdown_link}` Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¤ Õ±Ö‡Õ¡Õ¾Õ¸Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€" get_location: "ÕŠÕ¡Ö€Õ¦Õ¥Õ¬ Ö„Õ¸ Õ¿Õ¥Õ²Õ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨" - make_public: "Ô´Õ¡Ö€Õ±Õ¶Õ¥Õ¬ Õ°Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶" new_user_prefill: hello: "Ողջո՜ւյն, ÕªÕ¸Õ²Õ¸Õ¾Õ¸Ö‚Ö€Õ¤, #%{new_user_tag}Ö‰ " i_like: "Ô»Õ´ Õ°Õ¥Õ¿Õ¡Ö„Ö€Ö„Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¶ Õ¥Õ¶Õ %{tags}Ö‰ " @@ -1152,36 +996,14 @@ hy: newhere: "ÔµÕ½Õ†Õ¸Ö€Õ¥Õ¯ÔµÕ´" poll: add_a_poll: "Õ€Õ¡Ö€ÖÕ¸Ö‚Õ´ Õ¡Õ¶Õ¥Õ¬" - add_poll_answer: "ÕÕ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬" - option: "ÕÕ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯ 1" - question: "Õ€Õ¡Ö€Ö" - remove_poll_answer: "Õ‹Õ¶Õ»Õ¥Õ¬ Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ¨" - post_a_message_to: "Ô³Ö€Õ¡Õ¼Õ¥Õ¬ %{aspect} ÕÕ´Õ¢Õ« Õ°Õ¡Õ´Õ¡Ö€" posting: "Ô³Ö€Õ¡Õ¼Õ¾Õ¸Ö‚Õ´ Õ§..." - preview: "Õ†Õ¡ÕÕ¡Õ¤Õ«Õ¿Õ¥Õ¬" - publishing_to: "Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¾Õ¸Ö‚Õ´ Õ§ Õ¤Õ¥ÕºÕ«`  " remove_location: "Õ‹Õ¶Õ»Õ¥Õ¬ Õ¿Õ¥Õ²Õ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨" share: "Ô¿Õ«Õ½Õ¾Õ¥Õ¬" - share_with: "Ô¿Õ«Õ½Õ¾Õ¥Õ¬" upload_photos: "Õ†Õ¯Õ¡Ö€Õ¶Õ¥Ö€ Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬" whats_on_your_mind: "Ô»ÕžÕ¶Õ¹ Õ¯Õ¡ Õ´Õ¿Ö„Õ«Õ¤Ö‰" - reshare: - reshare: "ÕÕ¡Ö€Õ¡Õ®Õ¥Õ¬" stream_element: - connect_to_comment: "ÕÕ¯Õ½Õ«Ö€ Õ¯Õ«Õ½Õ¾Õ¥Õ¬ Õ¡ÕµÕ½ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ°Õ¥Õ¿, Õ¸Ö€ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¥Õ½ Õ¶Ö€Õ¡ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨" - currently_unavailable: "Õ„Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ´Õ¨ Õ¡ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ§" - dislike: "Õ‰Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬" - hide_and_mute: "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Ö‡ Õ¡Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨" - ignore_user: "Ô±Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬ %{name}-Õ«Õ¶" - ignore_user_description: "Ô±Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¶ Õ¸Ö‚ Õ»Õ¶Õ»Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ ÕÕ´Õ¢Õ¥Ö€Õ«ÕžÖÖ‰" - like: "Õ€Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬" - nsfw: "Ô±ÕµÕ½ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ Õ¶Õ·Õ¾Õ¥Õ¬ Õ§ Õ¸Ö€ÕºÕ¥Õ½ Õ”Ô¸Ô½ Õ°Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ« Õ¯Õ¸Õ²Õ´Õ«Ö. %{link}" - shared_with: "Ô¿Õ«Õ½Õ¾Õ¥Õ¬ Õ§ %{aspect_names} ÕÕ´Õ¢Õ¥Ö€Õ« Õ°Õ¥Õ¿" - show: "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬" - unlike: "Ô±ÕºÕ¡Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬" via: "Ô·Õ½Õ¿Õ¥Õ²Õ«Ö` %{link}" via_mobile: "Õ€Õ¥Õ¼Õ¡ÕÕ¸Õ½Õ«Ö" - viewable_to_anyone: "Ô±ÕµÕ½ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§ Õ°Õ¡Õ´Õ¡ÖÕ¡Õ¶ÖÕ¸Ö‚Õ´ Õ¡Õ´Õ¥Õ¶Ö„Õ«Õ¶" simple_captcha: label: "Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ«Ö€ Õ®Õ¡Õ®Õ¯Õ¡Õ£Õ«Ö€Õ¨." message: @@ -1207,21 +1029,12 @@ hy: status_messages: create: success: "Ô²Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² Õ¶Õ·Õ¾Õ¥Ö(Õ«Õ¶)` %{names}" - destroy: - failure: "Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ»Õ¶Õ»Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨Ö‰" - helper: - no_message_to_display: "Õ†Õ¡Õ´Õ¡Õ¯Õ¶Õ¥Ö€ Õ¹Õ¯Õ¡Õ¶ ÖÕ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰" new: mentioning: "Õ†Õ·Õ¸Ö‚Õ´ Õ¥Õ½ %{person}-Õ«Õ¶" too_long: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¤ Õ¹ÕºÕ¥Õ¿Ö„ Õ§ Õ£Õ¥Ö€Õ¡Õ¦Õ¡Õ¶ÖÕ« %{count} Õ¶Õ«Õ·Õ¨Ö‰ Ô±ÕµÕ¶ Õ¡ÕµÕªÕ´ %{current_length} Õ¶Õ«Õ·Õ«Ö Õ§ Õ¢Õ¡Õ²Õ¯Õ¡ÖÕ¡Õ®Ö‰" stream_helper: - hide_comments: "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨" no_more_posts: "Õ€Õ¡Õ½Õ¡Ö€ Õ¬Ö€Õ¡Õ°Õ¸Õ½Õ« Õ¾Õ¥Ö€Õ»Õ«Õ¶Ö‰" no_posts_yet: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ¤Õ¥Õ¼ Õ¹Õ¯Õ¡Õ¶Ö‰" - show_comments: - one: "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Ö‡Õ½ Õ´Õ¥Õ¯ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - other: "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Ö‡Õ½ %{count} Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" - zero: "Ô±ÕµÕ¬Ö‡Õ½ Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ¯Õ¡" streams: activity: title: "Ô»Õ´ Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¶Õ¥Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨" @@ -1248,13 +1061,6 @@ hy: tags: title: "%{tags} ÕºÕ«Õ¿Õ¡Õ¯Õ¸Õ¾ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨" tag_followings: - create: - failure: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ°Õ¥Õ¿Ö‡Õ¥Õ¬ #%{name} պիտակը։  ԳուÖÕ¥ Õ¡Ö€Õ¤Õ¥Õ¶ Õ°Õ¥Õ¿Ö‡Õ¸ÕžÖ‚Õ´ Õ¥Õ½ Õ¤Ö€Õ¡Õ¶Ö‰" - none: "Õ‰Õ¥Õ½ Õ¯Õ¡Ö€Õ¸Õ² Õ¤Õ¡Õ¿Õ¡Ö€Õ¯ ÕºÕ«Õ¿Õ¡Õ¯ Õ°Õ¥Õ¿Ö‡Õ¥Õ¬Ö‰" - success: "Հեհեե՜յ։ ÕÕ¯Õ½Õ¥ÖÕ«Ö€ Õ°Õ¥Õ¿Ö‡Õ¥Õ¬ #%{name} ÕºÕ«Õ¿Õ¡Õ¯Õ¨Ö‰" - destroy: - failure: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ¤Õ¡Õ¤Õ¡Ö€Õ¥Õ¬ Õ°Õ¥Õ¿Ö‡Õ¥Õ¬ #%{name} ÕºÕ«Õ¿Õ¡Õ¯Õ¨Ö‰ Ô³Õ¸Ö‚ÖÕ¥ Õ¡Ö€Õ¤Õ¥Õ¶ Õ¤Õ¡Õ¤Õ¡Ö€Õ¥ÕžÕ¬ Õ¥Õ½ Õ°Õ¥Õ¿Ö‡Õ¥Õ¬ Õ¤Ö€Õ¡Õ¶Ö‰" - success: "ÕÕ¡Õ¿Õ¡Õ¶Õ¡Õ¶ տանի՜։ Ô´Õ¸Ö‚ Õ¡ÕµÕ¬Ö‡Õ½ Õ¹Õ¥Õ½ Õ°Õ¥Õ¿Ö‡Õ¸Ö‚Õ´ #%{name} ÕºÕ«Õ¿Õ¡Õ¯Õ¨Ö‰" manage: no_tags: "ÕˆÕ¹ Õ´Õ« ÕºÕ«Õ¿Õ¡Õ¯Õ« Õ¹Õ¥Õ½ Õ°Õ¥Õ¿Ö‡Õ¸Ö‚Õ´Ö‰" title: "Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¥Õ¬ Õ°Õ¥Õ¿Ö‡Õ¾Õ¸Õ² ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ¨" @@ -1262,15 +1068,12 @@ hy: name_too_long: "ÕŠÕ«Õ¿Õ¡Õ¯Õ«Õ¤ Õ¡Õ¶Õ¾Õ¡Õ¶Õ¸Ö‚Õ´Õ¨ Õ¯Ö€Õ³Õ¡Õ¿Õ«Ö€ Õ´Õ«Õ¶Õ¹Ö‡ Õ¡Õ¼Õ¡Õ¾Õ¥Õ¬Õ¡Õ£Õ¸Ö‚ÕµÕ¶Õ¨ %{count} Õ¶Õ«Õ· (Õ¡ÕµÕªÕ´ Õ¡ÕµÕ¶ %{current_length}-Õ«Ö Õ§ Õ¢Õ¡Õ²Õ¯Õ¡ÖÕ¡Õ®)Ö‰" show: follow: "Õ€Õ¥Õ¿Ö‡Õ¥Õ¬ #%{tag}" - following: "Õ€Õ¥Õ¿Ö‡Õ¸Ö‚Õ´ Õ¥Õ½ #%{tag}" none: "Ô´Õ¡Õ¿Õ¡Ö€Õ¯ ÕºÕ«Õ¿Õ¡Õ¯ Õ£Õ¸ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ«Ö‰" stop_following: "Ô´Õ¡Õ¤Õ¡Ö€Õ¥Õ¬ Õ°Õ¥Õ¿Ö‡Õ¥Õ¬ #%{tag}" tagged_people: one: "Õ„Õ« Õ°Õ¸Õ£Õ« %{tag} ÕºÕ«Õ¿Õ¡Õ¯Õ¸Õ¾" other: "%{count} Õ°Õ¸Õ£Õ« %{tag} ÕºÕ«Õ¿Õ¡Õ¯Õ¸Õ¾" zero: "ÕˆÕ¹ Õ¸Ö„ Õ¹Õ¯Õ¡ %{tag} ÕºÕ«Õ¿Õ¡Õ¯Õ¸Õ¾" - terms_and_conditions: "ÕŠÕ¡ÕµÕ´Õ¡Õ¶Õ¶Õ¥Ö€ Õ¸Ö‚ Õ¤Ö€Õ¸Ö‚ÕµÕ©Õ¶Õ¥Ö€" - undo: "Õ‰Õ¥Õ²Õ¡Ö€Õ¯Õ¥ÕžÕ¬" username: "Õ•Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶" users: confirm_email: @@ -1285,13 +1088,13 @@ hy: auto_follow_aspect: "Ô½Õ¸Ö‚Õ´Õ¢Õ¨, Õ¸Ö€Õ¿Õ¥Õ² Õ¯Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¾Õ¥Õ¶ Õ¾Õ¥Ö€Õ»Õ«Õ¶Õ¶Õ¥Ö€Õ½`" auto_follow_back: "Ô±Õ¶Õ´Õ«Õ»Õ¡ÕºÕ¥Õ½ Õ¯Õ«Õ½Õ¾Õ¥Õ¬ Õ¶Ö€Õ¡Õ¶Ö Õ°Õ¥Õ¿, Õ¸Õ¾ Õ½Õ¯Õ½Õ¥Ö Õ¯Õ«Õ½Õ¾Õ¥Õ¬ Ö„Õ¸ Õ°Õ¥Õ¿" change: "Õ“Õ¸ÕÕ¥Õ¬" + change_color_theme: "Õ“Õ¸ÕÕ¥Õ¬ Õ£Õ¸Ö‚Õ¶Õ¡ÕµÕ«Õ¶ Õ©Õ¥Õ´Õ¡Õ¶" change_email: "Õ“Õ¸ÕÕ¥Õ¬ Õ§Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ¶" change_language: "Õ“Õ¸ÕÕ¥Õ¬ Õ¬Õ¥Õ¦Õ¸Ö‚Õ¶" change_password: "Õ“Õ¸ÕÕ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨" character_minimum_expl: "Õ¡Õ¼Õ¶Õ¾Õ¡Õ¦Õ¶ Õ¾Õ¥Ö Õ¶Õ«Õ·" close_account: dont_go: "Հեե՜յ, Õ´Õ« Õ°Õ¥Õ¼Õ¡ÖÕ«Ö€, Õ¡ÕµÕ½Õ¿Õ¥Õ² Õ¬Õ¡Õ¾ Õ§Ö‰" - if_you_want_this: "ÔµÕ©Õ¥ Õ«Ö€Õ¸Ö„ Õ¾Õ½Õ¿Õ¡Õ° Õ¥Õ½, Õ¡ÕºÕ¡ Õ½Õ¿Õ¸Ö€Ö‡ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ«Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¤ Ö‡ Õ½Õ¥Õ²Õ´Õ«Ö€ «Փակել հաշիվը»" lock_username: "Õ†Õ¥Ö€Õ¯Õ¡ÕµÕ«Õ½ Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶Õ¤ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¥Õ¬Õ¸Ö‚ Õ§Ö‰ Õ€Õ¥Õ¿Õ¡Õ£Õ¡ÕµÕ¸Ö‚Õ´ Õ¹Õ¥Õ½ Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡ Õ¡ÕµÕ½ ÖƒÕ¸Õ¤Õ¸Ö‚Õ´ Õ¶Õ¸Ö€ Õ°Õ¡Õ·Õ«Õ¾ Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ¡ÕµÕ¤ Õ¶Õ¸Ö‚ÕµÕ¶ Ô±ÕµÔ´Õ«-Õ¸Õ¾Ö‰" locked_out: "Õ„Õ«Õ¶Õ¹ Õ´Õ¥Õ¶Ö„ Õ¯Õ»Õ¶Õ»Õ¥Õ¶Ö„ Õ°Õ¡Õ·Õ«Õ¾Õ¤ Õ¡ÕµÕ¶ Õ¡ÕµÕ¬Ö‡Õ½ Ö„Õ¥Õ¦ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ« Õ¬Õ«Õ¶Õ«Ö‰" make_diaspora_better: "Ô¿Õ¸Ö‚Õ¦Õ¥Õ¶Õ¡ÕµÕ«Õ¶Ö„, Õ¸Ö€ Õ´Õ¶Õ¡ÕµÕ«Ö€ Õ¸Ö‚ Ö…Õ£Õ¶Õ¥Õ«Ö€ Õ´Õ¥Õ¦ Õ¤Õ¡Ö€Õ±Õ¶Õ¥Õ¬ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*Õ¶ Õ¡Õ¾Õ¥Õ¬Õ« Õ¬Õ¡Õ¾Õ¨Ö‰ Ô²Õ¡ÕµÖ Õ¥Õ©Õ¥ Õ¸Ö€Õ¸Õ·Õ¥Õ¬ Õ¥Õ½ Õ£Õ¶Õ¡Õ¬, Õ¡ÕºÕ¡ Õ®Õ¡Õ¶Õ¸Õ©Õ¡ÖÕ«Ö€, Õ©Õ¥ Õ«Õ¶Õ¹ Õ¯Õ¬Õ«Õ¶Õ« Õ¤Ö€Õ¡ Õ¡Ö€Õ¤ÕµÕ¸Ö‚Õ¶Ö„Õ¸Ö‚Õ´Õ" @@ -1304,14 +1107,12 @@ hy: current_password_expl: "Õ¸Ö€Õ¸Õ¾ Õ´Õ¸Ö‚Õ¿Ö„ Õ¥Õ½ Õ£Õ¸Ö€Õ®Õ¥Õ¬..." download_export: "Õ†Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ«Õ´ Õ§Õ»Õ¨" download_export_photos: "Õ†Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ«Õ´ Õ¶Õ¯Õ¡Ö€Õ¶Õ¥Ö€Õ¨" - download_photos: "Õ†Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ«Õ´ Õ¶Õ¯Õ¡Ö€Õ¶Õ¥Ö€Õ¨" edit_account: "Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥Õ¬ Õ°Õ¡Õ·Õ«Õ¾Õ¨" email_awaiting_confirmation: "Õ„Õ¥Õ¶Ö„ Õ¡Õ¯Õ¿Õ«Õ¾Õ¡ÖÕ´Õ¡Õ¶ Õ°Õ²Õ¸Ö‚Õ´ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥ÖÕ«Õ¶Ö„ %{unconfirmed_email} Õ§Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ«Õ¶Ö‰ Ô²Õ¡ÕµÖ Õ´Õ«Õ¶Õ¹ Õ¤Õ¸Ö‚ Õ¯Õ¡Õ¶ÖÕ¶Õ¥Õ½ Õ¡ÕµÕ¤ Õ°Õ²Õ´Õ¡Õ´Õ¢ Õ¸Ö‚ Õ¯Õ¡Õ¯Õ¿Õ«Õ¾Õ¡ÖÕ¶Õ¥Õ½ Õ¡ÕµÕ¶, Õ´Õ¥Õ¶Ö„ Õ¯Õ·Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¶Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Ö„Õ¸ Õ½Õ¯Õ¦Õ¢Õ¶Õ¡Õ¯Õ¡Õ¶Õ %{email} Õ§Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ¶Ö‰" export_data: "ÕÕ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¤Õ¸Ö‚Ö€Õ½ Õ¢Õ¥Ö€Õ¸Ö‚Õ´" export_in_progress: "Ô·Õ½ ÕºÕ¡Õ°Õ«Õ¶ Õ´Õ·Õ¡Õ¯Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Ö„Õ¸ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Õ„Õ« Ö„Õ¡Õ¶Õ« Ö€Õ¸ÕºÕ¥Õ«Ö Õ°Õ¥Õ¿ Õ¡Ö€Õ«Ö‰" export_photos_in_progress: "Ô·Õ½ ÕºÕ¡Õ°Õ«Õ¶ Õ´Õ·Õ¡Õ¯Õ¸Ö‚Õ´ Õ¥Õ¶Ö„ Ö„Õ¸ Õ¶Õ¯Õ¡Ö€Õ¶Õ¥Ö€Õ¨Ö‰ Õ„Õ« Ö„Õ¡Õ¶Õ« Ö€Õ¸ÕºÕ¥Õ«Ö Õ°Õ¥Õ¿ Õ¡Ö€Õ«Ö‰" following: "Ô¿Õ«Õ½Õ¾Õ¥Õ¬Õ¸Ö‚ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€" - getting_started: "Õ†Õ¸Ö€ Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ« Õ¶Õ¡ÕÕ¨Õ¶Õ¿Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€" last_exported_at: "(ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ¡Õ¶Õ£Õ¡Õ´ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¾Õ¥Õ¬ Õ§ %{timestamp}ÖŠÕ«Õ¶)" liked: "Õ¸Ö€Ö‡Õ§ Õ´Õ¥Õ¯Õ¨ Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬ Õ§ Ö„Õ¸ Õ£Ö€Õ¡Õ¼Õ¸ÕžÖ‚Õ´Õ¨Ö‰" mentioned: "Ö„Õ¥Õ¦ Õ¶Õ·Õ¥Õ¬ Õ¥Õ¶ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶ Õ´Õ¥ÕžÕ»Ö‰" @@ -1338,19 +1139,20 @@ hy: connect_to_facebook_link: "Õ´Õ«Õ¡ÖÕ¶Õ¥Õ¬Õ¸Õ¾ Õ–Õ¥ÕµÕ½Õ¢Õ¸Ö‚Ö„ÕµÕ¡Õ¶ Õ°Õ¡Õ·Õ«Õ¾Õ¤" hashtag_explanation: "ÕŠÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€Õ¨ Õ©Õ¸Ö‚ÕµÕ¬ Õ¥Õ¶ Õ¿Õ¡Õ¬Õ«Õ½ ÕÕ¸Õ½Õ¥Õ¬ Ö„Õ¸ Õ°Õ¥Õ¿Õ¡Ö„Ö€Ö„Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« Õ´Õ¡Õ½Õ«Õ¶ Õ¸Ö‚ Õ°Õ¥Õ¿Ö‡Õ¥Õ¬ Õ¤Ö€Õ¡Õ¶Ö։  Ինչպես Õ¶Õ¡Ö‡ Õ·Õ¡Õ¿ Õ°Õ¡Ö€Õ´Õ¡Ö€ Õ¸Ö‚ Õ°Õ¡Õ¾Õ¥Õ½ Õ´Õ«Õ»Õ¸Ö Õ¥Õ¶ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ¸Ö‚Õ´ Õ¶Õ¸Ö€ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö Õ£Õ¿Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰" hashtag_suggestions: "Ô¿Õ¡Ö€Õ¥Õ² Õ¥Õ½ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬ ÕºÕ«Õ¿Õ¡Õ¯Õ¶Õ¥Ö€, Õ«Õ¶Õ¹ÕºÕ«Õ½Õ«Ö„ Õ¥Õ¶, Ö…Ö€Õ«Õ¶Õ¡Õ¯, #Õ¡Ö€Õ¾Õ¥Õ½Õ¿ #Õ¯Õ«Õ¶Õ¸ #gif Ö‡ Õ¡ÕµÕ¬Õ¶Ö‰" - saved: "ÕŠÕ¡Õ°Õ¾Õ¡Õ® Õ§" well_hello_there: "Ô´Õ¥ Õ«Õ¶Õ¹, ողջո՜ւյն" what_are_you_in_to: "Ô»Õ¶Õ¹Õ¸ÕžÕ¾ Õ¥Õ½ Õ°Õ¥Õ¿Õ¡Ö„Ö€Ö„Ö€Õ¾Õ¡Õ®" who_are_you: "ÕˆÕžÕ¾ Õ¥Õ½ Õ¤Õ¸Ö‚" privacy_settings: ignored_users: "Ô±Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¾Õ¡Õ® Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¥Ö€" no_user_ignored_message: "Ô´Õ¥Õ¼Ö‡Õ½ Õ¸Õ¹ Õ´Õ¥Õ¯Õ« Õ¹Õ¥Õ½ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¸Ö‚Õ´Ö‰" - stop_ignoring: "Õ¤Õ¡Õ¤Õ¡Ö€Õ¥Õ¬ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬" + stop_ignoring: "Ô´Õ¡Õ¤Õ¡Ö€Õ¥Õ¬ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬" strip_exif: "Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ¾Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¾Õ¡Õ® Õ¶Õ¯Õ¡Ö€Õ¶Õ¥Ö€Õ«Ö Õ´Õ¥Õ¿Õ¡Õ¤Õ¡Õ¿Õ¡Õ¶, Õ«Õ¶Õ¹ÕºÕ¥Õ½ Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ Õ¿Õ¥Õ²Õ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨, Õ°Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ«Õ¶, Õ¿Õ¥Õ½Õ¡ÕÖÕ«Õ¯Õ« Õ´Õ¸Õ¤Õ¥Õ¬Õ¨ (ÕÕ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ§ Õ¿Ö€Õ¾Õ¸Ö‚Õ´)" title: "Ô³Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€" public: does_not_exist: "%{username} Ö…Õ£Õ¿Õ¡Õ¿Õ¥Ö€Õ¨ Õ£Õ¸ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ¸Ö‚Õ¶Õ«Ö‰" update: + color_theme_changed: "Ô³Õ¸Ö‚Õ¶Õ¡ÕµÕ«Õ¶ Õ©Õ¥Õ´Õ¡Õ¶ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ ÖƒÕ¸ÕÕ¾Õ¥ÖÖ‰" + color_theme_not_changed: "Ô»Õ¶Õ¹ÖŠÕ¸Ö€ ÕÕ¶Õ¤Õ«Ö€ Õ¥Õ²Õ¡Õ¾ Õ£Õ¸Ö‚Õ¶Õ¡ÕµÕ«Õ¶ Õ©Õ¥Õ´Õ¡Õ¶ ÖƒÕ¸ÕÕ¥Õ¬Õ«Õ½Ö‰" email_notifications_changed: "Էլ․հասÖÕ¥Õ«Õ¶ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ ÖƒÕ¸ÕÕ¾Õ¡Õ® Õ¥Õ¶" follow_settings_changed: "Õ€Õ¥Õ¿Ö‡Õ¥Õ¬Õ¸Ö‚ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ ÖƒÕ¸ÕÕ¾Õ¡Õ® Õ¥Õ¶" follow_settings_not_changed: "Õ€Õ¥Õ¿Ö‡Õ¥Õ¬Õ¸Ö‚ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ´Õ¨ Õ±Õ¡ÕÕ¸Õ²Õ¾Õ¥Ö" @@ -1362,13 +1164,6 @@ hy: settings_updated: "Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¾Õ¥ÖÕ«Õ¶" unconfirmed_email_changed: "Ô·Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ¶ ÖƒÕ¸ÕÕ¾Õ¡Õ® Õ§ Ö‡ Õ¡Õ¯Õ¿Õ«Õ¾Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ¯Õ¡Ö€Õ«Ö„ Õ¸Ö‚Õ¶Õ«" unconfirmed_email_not_changed: "Ô·Õ¬.Õ°Õ¡Õ½ÖÕ¥Õ« ÖƒÕ¸ÖƒÕ¸ÕÕ¸Ö‚Õ´Õ¨ Õ±Õ¡ÕÕ¸Õ²Õ¾Õ¥Ö" - webfinger: - fetch_failed: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ¾Õ¥Õ¢Ö†Õ«Õ¶Õ£Õ¥Ö€Õ« Õ§Õ» Õ½Õ¿Õ¡Õ¶Õ¡Õ¬ %{profile_url}-Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰" - hcard_fetch_failed: "%{account} Õ°Õ¡Õ·Õ¾Õ« Õ§ÕµÕ¹Ö„Õ¡Ö€Õ¤Õ¨ Õ½Õ¿Õ¡Õ¶Õ¡Õ¬Õ«Õ½ ÕÕ¶Õ¤Õ«Ö€ Õ¡Õ¼Õ¡Õ»Õ¡ÖÕ¡Õ¾Ö‰" - no_person_constructed: "Ô±ÕµÕ½ Õ§ÕµÕ¹Ö„Õ¡Ö€Õ¤Õ«Ö Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ§ Õ´Õ¡Ö€Õ¤ Õ±Ö‡Õ¡Õ¾Õ¸Ö€Õ¥Õ¬Ö‰" - not_enabled: "Ô¿Õ¡Ö€Õ®Õ¥Õ½` %{account}-Õ« ÕÕ¶Õ¡Õ´Õ¸Ö€Õ¤Õ« Õ°Õ¡Õ´Õ¡Ö€ Õ¾Õ¥Õ¢Ö†Õ«Õ¶Õ£Õ¥Ö€Õ¨ Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ¹Õ§Ö‰" - xrd_fetch_failed: "%{account} Õ°Õ¡Õ·Õ¾Õ«Ö Õ«Ö„Õ½Õ¡Õ¼Õ¤Õ«Õ¶ Õ½Õ¿Õ¡Õ¶Õ¡Õ¬Õ«Õ½ Õ½ÕÕ¡Õ¬ Õ¥Õ²Õ¡Õ¾Ö‰" - welcome: "Ô²Õ¡Ö€Õ« գալու՜ստ" will_paginate: next_label: "Õ°Õ¡Õ»Õ¸Ö€Õ¤ »" previous_label: "« Õ¶Õ¡ÕÕ¸Ö€Õ¤" \ No newline at end of file diff --git a/config/locales/diaspora/ia.yml b/config/locales/diaspora/ia.yml index 266a53c22dac48dfdbb4ca36bc9849ceee11e456..998d20ba0145c1dcf85bf6d082de1d2e359b971b 100644 --- a/config/locales/diaspora/ia.yml +++ b/config/locales/diaspora/ia.yml @@ -6,11 +6,8 @@ ia: _applications: "Applicationes" - _comments: "Commentos" _contacts: "Contactos" _help: "Adjuta" - _home: "Initio" - _photos: "photos" _services: "Servicios" _statistics: "Statisticas" _terms: "terminos" @@ -53,12 +50,19 @@ ia: taken: "es jam in uso." admins: admin_bar: + dashboard: "Pannello de instrumentos" pages: "Paginas" + pod_network: "Rete de pods" pod_stats: "Statisticas de pod" report: "Reportos" sidekiq_monitor: "Monitor Sidekiq" user_search: "Recerca de usatores" weekly_user_stats: "Statisticas septimanal de usatores" + dashboard: + fetching_diaspora_version: "Determina ultime version de diaspora*..." + pod_status: "Stato del pod" + pods: + pod_network: "Rete de pods" stats: 2weeks: "2 Septimana" 50_most: "Le 50 etiquettas le plus popular" @@ -93,7 +97,9 @@ ia: are_you_sure_unlock_account: "Es tu secur de voler disblocar iste conto?" close_account: "clauder conto" email_to: "Adresse de e-mail a invitar" + lock_account: "Blocar conto" under_13: "Monstrar usatores con minus de 13 annos (COPPA)" + unlock_account: "Disblocar conto" view_profile: "vider profilo" you_currently: one: "il te resta un invitation %{link}" @@ -105,13 +111,45 @@ ia: other: "Numero de nove usatores iste septimana: %{count}" zero: "Numero de nove usatores iste septimana: zero" current_server: "Le data actual del servitor es %{date}" - ago: "%{time} retro" all_aspects: "Tote le aspectos" - application: - helper: - unknown_person: "persona incognite" - video_title: - unknown: "Titulo de video incognite" + api: + openid_connect: + authorizations: + destroy: + fail: "Le tentativa de revocar le autorisation con ID %{id} ha fallite" + new: + access: "%{name} demanda accesso a:" + approve: "Approbar" + bad_request: "ID de cliente o URI de redirection mancante" + client_id_not_found: "Nulle cliente con client_id %{client_id} con URI de redirection %{redirect_uri} trovate" + deny: "Refusar" + no_requirement: "%{name} non require permissiones" + redirection_message: "Es tu secur de voler dar accesso a %{redirect_uri}?" + error_page: + contact_developer: "Per favor, contacta le programmator del application e include tote le message de error sequente:" + could_not_authorize: "Le application non poteva esser autorisate" + login_required: "Tu debe aperir session ante de poter autorisar iste application" + title: "Un problema ha occurrite." + scopes: + openid: + description: "Isto permitte que le application lege tu profilo basic" + name: "profilo basic" + read: + description: "Isto permitte que le application lege tu fluxo, tu conversationes e tu profilo complete" + name: "leger profilo, fluxo e conversationes" + write: + description: "Isto permitte que le application publica nove entratas, scribe conversationes e invia reactiones" + name: "inviar entratas, conversationes e reactiones" + user_applications: + index: + access: "%{name} ha accesso a:" + edit_applications: "Applicationes" + no_requirement: "%{name} non require permissiones" + title: "Applicationes autorisate" + no_applications: "Tu non ha applicationes autorisate" + policy: "Vider le politica de confidentialitate del application" + revoke_autorization: "Revocar" + tos: "Vider le conditiones de servicio del application" are_you_sure: "Es tu secur?" are_you_sure_delete_account: "Es tu secur de voler clauder tu conto? Isto non pote esser disfacite!" aspect_memberships: @@ -127,48 +165,27 @@ ia: success: "Le contacto ha essite addite al aspecto con successo." aspect_listings: add_an_aspect: "+ Adder un aspecto" - deselect_all: "Deseliger totes" - edit_aspect: "Modificar %{name}" - select_all: "Seliger totes" aspect_stream: make_something: "Crea qualcosa" stay_updated: "Tene te al currente" stay_updated_explanation: "Le fluxo principal es plenate con tote le contactos tue, le etiquettas que tu seque, e messages de alcun membros creative del communitate." - contacts_not_visible: "Le contactos in iste aspecto non potera vider le unes le alteres." - contacts_visible: "Le contactos in iste aspecto potera vider le unes le alteres." - create: - failure: "Le creation del aspecto ha fallite." - success: "Tu nove aspecto %{name} ha essite create" destroy: failure: "%{name} non es vacue e non pote esser removite." success: "%{name} ha essite removite con successo." success_auto_follow_back: "%{name} ha essite removite con successo. Tu ha usate iste aspecto pro automaticamente sequer le usatores que te seque. Verifica tu configuration de usator pro seliger un nove aspecto pro reciprocation automatic de sequimento." edit: - aspect_chat_is_enabled: "Le contactos in iste aspecto pote chattar con te." - aspect_chat_is_not_enabled: "Le contactos in iste aspecto non pote chattar con te." aspect_list_is_not_visible: "Le contactos in iste aspecto non pote vider le un le altere." aspect_list_is_visible: "Le contactos in iste aspecto pote vider le un le altere." confirm_remove_aspect: "Es tu secur de voler deler iste aspecto?" - grant_contacts_chat_privilege: "Conceder le privilegio de chat al contactos in iste aspecto?" - make_aspect_list_visible: "render contactos in iste aspecto visibile le unes pro le alteres?" - remove_aspect: "Deler iste aspecto" rename: "renominar" - set_visibility: "Definir visibilitate" update: "actualisar" updating: "actualisation in curso" index: - diaspora_id: - content_1: "Tu ID de diaspora* es:" - content_2: "Da lo a alteres e illes potera trovar te in diaspora*." - heading: "ID de diaspora*" donate: "Donar" - handle_explanation: "Isto es tu ID de diaspora*. Como un adresse de e-mail, tu pote dar isto a alteres a fin que illes pote attinger te." help: any_problem: "Problema?" contact_podmin: "Contacta le administrator de tu pod!" do_you: "Esque tu:" - email_feedback: "%{link} tu commentario, si tu lo prefere" - email_link: "E-mail" feature_suggestion: "... ha un suggestion de %{link}?" find_a_bug: "... ha trovate un %{link}?" have_a_question: "... ha un %{link}?" @@ -181,31 +198,21 @@ ia: tutorial_link_text: "Tutoriales" tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: Adjuta pro le prime passos." introduce_yourself: "Iste fluxo es le tue. Non hesita… presenta te!" - keep_diaspora_running: "Mantene le disveloppamento de diaspora* rapide con un donation mensual!" keep_pod_running: "Adjuta al mantenentia e melioration de %{pod} (e al caffeination de su gerentes) con un donation mensual!" new_here: follow: "Seque %{link} e saluta nove usatores in diaspora*!" learn_more: "Leger plus" title: "Accolliger nove usatores" - no_contacts: "Nulle contacto" - no_tags: "+ Cercar un etiquetta a sequer" - people_sharing_with_you: "Personas qui divide con te" - post_a_message: "publicar un message >>" services: content: "Tu pote connecter le sequente servicios a diaspora*:" heading: "Connecter servicios" - unfollow_tag: "Cessar de sequer #%{tag}" welcome_to_diaspora: "Benvenite a diaspora*, %{name}!" - new: - create: "Crear" - name: "Nomine (visibile solmente pro te)" no_contacts_message: community_spotlight: "usatores in evidentia" + invite_link_text: "invitar" or_spotlight: "O tu pote divider con %{link}" try_adding_some_more_contacts: "Tu pote cercar o invitar plus contactos." you_should_add_some_more_contacts: "Tu deberea adder plus contactos!" - no_posts_message: - start_talking: "Nemo ha ancora dicite qualcosa!" seed: acquaintances: "Cognoscitos" family: "Familia" @@ -214,7 +221,6 @@ ia: update: failure: "Tu aspecto, %{name}, ha un nomine troppo longe e non pote esser salveguardate." success: "Tu aspecto, %{name}, ha essite modificate con successo." - back: "Retornar" blocks: create: failure: "Io non poteva ignorar iste usator. #evasion" @@ -226,22 +232,15 @@ ia: explanation: "Invia cosas a diaspora* ab ubique con iste ligamine: %{link}" heading: "Mini-marcapaginas" post_something: "Inviar a diaspora*" - post_success: "Invio succedite!" cancel: "Cancellar" comments: new_comment: comment: "Commentar" commenting: "Commenta…" - one: "1 commento" - other: "%{count} commentos" - zero: "nulle commento" contacts: - create: - failure: "Creation de contacto fallite" index: add_a_new_aspect: "Adder un nove aspecto" add_contact: "Adder contacto" - add_to_aspect: "adder contactos a %{name}" all_contacts: "Tote le contactos" community_spotlight: "Usatores in evidentia" my_contacts: "Mi contactos" @@ -249,19 +248,13 @@ ia: no_contacts_in_aspect: "Tu non ha ancora contactos in iste aspecto. Infra es un lista de tu contactos existente le quales tu pote adder a iste aspecto." no_contacts_message: "Visita %{community_spotlight}" only_sharing_with_me: "Solmente qui divide cosas con me" - remove_contact: "Remover contacto" start_a_conversation: "Initiar un conversation" title: "Contactos" user_search: "Recerca de usatores" - your_contacts: "Tu contactos" - sharing: - people_sharing: "Qui divide cosas con te:" spotlight: community_spotlight: "Usatores in evidentia" suggest_member: "Suggerer un membro" conversations: - conversation: - participants: "Participantes" create: fail: "Message non valide" no_contact: "Tu debe adder le contacto primo." @@ -271,13 +264,11 @@ ia: hide_success: "Le conversation ha essite celate" index: conversations_inbox: "Conversationes – Cassa de entrata" - create_a_new_conversation: "initiar un nove conversation" inbox: "Cassa de entrata" new_conversation: "Nove conversation" - no_conversation_selected: "nulle conversation seligite" no_messages: "nulle message" new: - abandon_changes: "Abandonar modificationes?" + message: "Message" send: "Inviar" sending: "Invia…" subject: "subjecto" @@ -288,6 +279,7 @@ ia: show: delete: "deler e blocar conversation" hide: "celar e silentiar conversation" + last_message: "Ultime message recipite %{timeago}" reply: "responder" replying: "Responde…" date: @@ -300,10 +292,7 @@ ia: error_messages: helper: correct_the_following_errors_and_try_again: "Corrige le sequente errores e proba de novo." - invalid_fields: "Campos invalide" - login_try_again: "Per favor <a href='%{login_link}'>aperi session</a> e reproba." - post_not_public: "Le entrata que tu vole vider non es public!" - post_not_public_or_not_exist: "Le entrata que tu tenta vider non es public, o non existe." + need_javascript: "Iste sito web require JavaScript pro poter functionar. Si tu ha disactivate JavaScript, per favor reactiva lo e recarga iste pagina." fill_me_out: "Plena me" find_people: "Cercar personas o #etiquettas" help: @@ -523,42 +512,37 @@ ia: tutorial: "tutorial" tutorials: "tutoriales" wiki: "wiki" - hide: "Celar" - ignore: "Ignorar" + home: + default: + be_who_you_want_to_be: "Sia le persona que tu vole esser" + be_who_you_want_to_be_info: "Multe retes insiste que on usa su nomine real. Non diaspora*. Hic tu pote eliger le persona que vole esser, e divulgar si multo o si pauco de te como tu vole. Tu pote vermente decider como tu interage con altere personas." + byline: "Le mundo social in linea ubi tu ha le controlo" + choose_your_audience: "Elige tu audientia" + choose_your_audience_info: "Le \"aspectos\" de diaspora* permitte divider cosas solmente con le personas appropriate. Tu pote scriber in publico o si privatemente como tu vole. Divide un photo amusante con tote le mundo, o divide un secreto personal con tu amicos intime. Le controlo es tue." + headline: "Benvenite a %{pod_name}" + own_your_data: "Possede tu proprie datos" + own_your_data_info: "Multe retes usa tu datos pro ganiar moneta analysante tu interactiones e usante iste information pro diriger publicitate a te. diaspora* non usa tu datos pro alcun scopo, salvo illo de permitter te de connecter e divider cosas con altere personas." + podmin: + headline: "Benvenite, amico." invitation_codes: - excited: "%{name} es multo felice de vider te hic." not_valid: "Iste codice de invitation non plus es valide" invitations: a_facebook_user: "Un usator de Facebook" check_token: not_found: "Indicio de invitation non trovate" create: - already_contacts: "Tu es jam connectite con iste persona." - already_sent: "Tu ha jam invitate iste persona." empty: "Per favor, specifica al minus un adresse de e-mail." no_more: "Tu non ha altere invitationes." note_already_sent: "Invitationes ha jam essite inviate a: %{emails}" - own_address: "Non es possibile inviar un invitation a tu proprie adresse." rejected: "Le sequente adresses de e-mail habeva problemas: " sent: "Le sequente adresses ha recipite un invitation: %{emails}" - edit: - accept_your_invitation: "Acceptar tu invitation" - your_account_awaits: "Un conto te attende!" new: - already_invited: "Le sequente personas non ha acceptate tu invitation:" - aspect: "Aspecto" - check_out_diaspora: "Discoperi diaspora*!" comma_separated_plz: "Tu pote entrar plure adresses de e-mail separante los per commas." - if_they_accept_info: "si iste persona accepta, illa essera addite al aspecto in le qual tu la invitava." invite_someone_to_join: "Invita qualcuno a unir se a diaspora*!" language: "Lingua" paste_link: "Divide iste ligamine con tu amicos pro invitar les a diaspora*, o invia le ligamine directemente a illes per e-mail." - personal_message: "Message personal" - resend: "Reinviar" send_an_invitation: "Inviar un invitation" - send_invitation: "Inviar invitation" sending_invitation: "Invia invitation..." - to: "A" layouts: application: back_to_top: "Retornar al cyma" @@ -568,27 +552,14 @@ ia: statistics_link: "Statisticas del pod" toggle: "(dis)activar mobile" whats_new: "que es nove?" - your_aspects: "tu aspectos" header: - admin: "admin" - blog: "blog" code: "codice" - help: "Adjuta" - login: "aperir session" logout: "Clauder session" profile: "Profilo" - recent_notifications: "Notificationes recente" settings: "Configuration" - view_all: "Vider totes" - likes: - likes: - people_dislike_this: - one: "%{count} antipathia" - other: "%{count} antipathias" - zero: "nulle antipathia " + toggle_navigation: "Alternar navigation" limited: "Limitate" more: "Plus" - next: "sequente" no_results: "Nulle resultato trovate" notifications: also_commented: @@ -641,7 +612,6 @@ ia: a_limited_post_comment: "Il ha un nove commento pro te sur un entrata limitate in diaspora*." a_post_you_shared: "un entrata." a_private_message: "Il ha un nove message private pro te in diaspora*." - accept_invite: "Accepta tu invitation a diaspora*!" also_commented: limited_subject: "Il ha un nove commento sur un entrata que tu ha commentate" click_here: "clicca hic" @@ -718,10 +688,10 @@ ia: view_post: "Vider entrata >" mentioned: limited_post: "Tu ha essite mentionate in un entrata limitate." - mentioned: "te mentionava in un message:" subject: "%{name} te ha mentionate in diaspora*" private_message: reply_to_or_view: "Responde o lege iste conversation >" + subject: "Il ha un nove message private pro te" remove_old_user: body: |- Salute, @@ -772,20 +742,9 @@ ia: to_change_your_notification_settings: "pro cambiar tu configuration de notificationes" nsfw: "NSFW" ok: "OK" - or: "o" - password: "Contrasigno" - password_confirmation: "Confirmation del contrasigno" people: add_contact: invited_by: "tu ha essite inviate per" - add_contact_small: - add_contact_from_tag: "adder contacto ab etiquetta" - aspect_list: - edit_membership: "modificar membrato del aspecto" - helper: - is_not_sharing: "%{name} non divide cosas con te" - is_sharing: "%{name} is sharing with you" - results_for: " resultatos pro %{params}" index: couldnt_find_them: "Non trovate?" looking_for: "Cercar entratas con le etiquetta %{tag_link}?" @@ -795,101 +754,57 @@ ia: search_handle: "Usa lor ID de diaspora* (p.ex. nominedeusator@pod.tld) pro cercar tu amicos." searching: "recerca in curso, un momento per favor..." send_invite: "Ancora nihil? Invia un invitation!" - one: "1 persona" - other: "%{count} personas" person: - add_contact: "adder contacto" - already_connected: "Jam connectite" - pending_request: "Requesta pendente" thats_you: "Es tu!" profile_sidebar: bio: "Bio" born: "Data de nascentia" - edit_my_profile: "Modificar mi profilo" gender: "Sexo" - in_aspects: "in aspectos" location: "Loco" - photos: "Photos" - remove_contact: "remover contacto" - remove_from: "Remover %{name} de %{aspect}?" show: closed_account: "Iste conto ha essite claudite." does_not_exist: "Iste persona non existe!" has_not_shared_with_you_yet: "%{name} non ha ancora dividite alcun cosa con te!" - ignoring: "Tu ignora tote le entratas de %{name}." - incoming_request: "%{name} vole divider con te" - mention: "Mention" - message: "Message" - not_connected: "Tu non divide con iste persona" - recent_posts: "Entratas recente" - recent_public_posts: "Entratas public recente" - return_to_aspects: "Retornar a tu pagina de aspectos" - see_all: "Vider totes" - start_sharing: "comenciar a divider" - to_accept_or_ignore: "pro acceptar o ignorar lo." - sub_header: - add_some: "adder alcunes" - edit: "modificar" - you_have_no_tags: "tu non ha etiquettas!" - webfinger: - fail: "%{handle} non ha essite trovate." - zero: "nemo" photos: - comment_email_subject: "Photo de %{name}" create: integrity_error: "Le incargamento del photo ha fallite. Es tu secur que iste file contine un imagine?" runtime_error: "Le incargamento del photo ha fallite a causa de un problema interne." type_error: "Le incargamento del photo ha fallite. Es tu secur que un imagine ha essite addite?" destroy: notice: "Photo delite." - edit: - editing: "In processo de modification" - new: - back_to_list: "Retornar al lista" - new_photo: "Nove photo" - post_it: "inviar lo!" new_photo: empty: "{file} es vacue. Per favor re-selige le files sin iste." invalid_ext: "{file} ha un extension inadmissibile. Solmente {extensions} es permittite." size_error: "{file} es troppo grande. Le dimension maxime es {sizeLimit}." new_profile_photo: - or_select_one_existing: "o selige un de tu %{photos} jam existente" upload: "Incargar un nove photo de profilo!" - photo: - view_all: "vider tote le photos de %{name}" show: - collection_permalink: "permaligamine al collection" - delete_photo: "Deler photo" - edit: "modificar" - edit_delete_photo: "Modificar description del photo / deler photo" - make_profile_photo: "facer photo de profilo" show_original_post: "Monstrar entrata original" - update_photo: "Actualisar photo" - update: - error: "Le modification del photo ha fallite." - notice: "Photo actualisate con successo." posts: presenter: title: "Un entrata de %{name}" show: - destroy: "Deler" forbidden: "Tu non ha le permission de facer isto" - not_found: "Impossibile trovar iste entrata." - permalink: "permaligamine" + location: "Inviate ab: %{location}" reshare_by: "Repetite per %{author}" - previous: "precedente" privacy: "Confidentialitate" - privacy_policy: "Politica de confidentialitate" profile: "Profilo" profiles: edit: allow_search: "Permitter que on te cerca in diaspora*" - edit_profile: "Modificar profilo" + basic: "Mi profilo basic" + basic_hint: "Cata elemento de profilo es facultative. Le profilo basic es sempre visibile pro le publico." + extended: "Mi profilo extendite" + extended_hint: "Clicca sur le commutator pro definir le visibilitate de tu profilo extendite. \"Public\" vole dicer que illo es visibile pro tote le internet, \"limitate\" vole dicer que solmente le personas in tu aspectos de contacto videra iste information." + extended_visibility_text: "Visibilitate de tu profilo extendite:" first_name: "Prenomine" last_name: "Nomine de familia" + limited: "Limitate" nsfw_check: "Marcar toto que io divide como NSFW" nsfw_explanation: "NSFW (‘not safe for work’, non appropriate pro le travalio) es un standard communitari pro contento que poterea esser inappropriate a vider durante que on es al travalio. Si tu intende a frequentemente divider tal material, per favor, marca iste option, de sorta que tote le cosas que tu divide essera celate pro le personas qui non ha optate pro vider los." nsfw_explanation2: "Si tu non selige iste option, per favor, adde le etiquetta #nsfw cata vice que tu divide tal material." + public: "Public" + settings: "Configuration de profilo" update_profile: "Actualisar profilo" your_bio: "Tu bio" your_birthday: "Tu data de nascentia" @@ -897,8 +812,6 @@ ia: your_location: "Tu loco" your_name: "Tu nomine" your_photo: "Tu photo" - your_private_profile: "Tu profilo private" - your_public_profile: "Tu profilo public" your_tags: "Describe te in 5 parolas" your_tags_placeholder: "p.ex. #films #cattones #viages #docente #interlingua" update: @@ -909,26 +822,16 @@ ia: closed: "Le creation de contos es claudite in iste pod de diaspora*." create: success: "Tu ha adherite a diaspora*!" - edit: - cancel_my_account: "Cancellar mi conto" - edit: "Modificar %{name}" - leave_blank: "(lassa isto vacue si tu non vole cambiar lo)" - password_to_confirm: "(nos require tu contrasigno actual pro confirmar le cambiamentos)" - unhappy: "Non felice?" - update: "Actualisar" invalid_invite: "Le ligamine de invitation que tu ha fornite non plus es valide." new: - create_my_account: "Crear mi conto!" email: "E-MAIL" enter_email: "Specifica adresse de e-mail" enter_password: "Elige un contrasigno (de sex characteres al minimo)" enter_password_again: "Repete le contrasigno" enter_username: "Elige un nomine de usator (usa solmente litteras, numeros e tractos de sublineamento)" - join_the_movement: "Adhere al movimento!" password: "CONTRASIGNO" password_confirmation: "CONFIRMA CONTRASIGNO" sign_up: "CREAR CONTO" - sign_up_message: "Rete social con ♥" submitting: "Submitte…" terms: "Per crear un conto tu accepta le %{terms_link}." terms_link: "conditiones de servicio" @@ -941,36 +844,18 @@ ia: post_label: "<b>Entrata</b>: %{title}" reason_label: "Motivo: %{text}" reported_label: "<b>Reportate per</b> %{person}" + reported_user_details: "Detalios sur le usator reportate" review_link: "Marcar como revidite" status: - created: "Un reporto ha essite create" destroyed: "Le entrata ha essite destruite" failed: "Qualcosa ha errate" - marked: "Le reporto ha essite marcate como revidite" title: "Summario de reportos" - requests: - create: - sending: "Invio in curso" - sent: "Tu ha demandate de divider con %{name}. Iste persona lo videra le proxime vice que illa aperira session in diaspora*." - destroy: - error: "Per favor selige un aspecto!" - ignore: "Demanda de contacto ignorate." - success: "Tu ha comenciate a divider." - manage_aspect_contacts: - existing: "Contactos existente" - manage_within: "Gerer contactos intra" - new_request_to_person: - sent: "inviate!" reshares: comment_email_subject: "Repetition de %{resharer} del entrata de %{author}" - create: - failure: "Un error occurreva durante le repetition de iste entrata." reshare: deleted: "Le entrata original ha essite delite per le autor." reshare_confirmation: "Repeter iste entrata de %{author}?" - reshare_original: "Repeter le original" reshared_via: "repetite via" - show_original: "Monstrar le original" search: "Cercar" services: create: @@ -982,10 +867,6 @@ ia: success: "Authentication delite con successo." failure: error: "un error occurreva durante le connexion a iste servicio" - finder: - fetching_contacts: "diaspora* obtene presentemente tu amicos de %{service}. Per favor, reveni in alcun momentos." - no_friends: "Nulle amico de Facebook trovate." - service_friends: "Amicos de %{service}" index: connect: "Connecter" disconnect: "disconnecter" @@ -995,52 +876,22 @@ ia: not_logged_in: "Nulle session aperte in iste momento." really_disconnect: "disconnecter %{service}?" services_explanation: "Le connexion a servicios da le possibilitate de publicar tu messages anque in illos si tu los scribe in diaspora*." - inviter: - click_link_to_accept_invitation: "Seque iste ligamine pro acceptar tu invitation" - join_me_on_diaspora: "Veni con me in diaspora*" + title: "Gerer servicios connectite" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "invitar" - not_on_diaspora: "Non ancora in diaspora*" - resend: "reinviar" settings: "Configuration" - share_visibilites: - update: - post_hidden_and_muted: "Le entrata de %{name} ha essite celate, e le notificationes ha essite silentiate." - see_it_on_their_profile: "Si tu vole vider actualisationes sur iste entrata, visita le profilo de %{name}." shared: - add_contact: - add_new_contact: "Adder un nove contacto" - create_request: "Cercar per ID de diaspora*" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Entra un nomine de usator de diaspora*:" - know_email: "Si tu cognosce su adresse de e-mail, tu deberea invitar le/la." - your_diaspora_username_is: "Tu nomine de usator de diaspora* es: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Adder contacto" mobile_row_checked: "%{name} (remover)" mobile_row_unchecked: "%{name} (adder)" - contact_list: - all_contacts: "Tote le contactos" - footer: - logged_in_as: "identificate como %{name}" - your_aspects: "tu aspectos" invitations: by_email: "Per e-mail" - dont_have_now: "Tu non ha invitationes pro le momento, ma alteres arrivara bentosto!" - from_facebook: "De Facebook" - invitations_left: "%{count} restante" - invite_someone: "Invitar un persona" invite_your_friends: "Invitar tu amicos" invites: "Invitationes" - invites_closed: "Le invitationes es actualmente claudite pro iste pod de diaspora*." share_this: "Divide iste ligamine per e-mail, blog o rete social!" - notification: - new: "Nove %{type} de %{from}" public_explain: atom_feed: "Syndication Atom" control_your_audience: "Controlar tu audientia" @@ -1052,12 +903,9 @@ ia: title: "Connecter altere servicios" visibility_dropdown: "Iste menu disrolante es pro cambiar le visibilitate de tu message. (Nos suggere que tu rende iste prime message public.)" publisher: - all: "totes" - all_contacts: "tote le contactos" discard_post: "Abandonar entrata" formatWithMarkdown: "Tu pote usar %{markdown_link} pro formatar tu entrata" get_location: "Localisar te" - make_public: "render public" new_user_prefill: hello: "Salute, io es #%{new_user_tag}. " i_like: "Io me interessa in %{tags}. " @@ -1065,36 +913,14 @@ ia: newhere: "NewHere" poll: add_a_poll: "Adder un sondage" - add_poll_answer: "Adder option" - option: "Option 1" - question: "Question" - remove_poll_answer: "Remover option" - post_a_message_to: "Inviar un message a %{aspect}" posting: "Invio in curso…" - preview: "Previsualisation" - publishing_to: "va publicar in: " remove_location: "Remover loco" share: "Divider" - share_with: "divider con" upload_photos: "Incargar photos" whats_on_your_mind: "De que pensa tu?" - reshare: - reshare: "Repeter" stream_element: - connect_to_comment: "Adde iste usator como contacto pro commentar su message" - currently_unavailable: "es impossibile commentar pro le momento" - dislike: "Disappreciar" - hide_and_mute: "Celar e silentiar iste message" - ignore_user: "Ignorar %{name}" - ignore_user_description: "Ignorar e remover iste usator de tote le aspectos?" - like: "Appreciar" - nsfw: "Iste message ha essite marcate como NSFW per su autor. %{link}" - shared_with: "Dividite con: %{aspect_names}" - show: "monstrar" - unlike: "Non plus appreciar" via: "via %{link}" via_mobile: "via mobile" - viewable_to_anyone: "Iste message es visibile pro tote le mundo in le web" simple_captcha: label: "Scribe le codice in le quadro:" message: @@ -1120,15 +946,10 @@ ia: status_messages: create: success: "Ha essite mentionate: %{names}" - destroy: - failure: "Le deletion del message ha fallite" - helper: - no_message_to_display: "Nulle message a presentar." new: mentioning: "Mentiona: %{person}" too_long: "Per favor, non scribe plus de %{count} characteres in tu message de stato. In iste momento illo ha %{current_length} characteres." stream_helper: - hide_comments: "Celar tote le commentos" no_more_posts: "Fin del fluxo." no_posts_yet: "Il non ha ancora entratas." streams: @@ -1157,13 +978,6 @@ ia: tags: title: "Messages con etiquettas: %{tags}" tag_followings: - create: - failure: "Impossibile sequer #%{name}. Esque tu jam lo seque?" - none: "Non es possibile sequer un etiquetta vacue!" - success: "Hurrah! Tu seque ora #%{name}." - destroy: - failure: "Impossibile cessar de sequer #%{name}. Esque tu ha jam cessate de sequer lo?" - success: "Guai! Tu non plus seque #%{name}." manage: no_tags: "Tu non seque alcun etiquetta." title: "Gerer etiquettas sequite" @@ -1171,15 +985,12 @@ ia: name_too_long: "Per favor, non scribe plus de %{count} characteres in le nomine del etiquetta. In iste momento illo ha %{current_length} characteres." show: follow: "Sequer #%{tag}" - following: "Tu seque #%{tag}" none: "Le etiquetta vacue non existe!" stop_following: "Non plus sequer #%{tag}" tagged_people: one: "1 persona con etiquetta %{tag}" other: "%{count} personas con etiquetta %{tag}" zero: "Nemo con etiquetta %{tag}" - terms_and_conditions: "Terminos e conditiones" - undo: "Disfacer?" username: "Nomine de usator" users: confirm_email: @@ -1194,13 +1005,13 @@ ia: auto_follow_aspect: "Aspecto pro contactos automaticamente addite:" auto_follow_back: "Divider automaticamente con omne persona qui comencia a divider con te" change: "Cambiar" + change_color_theme: "Cambiar thema de colores" change_email: "Cambiar adresse de e-mail" change_language: "Cambiar de lingua" change_password: "Cambiar contrasigno" character_minimum_expl: "al minus 6 characteres" close_account: dont_go: "Per favor, non parti!" - if_you_want_this: "Si tu vermente vole facer isto, entra hic infra tu contrasigno e clicca sur 'Clauder conto'." lock_username: "Isto reserva tu nomine de usator in caso que tu decide de re-crear tu conto." locked_out: "Tu session essera claudite e tu essera excludite de tu conto." make_diaspora_better: "Nos ha besonio de adjuta pro meliorar diaspora*, dunque, per favor contribue in loco de quitar. Si tu vermente vole quitar, nos vole informar te de lo que evenira." @@ -1213,14 +1024,12 @@ ia: current_password_expl: "illo con que tu aperi session..." download_export: "Discargar mi profilo" download_export_photos: "Discargar mi photos" - download_photos: "discargar mi photos" edit_account: "Modificar conto" email_awaiting_confirmation: "Nos te ha inviate un ligamine de activation al adresse %{unconfirmed_email}. Usque al momento que tu seque iste ligamine pro activar le nove adresse, nos va continuar a usar tu adresse original %{email}." export_data: "Exportar datos" export_in_progress: "Le datos personal tue es actualmente sub preparation. Per favor, reveni in alcun momentos." export_photos_in_progress: "Le tractamento de tu photos non ha ancora terminate. Per favor, essaya lo de novo in qualque momentos." following: "Configuration de divider" - getting_started: "Preferentias de nove usator" last_exported_at: "(Ultime actualisation: %{timestamp})" liked: "un persona apprecia un entrata tue" mentioned: "un persona te mentiona in un entrata sue" @@ -1247,7 +1056,6 @@ ia: connect_to_facebook_link: "connecter tu conto de Facebook" hashtag_explanation: "Le #etiquettas permitte discuter e sequer tu interesses. Illos anque es un bon maniera de trovar nove personas in diaspora*." hashtag_suggestions: "Tenta sequer etiquettas como #arte, #films, #gif, etc." - saved: "Salveguardate!" well_hello_there: "Salutationes a te!" what_are_you_in_to: "Quales es tu interesses?" who_are_you: "Qui es tu?" @@ -1260,6 +1068,8 @@ ia: public: does_not_exist: "Le usator %{username} non existe!" update: + color_theme_changed: "Le thema de colores ha essite cambiate." + color_theme_not_changed: "Un error ha occurrite durante le cambio de thema de colores." email_notifications_changed: "Notificationes per e-mail cambiate" follow_settings_changed: "Configuration de sequimento cambiate" follow_settings_not_changed: "Cambiamento de configuration de sequimento fallite" @@ -1271,13 +1081,6 @@ ia: settings_updated: "Configuration actualisate" unconfirmed_email_changed: "Adresse de e-mail cambiate. Necessita activation." unconfirmed_email_not_changed: "Cambio de e-mail fallite" - webfinger: - fetch_failed: "obtention de profilo webfinger pro %{profile_url} fallite" - hcard_fetch_failed: "il habeva un problema durante le obtention del hcard pro %{account}" - no_person_constructed: "Nulle persona poteva esser construite a partir de iste hcard." - not_enabled: "le servicio webfinger non pare esser activate pro le host del conto %{account}" - xrd_fetch_failed: "il habeva un error durante le obtention del XRD ab le conto %{account}" - welcome: "Benvenite!" will_paginate: next_label: "sequente »" previous_label: "« precedente" \ No newline at end of file diff --git a/config/locales/diaspora/id.yml b/config/locales/diaspora/id.yml index a35fa2db8a3c1cfeccb068d3c726fab9ec54b211..983e1daa157188adb7c7f0633b766ae4473def74 100644 --- a/config/locales/diaspora/id.yml +++ b/config/locales/diaspora/id.yml @@ -6,10 +6,7 @@ id: _applications: "Aplikasi" - _comments: "Komentar" _contacts: "Kontak" - _home: "Beranda" - _photos: "foto" _services: "Layanan" account: "Akun" activerecord: @@ -40,13 +37,7 @@ id: username: invalid: "tidak valid. Hanya boleh huruf, angka dan garis bawah." taken: "sudah dipakai" - ago: "%{time} yang lalu" all_aspects: "Semua Hal" - application: - helper: - unknown_person: "orang tak dikenal" - video_title: - unknown: "Judul Video Tidak Diketahui" are_you_sure: "Anda yakin?" are_you_sure_delete_account: "Anda yakin akan menghapus akun anda? ini tidak dapat di batalkan!" aspect_memberships: @@ -62,17 +53,9 @@ id: success: "Successfully added friend to aspect." aspect_listings: add_an_aspect: "+ Tambah satu aspek" - deselect_all: "Batalkan semua pilihan" - edit_aspect: "Ubah %{name}" - select_all: "Pilih semua" aspect_stream: stay_updated: "Selalu Terbarui" stay_updated_explanation: "Aliran utamamu dipenuhi oleh semua kontakmu, tandai yang kamu ikuti, dan kirimkan beberapa anggota komunitas." - contacts_not_visible: "Kontak di aspek ini tidak dapat saling melihat." - contacts_visible: "Kontak di aspek ini dapat saling melihat." - create: - failure: "Aspek gagal dibuat." - success: "Klik pada tanda plus di sisi kiri untuk memberitahu Diaspora siapa yang dapat melihat aspek baru Anda." destroy: failure: "%{name} tidak terisi dan tidak dapat dihapus." success: "%{name} berhasil dihapus." @@ -80,21 +63,13 @@ id: aspect_list_is_not_visible: "Kontak di dalam aspek ini tidak dapat saling melihat" aspect_list_is_visible: "Kontak di dalam aspek ini dapat saling melihat." confirm_remove_aspect: "Anda yakin ingin menghapus aspek ini?" - make_aspect_list_visible: "make aspect list visible?" - remove_aspect: "Hapus aspek ini" rename: "Ganti nama" update: "Perbarui" updating: "Memperbarui" index: - diaspora_id: - content_1: "ID diaspora* anda:" - content_2: "Berikan ke semua orang dan mereka akan dapat menemukanmu di diaspora*" - heading: "ID diaspora*" donate: "Donasi" - handle_explanation: "This is your diaspora handle. Like an email address, you can give this to people to reach you." help: do_you: "Apakah kamu:" - email_feedback: "%{link} timbal balik, jika anda ingin" feature_suggestion: "... punya %{link} anjuran?" find_a_bug: ".... menemukan %{link}" have_a_question: "... punya %{link}" @@ -108,25 +83,15 @@ id: follow: "Ikuti %{link} dan selamat datang di diaspora*!" learn_more: "Pelajari" title: "Selamat Datang Pengguna Baru" - no_contacts: "Tak ada kontak" - no_tags: "No tags" - people_sharing_with_you: "Orang orang yang berbagi dengan anda" - post_a_message: "Kirim pesan" services: content: "Anda dapat menyambungkan layanan berikut ke diaspora*:" heading: "Sambungkan Layanan" - unfollow_tag: "Berhenti mengikuti #%{tag}" welcome_to_diaspora: "Selamat datang di diaspora*, %{name}" - new: - create: "Buat" - name: "Name" no_contacts_message: community_spotlight: "Sorotan komunitas" or_spotlight: "Atau anda dapat berbagi dengan %{link}" try_adding_some_more_contacts: "You can search (top) or invite (right) more contacts." you_should_add_some_more_contacts: "Anda perlu menambahkan beberapa kontak baru!" - no_posts_message: - start_talking: "Nobody has said anything yet. Get the conversation started!" seed: acquaintances: "Kenalan" family: "Keluarga" @@ -135,26 +100,18 @@ id: update: failure: "Nama aspek anda, %{name}, terlalu panjang untuk disimpan." success: "Aspek anda, %{name}, telah berhasil diubah." - back: "Kembali" bookmarklet: explanation: "%{link} from anywhere by bookmarking this link." heading: "Diaspora Bookmarklet" post_something: "Kirimkan ke diaspora*" - post_success: "Terkirim! Menutup!" cancel: "Batal" comments: new_comment: comment: "Komentar" commenting: "Mengomentari" - one: "1 komentar" - other: "%{count} komentar" - zero: "tak ada komentar" contacts: - create: - failure: "gagal membuat kontak" index: add_a_new_aspect: "Tambahkan aspek baru" - add_to_aspect: "Add contacts to %{name}" all_contacts: "Semua Kontak" community_spotlight: "Sorotan komunitas" my_contacts: "Kontakku" @@ -163,29 +120,16 @@ id: only_sharing_with_me: "Hanya berbagi dengan saya" start_a_conversation: "Mulai pembicaraan" title: "Kontak" - your_contacts: "Kontakmu" - sharing: - people_sharing: "Orang-orang yang berbagi dengan anda" spotlight: community_spotlight: "Sorotan Komunitas" conversations: create: fail: "Pesan tak valid" sent: "Pesan terkirim" - helper: - new_messages: - few: "%{count} new messages" - many: "%{count} new messages" - one: "1 new messages" - other: "%{count} new messages" - two: "%{count} new messages" - zero: "no new messages" index: inbox: "Kotak Masuk" - no_conversation_selected: "tidak ada pembicaraan yang dipilih" no_messages: "tak ada pesan" new: - abandon_changes: "Abaikan perubahan?" send: "Kirim" sending: "Mengirim..." subject: "subjek" @@ -204,10 +148,8 @@ id: error_messages: helper: correct_the_following_errors_and_try_again: "Perbaiki kesalahan berikut dan coba lagi." - invalid_fields: "Field tidak valid" fill_me_out: "Isi di sini" find_people: "Temukan orang" - hide: "Sembunyikan" invitation_codes: not_valid: "Kode undangan sudah tidak valid." invitations: @@ -215,70 +157,26 @@ id: check_token: not_found: "Token undangan tidak ditemukan" create: - already_contacts: "Kamu sudah tersambung dengan orang ini" - already_sent: "Kamu sudah mengajak orang ini" no_more: "Anda tidak dapat memberikan undangan lagi." - own_address: "Kamu tidak dapat mengirim undangan ke alamatmu sendiri." rejected: "Alamat email berikut bermasalah dengan: " sent: "Undangan telah dikirimkan ke:" - edit: - accept_your_invitation: "Terima undanganmu" - your_account_awaits: "Akunmu sudah menunggu!" new: - already_invited: "Already invited" - aspect: "Aspek" - check_out_diaspora: "Lihat diaspora*!" - if_they_accept_info: "Jika mereka menerima, mereka akan ditambahkan ke Aspek yang kamu undang." invite_someone_to_join: "Undang seseorang untuk bergabung di Diaspora!" language: "Bahasa" - personal_message: "Pesan pribadi" - resend: "Kirim ulang" send_an_invitation: "Kirim sebuah undangan" - send_invitation: "Kirim undangan" - to: "Ke" layouts: application: back_to_top: "Kembali ke atas" powered_by: "DIDUKUNG OLEH diaspora*" toggle: "toggle mobile site" whats_new: "apa yang baru?" - your_aspects: "Aspekmu" header: - admin: "Admin" - blog: "blog" code: "Kode" - login: "login" logout: "logout" profile: "profile" - recent_notifications: "Pemberitahuan baru-baru ini" settings: "settings" - view_all: "Lihat semua" - likes: - likes: - people_dislike_this: - few: "%{count} people disliked this" - many: "%{count} people disliked this" - one: "1 person disliked this" - other: "%{count} people disliked this" - two: "%{count} dislikes" - zero: "no people disliked this" - people_like_this: - few: "%{count} people liked this" - many: "%{count} people liked this" - one: "1 person liked this" - other: "%{count} people liked this" - two: "%{count} likes" - zero: "no people liked this" - people_like_this_comment: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" limited: "Terbatas" more: "lainnya" - next: "Selanjutnya" no_results: "Tidak ada hasil yang ditemukan." notifications: also_commented: @@ -302,14 +200,6 @@ id: other: "%{actors} commented on your %{post_link}." two: "%{actors} commented on your %{post_link}." zero: "%{actors} commented on your %{post_link}." - helper: - new_notifications: - few: "%{count} new notifications" - many: "%{count} new notifications" - one: "1 new notifications" - other: "%{count} new notifications" - two: "%{count} new notifications" - zero: "no new notifications" index: and: "dan" and_others: @@ -392,7 +282,6 @@ id: liked: "%{name} has just liked your post: " view_post: "Lihat kiriman >" mentioned: - mentioned: "menyebut anda di kiriman:" subject: "%{name} menyebutmu di diaspora*" private_message: reply_to_or_view: "Balas atau lihat pembicaraan ini >" @@ -410,59 +299,23 @@ id: to_change_your_notification_settings: "untuk mengganti pengaturan pemberitahuan" nsfw: "Konten Dewasa" ok: "Oke" - or: "atau" - password: "Kata sandi" - password_confirmation: "Pengesahan kata sandi" people: - add_contact_small: - add_contact_from_tag: "tambah kontak dari tag" - aspect_list: - edit_membership: "sunting keanggotaan Aspek" - helper: - results_for: " hasil untuk %{params}" index: looking_for: "Mencari kiriman dengan tag %{tag_link}" no_one_found: "...dan tak menemukan siapapun." no_results: "Hei! Kamu harus cari sesuatu." results_for: "hasil pencarian untuk" - one: "1 person" - other: "%{count} people" person: - add_contact: "tambah kontak" - already_connected: "Sudah terhubung" - pending_request: "permintaan tertunda" thats_you: "Itu anda!" profile_sidebar: bio: "Biografi" born: "born" - edit_my_profile: "Sunting profil saya" gender: "Gender" - in_aspects: "pada Aspek" location: "Lokasi" - remove_contact: "hapus kontak" - remove_from: "hapus %{name} dari %{aspect}?" show: closed_account: "Akun ini telah ditutup." does_not_exist: "Orang tidak ada!" has_not_shared_with_you_yet: "%{name} belum berbagi apapun dengan kamu!" - ignoring: "Kamu mengabaikan semua kiriman dari %{name}" - incoming_request: "You have an incoming request from this person." - mention: "Panggilan" - message: "Pesan" - not_connected: "You are not connected with this person" - recent_posts: "Kiriman baru-baru ini" - recent_public_posts: "Kiriman Publik baru-baru ini" - return_to_aspects: "Kembali ke laman Aspek-mu" - see_all: "Lihat semua" - start_sharing: "mulai berbagi" - to_accept_or_ignore: "terima atau abaikan" - sub_header: - add_some: "tambah beberapa" - edit: "sunting" - you_have_no_tags: "kamu tak punya tag!" - webfinger: - fail: "Maaf, kita tak dapat mencari %{handle}" - zero: "no people" photos: create: integrity_error: "Pengunggahan foto gagal. Itu tadi beneran gambar?" @@ -470,29 +323,12 @@ id: type_error: "Pengunggahan foto gagal. Kamu yakin sudah menambahkan gambar?" destroy: notice: "Foto dihapus." - edit: - editing: "Mengubah" - new: - back_to_list: "Kembali ke Daftar" - new_photo: "Foto Baru" - post_it: "posting!" new_photo: empty: "{file} kosong, mohon pilih berkas lagi tanpanya." invalid_ext: "ekstensi {file} tak valid. Hanya {extensions} yang diperbolehkan." size_error: "{file} terlalu besar, ukuran maksimal berkas adalah {sizeLimit}" - photo: - view_all: "lihat semua foto %{name}" show: - collection_permalink: "koleksi permalink" - delete_photo: "Hapus Foto" - edit: "sunting" - edit_delete_photo: "Sunting deskripsi foto / hapus foto" - make_profile_photo: "membuat foto profil" show_original_post: "Perlihatkan kiriman asli" - update_photo: "Perbarui Foto" - update: - error: "Gagal mengubah foto." - notice: "Foto berhasil diperbarui." posts: show: forbidden: "Kamu tidak boleh melakukannya" @@ -503,9 +339,7 @@ id: other: "%{count} photos by %{author}" two: "Two photos by %{author}" zero: "No photos by %{author}" - previous: "Sebelumnya" privacy: "Privasi" - privacy_policy: "Kebijakan Privasi" profile: "Profil" profiles: edit: @@ -523,51 +357,19 @@ id: create: success: "Anda telah bergabung dengan Diaspora!" new: - create_my_account: "Create my account" enter_email: "Enter an e-mail" - sign_up_message: "Social Networking with a <3" - requests: - create: - sending: "Sending..." - destroy: - error: "Silahkan pilih sebuah aspek!" - ignore: "Permintaan pertemanan yang diabaikan." - success: "Anda sekarang berteman." - helper: - new_requests: - few: "%{count} new requests!" - many: "%{count} new requests!" - one: "new request!" - other: "%{count} new requests!" - two: "%{count} new requests!" - zero: "no new requests" reshares: reshare: - reshare: - few: "%{count} Reshares" - many: "%{count} Reshares" - one: "1 Reshare" - other: "%{count} Reshares" - two: "%{count} reshares" - zero: "Reshare" reshare_confirmation: "Reshare %{author} - %{text}?" - reshare_original: "Reshare orignial" - show_original: "Show Original" search: "Cari" services: destroy: success: "Successfully destroyed authentication." index: logged_in_as: "telah masuk sebagai" - inviter: - click_link_to_accept_invitation: "Click this link to accept your invitation" settings: "Pengaturan" shared: - add_contact: - create_request: "Find by Diaspora handle" - diaspora_handle: "Diaspora handle" aspect_dropdown: - add_to_aspect: "Add to aspect" toggle: few: "In %{count} aspects" many: "In %{count} aspects" @@ -577,49 +379,20 @@ id: zero: "Add to aspect" invitations: by_email: "by Email" - invitations_left: "(%{count} left)" - invites_closed: "Invites are currently closed on this Diaspora seed" - notification: - new: "%{type} baru dari %{from}" public_explain: title: "You are about to post a public message!" publisher: new_user_prefill: i_like: "I'm interested in %{tags}." share: "Bagikan" - share_with: "Share with %{aspect}" whats_on_your_mind: "what's on your mind?" - stream_element: - dislike: "I dislike this" - hide_and_mute: "Hide and Mute" - like: "I like this" status_messages: - helper: - no_message_to_display: "Tidak ada pesan yang dapat ditampilkan." too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - hide_comments: "hide comments" - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: aspects: title: "Your Aspects" mentions: title: "Your Mentions" - tag_followings: - create: - failure: "Failed to follow: #%{name}" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" - terms_and_conditions: "Syarat dan Ketentuan" - undo: "Batalkan?" username: "Username" users: confirm_email: @@ -632,7 +405,6 @@ id: change_password: "Change Password" close_account: what_we_delete: "We delete all of your posts, profile data, as soon as humanly possible. Your comments will hang around, but be associated with your Diaspora Handle." - download_photos: "Unduh foto-fotoku" email_awaiting_confirmation: "We have sent you an activation link to %{unconfirmed_email}. Till you follow this link and activate the new address, we will continue to use your original address %{email}." new_password: "New Password" receive_email_notifications: "Receive email notificaions?" @@ -644,7 +416,4 @@ id: password_changed: "Password Changed" password_not_changed: "Password Change Failed" unconfirmed_email_changed: "E-Mail Changed. Needs activation." - unconfirmed_email_not_changed: "E-Mail Change Failed" - webfinger: - hcard_fetch_failed: "there was a problem fetching the hcard for #{@account}" - welcome: "Selamat Datang!" \ No newline at end of file + unconfirmed_email_not_changed: "E-Mail Change Failed" \ No newline at end of file diff --git a/config/locales/diaspora/io.yml b/config/locales/diaspora/io.yml index 1a57fc1475cd94c6d7db85539e2e3d3521d84789..788f4a5b4f7c091f8b48cda2390f7b130d36843b 100644 --- a/config/locales/diaspora/io.yml +++ b/config/locales/diaspora/io.yml @@ -6,10 +6,7 @@ io: _applications: "Utilaji" - _comments: "Komenti" _contacts: "Konocati" - _home: "Frontispico" - _photos: "fotografuri" _services: "Servi" account: "Konto" activerecord: @@ -36,32 +33,18 @@ io: stats: month: "Monato" week: "Semano" - ago: "%{time} ante nun" all_aspects: "Omna Aspekti" - application: - helper: - unknown_person: "nekonocato" are_you_sure: "Ka vu esas certa?" are_you_sure_delete_account: "Ka vu certe volas klozar vua konto? To ne povas esar desfacota." aspects: aspect_listings: add_an_aspect: "+ Adjuntez aspekto" - deselect_all: "Des-selektez omna" - edit_aspect: "Redaktez %{name}" - select_all: "Selektez omna" - contacts_not_visible: "Konocati en ita aspekto ne povos vidar l'una l'altra." - contacts_visible: "Konocati en ita aspekto povos vidar l'una l'altra." - create: - failure: "Aspekto kreado ne-sucesis." - success: "Tua nov aspekto %{name} kre-esis" destroy: success: "%{name} sucesoze efacesis." edit: aspect_list_is_not_visible: "Konocati en ita aspekto ne povas vidar l'una l'altra." aspect_list_is_visible: "Konocati en ita aspekto povas vidar l'una l'altra." confirm_remove_aspect: "Ka vu certe volas efacar ita aspekto?" - make_aspect_list_visible: "igar konocati en ita aspekto videbla a l'una l'altra?" - remove_aspect: "Efacez ita aspekto" rename: "ri-nomizez" update: "aktualigez" updating: "aktualigas" @@ -74,19 +57,13 @@ io: new_here: learn_more: "Lektez pluse" title: "Bonvenez Nova Uzanti" - new: - create: "Kreez" - name: "Nomo (nur videbla da tu)" no_contacts_message: try_adding_some_more_contacts: "Vu povas serchar od invitar plusa konocati." you_should_add_some_more_contacts: "Vu devas adjuntar plusa konocati!" - no_posts_message: - start_talking: "Nulu dicis irgo ankore!" seed: acquaintances: "Konocati" family: "Familio" friends: "Amiki" - back: "Retro-irar" cancel: "Anular" contacts: index: @@ -94,7 +71,6 @@ io: delete: "Efacar" email: "E-posto" find_people: "Serchez personi o #\"tag\" -i" - hide: "Celar" invitations: new: language: "Linguo" @@ -103,38 +79,17 @@ io: profile: "Profilo" limited: "Limitizita" more: "Plusa" - next: "sequanta" no_results: "Nula rezultajo trovesis" nsfw: "NSFW" ok: "Bone" - or: "od" - password: "Pasovorto" - password_confirmation: "Konfirmo di pasovorto" people: - person: - add_contact: "adjuntez konocato" profile_sidebar: born: "Naskodio" location: "Loko" - show: - message: "Mesajo" - see_all: "Videz omno" - sub_header: - edit: "redaktar" photos: destroy: notice: "Fotografuro efacata" - new: - new_photo: "Nova Fotografuro" - show: - delete_photo: "Efacar fotografuro" - edit: "redaktar" - posts: - show: - destroy: "Efacar" - previous: "antea" privacy: "Privateso" - privacy_policy: "Politiko pri privateso" profile: "Profilo" profiles: edit: @@ -146,21 +101,10 @@ io: new: password: "PASOVORTO" search: "Serchar" - services: - remote_friend: - invite: "invitez" - resend: "risendez" settings: "Selektaji" - shared: - contact_list: - all_contacts: "Omna konocati" - publisher: - all_contacts: "omna konocati" streams: followed_tag: follow: "Sequez" - terms_and_conditions: "Reguli e Kondicioni" - undo: "Ka desfacar?" username: "Uzantonomo" users: edit: @@ -168,6 +112,4 @@ io: change_language: "Chanjez linguo" change_password: "Chanjez pasovorto" current_password: "Nuna pasovorto" - download_photos: "Deskargez mea fotografuri" - new_password: "Nova pasovorto" - welcome: "Bonveno!" \ No newline at end of file + new_password: "Nova pasovorto" \ No newline at end of file diff --git a/config/locales/diaspora/is.yml b/config/locales/diaspora/is.yml index 83a565921f37c0ea4a28ce0a9534b82ff699c12c..1944f1a7daf271521b13b9bfb5e94a6d60d5a4e6 100644 --- a/config/locales/diaspora/is.yml +++ b/config/locales/diaspora/is.yml @@ -6,10 +6,7 @@ is: _applications: "Forrit" - _comments: "Athugasemdir" _contacts: "Tengiliðir" - _home: "ForsÃða" - _photos: "myndir" _services: "Þjónusta" account: "Notandastillingar" activerecord: @@ -22,7 +19,7 @@ is: person: attributes: diaspora_handle: - taken: "er þegar frátekið." + taken: "er þegar à notkun." request: attributes: from_id: @@ -46,17 +43,28 @@ is: user_search: "Leit að notanda" stats: 2weeks: "2 vikur" + comments: + one: "%{count} athugasemd" + other: "%{count} athugasemdir" + zero: "Engar athugasemdir" daily: "Daglega" + go: "Fara" month: "Mánuður" + posts: + one: "%{count} færsla" + other: "%{count} færslur" + zero: "Engin færsla" + shares: + one: "%{count} deiling" + other: "%{count} deilingar" + zero: "Engar deilingar" usage_statistic: "Tölfræði notkunar" + users: + one: "%{count} notandi" + other: "%{count} notendur" + zero: "Engir notendur" week: "Vika" - ago: "%{time} sÃðan" all_aspects: "Allar ásýndir" - application: - helper: - unknown_person: "óþekkt manneskja" - video_title: - unknown: "Óþekktur titill á myndskeiði" are_you_sure: "Ertu viss?" are_you_sure_delete_account: "Ertu viss um að þú viljir loka aðganginum þÃnum? Þetta er óafturkræf aðgerð!" aspect_memberships: @@ -70,39 +78,23 @@ is: success: "Það heppnaðist að bæta tengilið við ásýnd." aspect_listings: add_an_aspect: "+ Bæta við ásýnd" - deselect_all: "Velja ekkert" - edit_aspect: "Breyta %{name}" - select_all: "Velja allt" aspect_stream: stay_updated: "Fylgstu með" - contacts_not_visible: "Tengiliðir à þessari ásýnd geta ekki séð hvern annan." - contacts_visible: "Tengiliðir à þessari ásýnd geta séð hvern annan." - create: - failure: "Ekki tókst að búa til ásýnd." - success: "Nýja %{name} ásýndin þÃn var búin til" destroy: - failure: "%{name} er ekki tóm og þvà ekki hægt að fjarlægja hana." + failure: "%{name} er ekki hægt að fjarlægja." success: "það heppnaðist að fjarlægja %{name}." edit: aspect_list_is_not_visible: "Tengiliðir à þessari ásýnd geta ekki séð hvern annan." aspect_list_is_visible: "Tengiliðir à þessari ásýnd geta séð hvern annan." confirm_remove_aspect: "Ertu viss um að þú viljir eyða þessari ásýnd?" - make_aspect_list_visible: "gera þáttökulista ásýndar sýnilegan öðrum?" - remove_aspect: "Eyða þessari ásýnd" - rename: "breyta nafni" - set_visibility: "Stilla sýnileika" - update: "uppfæra" + rename: "Breyta nafni" + update: "Uppfæra" updating: "uppfæri" index: - diaspora_id: - content_1: "Diaspora*-auðkennið þitt er:" - heading: "DÃaspora* auðkenni" donate: "Styrkja" - handle_explanation: "Þetta er auðkennið þitt hjá DÃaspora*. Eins og með venjulegt netfang, geturðu gefið fólki það svo þau geti haft samband við þig." help: any_problem: "Einhver vandamál?" do_you: "Þú:" - email_link: "Netfang" feature_suggestion: "... ert með %{link} uppástungu?" find_a_bug: "... fannst %{link}?" have_a_question: "... ert með %{link}?" @@ -114,25 +106,15 @@ is: new_here: follow: "Fylgstu með %{link} og bjóddu nýja notendur velkomna á Diaspora*!" learn_more: "Vita meira" - title: "Bjóða Nýja Notendur Velkomna" - no_contacts: "Engir tengiliðir" - no_tags: "+ finna merki til að fylgjast með" - people_sharing_with_you: "Fólk sem deilir með þér:" - post_a_message: "skrifa skilaboð >>" + title: "Bjóða nýja notendur velkomna" services: - heading: "Tengja Þjónustur" - unfollow_tag: "Hætta að fylgjast með #%{tag}" + heading: "Tengja þjónustur" welcome_to_diaspora: "Velkomin à Diaspora* %{name}!" - new: - create: "Búa til" - name: "Nafn (sýnilegt þér einum)" no_contacts_message: community_spotlight: "efst á baugi à samfélaginu" or_spotlight: "Eða þú getur deilt með %{link}" - try_adding_some_more_contacts: "You can search (top) or invite (right) more contacts." + try_adding_some_more_contacts: "Þú getur leitað eða %{invite_link} fleiri tengiliðum." you_should_add_some_more_contacts: "Þú ættir að bæta við tengiliðum!" - no_posts_message: - start_talking: "Enginn hefur sagt neitt enn!" seed: acquaintances: "Kunningjar" family: "Fjölskylda" @@ -141,51 +123,33 @@ is: update: failure: "Ãsýnd þÃn, %{name}, hefur of langt nafn til að hægt sé að vista hana." success: "Ãsýnd þinni, %{name}, hefur verið breytt." - back: "Til baka" bookmarklet: - explanation: "%{link} from anywhere by bookmarking this link." + explanation: "Sendu færslu á diaspora* hvaðan sem er með þvà að bókamerkja þennan tengil => %{link}." heading: "Diaspora Bookmarklet" post_something: "Senda á Diaspora*" - post_success: "Sent! Loka!" cancel: "Hætta við" comments: new_comment: comment: "Athugasemd" commenting: "Athugasemd gerð..." - one: "1 comment" - other: "%{count} comments" - zero: "no comments" contacts: - create: - failure: "Ekki tókst að mynda tengsl" index: - add_to_aspect: "Add contacts to %{name}" all_contacts: "Allir tengiliðir" community_spotlight: "Efst á baugi à samfélaginu" my_contacts: "Tengiliðirnir mÃnir" no_contacts: "No contacts." start_a_conversation: "Hefja umræðu" title: "Tengiliðir" - your_contacts: "ÞÃnir tegiliðir" - sharing: - people_sharing: "Fólk sem deilir með þér:" spotlight: community_spotlight: "Efst á baugi à samfélaginu" conversations: create: fail: "Ógild skilaboð" sent: "Skilaboð send" - helper: - new_messages: - one: "1 ný skilaboð" - other: "%{count} ný skilaboð" - zero: "Engin ný skilaboð" index: inbox: "Innhólf" - no_conversation_selected: "engin umræða valin" no_messages: "engin skilaboð" new: - abandon_changes: "Hætta við breytingar?" send: "Senda" sending: "Sendi..." subject: "efni" @@ -203,8 +167,6 @@ is: error_messages: helper: correct_the_following_errors_and_try_again: "Það þarf að lagfæra eftirfarandi villur og reyna sÃðan aftur. " - invalid_fields: "Ógildir reitir" - post_not_public_or_not_exist: "Skeytið sem þú ert að reyna að skoða er ekki aðgengilegt eða er ekki til!" fill_me_out: "Fylla þetta út" find_people: "Finna fólk eða #merki" help: @@ -226,64 +188,30 @@ is: embed_multimedia_a: "Oftast er hægt að setja URLið (t.d. http://www.youtube.com/watch?v=nnnnnnnnnnn) beint inn à skilaboðin og myndin eða myndbandið verður fellt sjálfkrafa inn à skeytið. Við styðjum meðal annars. YouTube, Vimeo, SoundCloud, Flickr ásamt nokkrum öðrum. diaspora* notar oEmbed til að framkvæma innfellinguna sem gerir það að verkum að nýjar þjónustur eru stöðugt að bætast à hópinn. Mundu að setja alltaf inn fulla slóð inn, ekki stytta hana né bæta aftan við sem og að smá stund getur tekið áður en innfellingin er verður sýnileg." private_profiles: whats_in_profile_a: "Ferilskráin, staðsetning, kyn og fæðingardagur. Þetta eru allt hlutir sem eru neðst á SÃðunni Þinni. Þú ræður hvort þú setur upplýsingar þar inn. Eingöngu einstaklingar sem þú hefur bætt à eina af þÃnum sýnum, og eru skráðir inn, geta séð þessar upplýsingar. Þegar þeir fara á sÃðuna þÃna geta þeir séð þau skeyti sem þú hefur deilt með öllum, sem og þau skeyti sem þú hefur valið að deila með sýnum sem þeir eru Ã." - hide: "Fela" - ignore: "Hunsa" invitations: a_facebook_user: "Facebook-notandi" create: - already_contacts: "Þú tengist þessari manneskju nú þegar" - already_sent: "Þessari manneskju hefur þegar verið boðið." no_more: "Ekki eru til fleiri boðsmiðar." rejected: "Eftirfarandi netföng ollu vandræðum: " sent: "Boðsmiðar hafa verið sendir til: %{emails}" new: - already_invited: "Nu þegar boðið" - aspect: "Ãsýnd" - check_out_diaspora: "Skoðaðu DÃaspora*!" - if_they_accept_info: "ef þau þiggja boðið, verður þeim bætt við þá ásýnd sem þú bauðst þeim á." invite_someone_to_join: "Bjóddu einhverjum að tengjast DÃaspora*!" language: "Tungumál" paste_link: "Deildu þessum tengil með vinum þÃnum til þess að bjóða þeim á diaspora*, eða sendu þeim tengilinn beint à gegnum tölvupóst." - personal_message: "Persónuleg skilaboð" - resend: "Endursenda" send_an_invitation: "Sendu boðsmiða" - send_invitation: "Senda boðsmiða" - to: "Til" layouts: application: back_to_top: "Fara efst" - powered_by: "KEYRT AF dÃaspora*" - toggle: "toggle mobile site" - whats_new: "hvað er að frétta?" - your_aspects: "þÃnar ásýndir" + powered_by: "Keyrt með dÃaspora*" + toggle: "VÃxla farsÃmavef af/á" + whats_new: "Hvað er að frétta?" header: - admin: "kerfisstjóri" - blog: "blogg" code: "kóði" - help: "Hjálp" - login: "Innskráning" logout: "Útskrá" - profile: "profile" - recent_notifications: "Nýlegar tilkynningar" - settings: "settings" - view_all: "Skoða allt" - likes: - likes: - people_dislike_this: - one: "%{count} aðili kann ekki að meta þetta" - other: "%{count} aðilar kunna ekki að meta þetta" - zero: "enginn kann ekki að meta þetta" - people_like_this: - one: "%{count} aðili kann að meta þetta" - other: "%{count} aðilar kunna að meta þetta" - zero: "enginn kann að meta þetta" - people_like_this_comment: - one: "%{count} aðili kann að meta þetta" - other: "%{count} aðilar kunna að meta þetta" - zero: "enginn kann að meta þetta" + profile: "ForsÃða" + settings: "Stillingar" limited: "Takmarkað" more: "Meira" - next: "næsta" no_results: "Engar niðurstöður" notifications: also_commented: @@ -300,12 +228,7 @@ is: comment_on_post: one: "%{actors} skrifaði ummæli við %{post_link}." other: "%{actors} skrifuðu ummæli við %{post_link}." - zero: "%{actors} hefur skrifa ummæli við %{post_link}." - helper: - new_notifications: - one: "1 ný skilaboð" - other: "%{count} ný skilaboð" - zero: "engin ný skilaboð" + zero: "%{actors} hefur skrifað ummæli við %{post_link}." index: all_notifications: "Allar tilkynningar" and: "og" @@ -318,8 +241,8 @@ is: mark_read: "Merkja sem lesið" mark_unread: "Merkja sem ólesið" notifications: "Tilkynningar" - show_all: "sýna allt" - show_unread: "sýna ólesið" + show_all: "Sýna allt" + show_unread: "Sýna ólesið" liked: few: "%{actors} has just liked your %{post_link}." many: "%{actors} has just liked your %{post_link}." @@ -372,34 +295,41 @@ is: other: "%{actors} hafa byrjað að deila með þér." zero: "%{actors} hafa byrjað að deila með þér." notifier: - click_here: "smelltu hér" + a_post_you_shared: "færslu." + click_here: "Smelltu hér" confirm_email: - click_link: "To activate your new e-mail address %{unconfirmed_email}, please click this link:" - subject: "Please activate your new e-mail address %{unconfirmed_email}" + click_link: "Til að virkja nýja netfangið þitt %{unconfirmed_email}, smelltu á þennan tengil:" + subject: "Virkjaðu nýja netfangið þitt %{unconfirmed_email}" hello: "Halló %{name}!" invite: message: |- Halló! - Þér hefur verið boðið að vera með á Diaspora*! + Þér hefur verið boðið að vera með á Diaspora* af %{diaspora_id}! Smelltu á þennan tengil til að hefjast handa [%{invite_url}][1] + Eða að þú getur bætt %{diaspora_id} à tengiliðasafn þitt, ef þú ert þegar með aðgang. + Bestu kveðjur, Diaspora* póst-róbótinn! + P.S.: Ef svo vill til að þú vitir ekki (ennþá) hvað diaspora* sé, þá er svarið hér [2] ! + [1]: %{invite_url} + [2]: %{diasporafoundation_url} liked: liked: "%{name} has just liked your post: " + view_post: "Skoða færslu >" mentioned: - mentioned: "gat þÃn à pósti:" subject: "%{name} hefur getið þÃn á Diaspora*" reshared: - reshared: "%{name} just reshared your post" + reshared: "%{name} endurdeildi færslunni þinni" + view_post: "Skoða færslu >" single_admin: subject: "Skilaboð um notandastillingar þÃnar à Diaspora*:" started_sharing: @@ -407,110 +337,59 @@ is: thanks: "Takk," nsfw: "NSFW (Ekki við hæfi allra)" ok: "à lagi" - or: "eða" - password: "Lykilorð" - password_confirmation: "Staðfesting lykilorðs" people: add_contact: - invited_by: "þér var boðið af" - aspect_list: - edit_membership: "breyta aðild að ásýnd" - helper: - results_for: " niðurstöður fyrir %{params}" + invited_by: "Þér var boðið af" index: no_one_found: "...og enginn fannst." no_results: "Hey! Þú þarft að leita að einhverju." results_for: "Notendur sem samsvara %{search_term}" - one: "1 person" - other: "%{count} people" person: - add_contact: "bæta tengilið við" - already_connected: "Þegar tengdur" - pending_request: "pending request" - thats_you: "thats you!" + thats_you: "Það ert þú!" profile_sidebar: + bio: "Æviágrip" born: "Afmælisdagur" - edit_my_profile: "Breyta sÃðunni minni" gender: "Kyn" - in_aspects: "à ásýnd" location: "Staðsetning" - remove_contact: "fjarlægja tengilið" - remove_from: "Fjarlægja %{name} úr %{aspect}?" show: does_not_exist: "Manneskjan er ekki til!" - incoming_request: "%{name} vill samnýta með þér" - message: "Skilaboð" - not_connected: "Þú samnýtir ekki með %{name}" - recent_posts: "Nýlegar færslur" - see_all: "Sjá allt" - start_sharing: "Byrja að samnýta" - to_accept_or_ignore: "að samþykkja eða hunsa það." - sub_header: - edit: "breyta" - webfinger: - fail: "Þvà miður, %{handle} fannst ekki." - zero: "no people" photos: - comment_email_subject: "Mynd af %{name}" create: - integrity_error: "Innhlöðunn myndar mistókst. Ertu viss um að þetta hafi verið mynd?" - runtime_error: "Innsetning á mynd mistóḱst. Ertu viss um að sætisbeltin séu spennt?" - type_error: "Innsetning á mynd mistóḱst. Ertu viss um að mynd hafi verið bætt við?" + integrity_error: "Innsending á mynd mistókst. Ertu viss um að þetta hafi verið mynd?" + runtime_error: "Innsending á mynd mistókst. Ertu viss um að sætisbeltin séu spennt?" + type_error: "Innsending á mynd mistókst. Ertu viss um að mynd hafi verið bætt við?" destroy: - notice: "Mynd eytt." - edit: - editing: "Breyti" - new: - back_to_list: "Til baka à listann" - new_photo: "Ný mynd" - post_it: "færa inn!" + notice: "Mynd var eytt." new_photo: - empty: "{file} skráin er tóm, veldu vinsamlegast skrárnar aftur en slepptu henni." - invalid_ext: "{file} hefur ógilt viðskeyti. Aðeins {extensions} eru leyfð." - size_error: "{file} skráin er of stór, mesta stærð er {sizeLimit}." + empty: "{file} skráin er tóm, veldu skrárnar aftur en slepptu þessari skrá." + invalid_ext: "{file} er með ógilda skráarendingu. Aðeins {extensions} eru leyfðar." + size_error: "{file} skráin er of stór, hámarksstærð er {sizeLimit}." new_profile_photo: - or_select_one_existing: "eða velja eina af þeim %{photos} sem þú átt fyrir" - upload: "Setja upp nýja mynd!" - photo: - view_all: "skoða allar myndir hjá notandanum %{name}'" + upload: "Senda inn nýja forsÃðumynd!" show: - collection_permalink: "safn varanlegra tengla" - delete_photo: "Eyða mynd" - edit: "breyta" - edit_delete_photo: "Breyta lýsingu við mynd / eyða mynd" - make_profile_photo: "setja mynd á sÃðuna mÃna" - show_original_post: "Birta upprunalegan póst" - update_photo: "Uppfæra mynd" - update: - error: "Ekki tókst að breyta mynd." - notice: "Velheppnuð uppfærsla á mynd. " + show_original_post: "Birta upprunalega færslu" posts: show: - destroy: "Eyða" - permalink: "varanlegur tengill" photos_by: one: "Ein mynd frá %{author}" other: "%{count} myndir frá %{author}" zero: "Engar myndir frá %{author}" - previous: "fyrra" privacy: "Gagnaleynd" - privacy_policy: "Stefna varðandi gagnaleynd" profile: "SÃðan mÃn" profiles: edit: allow_search: "Leyfa fólki að leita að þér á DÃaspora*" - edit_profile: "Breyta sÃðunni minni" first_name: "Fornafn" last_name: "Kenninafn/Eftirnafn" update_profile: "Uppfæra sÃðuna mÃna" - your_bio: "Ferilskrá þÃn" + your_bio: "Æviágrip þitt" your_birthday: "Fæðingardagur þinn" your_gender: "Kyn þitt" your_location: "Staðsetning þÃn" your_name: "Nafn þitt" - your_photo: "Mynd þÃn" - your_tags: "You: in 5 #tags" - your_tags_placeholder: "i.e. #diaspora #ironing #kittens #music" + your_photo: "Mynd af þér" + your_tags: "Lýstu þér à 5 orðum" + your_tags_placeholder: "t.d. #kvikmyndir #kittens #fjallahjol #hestar #music" update: failed: "Ekki tókst að uppfæra sÃðuna mÃna" updated: "SÃðan mÃn uppfærð" @@ -523,153 +402,84 @@ is: closed: "Lokað er fyrir innskráningar á þessum Diaspora* pod." create: success: "Nú hefurðu tengst Diaspora*!" - edit: - cancel_my_account: "Aflýsa mÃnum notandastillingum" - edit: "Breyta %{name}" - leave_blank: "(Skildu eftir autt ef þú vilt ekki gera breytingu)" - password_to_confirm: "(Við þurfum núverandi lykilorðið þitt til að staðfesta breytingar þÃnar)" - unhappy: "Óhamingjusamur?" - update: "Uppfæra" new: - create_my_account: "Create my account" - email: "NETFANG" + email: "Netfang" enter_email: "Gefðu upp netfang" enter_password: "Skrifaðu lykilorð (lágmark sex stafir)" enter_password_again: "Skrifaðu sama lykilorð og áður" enter_username: "Veldu notandanafn (aðeins bókstafi, tölur, og undirstrikun)" - password: "LYKILORÃ" - password_confirmation: "STAÃFESTING LYKILORÃS" - sign_up: "STOFNA AÃGANG" - sign_up_message: "Social Networking with a <3" + password: "Lykilorð" + password_confirmation: "Staðfesting lykilorðs" + sign_up: "Stofna aðgang" submitting: "Sendi inn..." - username: "NOTANDANAFN" - requests: - create: - sending: "Sendi" - sent: "%{name} hefur verið beðin(n) um að tengjast þér. Þau ættu að sjá það þegar þau logga næst inn à DÃaspora." - destroy: - error: "Þú þarft að velja ásýnd!" - ignore: "Hundsaði vinabeiðni. " - success: "Nú er vinátta á milli ykkar." - helper: - new_requests: - one: "Ein ný beiðni!" - other: "%{count} nýjar beiðnir!" - zero: "engar nýjar beiðnir" - manage_aspect_contacts: - existing: "Núverandi tengiliðir" - manage_within: "Umsjón tengiliða innan" - new_request_to_person: - sent: "sent!" + username: "Notandanafn" reshares: reshare: - reshare: - one: "1 endurdeiling" - other: "%{count} endurdeilingar" - zero: "Endurdeila" - reshare_confirmation: "Reshare %{author} - %{text}?" - reshare_original: "Reshare orignial" - show_original: "Show Original" + reshare_confirmation: "Endurdeila frá %{author}?" search: "Leita" services: create: + failure: "Auðkenning mistókst." success: "Auðkenning tókst." failure: - error: "villa kom upp við að tengjast þeirri þjónustu" + error: "Villa kom upp við að tengjast þeirri þjónustu" index: - disconnect: "aftengja" + disconnect: "Aftengjast" edit_services: "Breyta þjónustum" - logged_in_as: "innskráning þÃn sem " - really_disconnect: "aftengja %{service}?" - inviter: - click_link_to_accept_invitation: "Smelltu á þessa krækju til að þiggja boðið" - join_me_on_diaspora: "Tengstu mér á DÃASPORA*" - remote_friend: - invite: "bjóða" - resend: "endursenda" + logged_in_as: "Skráð inn sem %{nickname}" + really_disconnect: "Aftengjast %{service}?" settings: "Stillingar" shared: - add_contact: - create_request: "Leita eftir DÃaspora* auðkenni" - diaspora_handle: "diaspora@handle.org" - enter_a_diaspora_username: "Settu inn notandanafn hjá Diaspora*:" - know_email: "Veistu netföngin þeirra? Þú ættir að senda þeim boðsmiða" - your_diaspora_username_is: "Notandanafn þitt hjá Diaspora* er: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Add to aspect" toggle: one: "à %{count} ásýnd" other: "à %{count} ásýndir" zero: "Bæta við tengilið" - contact_list: - all_contacts: "Allir tengiliðir" invitations: by_email: "með tölvupósti" - dont_have_now: "Þú átt enga boðsmiða núna, en þeir koma fljótlega!" - from_facebook: "Frá Facebook" - invitations_left: "(%{count} eftir)" - invite_someone: "Bjóddu einhverjum" - invite_your_friends: "Bjóddu vinafólki þÃnu" - invites: "Boðsmiðar" - notification: - new: "Nýtt %{type} frá %{from}" + invite_your_friends: "Bjóddu vinum þÃnum" + invites: "Boð" public_explain: - outside: "Almennt aðgengileg skilaboð verða sýnileg öðrum utan Diaspora." - title: "Þú ert að fara að setja þetta á almannafæri!" + logged_in: "Skráður inn á %{service}" + manage: "Sýsla með tengdar þjónustur" + outside: "Opnber skilaboð verða sýnileg öðrum utan DÃaspora*." + share: "Deila" + title: "Setja upp tengdar þjónustur" publisher: - all: "allt" - all_contacts: "Allir tengiliðir" - make_public: "gera almennt" + discard_post: "Henda færslu" new_user_prefill: - i_like: "I'm interested in %{tags}." - post_a_message_to: "Skrifa skilaboð til %{aspect}" + hello: "Hæ allir, ég er #%{new_user_tag}. " + i_like: "Ég hef áhuga á %{tags}. " + invited_by: "Takk fyrir boðið. " + newhere: "nýr hér" posting: "Senda..." share: "Deila" - share_with: "deila með" - whats_on_your_mind: "hvað er þér efst à huga?" - reshare: - reshare: "Endurdeila" + upload_photos: "Senda inn myndir" + whats_on_your_mind: "Hvað er þér efst à huga?" stream_element: - dislike: "I dislike this" - hide_and_mute: "Hide and Mute" - like: "I like this" + via: "með %{link}" via_mobile: "á farsÃma" status_messages: - destroy: - failure: "Ekki tókst að eyða færslu" - helper: - no_message_to_display: "Engin skilaboð að sýna!" - too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - hide_comments: "fela athugasemdir" - show_comments: - one: "Birta eina athugasemd til viðbótar" - other: "Birta %{count} athugasemdir til viðbótar" - zero: "Engar fleiri athugasemdir" + too_long: "Hafðu stöðufærsluna þÃna með færri en %{count} stöfum. Núna er hún %{current_length} stafir" streams: aspects: - title: "Your Aspects" - mentions: - title: "Your Mentions" - tag_followings: - create: - failure: "Failed to follow: #%{name}" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" - terms_and_conditions: "Skilmálar" - undo: "Afturkalla?" + title: "Ãsýndirnar þÃnar" + aspects_stream: "Ãsýndir" + community_spotlight_stream: "Efst á baugi à samfélaginu" + tags: + show: + follow: "Fylgjast með #%{tag}" + stop_following: "Hætta að fylgjast með #%{tag}" username: "Notandanafn" users: confirm_email: - email_confirmed: "E-Mail %{email} activated" - email_not_confirmed: "E-Mail could not be activated. Wrong link?" + email_confirmed: "Tölvupóstfang %{email} virkjað" + email_not_confirmed: "Ekki var hægt að virkja tölvupóstfang. Rangur tengill?" edit: - auto_follow_back: "Automatically follow back if a someone follows you" - change: "Breyting" - change_email: "Change E-Mail" - change_language: "Breyta um tungumál" + auto_follow_back: "Byrja sjálfkrafa að deila með notendum sem deila með þér" + change: "Breyta" + change_email: "Breyta netfangi" + change_language: "Skipta um tungumál" change_password: "Breyta lykilorði" close_account: what_we_delete: "We delete all of your posts, profile data, as soon as humanly possible. Your comments will hang around, but be associated with your Diaspora Handle." @@ -677,17 +487,24 @@ is: edit_account: "Breyta notandastillingum" email_awaiting_confirmation: "We have sent you an activation link to %{unconfirmed_email}. Till you follow this link and activate the new address, we will continue to use your original address %{email}." new_password: "Nýtt lykilorð" - receive_email_notifications: "Fá tilkynningar à tölvupósti?" + receive_email_notifications: "Fá tilkynningar à tölvupósti þegar:" your_email: "Netfangið þitt" your_handle: "DÃaspora* auðkennið þitt" + privacy_settings: + ignored_users: "Hunsaðir notendur" + title: "Gagnaleynd" public: does_not_exist: "Notandinn %{username} er ekki til!" update: - email_notifications_changed: "Tilkynningum à tölvupósti var breytt." - language_changed: "breytt var um tungumál" - language_not_changed: "ekki tókst að breyta um tungumál" + email_notifications_changed: "Tilkynningum à tölvupósti var breytt" + language_changed: "Skipt var um tungumál" + language_not_changed: "Ekki tókst að skipta um tungumál" password_changed: "Lykilorði var breytt" password_not_changed: "Breyting á lykilorði mistókst" - unconfirmed_email_changed: "E-Mail Changed. Needs activation." - unconfirmed_email_not_changed: "E-Mail Change Failed" - welcome: "Velkomin(n)!" \ No newline at end of file + settings_not_updated: "Uppfærsla stillinga mistókst" + settings_updated: "Stillingar uppfærðar" + unconfirmed_email_changed: "Breytt tölvupóstfang. Krefst virkjunar." + unconfirmed_email_not_changed: "Breyting á tölvupóstfangi mistókst" + will_paginate: + next_label: "næsta »" + previous_label: "« fyrra" \ No newline at end of file diff --git a/config/locales/diaspora/it.yml b/config/locales/diaspora/it.yml index 780e07894baedf96ca1cdeb7ceee731f22273df4..afe0983119d559f5b64e858529747ea0d97755df 100644 --- a/config/locales/diaspora/it.yml +++ b/config/locales/diaspora/it.yml @@ -6,11 +6,8 @@ it: _applications: "Applicazioni" - _comments: "Commenti" _contacts: "Contatti" _help: "Aiuto" - _home: "Home" - _photos: "foto" _services: "Servizi" account: "Account" activerecord: @@ -19,7 +16,7 @@ it: contact: attributes: person_id: - taken: "deve essere univoco tra i contatti di questo utente." + taken: "deve essere unica tra i contatti di questo utente." person: attributes: diaspora_handle: @@ -31,7 +28,7 @@ it: reshare: attributes: root_guid: - taken: "Bello eh? Ma hai già condiviso quel post!" + taken: "Figo eh? Ma hai già condiviso quel post!" user: attributes: email: @@ -58,7 +55,7 @@ it: current_segment: "L'intervallo attuale ha una media di <b>%{post_yest}</b> post per utente, dal <b>%{post_day}</b>" daily: "1 giorno" display_results: "Risultati sull'intervallo di <b>%{segment}</b>" - go: "vai" + go: "Vai" month: "1 mese" posts: one: "%{count} post" @@ -81,7 +78,7 @@ it: ? "yes" : Si user_search: - add_invites: "aggiungi inviti" + add_invites: "Aggiungi inviti" close_account: "Chiudi l'account" email_to: "Email a cui mandare l'invito" under_13: "Mostra utenti sotto i 13 anni (Children's Online Privacy Protection Act)" @@ -99,13 +96,7 @@ it: other: "Numero di nuovi utenti questa settimana: %{count}" zero: "Numero di nuovi utenti questa settimana: nessuno" current_server: "La data attuale del server è %{date}" - ago: "%{time} fa" all_aspects: "Tutti gli aspetti" - application: - helper: - unknown_person: "persona sconosciuta" - video_title: - unknown: "Video senza titolo" are_you_sure: "Sei sicuro?" are_you_sure_delete_account: "Sei sicuro di voler chiudere il tuo account? È un'operazione irreversibile!" aspect_memberships: @@ -119,80 +110,52 @@ it: success: "Il contatto è stato aggiunto all'aspetto." aspect_listings: add_an_aspect: "+ Aggiungi un aspetto" - deselect_all: "Deseleziona tutti" - edit_aspect: "Modifica %{name}" - select_all: "Seleziona tutti" aspect_stream: make_something: "Crea qualcosa" stay_updated: "Segui lo stream" stay_updated_explanation: "Lo stream è popolato da tutti i tuoi contatti, dai tag che segui e dai post dei membri più creativi della comunità ." - contacts_not_visible: "I contatti in questo aspetto non potranno vedersi tra loro." - contacts_visible: "I contatti in questo aspetto potranno vedersi tra loro." - create: - failure: "Creazione dell'aspetto fallita." - success: "Il tuo nuovo aspetto %{name} è stato creato" destroy: - failure: "%{name} non è stato rimosso perché non è vuoto." + failure: "%{name} non è possibile rimuovere questo contatto." success: "%{name} è stato rimosso con successo." edit: aspect_list_is_not_visible: "i Contatti in questo aspetto non sono visibili tra loro" aspect_list_is_visible: "I Contatti in questo aspetto sono visibili tra loro" confirm_remove_aspect: "Sei sicuro di voler eliminare questo aspetto?" - make_aspect_list_visible: "Vuoi che i contatti di questo aspetto vedano gli altri che ne fanno parte?" - remove_aspect: "Elimina questo aspetto" - rename: "rinomina" - update: "aggiorna" - updating: "aggiornamento in corso" + rename: "Rinomina" + update: "Aggiorna" + updating: "Aggiornamento in corso" index: - diaspora_id: - content_1: "Il tuo ID è:" - content_2: "Chi lo conosce potrà trovarti facilmente su Diaspora, spargi la voce!" - heading: "ID Diaspora" donate: "Fai una donazione" - handle_explanation: "Questo è il tuo ID su Diaspora*. Lo puoi dare alle persone per farti trovare, come un indirizzo email." help: any_problem: "Qualche problema?" contact_podmin: "Contatta l'amministratore del tuo pod!" do_you: "Vuoi..." - email_feedback: "Se preferisci, manda un feedback a %{link}" - email_link: "Email" feature_suggestion: "...proporre un'%{link}?" find_a_bug: "...segnalare un %{link}?" have_a_question: "...fare una %{link}?" - here_to_help: "La comunità di Diaspora è qui!" + here_to_help: "La comunità Diaspora è qui per aiutarti!" mail_podmin: "Email amministratore del pod" need_help: "Hai bisogno di aiuto?" tag_bug: "problema" tag_feature: "idea" tag_question: "domanda" - tutorial_link_text: "Guide" + tutorial_link_text: "Istruzioni" tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: un aiuto per i tuoi primi passi." introduce_yourself: "Questo è il tuo stream. Sali a bordo e presentati!" - keep_diaspora_running: "Velocizza lo sviluppo di diaspora con una donazione mensile!" keep_pod_running: "Mantieni %{pod} veloce e scattante, la tua donazione mensile sarà il caffè per i nostri server!" new_here: follow: "Segui %{link} per dare il benvenuto ai nuovi iscritti su Diaspora*!" learn_more: "Scopri i dettagli" title: "Saluta i nuovi arrivati" - no_contacts: "Nessun contatto" - no_tags: "+ Cerca tag da seguire" - people_sharing_with_you: "Persone che condividono con te" - post_a_message: "invia un messaggio >>" services: content: "Puoi collegare i seguenti servizi a Diaspora:" - heading: "Servizi connessi" - unfollow_tag: "Smetti di seguire #%{tag}" + heading: "Connetti i servizi" welcome_to_diaspora: "Benvenuto in diaspora, %{name}!" - new: - create: "Crea" - name: "Nome (visibile solo a te)" no_contacts_message: - community_spotlight: "in evidenza nella comunità " + community_spotlight: "Evidenzia tra i membri della comunità " or_spotlight: "Oppure puoi iniziare a condividere con %{link}" try_adding_some_more_contacts: "Puoi cercare o invitare altri contatti." you_should_add_some_more_contacts: "Dovresti aggiungere qualche altro contatto!" - no_posts_message: - start_talking: "Ancora nessuno ha scritto nulla!" seed: acquaintances: "Conoscenti" family: "Famiglia" @@ -201,33 +164,25 @@ it: update: failure: "Il tuo aspetto, %{name}, ha un nome troppo lungo per poter essere salvato." success: "Il tuo aspetto, %{name}, è stato modificato con successo." - back: "Indietro" blocks: create: failure: "Non posso ignorare quell'utente. #evasion" - success: "Ok, non vedrai più quell'utente nel tuo stream. #silencio!" + success: "Ok, non vedrai più quell'utente nel tuo stream. #silenzio!" destroy: - failure: "Non posso smettere di ignorare l'utente. #evasion" + failure: "Non è possibile ignorare l'utente. #evasion" success: "Vediamo cosa hanno da dire! #sayhello" bookmarklet: explanation: "Condividi su diaspora* quando vuoi aggiungendo %{link} tra i preferiti." heading: "Bookmarklet" post_something: "Pubblica su Diaspora" - post_success: "Inviato! Chiusura in corso!" cancel: "Annulla" comments: new_comment: comment: "Commenta" commenting: "Invio commento in corso..." - one: "1 commento" - other: "%{count} commenti" - zero: "nessun commento" contacts: - create: - failure: "Impossibile creare il contatto" index: add_a_new_aspect: "Aggiungi un aspetto" - add_to_aspect: "aggiungi i contatti a %{name}" all_contacts: "Tutti i contatti" community_spotlight: "In evidenza nella comunità " my_contacts: "I miei contatti" @@ -236,41 +191,28 @@ it: only_sharing_with_me: "Condividono con me" start_a_conversation: "Inizia una conversazione" title: "Contatti" - your_contacts: "I tuoi contatti" - sharing: - people_sharing: "Persone che condividono con te:" spotlight: community_spotlight: "In evidenza nella comunità " suggest_member: "Suggerisci un utente" conversations: - conversation: - participants: "Partecipanti" create: fail: "Messaggio non valido" no_contact: "Hey, devi prima aggiungere un contatto!" sent: "Messaggio inviato" - helper: - new_messages: - one: "%{count} nuovo messaggio" - other: "%{count} nuovi messaggi" - zero: "Nessun nuovo messaggio" index: - create_a_new_conversation: "Inizia una nuova conversazione" inbox: "In arrivo" new_conversation: "Nuova conversazione" - no_conversation_selected: "nessuna conversazione selezionata" - no_messages: "nessun messaggio" + no_messages: "Nessun messaggio" new: - abandon_changes: "Annulla i cambiamenti?" send: "Invia" sending: "Invio in corso..." - subject: "oggetto" - to: "a" + subject: "Oggetto" + to: "A" new_conversation: fail: "Messaggio non valido" show: - delete: "elimina e blocca la conversazione" - reply: "rispondi" + delete: "Elimina la conversazione" + reply: "Rispondi" replying: "Invio risposta..." date: formats: @@ -282,10 +224,6 @@ it: error_messages: helper: correct_the_following_errors_and_try_again: "Correggi i seguenti errori e riprova." - invalid_fields: "Campi non validi" - login_try_again: "Per favore <a href='%{login_link}'> accedi </a> e riprova" - post_not_public: "Il post che stai cercando di vedere non è pubblico!" - post_not_public_or_not_exist: "Il post che stai cercando di visualizzare non è pubblico o non esiste!" fill_me_out: "Scrivi qui" find_people: "Cerca persone o #tag" help: @@ -306,7 +244,7 @@ it: change_aspect_of_post_q: "Dopo aver postato qualcosa posso cambiare gli aspetti a cui è visibile?" contacts_know_aspect_a: "No. Non possono sapere in nessun caso il nome dell'aspetto di cui fanno parte." contacts_know_aspect_q: "I miei contatti possono scoprire in quali aspetti li ho messi?" - contacts_visible_a: "Se scegli questa opzione, i contatti di quell'aspetto potranno vedere tutti gli altri che ne fanno parte sotto la tua foto. E' opportuno scegliere questa opzione solo se i contatti nell'aspetto si conoscono già tra loro. Comunque non potranno sapere il nome che hai dato all'aspetto." + contacts_visible_a: "Se scegli questa opzione, i contatti di quell'aspetto potranno vedere tutti gli altri che ne fanno parte sotto la tua immagine. E' opportuno scegliere questa opzione solo se i contatti nell'aspetto si conoscono già tra loro. Comunque non potranno sapere il nome che hai dato all'aspetto." contacts_visible_q: "Cosa significa \"rendi i contatti in questo aspetto visibili gli uni agli altri\"?" delete_aspect_a: "Nella lista dei tuoi aspetti, sulla colonna laterale della pagina principale, passa con il mouse sull'aspetto che vuoi eliminare. Clicca sulla piccola matita che comparirà a destra. Nel riquadro che comparirà dovrai premere il bottone per eliminare l'aspetto." delete_aspect_q: "Come posso eliminare un aspetto?" @@ -314,11 +252,11 @@ it: person_multiple_aspects_q: "Posso mettere una persona in più aspetti?" post_multiple_aspects_a: "Sì. Quando scrivi un post, usa il bottone per selezionare e deselezionare gli aspetti. Il tuo post sarà visibile a tutti gli aspetti che scegli. Puoi anche scegliere gli aspetti dalla colonna laterale. Gli aspetti che avrai selezionato nella lista a sinistra saranno attivi anche nel bottone quando inizierai a scrivere il nuovo post." post_multiple_aspects_q: "Posso fare un post che sia visibile a molti aspetti?" - remove_notification_a: "No." + remove_notification_a: "No. Non verranno neanche informati quando li aggiungi ad altri aspetti oltre a quelli già condivisi." remove_notification_q: "Se rimuovo qualcuno da un aspetto o da tutti i miei aspetti, gli sarà notificato?" rename_aspect_a: "Sì. Nell'elenco dei tuoi aspetti nella pagina principale fai clic sulla piccola matita che compare alla destra del nome dell'aspetto. Scegli \"rinomina\" nel riquadro che comparirà ." rename_aspect_q: "Posso rinominare un aspetto?" - restrict_posts_i_see_a: "Sì. Clicca su \"Aspetti\" nella colonna laterale e poi scegli i singoli aspetti che vuoi vedere nella lista. Così appariranno solamente i post delle persone che appartengono agli aspetti scelti." + restrict_posts_i_see_a: "Sì. Clicca su \"Aspetti\" nella colonna laterale e poi scegli i singoli aspetti che vuoi vedere nella lista. Così si appariranno solamente i post delle persone che appartengono agli aspetti scelti." restrict_posts_i_see_q: "Posso restringere l'elenco dei post, in modo da vedere solo quelli di certi aspetti?" title: "Aspetti" what_is_an_aspect_a: "Gli aspetti sono il sistema per raggruppare i tuoi contatti su diaspora*. Ogni aspetto è una delle facce che mostri al mondo. Potrebbe essere come ti presenti a lavoro o alla tua famiglia, ma anche ai tuoi amici o a un club di cui fai parte." @@ -328,12 +266,12 @@ it: foundation_website: "Sito web diaspora foundation" getting_help: get_support_a_hashtag: "Invia la domanda in un post pubblico in diaspora* usando %{question} come hashtag" - get_support_a_irc: "raggiungici in %{irc} (Live chat)" + get_support_a_irc: "Raggiungici in %{irc} (Live chat)" get_support_a_tutorials: "Controlla i nostri %{tutorials}" - get_support_a_website: "visita il nostro %{link}" - get_support_a_wiki: "cerca il %{link}" + get_support_a_website: "Visita il nostro %{link}" + get_support_a_wiki: "Cerca il %{link}" get_support_q: "Cosa fare se la mia domanda non è in queste FAQ? Dove altro posso avere supporto?" - getting_started_a: "Sei fortunato. Prova i %{tutorial_series} sul nostro sito. Ti guideranno passo passo nella registrazione e ti spiegheranno i concetti base di cui hai bisogno per iniziare ad usare diaspora" + getting_started_a: "Sei fortunato. Prova i %{tutorial_series} sul nostro sito. Ti guiderà passo passo nella registrazione e ti spiegherà i concetti base di cui hai bisogno per iniziare ad usare diaspora" getting_started_q: "Aiuto! Ho bisogno di informazioni di base per iniziare!" title: "Ottenere aiuto" getting_started_tutorial: "Serie di tutorial \"per inziare\"" @@ -356,6 +294,7 @@ it: diaspora_app_q: "Esiste l'app diaspora per Android o iOS?" photo_albums_a: "Al momento no. Tuttavia puoi vedere uno stream delle loro foto caricate dalla sezione foto nella barra laterale del loro profilo." photo_albums_q: "Ci sono album di foto o video?" + subscribe_feed_q: "Posso seguire i contributi pubblici di una persona con un Feedreader?" title: "Varie" pods: find_people_a: "Puoi invitare i tuoi amici inviando per email il link che trovi sulla barra laterale. Inizia a seguire dei #tag per scoprire altre persone con cui hai interessi in comune e aggiungi ai tuoi aspetti quelle interessanti. Puoi anche scrivere un post annunciando che sei #NuovoUtente e vedrai che qualcuno si presenterà per darti il benvenuto." @@ -363,22 +302,22 @@ it: title: "Pod" use_search_box_a: "Se conosci il loro identificativo su diaspora* (del tipo nomeutente@nomepod.org), puoi usarlo per effettuare la ricerca. Se siete sullo stesso pod puoi effettuare la ricerca anche con il solo nome utente. Un'alternativa è cercare il nome che hanno scelto per il loro profilo (il nome che compare a schermo). Se una ricerca non ha risultati al primo tentativo prova di nuovo." use_search_box_q: "Come uso il campo di ricerca per trovare qualcuno in particolare?" - what_is_a_pod_a: "Un pod è un server con installato il software diaspora* ed è connesso alla rete di diaspora*. \"Pod\" è una metafora, come per una pianta lo stelo sostiene i semi, il server conserva gli account degli utenti. Ci sono molti pod differenti al mondo, ma puoi aggiungere amici da tutti i pod e comunicare con loro. Il funzionamento di diaspora* è simile a quello del sistema email: ci sono molti server pubblici, quelli privati e, con un po' di impegno, puoi creare anche un tuo server personale." + what_is_a_pod_a: "Un pod è un server sul quale è installato il software diaspora* ed è connesso alla rete di diaspora*. \"Pod\" è una metafora: come per una pianta lo stelo sostiene i semi, il server conserva gli account degli utenti. Ci sono molti pod differenti al mondo, ma puoi aggiungere amici da tutti i pod e comunicare con loro. Il funzionamento di diaspora* è simile a quello del sistema email: ci sono molti server pubblici, quelli privati e, con un po' di impegno, puoi creare anche un tuo server personale." what_is_a_pod_q: "Cosa è un pod?" posts_and_posting: - char_limit_services_a: "In questo caso il tuo messaggio è limitato ad un numero inferiore di caratteri (140 nel caso di Twitter; 1000 nel caso di Tumblr), ed il numero di caratteri rimanenti a disposizione è indicato quando l'icona del servizio è attiva. Puoi comunque inviare post a questi servizi, ma se il tuo post supera il numero di caratteri il testo risulterà troncato dagli stessi servizi." + char_limit_services_a: "In questo caso il tuo messaggio è limitato ad un numero inferiore (140 nel caso di Twitter; 1000 nel caso di Tumblr), e il numero di caratteri rimanenti a disposizione è indicato quando l'icona del servizio è attiva. Puoi comunque inviare post a questi servizi, ma se il tuo post supera il numero di caratteri il testo risulterà troncato dagli stessi servizi." char_limit_services_q: "Quale è il limite di caratteri per messaggi condivisi tramite servizi che hanno un limite di caratteri inferiore?" character_limit_a: "65535 caratteri. Esattamente 65395 caratteri in più di quanti ne hai su Twitter! ;)" character_limit_q: "Quale è il limite di lunghezza dei post?" - embed_multimedia_a: "Puoi semplicemente inserire l'URL nel post (per esempio http://www.youtube.com/watch?v=nnnnnnnnnnn ) e il contenuto verrà visualizzato automaticamente. Alcuni dei siti supportati sono: YouTube, Vimeo, SoundCloud, Flickr ed alcuni altri. diaspora* realizza questa funzionalità grazie a oEmbed. Aggiungiamo via via sempre nuovi siti. Ma ricorda sempre di aggiungere i URL originali, non dei link abbreviati o con altri operatori alla fine; inoltre, potrebbe essere necessario qualche attimo prima che compaia l'anteprima dopo aver aggiornato la pagina." + embed_multimedia_a: "Puoi semplicemente inserire l'URL nel post (per esempio http://www.youtube.com/watch?v=nnnnnnnnnnn ) e il contenuto verrà visualizzato automaticamente. Alcuni dei siti supportati sono: YouTube, Vimeo, SoundCloud, Flickr ed alcuni altri. diaspora* realizza questa funzionalità grazie a oEmbed. Aggiungeremo via via sempre nuovi siti. Ma ricorda sempre di aggiungere i URL originali, non dei link abbreviati o con altri operatori alla fine; inoltre, potrebbe essere necessario qualche attimo precedente all'anteprima dopo aver aggiornato la pagina." embed_multimedia_q: "Come posso inserire un contenuto multimediale come un video o un audio in un post?" format_text_a: "Puoi utilizzare un sistema semplice chiamato %{markdown}. Puoi trovare %{here} l'elenco di tutti i codici disponibili. Ma a questo punto ti sarà molto utile il bottone dell'anteprima, così potrai verificare il risultato prima di creare il post." format_text_q: "Come posso formattare il testo dei miei post (grassetto, corsivo, ecc.)?" - hide_posts_a: "Se sposti il mouse un cima al post, vedrai comparire una X a destra. Cliccandola nasconderai il post e non riceverai più le notifiche che lo riguardano. Potrai vedere il post cercandolo sulla pagina del profilo dell'autore." + hide_posts_a: "Se sposti il mouse in cima al post, vedrai comparire una X a destra. Cliccandola nasconderai il post e non riceverai più le notifiche che lo riguardano. Potrai vedere il post cercandolo sulla pagina del profilo dell'autore." hide_posts_q: "Come posso nascondere un post? Come posso smettere di ricevere notifiche da un post che ho commentato?" - image_text: "descrizione immagine" - image_url: "url immagine" - insert_images_a: "Clicca l'icona a forma di macchina fotografica per inserire un'immagine. Puoi cliccare di nuovo per inserire un'altra foto, oppure puoi scegliere di aggiungere più immagini in una volta sola." + image_text: "Descrizione immagine" + image_url: "URL immagine" + insert_images_a: "Clicca l'icona a forma di macchina fotografica per inserire un'immagine. Puoi cliccare di nuovo per inserirne un'altra, oppure puoi scegliere di aggiungere più immagini in una volta sola." insert_images_comments_a1: "Devi usare il codice markdown seguente" insert_images_comments_a2: "così potrai aggiungere immagini non solo ai commenti ma anche ai post." insert_images_comments_q: "Posso inserire immagini nei commenti?" @@ -390,7 +329,7 @@ it: stream_full_of_posts_li2: "I messaggi pubblici contengono un tag che stai seguendo. Per rimuoverli, smetti di seguire il tag." stream_full_of_posts_li3: "Post pubblici di utenti in evidenza. Questi possono essere rimossi cliccando sull'opzione \"mostra utenti in evidenza nello stream?\" nella scheda account delle tue impostazioni." stream_full_of_posts_q: "Perchè il mio stream è pieno di post di gente che non conosco e con cui non condivido nulla?" - title: "I post" + title: "Contributi e Post" private_posts: can_comment_a: "Solo gli utenti loggati in diaspora che hai inserito in questo aspect possono commentare o apprezzare il tuo post privato" can_comment_q: "Chi può commentare o apprezzare il mio post privato?" @@ -403,7 +342,7 @@ it: who_sees_post_q: "Quando posto un messaggio ad un Aspetto (es: un messaggio privato), chi può vederlo?" private_profiles: title: "Profili privati" - whats_in_profile_a: "Biografia, luogo, sesso e data di nascita. Sono tutti dati della sezione inferiore della pagina editabile del profilo. Tutte queste informazioni sono opzionali (sta a te se inserirle o no). Gli utenti registrati che hai aggiunto ai tuoi aspetti sono le sole persone che possono vedere il tuo profilo privato. Essi potranno anche vedere i post privati pertinenti agli aspetti di cui fanno parte, assieme ai post pubblici, quando visitano la pagina del tuo profilo." + whats_in_profile_a: "Biografia, luogo, sesso e data di nascita. Sono tutti dati della sezione inferiore della pagina editabile del profilo. Tutte queste informazioni sono opzionali (sta a te inserirle o no). Gli utenti registrati che hai aggiunto ai tuoi aspetti sono le sole persone che possono vedere il tuo profilo privato. Essi potranno anche vedere i post privati pertinenti agli aspetti di cui fanno parte, assieme ai post pubblici, quando visitano la pagina del tuo profilo." whats_in_profile_q: "Cosa c'è nel mio profilo privato?" who_sees_profile_a: "Qualunque utente loggato con cui lo stai condividendo (cioè, lo hai aggiunto ad uno dei tuoi aspetti). Tuttavia, le persone che ti seguono, ma che tu non segui, vedranno solo le tue informazioni pubbliche." who_sees_profile_q: "Chi vede il mio profilo privato?" @@ -423,9 +362,9 @@ it: who_sees_post_q: "Quando posto qualcosa pubblicamente, chi può vederla?" public_profiles: title: "Profili pubblici" - what_do_tags_do_a: "Aiutano le persone a conoscerti. L'immagine del tuo profilo apparirà anch'essa a sinistra di quelle particolari pagine di tag, insieme con chiunque altro le abbia nel loro profilo pubblico." + what_do_tags_do_a: "Aiutano le persone a conoscerti meglio. L'immagine del tuo profilo apparirà anch'essa a sinistra di quelle particolari pagine di tag, insieme con chiunque altro le abbia nel loro profilo pubblico." what_do_tags_do_q: "Cosa fanno le tag nel mio profilo pubblico?" - whats_in_profile_a: "Il tuo nome, le cinque tag che hai scelto per descriverti, e la tua foto. Sono le cose nella sezione superiore della pagina modificabile del profilo. Puoi rendere queste informazioni di profilo quanto anonime o identificabili desideri. Le tue pagine di profilo mostrano anche qualunque post pubblico che hai creato." + whats_in_profile_a: "Il tuo nome, le cinque tag che hai scelto per descriverti, e la tua immagine di profilo. Sono le cose nella sezione superiore della pagina modificabile del profilo. Puoi rendere queste informazioni di profilo quanto anonime o identificabili desideri. Le tue pagine di profilo mostrano anche qualunque post pubblico che hai creato." whats_in_profile_q: "Cosa c'è nel mio profilo pubblico" who_sees_profile_a: "Qualunque utente loggato in diaspora*, così come il più ampio internet, può vederlo. Ogni profilo ha una URL diretta, perciò potrebbe essere linkata direttamente da siti esterni. Potrebbe essere indicizzata da motori di ricerca." who_sees_profile_q: "Chi vede il mio profilo pubblico?" @@ -440,7 +379,7 @@ it: sharing: add_to_aspect_a1: "Poniamo che Amy aggiunga Ben ad un Aspetto, ma Ben non abbia (ancora) aggiunto Amy ad un Aspetto." add_to_aspect_a2: "Questa è nota come condivisione assimetrica. Solo e quando Ben aggiungerà Amy ad un aspetto allora questa diventerà una condivisione mutua, con i post pubblici e rilevanti post privati di entrambi visibili nei relativi stream, etc. " - add_to_aspect_li1: "Bill riceverà una notifica che dirà che Amy ha \"iniziato a condividere\" con lui." + add_to_aspect_li1: "Ben riceverà una notifica che dirà che Amy ha \"iniziato a condividere\" con lui." add_to_aspect_li2: "Amy inizierà a vedere i post pubblici di Ben nel suo profilo." add_to_aspect_li3: "Amy non vedrà alcun post privato di Ben." add_to_aspect_li4: "Ben non vedrà i post pubblici o privati di Amy nel suo stream." @@ -467,101 +406,53 @@ it: title: "Tag" what_are_tags_for_a: "Le tag sono un modo per categorizzare un post, normalmente per argomento. Cercando un tag verranno mostrati tutti i post con quel tag (sia pubblici che privati). Ciò permette a coloro interessati a certi argomenti di trovare i post pubblici su di essi." what_are_tags_for_q: "A cosa servono i tag?" - third_party_tools: "tool di terze parti" + third_party_tools: "Tool di terze parti" title_header: "Aiuto" - tutorial: "guida" - tutorials: "guide" + tutorial: "Guida" + tutorials: "Guide" wiki: "wiki" - hide: "Nascondi" - ignore: "Ignora" - invitation_codes: - excited: "%{name} è entusiasta di vederti qui." invitations: a_facebook_user: "Un utente Facebook" check_token: not_found: "Token di invito non trovato" create: - already_contacts: "Questa persona è già tra i tuoi contatti" - already_sent: "Hai già invitato questa persona." empty: "Perfavore inserire almeno un indirizzo email." no_more: "Non hai più inviti a disposizione" note_already_sent: "Gli inviti sono stati già inviati a: %{emails}" - own_address: "Non puoi inviare un invito al tuo indirizzo." rejected: "Questi indirizzi email hanno dei problemi:" sent: "Gli inviti sono stati inviati a: " - edit: - accept_your_invitation: "Accetta il tuo invito" - your_account_awaits: "Il tuo account ti aspetta!" new: - already_invited: "Le seguenti persone non hanno accettato il tuo invito:" - aspect: "Aspetto" - check_out_diaspora: "Prova Diaspora!" codes_left: one: "Ti resta 1 invito" other: "Ti restano %{count} inviti" zero: "Ti restano 0 inviti" comma_separated_plz: "Puoi inserire più indirizzi di posta separati da virgole." - if_they_accept_info: "se accettano, saranno aggiunti all'aspetto in cui li hai invitati." invite_someone_to_join: "Invita qualcuno ad entrare in diaspora*!" language: "Lingua" paste_link: "Condividi questo link con i tuoi amici per invitarli su Diaspora*, puoi anche inviarlo per email." - personal_message: "Messaggio privato" - resend: "Invia di nuovo" send_an_invitation: "Spedisci un invito" - send_invitation: "Invito spedito" sending_invitation: "Invio dell'invito in corso..." - to: "A" layouts: application: back_to_top: "Torna all'inizio" powered_by: "POWERED BY DIASPORA*" public_feed: "Feed pubblici diaspora* di %{name}" - toggle: "attiva/disattiva versione mobile" - whats_new: "novità " - your_aspects: "i tuoi aspetti" + source_package: "Scaricare pacchetto fonte" + toggle: "Attiva/disattiva versione mobile" + whats_new: "Novità ?" header: - admin: "admin" - blog: "blog" - code: "codice" - help: "Aiuto" - login: "accedi" + code: "Codice" logout: "Esci" profile: "Profilo" - recent_notifications: "Notifiche recenti" settings: "Impostazioni" - view_all: "Elenco completo" - likes: - likes: - people_dislike_this: - one: "%{count} Non mi piace" - other: "%{count} Non mi piacciono" - zero: "0 Non mi piace" - people_like_this: - few: "%{count} mi piace" - many: "%{count} mi piace" - one: "%{count} mi piace" - other: "%{count} mi piace" - two: "%{count} mi piace" - zero: "0 mi piace" - people_like_this_comment: - few: "%{count} mi piace" - many: "%{count} mi piace" - one: "%{count} mi piace" - other: "%{count} mi piace" - two: "%{count} mi piace" - zero: "0 mi piace" limited: "Non pubblico" more: "Altro" - next: "successivo" - no_results: "La ricerca non ha risultati" + no_results: "La ricerca non ha prodotto risultati" notifications: also_commented: - few: "Anche %{actors} hanno commentato il %{post_link} di %{post_author}." - many: "Anche %{actors} hanno commentato il %{post_link} di %{post_author}." - one: "Anche %{actors} ha commentato il %{post_link} di %{post_author}." - other: "Anche %{actors} hanno commentato il %{post_link} di %{post_author}." - two: "Anche %{actors} hanno commentato il %{post_link} di %{post_author}." - zero: "%{actors} ha commentato il %{post_link} di %{post_author}." + one: "Anche %{actors} ha commentato %{post_link} di %{post_author}." + other: "Anche %{actors} hanno commentato %{post_link} di %{post_author}." + zero: "%{actors} ha commentato %{post_link} di %{post_author}." also_commented_deleted: one: "%{actors} ha commentato un post che è stato eliminato." other: "%{actors} hanno commentato un post che è stato eliminato." @@ -573,11 +464,6 @@ it: other: "%{actors} hanno commentato il tuo %{post_link}." two: "%{actors} hanno commentato il tuo %{post_link}." zero: "%{actors} ha commentato il tuo %{post_link}." - helper: - new_notifications: - one: "%{count} nuova notifica" - other: "%{count} nuove notifiche" - zero: "Nessuna nuova notifica" index: all_notifications: "Vedi tutte le notifiche" and: "e" @@ -625,7 +511,7 @@ it: reshared: one: "%{actors} ha condiviso il tuo %{post_link}." other: "%{actors} hanno condiviso il tuo %{post_link}." - zero: "%{actors} hanno condiviso il tuo %{post_link}." + zero: "%{actors} ha condiviso il tuo %{post_link}." reshared_post_deleted: few: "%{actors} hanno condiviso il post che hai eliminato." many: "%{actors} hanno condiviso il post che hai eliminato." @@ -642,8 +528,7 @@ it: zero: "%{actors} ha iniziato a condividere con te." notifier: a_post_you_shared: "un post." - accept_invite: "Accetta il tuo invito per Diaspora*!" - click_here: "clicca qui" + click_here: "Clicca qui" comment_on_post: reply: "Rispondi o leggi il post di %{name} >" confirm_email: @@ -672,7 +557,6 @@ it: liked: "A %{name} piace il tuo post" view_post: "Leggi il post >" mentioned: - mentioned: "ti ha menzionato in un post:" subject: "%{name} ti ha menzionato su Diaspora*" private_message: reply_to_or_view: "Rispondi o leggi questa conversazione >" @@ -684,7 +568,7 @@ it: view_post: "Leggi il post >" single_admin: admin: "L'amministratore di Diaspora" - subject: "Novità sul tuo account Diaspora:" + subject: "Un nuovo messaggio nel tuo account Diaspora:" started_sharing: sharing: "ha iniziato a condividere con te!" subject: "%{name} ha iniziato a condividere con te su Diaspora*" @@ -693,20 +577,9 @@ it: to_change_your_notification_settings: "per cambiare le opzioni delle notifiche" nsfw: "NSFW (non adatto ad un luogo di lavoro)" ok: "OK" - or: "o" - password: "Password" - password_confirmation: "Conferma password" people: add_contact: - invited_by: "hai ricevuto l'invito da" - add_contact_small: - add_contact_from_tag: "aggiungi contatto dal #tag" - aspect_list: - edit_membership: "modifica appartenenza all'aspetto" - helper: - is_not_sharing: "%{name} non condivide con te" - is_sharing: "%{name} sta condividendo con te" - results_for: " risultati per %{params}" + invited_by: "Hai ricevuto l'invito da" index: couldnt_find_them: "Non sei riuscito a trovarli?" looking_for: "Cerchi i post con il tag %{tag_link}?" @@ -714,104 +587,48 @@ it: no_results: "Ehi! Devi inserire qualcosa da cercare." results_for: "Risultati della ricerca di %{search_term}" search_handle: "Utilizza la loro ID diaspora* (nomeutente@pod.tld) per essere sicuro di trovare i tuoi amici." - searching: "ricerca in corso, devi avere pazienza..." + searching: "Ricerca in corso, devi avere pazienza..." send_invite: "Ancora niente? Manda un invito!" - one: "una persona" - other: "%{count} persone" person: - add_contact: "aggiungi contatto" - already_connected: "Già connesso" - pending_request: "Richiesta in sospeso" thats_you: "Sei tu!" profile_sidebar: bio: "biografia" born: "data di nascita" - edit_my_profile: "Modifica il mio profilo" gender: "sesso" - in_aspects: "negli aspetti" location: "Luogo" - photos: "Foto" - remove_contact: "rimuovi contatto" - remove_from: "Rimuovere %{name} da %{aspect}?" show: closed_account: "Questo account è stato chiuso." does_not_exist: "La persona non esiste!" has_not_shared_with_you_yet: "%{name} non ha ancora condiviso dei post con te!" - ignoring: "Stai ignorando tutti i post di %{name}." - incoming_request: "%{name} vuole condividere con te" - mention: "Menziona" - message: "Messaggio" - not_connected: "Non stai condividendo i post con questa persona" - recent_posts: "Post recenti" - recent_public_posts: "Post pubblici recenti" - return_to_aspects: "Torna alla pagina dei tuoi aspetti" - see_all: "Visualizza tutti" - start_sharing: "inizia a condividere" - to_accept_or_ignore: "per accettarla o ignorarla." - sub_header: - add_some: "aggiungi" - edit: "modifica" - you_have_no_tags: "non hai alcun tag!" - webfinger: - fail: "Spiacenti, non possiamo trovare %{handle}." - zero: "nessuna persona" photos: - comment_email_subject: "La foto di %{name}" create: integrity_error: "Il caricamento della foto non è riuscito. Sei sicuro che fosse un'immagine?" runtime_error: "Il caricamento della foto non è riuscito. Hai dimenticato di allacciare la cintura?" type_error: "Il caricamento della foto non è riuscito. Sei sicuro che fosse un'immagine?" destroy: notice: "Foto eliminata." - edit: - editing: "Modifica in corso" - new: - back_to_list: "Torna all'elenco" - new_photo: "Nuova foto" - post_it: "condividi!" new_photo: empty: "{file} è vuoto, per favore seleziona di nuovo i file senza includerlo." invalid_ext: "{file} ha un'estensione non valida. Sono permesse soltanto {extensions}." size_error: "{file} è troppo grande, la dimensione massima è {sizeLimit}." new_profile_photo: - or_select_one_existing: "oppure seleziona una delle %{photos} che hai caricato" upload: "Carica una nuova foto nel profilo!" - photo: - view_all: "guarda tutte le foto di %{name}" show: - collection_permalink: "permalink della collezione" - delete_photo: "Elimina foto" - edit: "modifica" - edit_delete_photo: "Modifica descrizione della foto / elimina foto" - make_profile_photo: "usa come immagine del profilo" show_original_post: "Mostra il post originale" - update_photo: "Aggiorna foto" - update: - error: "La modifica della foto non è riuscita." - notice: "Foto aggiornata con successo." posts: presenter: title: "Un post di %{name}" show: - destroy: "Elimina" - not_found: "Scusa, non riusciamo a trovare il post." - permalink: "permalink" photos_by: - few: "%{count} foto di %{author}" - many: "%{count} foto di %{author}" - one: "Una foto di %{author}" - other: "%{count} foto di %{author}" - two: "Due foto di %{author}" - zero: "Nessuna foto di %{author}" + one: "Una immagine di %{author}" + other: "%{count} immagine di %{author}" + zero: "Nessuna immagine di %{author}" reshare_by: "Condiviso da %{author}" - previous: "precedente" privacy: "Privacy" - privacy_policy: "Norme sulla privacy" profile: "Profilo" profiles: edit: allow_search: "Permetti ad altri di trovarti su Diaspora" - edit_profile: "Modifica il profilo" first_name: "Nome" last_name: "Cognome" update_profile: "Aggiorna il profilo" @@ -821,10 +638,8 @@ it: your_location: "Dove ti trovi" your_name: "Il tuo nome" your_photo: "La tua foto" - your_private_profile: "Il tuo profilo privato" - your_public_profile: "Il tuo profilo pubblico" your_tags: "Descriviti con 5 #tag" - your_tags_placeholder: "per esempio #cinema #viaggi #gattini #musica #cagliari" + your_tags_placeholder: "Per esempio #cinema #viaggi #gattini #musica #cagliari" update: failed: "Aggiornamento del profilo non riuscito" updated: "Profilo aggiornato" @@ -840,64 +655,25 @@ it: closed: "Su questo pod Diaspora le iscrizioni sono chiuse." create: success: "Ora fai parte di Diaspora!" - edit: - cancel_my_account: "Elimina il mio account" - edit: "Modifica %{name}" - leave_blank: "(lascia vuoto se non vuoi modificare)" - password_to_confirm: "(abbiamo bisogno della tua password attuale per confermare le modifiche)" - unhappy: "Triste?" - update: "Aggiorna" invalid_invite: "L'invito che hai usato non è più valido!" new: - create_my_account: "Crea il mio account!" email: "EMAIL" enter_email: "Inserisci un indirizzo email" enter_password: "Scegli una password (minimo 6 caratteri)" enter_password_again: "Scrivi di nuovo la password per verifica" enter_username: "Scegli un nome utente (usa solo lettere, numeri e trattino basso)" - join_the_movement: "Partecipa al movimento!" password: "PASSWORD" password_confirmation: "CONFERMA PASSWORD" sign_up: "ISCRIVITI" - sign_up_message: "Il Social Network con un ♥ così" submitting: "Invio..." terms_link: "Termini di servizio" username: "NOME UTENTE" - requests: - create: - sending: "Invio in corso..." - sent: "Hai chiesto di condividere con %{name}. Gli sarà notificato al prossimo accesso su diaspora*." - destroy: - error: "Seleziona un aspetto!" - ignore: "Richiesta di contatto ignorata." - success: "Hai iniziato a condividere." - helper: - new_requests: - few: "%{count} nuove richieste!" - many: "%{count} nuove richieste!" - one: "una nuova richiesta!" - other: "%{count} nuove richieste!" - two: "%{count} nuove richieste!" - zero: "nessuna nuova richiesta" - manage_aspect_contacts: - existing: "Contatti esistenti" - manage_within: "Gestisci contatti" - new_request_to_person: - sent: "richiesta inviata!" reshares: comment_email_subject: "La condivisione di %{resharer} del post di %{author}" - create: - failure: "C'è stato un errore nel condividere questo post." reshare: deleted: "Il post originale è stato eliminato dall'autore." - reshare: - one: "%{count} condivisione" - other: "%{count} condivisioni" - zero: "%{count} condivisioni" reshare_confirmation: "Vuoi condividere il post di %{author} con i tuoi contatti?" - reshare_original: "Condividi l'originale" reshared_via: "condiviso via" - show_original: "Mostra l'originale" search: "Cerca" services: create: @@ -908,39 +684,16 @@ it: destroy: success: "Autenticazione rimossa con successo." failure: - error: "si è verificato un errore durante la connessione a quel servizio" - finder: - fetching_contacts: "diaspora* sta importando i tuoi amici su %{service}, il risultato sarà visibile tra alcuni minuti." - no_friends: "Non ho trovato amici su Facebook." - service_friends: "Amici su %{service}" + error: "Si è verificato un errore durante la connessione a quel servizio" index: - disconnect: "disconnetti" + disconnect: "Disconnetti" edit_services: "Modifica servizi" logged_in_as: "accesso effettuato come" - really_disconnect: "disconnettere %{service}?" + really_disconnect: "Disconnettersi da %{service}?" services_explanation: "Il collegamento ad altri servizi ti dà la possibilità di pubblicare i post che invii su diaspora*." - inviter: - click_link_to_accept_invitation: "Vai a questo indirizzo per accettare l'invito" - join_me_on_diaspora: "Vieni con me su DIASPORA*" - remote_friend: - invite: "invita" - not_on_diaspora: "Non ancora su Diaspora" - resend: "invia di nuovo" settings: "Impostazioni" - share_visibilites: - update: - post_hidden_and_muted: "Il post di %{name} è stato nascosto e le notifiche disattivate." - see_it_on_their_profile: "Se vuoi vedere gli aggiornamenti di questi post, visita il profilo di %{name}." shared: - add_contact: - add_new_contact: "Aggiungi un nuovo contatto" - create_request: "Cerca per ID" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Inserisci un nome utente Diaspora" - know_email: "Conosci i loro indirizzi email? Dovresti invitarli" - your_diaspora_username_is: "Il tuo nome utente (ID) è: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Aggiungi" toggle: few: "In %{count} aspetti" many: "In %{count} aspetti" @@ -948,39 +701,24 @@ it: other: "In %{count} aspetti" two: "In %{count} aspetti" zero: "Aggiungi" - contact_list: - all_contacts: "Tutti i contatti" - footer: - logged_in_as: "accesso effettuato come %{name}" - your_aspects: "i tuoi aspetti" invitations: by_email: "Via email" - dont_have_now: "Per il momento non ne hai, ma altri arriveranno presto!" - from_facebook: "Da Facebook" - invitations_left: "%{count} rimanenti" - invite_someone: "Invita qualcuno" invite_your_friends: "Invita i tuoi amici" invites: "Inviti" - invites_closed: "Al momento non è permesso spedire inviti per questo pod Diaspora." share_this: "Condividi questo link tramite email, blog, o altri social network!" - notification: - new: "Nuovo %{type} da %{from}" public_explain: atom_feed: "Atom feed" control_your_audience: "Controlla il tuo pubblico" - logged_in: "accesso effettuato su %{service}" - manage: "gestisci i servizi collegati" + logged_in: "Accesso effettuato su %{service}" + manage: "Gestisci i servizi collegati" new_user_welcome_message: "Usa i #tag per classificare i post e trovare chi ha i tuoi stessi interessi. Richiama l'attenzione di chi vuoi usando le @Menzioni" outside: "I messaggi pubblici saranno visibili a persone al di fuori di Diaspora." share: "Condividi" title: "Configura i servizi collegati" visibility_dropdown: "Usa questo menu per cambiare la visibilità del tuo post. (Ti suggeriamo di rendere pubblico il primo che stai scrivendo.)" publisher: - all: "tutti" - all_contacts: "tutti i contatti" discard_post: "Elimina il post" get_location: "Ottieni la tua posizione" - make_public: "rendi pubblico" new_user_prefill: hello: "Ciao a tutti, sono un #%{new_user_tag}." i_like: "I miei interessi sono %{tags}." @@ -988,33 +726,14 @@ it: newhere: "NuovoUtente" poll: add_a_poll: "Aggiungi un sondaggio" - option: "Opzione 1" - post_a_message_to: "Invia un messaggio a %{aspect}" posting: "Invio in corso..." - preview: "Anteprima" - publishing_to: "stai condividendo con: " remove_location: "Rimuovi posizione" share: "Condividi" - share_with: "condividi con" upload_photos: "Carica foto" whats_on_your_mind: "A cosa stai pensando?" - reshare: - reshare: "Condividi" stream_element: - connect_to_comment: "Segui questo utente per commentare il post" - currently_unavailable: "al momento non è possibile commentare" - dislike: "Non mi piace" - hide_and_mute: "Nascondi il post e disattiva le notifiche" - ignore_user: "Ignora %{name}" - ignore_user_description: "Vuoi ignorare questo utente e rimuoverlo da tutti gli aspetti?" - like: "Mi piace" - nsfw: "Questo post è stato segnato dall'autore come NSFW (non adatto a un luogo di lavoro). %{link}" - shared_with: "Condiviso con: %{aspect_names}" - show: "mostra" - unlike: "Non mi piace più" via: "via %{link}" - via_mobile: "via mobile" - viewable_to_anyone: "Questo post è visibile a tutti sul web" + via_mobile: "Via mobile" simple_captcha: label: "Inserisci il codice nel box" message: @@ -1024,19 +743,9 @@ it: status_messages: create: success: "Menzionati con successo: %{names}" - destroy: - failure: "L'eliminazione del post non è riuscita" - helper: - no_message_to_display: "Nessun messaggio da visualizzare." new: mentioning: "Stai menzionando: %{person}" - too_long: "Per favore scrivi i tuoi stati con meno di %{count} carattere. Al momento ci sono %{current_length} caratteri" - stream_helper: - hide_comments: "Nascondi i commenti" - show_comments: - one: "Mostra un altro commento" - other: "Mostra gli altri %{count} commenti" - zero: "Nessun altro commento" + too_long: "Per favore, commenta con meno di %{count} carattere. Al momento sono %{current_length} caratteri" streams: activity: title: "Attività " @@ -1062,22 +771,11 @@ it: title: "Attività pubblica" tags: title: "Post con tag: %{tags}" - tag_followings: - create: - failure: "Errore nel tentativo di seguire: #%{name}. Lo stai già seguendo?" - none: "Non puoi seguire un tag vuoto!" - success: "Fantastico! Hai iniziato a seguire #%{name}." - destroy: - failure: "Non è stato possibile smettere di seguire #%{name}. Lo stavi ancora seguendo?" - success: "Peccato! Hai appena smesso di seguire #%{name}." tags: show: follow: "Segui #%{tag}" - following: "Stai seguendo #%{tag}" none: "Il tag vuoto non esiste!" - stop_following: "Smetti di seguire #%{tag}" - terms_and_conditions: "Termini e condizioni d'uso" - undo: "Annullare?" + stop_following: "Non seguire più #%{tag}" username: "Nome Utente" users: confirm_email: @@ -1085,10 +783,10 @@ it: email_not_confirmed: "L'email non è stata attivata. C'è un errore nel link?" destroy: no_password: "Per favore inserisci la password per chiudere l'account." - success: "Il tuo account è stato bloccato. Il processo di chiusura dovrebbe essere completato in circa 20 minuti. Grazie per aver provato diaspora*." + success: "Il tuo account è stato bloccato. Il processo di chiusura dovrebbe essere completato tra circa 20 minuti. Grazie per aver provato diaspora*." wrong_password: "La password inserita non corrisponde." edit: - also_commented: "qualcuno ha commentato un post che hai commentato" + also_commented: "qualcuno ha risponde a un tuo post" auto_follow_aspect: "Scegli un aspetto per gli utenti seguiti in automatico:" auto_follow_back: "Segui automaticamente chi inizia a seguirti" change: "Cambia" @@ -1098,23 +796,20 @@ it: character_minimum_expl: "deve essere di almeno sei caratteri" close_account: dont_go: "Dai, non te ne andare!" - if_you_want_this: "Se vuoi davvero farlo, scrivi la tua password e clicca sul bottone 'Chiudi l'account'" lock_username: "Il tuo nome utente verrà bloccato. Non potrai creare un nuovo account su questo pod con lo stesso ID." locked_out: "Sarai disconnesso e non potrai più accedere al tuo account fino a che non è stato eliminato." make_diaspora_better: "Vorremmo che tu ci aiutassi a migliorare diaspora*, considera che puoi darci una mano invece di andare via. Se sei davvero convinto, vogliamo che tu sappia come funzionerà la rimozione del tuo account." mr_wiggles: "Il Fantasma Formaggino ti perseguiterà perché te ne vai!" - no_turning_back: "Al momento, non è possibile tornare indietro! Se sei veramente sicuro allora inserisci la tua password qui sotto." - what_we_delete: "Cancelleremo tutti i tuoi post e i dati del profilo nel tempo più breve possibile. I commenti che hai lasciato su post di altre persone rimarranno visibili ma verranno associati al tuo ID di diaspora* al posto che al tuo nome." + no_turning_back: "Al momento, non è possibile tornare indietro! Se sei veramente sicuro allora inserisci la tua password in basso." + what_we_delete: "Cancelleremo tutti i tuoi post e i dati del profilo nel minor' tempo possibile. I commenti che hai lasciato su post di altre persone rimarranno visibili ma verranno associati al tuo ID di diaspora* e non al tuo nome." close_account_text: "Chiudi l'account" comment_on_post: "qualcuno commenta un tuo post" current_password: "Password attuale" current_password_expl: "quella con cui accedi..." - download_photos: "scarica le mie foto" edit_account: "Modifica account" email_awaiting_confirmation: "Il link di attivazione è stato spedito a %{unconfirmed_email}. Continueremo ad usare la tua email originale %{email} finché non cliccherai sul link e attiverai il nuovo indirizzo." export_data: "Esporta dati" following: "Impostazioni dei contatti" - getting_started: "Preferenze nuovo utente" liked: "a qualcuno piace un tuo post" mentioned: "sei menzionato in un post" new_password: "Nuova password" @@ -1124,24 +819,23 @@ it: show_community_spotlight: "Mostra nel tuo stream anche gli utenti in evidenza" show_getting_started: "Mostra la guida iniziale" started_sharing: "qualcuno ha iniziato a seguirti" - stream_preferences: "Preferenze dello stream" + stream_preferences: "Impostazioni dello stream" your_email: "La tua email" your_handle: "Il tuo ID" getting_started: awesome_take_me_to_diaspora: "Fantastico! Fammi entrare in Diaspora*" community_welcome: "La comunità di diaspora* ti dà il benvenuto a bordo!" connect_to_facebook: "Possiamo rendere le cose veloci con %{link} a diaspora*. Così caricherai il nome e la tua foto, oltre che abilitare la condivisione dei post." - connect_to_facebook_link: "collegando il tuo account Facebook" + connect_to_facebook_link: "Collegando il tuo account Facebook" hashtag_explanation: "Gli hashtags ti permettono di parlare dei tuoi interessi e di seguirli. Sono anche un ottimo sistema per trovare nuove persone su diaspora*." hashtag_suggestions: "Prova a seguire tag tipo #art, #movies, #gif, ecc." - saved: "Salvato!" well_hello_there: "Ciao!" what_are_you_in_to: "Di cosa ti interessi?" who_are_you: "Chi sei?" privacy_settings: ignored_users: "Utenti ignorati" stop_ignoring: "Smetti di ignorare" - title: "Impostazioni privacy" + title: "Impostazioni di privacy" public: does_not_exist: "L'utente %{username} non esiste!" update: @@ -1156,13 +850,6 @@ it: settings_updated: "Le impostazioni sono state modificate" unconfirmed_email_changed: "L'email è cambiata. E' necessario attivare l'indirizzo." unconfirmed_email_not_changed: "Impossibile cambiare email" - webfinger: - fetch_failed: "impossibile recuperare il profilo webfinger da %{profile_url}" - hcard_fetch_failed: "impossibile recuperare l'hcard di %{account}" - no_person_constructed: "Non si può risalire a una persona da questa hcard." - not_enabled: "webfinger non attivo sull'host di %{account}" - xrd_fetch_failed: "impossibile recuperare il xrd dall'account %{account}" - welcome: "Benvenuto!" will_paginate: next_label: "successivo »" previous_label: "« precedente" \ No newline at end of file diff --git a/config/locales/diaspora/ja.yml b/config/locales/diaspora/ja.yml index c7891bcd2f47af608c206e60a9fb59d869609cf9..69442e62afe2332502821a09eaf7679d3d3bf248 100644 --- a/config/locales/diaspora/ja.yml +++ b/config/locales/diaspora/ja.yml @@ -6,11 +6,11 @@ ja: _applications: "アプリケーション" - _comments: "コメント" _contacts: "連絡先" - _home: "ホーム" - _photos: "写真" + _help: "ヘルプ" _services: "サービス" + _statistics: "統計" + _terms: "æ¡ä»¶" account: "アカウント" activerecord: errors: @@ -23,6 +23,14 @@ ja: attributes: diaspora_handle: taken: "æ—¢ã«ä½¿ã‚ã‚Œã¦ã„ã¾ã™ã€‚" + poll: + attributes: + poll_answers: + not_enough_poll_answers: "å分ãªæŠ•ç¥¨ã®é¸æŠžè‚¢ãŒæä¾›ã•ã‚Œã¦ã„ã¾ã›ã‚“。" + poll_participation: + attributes: + poll: + already_participated: "ã‚ãªãŸã¯ã™ã§ã«ã“ã®æŠ•ç¥¨ã«å‚åŠ ã—ã¾ã—ãŸï¼" request: attributes: from_id: @@ -30,7 +38,7 @@ ja: reshare: attributes: root_guid: - taken: "You've already reshared that post!" + taken: "ãˆã£ï¼Ÿ ã™ã§ã«ã“ã®æŠ•ç¨¿ã‚’共有ã—ã¦ã„ã¾ã™ï¼" user: attributes: email: @@ -38,28 +46,150 @@ ja: person: invalid: "無効ã§ã™ã€‚" username: - invalid: "is invalid. We only allow letters, numbers, and underscores" + invalid: "ã¯ç„¡åŠ¹ã§ã™ã€‚æ–‡å—ã€æ•°å—ã€ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢ã®ã¿åˆ©ç”¨ã§ãã¾ã™ã€‚" taken: "æ—¢ã«ä½¿ã‚ã‚Œã¦ã„ã¾ã™ã€‚" admins: admin_bar: - report: "レãƒãƒ¼ãƒˆ" + dashboard: "ダッシュボード" + pages: "ページ" + pod_network: "ãƒãƒƒãƒ‰ ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" + pod_stats: "ãƒãƒƒãƒ‰ã®çŠ¶æ…‹" + report: "å ±å‘Š" + sidekiq_monitor: "Sidekiq モニター" user_search: "ユーザー検索" + weekly_user_stats: "週次ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼çµ±è¨ˆ" + dashboard: + fetching_diaspora_version: "最新ã®ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©* ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’判æ–ã—ã¦ã„ã¾ã™..." + pod_status: "ãƒãƒƒãƒ‰ ステータス" + pods: + pod_network: "ãƒãƒƒãƒ‰ ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" stats: + 2weeks: "2 週間" 50_most: "最も人気ã®ã‚ã‚‹50ã®ã‚¿ã‚°" + comments: + other: "%{count} コメント" + zero: "コメントãªã—" + current_segment: "ç¾åœ¨ã®ã‚»ã‚°ãƒ¡ãƒ³ãƒˆã¯ã€<b>%{post_day}</b> ã‹ã‚‰ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚ãŸã‚Š <b>%{post_yest}</b> 投稿ã®å¹³å‡ã§ã™" + daily: "毎日" + display_results: "<b>%{segment}</b> セグメントã‹ã‚‰çµæžœã‚’表示ã—ã¦ã„ã¾ã™" + go: "実行" + month: "月" + posts: + other: "%{count} 投稿" + zero: "投稿ãªã—" + shares: + other: "%{count} 共有" + zero: "共有ãªã—" + tag_name: "ã‚¿ã‚°å: <b>%{name_tag}</b> 件数: <b>%{count_tag}</b>" + usage_statistic: "利用統計" + users: + other: "%{count} ユーザー" + zero: "ユーザーãªã—" + week: "週" + user_entry: + account_closed: "アカウントを削除ã—ã¾ã—ãŸ" + diaspora_handle: "ダイアスãƒãƒ©* ãƒãƒ³ãƒ‰ãƒ«" + email: "メール" + guid: "GUID" + id: "ID" + invite_token: "招待トークン" + last_seen: "最後ã«å‚ç…§" + ? "no" + : ã„ã„㈠+ nsfw: "#nsfw" + unknown: "ä¸æ˜Ž" + ? "yes" + : ã¯ã„ user_search: + account_closing_scheduled: "%{name} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯å‰Šé™¤ã•ã‚Œã‚‹äºˆå®šã§ã™ã€‚ã“ã‚Œã¯ã™ãã«å‡¦ç†ã•ã‚Œã¾ã™..." + account_locking_scheduled: "%{name} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ãƒãƒƒã‚¯ã•ã‚Œã‚‹äºˆå®šã§ã™ã€‚ã“ã‚Œã¯ã™ãã«å‡¦ç†ã•ã‚Œã¾ã™..." + account_unlocking_scheduled: "%{name} ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ãƒãƒƒã‚¯è§£é™¤ã•ã‚Œã‚‹äºˆå®šã§ã™ã€‚ã“ã‚Œã¯ã™ãã«å‡¦ç†ã•ã‚Œã¾ã™..." + add_invites: "æ‹›å¾…ã‚’è¿½åŠ " + are_you_sure: "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ" + are_you_sure_lock_account: "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ãƒãƒƒã‚¯ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ" + are_you_sure_unlock_account: "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒãƒƒã‚¯ã‚’解除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ" + close_account: "アカウントを削除ã™ã‚‹" + email_to: "招待ã®ãƒ¡ãƒ¼ãƒ«" + invite: "招待" + lock_account: "アカウントをãƒãƒƒã‚¯ã™ã‚‹" under_13: "13æ³ä»¥ä¸‹ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«è¡¨ç¤ºã™ã‚‹ (COPPA)" - ago: "%{time}å‰" + unlock_account: "アカウントã®ãƒãƒƒã‚¯ã‚’解除ã™ã‚‹" + users: + other: "%{count} ユーザーãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ" + zero: "ユーザーãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + view_profile: "プãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’表示" + you_currently: + other: "ç¾åœ¨ %{count} 招待ãŒæ®‹ã£ã¦ã„ã¾ã™ %{link}" + zero: "ç¾åœ¨æ‹›å¾…ã¯æ®‹ã£ã¦ã„ã¾ã›ã‚“ %{link}" + weekly_user_stats: + amount_of: + other: "今週ã®æ–°ã—ã„ユーザー数: %{count}" + zero: "今週ã®æ–°ã—ã„ユーザー数: ãªã—" + current_server: "ç¾åœ¨ã®ã‚µãƒ¼ãƒãƒ¼æ—¥ä»˜ %{date}" all_aspects: "å…¨ã¦ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆ" - application: - helper: - unknown_person: "ä¸æ˜Žãªé€£çµ¡å…ˆ" - video_title: - unknown: "ä¸æ˜Žãªå‹•ç”»ã‚¿ã‚¤ãƒˆãƒ«" + api: + openid_connect: + authorizations: + destroy: + fail: "ID %{id} ã®è¨±å¯ã‚’å–り消ã™ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸ" + new: + access: "%{name}ã¯ã‚¢ã‚¯ã‚»ã‚¹æ¨©ãŒå¿…è¦ã§ã™:" + approve: "承èª" + bad_request: "クライアント ID ã¾ãŸã¯ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆ URI ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + client_id_not_found: "client_id %{client_id} ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã€ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆ URI %{redirect_uri} ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + deny: "æ‹’å¦" + no_requirement: "%{name}ã¯ä½•ã®æ¨©é™ã‚‚å¿…è¦ã‚ã‚Šã¾ã›ã‚“" + redirection_message: "%{redirect_uri} ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©ã‚’付与ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ" + error_page: + contact_developer: "アプリケーションã®é–‹ç™ºè€…ã«é€£çµ¡ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚以下ã®è©³ç´°ãªã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’å«ã‚ã¦ãã ã•ã„:" + could_not_authorize: "アプリケーションãŒè¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“" + login_required: "ã“ã®ã‚¢ãƒ—リケーションを許å¯ã™ã‚‹ã«ã¯ã€ã¾ãšãƒã‚°ã‚¤ãƒ³ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™" + title: "何ã‹å•é¡ŒãŒã‚ã‚Šã¾ã™ :(" + scopes: + aud: + description: "ã“ã‚Œã¯ã€ã‚¢ãƒ—リケーションã«ç›£æŸ»æ¨©é™ã‚’付与ã—ã¾ã™" + name: "監査" + name: + description: "ã“ã‚Œã¯ã€ã‚¢ãƒ—リケーションã«åå‰ã®ã‚¢ã‚¯ã‚»ã‚¹è¨±å¯ã‚’付与ã—ã¾ã™" + name: "åå‰" + nickname: + description: "ã“ã‚Œã¯ã€ã‚¢ãƒ—リケーションã«ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã®ã‚¢ã‚¯ã‚»ã‚¹è¨±å¯ã‚’付与ã—ã¾ã™" + name: "ニックãƒãƒ¼ãƒ " + openid: + description: "アプリケーションãŒã‚ãªãŸã®åŸºæœ¬ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’èªã‚€ã“ã¨ãŒã§ãã¾ã™" + name: "基本プãƒãƒ•ã‚£ãƒ¼ãƒ«" + picture: + description: "ã“ã‚Œã¯ã€ã‚¢ãƒ—リケーションã«å†™çœŸã®ã‚¢ã‚¯ã‚»ã‚¹è¨±å¯ã‚’付与ã—ã¾ã™" + name: "写真" + profile: + description: "ã“ã‚Œã¯ã€ã‚¢ãƒ—リケーションãŒã‚ãªãŸã®æ‹¡å¼µãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’èªã‚€ã“ã¨ãŒã§ãるよã†ã«ã—ã¾ã™" + name: "拡張プãƒãƒ•ã‚£ãƒ¼ãƒ«" + read: + description: "ã“ã‚Œã¯ã‚¢ãƒ—リケーションãŒã€ã‚ãªãŸã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã€ã‚ãªãŸã®ä¼šè©±ã€ã‚ãªãŸã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’èªã‚€ã“ã¨ãŒã§ãるよã†ã«ã—ã¾ã™" + name: "プãƒãƒ•ã‚£ãƒ¼ãƒ«ã€ã‚¹ãƒˆãƒªãƒ¼ãƒ ã€ä¼šè©±ã‚’èªã‚€" + sub: + description: "ã“ã‚Œã¯ã€ã‚¢ãƒ—リケーションã«ã‚µãƒ–権é™ã‚’付与ã—ã¾ã™" + name: "サブ" + write: + description: "アプリケーションãŒã€æ–°ã—ã„投稿ã®é€ä¿¡ã€ä¼šè©±ã®æ›¸ãè¾¼ã¿ã€ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã®é€ä¿¡ã‚’ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™" + name: "投稿ã®é€ä¿¡ã€ä¼šè©±ã€ãƒªã‚¢ã‚¯ã‚·ãƒ§ãƒ³" + user_applications: + index: + access: "%{name}ã¯ã‚¢ã‚¯ã‚»ã‚¹è¨±å¯ãŒã‚ã‚Šã¾ã™:" + edit_applications: "アプリケーション" + no_requirement: "%{name}ã¯ä½•ã®æ¨©é™ã‚‚å¿…è¦ã‚ã‚Šã¾ã›ã‚“" + title: "許å¯ã•ã‚ŒãŸã‚¢ãƒ—リケーション" + no_applications: "許å¯ã•ã‚ŒãŸã‚¢ãƒ—リケーションã¯ã‚ã‚Šã¾ã›ã‚“" + policy: "アプリケーションã®ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼ã‚’å‚ç…§" + revoke_autorization: "アクセスをå–り消ã™" + tos: "アプリケーションã®åˆ©ç”¨è¦ç´„ã‚’å‚ç…§" are_you_sure: "本当ã«ã„ã„ã§ã™ã‹ã€‚" are_you_sure_delete_account: "本当ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’削除ã—ã¾ã™ã‹? ã“ã®æ“作をå–り消ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“ï¼" aspect_memberships: destroy: failure: "連絡先をアスペクトã‹ã‚‰é™¤å¤–ã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸã€‚" + forbidden: "ã“ã®æ“作ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。" + invalid_statement: "é‡è¤‡ã—ãŸãƒ¬ã‚³ãƒ¼ãƒ‰ã¯æ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚" no_membership: "é¸æŠžã—ãŸé€£çµ¡å…ˆã¯ãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆå†…ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ" success: "連絡先をアスペクトã‹ã‚‰é™¤å¤–ã™ã‚‹ã®ã«æˆåŠŸã—ã¾ã—ãŸã€‚" aspects: @@ -68,73 +198,54 @@ ja: success: "連絡先をアスペクトã«è¿½åŠ ã™ã‚‹ã®ã«æˆåŠŸã—ã¾ã—ãŸã€‚" aspect_listings: add_an_aspect: "ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’è¿½åŠ ã™ã‚‹" - deselect_all: "ã™ã¹ã¦é¸æŠžè§£é™¤" - edit_aspect: "%{name}を編集ã™ã‚‹" - select_all: "ã™ã¹ã¦é¸æŠž" aspect_stream: + make_something: "何ã‹ã‚’作り出ã™" stay_updated: "常ã«æœ€æ–°æƒ…å ±ã‚’è¡¨ç¤ºã™ã‚‹" stay_updated_explanation: "メインã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã«ã¯ã‚ãªãŸã®é€£çµ¡å…ˆã€ãƒ•ã‚©ãƒãƒ¼ã—ãŸã‚¿ã‚°ã‚„コミュニティã®ã‚¯ãƒªã‚¨ã‚¤ãƒ†ã‚£ãƒ–ãªäººãŸã¡ã®æŠ•ç¨¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚" - contacts_not_visible: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®é€£çµ¡å…ˆã¯ãŠäº’ã„ã®å˜åœ¨ãŒç¢ºèªã§ãã¾ã›ã‚“。" - contacts_visible: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®é€£çµ¡å…ˆã¯ãŠäº’ã„ã®å˜åœ¨ãŒç¢ºèªã§ãã¾ã™ã€‚" - create: - failure: "アスペクトを作æˆã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸã€‚" - success: "æ–°ã—ã„アスペクト「%{name}ã€ã‚’作æˆã—ã¾ã—ãŸã€‚" destroy: failure: "%{name}ã«é€£çµ¡å…ˆãŒæ®‹ã£ã¦ã„ã‚‹ã®ã§å‰Šé™¤ã§ãã¾ã›ã‚“。" success: "%{name}ã•ã‚“を除外ã™ã‚‹ã®ã«æˆåŠŸã—ã¾ã—ãŸã€‚" + success_auto_follow_back: "%{name} ã•ã‚“ã¯æ£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚ã‚ãªãŸã¯ã€è‡ªå‹•çš„ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’フォãƒãƒ¼ãƒãƒƒã‚¯ã™ã‚‹ãŸã‚ã«ã€ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’使用ã—ã¦ã„ã¾ã—ãŸã€‚ユーザーã®è¨å®šã‚’確èªã—ã¦ã€æ–°ã—ã自動フォãƒãƒ¼ãƒãƒƒã‚¯ã™ã‚‹ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’é¸æŠžã—ã¦ãã ã•ã„。" edit: aspect_list_is_not_visible: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ãƒ¡ãƒ³ãƒãƒ¼ä¸€è¦§ã¯ãƒ¡ãƒ³ãƒãƒ¼ã¸å…¬é–‹ã•ã‚Œã¦ã„ã¾ã›ã‚“" aspect_list_is_visible: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ãƒ¡ãƒ³ãƒãƒ¼ä¸€è¦§ã¯ãƒ¡ãƒ³ãƒãƒ¼ã«å…¬é–‹ã•ã‚Œã¦ã„ã¾ã™" confirm_remove_aspect: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’本当ã«å‰Šé™¤ã—ã¦ã„ã„ã§ã™ã‹ã€‚" - make_aspect_list_visible: "アスペクトã®ãƒ¡ãƒ³ãƒãƒ¼ä¸€è¦§ã‚’公開ã—ã¾ã™ã‹ã€‚" - remove_aspect: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’削除ã™ã‚‹" rename: "åå‰ã®å¤‰æ›´" update: "æ›´æ–°" updating: "æ›´æ–°ä¸" index: - diaspora_id: - content_1: "ã‚ãªãŸã®ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©IDã¯:" - content_2: "誰ã‹ã«æ¸¡ã™ã¨ã€ãã®äººã¯ diaspora* ã§ã‚ãªãŸã‚’見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" - heading: "ダイアスãƒãƒ©ID" donate: "寄付" - handle_explanation: "ã“ã‚ŒãŒã‚ãªãŸã®ãƒãƒ³ãƒ‰ãƒ«åã§ã™ã€‚メールアドレスã¨åŒã˜ã‚ˆã†ã«ã»ã‹ã®äººã«æ•™ãˆã¦ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©ã§é€£çµ¡ã‚’å–ã‚Šåˆã†ã“ã¨ãŒã§ãã¾ã™ã€‚" help: + any_problem: "å•é¡ŒãŒã‚ã‚Šã¾ã™ã‹ï¼Ÿ" + contact_podmin: "ã‚ãªãŸã®ãƒãƒƒãƒ‰ã®ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„ï¼" do_you: "ã‚ãªãŸã¯:" - email_feedback: "ã‚‚ã—よã‚ã—ã‘ã‚Œã°ã€%{link}ã§ãƒ•ã‚£ãƒ¼ãƒ‰ãƒãƒƒã‚¯ã‚’é€ã£ã¦ãã ã•ã„" - email_link: "メール" feature_suggestion: "... %{link}ã®æ案ãŒã‚ã‚Šã¾ã™ã‹?" find_a_bug: "... %{link}を見ã¤ã‘ã¾ã—ãŸã‹?" have_a_question: "... %{link}ãŒã‚ã‚Šã¾ã™ã‹?" - here_to_help: "Diaspora community is here to help!" + here_to_help: "ã“ã“ãŒãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã§ã™ï¼" + mail_podmin: "ãƒãƒƒãƒ‰ç®¡ç†è€…メール" need_help: "ヘルプãŒå¿…è¦ã§ã™ã‹?" tag_bug: "#bug" tag_feature: "#feature" tag_question: "#question" tutorial_link_text: "ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«" + tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: 最åˆã®ã‚¹ãƒ†ãƒƒãƒ—ã¸ã®æ‰‹åŠ©ã‘。" introduce_yourself: "ã“ã‚ŒãŒã‚ãªãŸã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã§ã™ã€‚ 飛ã³è¾¼ã‚“ã§è‡ªå·±ç´¹ä»‹ã‚’ã—ã¦ã¿ã¾ã—ょã†ã€‚" + keep_pod_running: "毎月ã®å¯„付ã§ã€%{pod}ã®é«˜é€Ÿå®Ÿè¡Œã‚’ç¶æŒã—ã€ã‚µãƒ¼ãƒãƒ¼ã€å½¼ã‚‰ã®ã‚³ãƒ¼ãƒ’ーã€ä¿®æ£ã‚’è²·ã„ã¾ã™ï¼" new_here: follow: "%{link}をフォãƒãƒ¼ã—ã¦ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã®æ–°ã—ã„ユーザーをæ“è¿Žã—ã¾ã—ょã†!" learn_more: "ã•ã‚‰ã«è©³ã—ã" title: "æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®çš†ã•ã‚“よã†ã“ã" - no_contacts: "連絡先無ã—" - no_tags: "No tags" - people_sharing_with_you: "ã‚ãªãŸã«å…±æœ‰ã—ã¦ã„る人ãŸã¡" - post_a_message: "投稿ã™ã‚‹" services: content: "次ã®ã‚µãƒ¼ãƒ“スをダイアスãƒãƒ©ã«é€£æºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" heading: "外部サービス連æº" - unfollow_tag: "#%{tag} ã®ãƒ•ã‚©ãƒãƒ¼ã‚’ä¸æ¢ã™ã‚‹" welcome_to_diaspora: "%{name}ã•ã‚“ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©ã¸ã‚ˆã†ã“ãï¼" - new: - create: "æ–°è¦ä½œæˆ" - name: "Name" no_contacts_message: community_spotlight: "コミュニティスãƒãƒƒãƒˆãƒ©ã‚¤ãƒˆ" + invite_link_text: "招待" or_spotlight: "ã¾ãŸã¯%{link}ã«å…±æœ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™" - try_adding_some_more_contacts: "You can search (top) or invite (right) more contacts." + try_adding_some_more_contacts: "ã‚‚ã£ã¨é€£çµ¡å…ˆã‚’検索ã¾ãŸã¯%{invite_link}ã§ãã¾ã™ã€‚" you_should_add_some_more_contacts: "ã‚‚ã£ã¨é€£çµ¡å…ˆã‚’è¿½åŠ ã—ã¾ã—ょã†!" - no_posts_message: - start_talking: "投稿ãŒã¾ã ã‚ã‚Šã¾ã›ã‚“。会話を始ã‚ã¾ã—ょã†ï¼" seed: acquaintances: "知りåˆã„" family: "家æ—" @@ -143,70 +254,66 @@ ja: update: failure: "アスペクトå「%{name}ã€ã¯é•·ã™ãŽã¦ä¿å˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" success: "アスペクト「%{name}ã€ã®ç·¨é›†ã«æˆåŠŸã—ã¾ã—ãŸã€‚" - back: "å‰ã¸" blocks: create: failure: "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’無視ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ #evasion" + success: "OKã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯å†åº¦ã‚¹ãƒˆãƒªãƒ¼ãƒ ã«è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。 #silencio!" destroy: failure: "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ç„¡è¦–を解除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ #evasion" + success: "彼らãŒä½•ã‚’言ã†ã‹è¦‹ã¦ã¿ã¾ã—ょã†! #sayhello" bookmarklet: explanation: "ã“ã®ãƒªãƒ³ã‚¯ã‚’ãŠæ°—ã«å…¥ã‚Šã«ç™»éŒ²ã™ã‚‹ã¨ã€ã©ã“ã‹ã‚‰ã§ã‚‚%{link}ã§ãã¾ã™ã€‚" - heading: "Diaspora Bookmarklet" + heading: "ãŠæ°—ã«å…¥ã‚Š" post_something: "ダイアスãƒãƒ©ã«æŠ•ç¨¿" - post_success: "投稿完了ï¼ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‰ã˜ã¾ã™ã€‚" - cancel: "å–り消ã™" + cancel: "å–消" comments: new_comment: comment: "コメント" commenting: "コメント投稿ä¸â€¦" - one: "コメント1件" - other: "コメント%{count}件" - zero: "コメントãŒã‚ã‚Šã¾ã›ã‚“" contacts: - create: - failure: "連絡先ã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚" index: add_a_new_aspect: "æ–°ã—ã„ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’è¿½åŠ ã™ã‚‹" - add_to_aspect: "Add contacts to %{name}" + add_contact: "é€£çµ¡å…ˆã‚’è¿½åŠ ã™ã‚‹" all_contacts: "ã™ã¹ã¦ã®é€£çµ¡å…ˆ" community_spotlight: "コミュニティスãƒãƒƒãƒˆãƒ©ã‚¤ãƒˆ" my_contacts: "ç§ã®é€£çµ¡å…ˆ" - no_contacts: "No contacts." + no_contacts: "é€£çµ¡å…ˆã‚’è¿½åŠ ã™ã‚‹å¿…è¦ãŒã‚るよã†ã§ã™ï¼" + no_contacts_in_aspect: "ã¾ã ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«é€£çµ¡å…ˆã¯ã‚ã‚Šã¾ã›ã‚“。以下ã¯ã€ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«è¿½åŠ ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã€æ—¢å˜ã®é€£çµ¡å…ˆã®ãƒªã‚¹ãƒˆã§ã™ã€‚" no_contacts_message: "%{community_spotlight}ã‚’ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã™ã‚‹" - only_sharing_with_me: "自分ã ã‘ã«å…±æœ‰ã™ã‚‹" + only_sharing_with_me: "自分ã ã‘ã«å…±æœ‰" start_a_conversation: "会話を開始ã™ã‚‹" title: "連絡先" - your_contacts: "ã‚ãªãŸã®é€£çµ¡å…ˆ" - sharing: - people_sharing: "ã‚ãªãŸã«å…±æœ‰ã—ã¦ã„る人ãŸã¡:" + user_search: "連絡先検索" spotlight: community_spotlight: "コミュニティスãƒãƒƒãƒˆãƒ©ã‚¤ãƒˆ" + no_members: "ã¾ã メンãƒãƒ¼ã¯ã„ã¾ã›ã‚“。" + suggest_member: "メンãƒãƒ¼ã®æ案" conversations: create: fail: "無効ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã§ã™ã€‚" + no_contact: "最åˆã«é€£çµ¡å…ˆã‚’è¿½åŠ ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ï¼" sent: "メッセージをé€ä¿¡ã—ã¾ã—ãŸ" - helper: - new_messages: - few: "æ–°ç€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸%{count}通" - many: "æ–°ç€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸%{count}通" - one: "æ–°ç€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸1通" - other: "æ–°ç€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸%{count}通" - two: "%{count} new messages" - zero: "æ–°ç€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ç„¡ã—" + destroy: + delete_success: "会話をæ£å¸¸ã«å‰Šé™¤ã—ã¾ã—ãŸ" + hide_success: "会話をæ£å¸¸ã«éžè¡¨ç¤ºã«ã—ã¾ã—ãŸ" index: + conversations_inbox: "会話 – å—信トレイ" inbox: "å—信トレイ" - no_conversation_selected: "é¸æŠžä¸ã®ä¼šè©±ãŒã‚ã‚Šã¾ã›ã‚“" + new_conversation: "æ–°ã—ã„会話" no_messages: "メッセージãŒã‚ã‚Šã¾ã›ã‚“" new: - abandon_changes: "å¤‰æ›´å†…å®¹ã‚’ç ´æ£„ã—ã¾ã™ã‹?" + message: "メッセージ" send: "é€ä¿¡ã™ã‚‹" sending: "é€ä¿¡ä¸â€¦" subject: "件å" + subject_default: "件åãªã—" to: "宛先" new_conversation: fail: "無効ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸" show: delete: "会話を削除ã—ã¦ã€ãƒ–ãƒãƒƒã‚¯ã™ã‚‹" + hide: "会話をéžè¡¨ç¤ºãŠã‚ˆã³ãƒŸãƒ¥ãƒ¼ãƒˆ" + last_message: "最後ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®å—ä¿¡ %{timeago}" reply: "返信" replying: "返信ä¸..." date: @@ -219,135 +326,340 @@ ja: error_messages: helper: correct_the_following_errors_and_try_again: "次ã®å•é¡Œã‚’解決ã—ã¦ã‹ã‚‰ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。" - invalid_fields: "ä¸æ£ãªãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰å" - login_try_again: "<a href='%{login_link}'>ãƒã‚°ã‚¤ãƒ³</a>ã—ã¦ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。" - post_not_public: "閲覧ã—よã†ã¨ã—ãŸæŠ•ç¨¿ã¯å…¬é–‹ã•ã‚Œã¦ã„ã¾ã›ã‚“!" + need_javascript: "ã“ã®ã‚¦ã‚§ãƒ–サイトã¯æ£å¸¸ã«æ©Ÿèƒ½ã™ã‚‹ãŸã‚ã«JavaScriptãŒå¿…è¦ã§ã™ã€‚ JavaScriptを無効ã«ã—ãŸå ´åˆã¯ã€æœ‰åŠ¹ã«ã—ã¦ã“ã®ãƒšãƒ¼ã‚¸ã‚’æ›´æ–°ã—ã¦ãã ã•ã„。" fill_me_out: "記入ã—ã¦" - find_people: "Find people" + find_people: "人や #ã‚¿ã‚° を探ã™" help: + account_and_data_management: + close_account_a: "è¨å®šãƒšãƒ¼ã‚¸ã®ä¸€ç•ªä¸‹ã«ç§»å‹•ã—ã€ã€Œã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’é–‰ã˜ã‚‹ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¾ã™ã€‚手続ãを完了ã™ã‚‹ãŸã‚ã«ã€ãƒ‘スワードを入力ã™ã‚‹ã‚ˆã†ã«æ±‚ã‚られã¾ã™ã€‚覚ãˆã¦ãŠã„ã¦ãã ã•ã„ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’é–‰ã˜ãŸå ´åˆã€ãã®ãƒãƒƒãƒ‰ã«ã‚ãªãŸã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã§å†ç™»éŒ²ã™ã‚‹ã“ã¨ã¯<strong>ã§ãã¾ã›ã‚“</strong>。" + close_account_q: "ç§ã®ç¨®å (アカウント) を削除ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + data_other_podmins_a: "ã‚ãªãŸãŒåˆ¥ã®ãƒãƒƒãƒ‰ã®èª°ã‹ã¨å…±æœ‰ã•ã‚Œã‚‹ã¨ã€ã‚ãªãŸãŒå½¼ã‚‰ã¨å…±æœ‰ã—ãŸæŠ•ç¨¿ã‚„ã€ã‚ãªãŸã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒ‡ãƒ¼ã‚¿ã®ã‚³ãƒ”ーãŒãã®ãƒãƒƒãƒ‰ã«ã«ä¿å˜ (ã‚ャッシュ) ã•ã‚Œã€ãã®ãƒãƒƒãƒ‰ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ç®¡ç†è€…ã«ã‚¢ã‚¯ã‚»ã‚¹å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚ã‚ãªãŸãŒæŠ•ç¨¿ã‚„プãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒ‡ãƒ¼ã‚¿ã‚’削除ã™ã‚‹ã¨ã€ãã‚Œã¯ã‚ãªãŸã®ãƒãƒƒãƒ‰ã‹ã‚‰å‰Šé™¤ã•ã‚Œã€ãã‚ŒãŒä»¥å‰ã«ä¿å˜ã•ã‚Œã¦ã„ãŸä»–ã®ãƒãƒƒãƒ‰ã«å‰Šé™¤è¦æ±‚ãŒé€ä¿¡ã•ã‚Œã¾ã™ã€‚ã‚ãªãŸã®ç”»åƒã¯ã€ã‚ãªãŸè‡ªèº«ã®ãƒãƒƒãƒ‰ã‚’除ãã€ä¿å˜ã•ã‚Œã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。ãã®ãƒªãƒ³ã‚¯ã®ã¿ãŒã€ä»–ã®ãƒãƒƒãƒ‰ã«é€ä¿¡ã•ã‚Œã¾ã™ã€‚" + data_other_podmins_q: "ä»–ã®ãƒãƒƒãƒ‰ã®ç®¡ç†è€…ã¯ã€ç§ã®æƒ…å ±ã‚’è¦‹ã‚‹ã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + data_visible_to_podmin_a: "一言ã§ã„ãˆã°: ã™ã¹ã¦ã€‚ãƒãƒƒãƒ‰é–“ã®é€šä¿¡ã¯ã€å¸¸ã« (SSLã¨ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*独自ã®è»¢é€ã®æš—å·åŒ–を使用ã—ã¦) æš—å·åŒ–ã•ã‚Œã¦ã„ã¾ã™ãŒã€ãƒãƒƒãƒ‰ä¸Šã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã®ãƒ‡ãƒ¼ã‚¿ã¯æš—å·åŒ–ã•ã‚Œã¦ã„ã¾ã›ã‚“。彼らãŒæœ›ã‚ã°ã€ã‚ãªãŸã®ãƒãƒƒãƒ‰ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ç®¡ç†è€… (通常ã€ãƒãƒƒãƒ‰ã‚’実行ã—ã¦ã„る人) ã¯ã€(ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ‡ãƒ¼ã‚¿ã‚’æ ¼ç´ã™ã‚‹ã»ã¨ã‚“ã©ã®ã‚¦ã‚§ãƒ–サイトã®ã‚ˆã†ã«) ã™ã¹ã¦ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒ‡ãƒ¼ã‚¿ã¨ã‚ãªãŸãŒæŠ•ç¨¿ã—ãŸã™ã¹ã¦ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã‚ãªãŸã®ãƒ‡ãƒ¼ã‚¿ã‚’é ã‘ã¦ã‚‚å分ã«ä¿¡é ¼ã§ãる管ç†è€…ã®ãƒãƒƒãƒ‰ã‚’é¸ã¶ã“ã¨ãŒã§ãるよã†ã«ã€ã‚ãªãŸãŒã‚µã‚¤ãƒ³ã‚¢ãƒƒãƒ—ã™ã‚‹ãƒãƒƒãƒ‰ã«é¸æŠžè‚¢ã‚’与ãˆã¦ã„ã‚‹ã®ã¯ã“ã®ãŸã‚ã§ã™ã€‚ã‚ãªãŸç‹¬è‡ªã®ãƒãƒƒãƒ‰ã‚’実行ã™ã‚‹ã¨ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’制御ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ãŸã‚ã€ã‚ˆã‚Šé«˜ã„プライãƒã‚·ãƒ¼ã‚’æä¾›ã—ã¾ã™ã€‚" + data_visible_to_podmin_q: "ç§ã®ãƒãƒƒãƒ‰ç®¡ç†è€…ã¯ã©ã®ãらã„ç§ã®æƒ…å ±ã‚’è¦‹ã‚‹ã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + download_data_a: "ã¯ã„。è¨å®šãƒšãƒ¼ã‚¸ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚¿ãƒ–ã®ä¸‹éƒ¨ã«ã€2ã¤ã®ãƒœã‚¿ãƒ³ãŒè¡¨ç¤ºã•ã‚Œã¾ã™: 1ã¤ã¯ã‚ãªãŸã®ãƒ‡ãƒ¼ã‚¿ã‚’ダウンãƒãƒ¼ãƒ‰ã™ã‚‹ãŸã‚ã€1ã¤ã¯ã‚ãªãŸã®å†™çœŸã‚’ダウンãƒãƒ¼ãƒ‰ã™ã‚‹ãŸã‚ã§ã™ã€‚" + download_data_q: "ç§ã®ç¨®å (アカウント) ã«å«ã¾ã‚Œã¦ã„るデータã®ã™ã¹ã¦ã®ã‚³ãƒ”ーをダウンãƒãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + move_pods_a: "å°†æ¥çš„ã«ã¯ã€ãƒãƒƒãƒ‰ã‹ã‚‰è‡ªåˆ†ã®ç¨®åをエクスãƒãƒ¼ãƒˆã—ã¦ã€åˆ¥ã®ãƒãƒƒãƒ‰ã§ãれをインãƒãƒ¼ãƒˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ãŒã€ã“ã‚Œã¯ç¾åœ¨å¯èƒ½ã§ã¯ã‚ã‚Šã¾ã›ã‚“。ã„ã¤ã§ã‚‚ã€ã‚ãªãŸã¯æ–°ã—ã„アカウントを開è¨ã—ã€ãã®æ–°ã—ã„種åã§ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«é€£çµ¡å…ˆã‚’è¿½åŠ ã—ã€å½¼ã‚‰ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«ã‚ãªãŸã®æ–°ã—ã„種åã‚’è¿½åŠ ã™ã‚‹ã‚ˆã†ã«ã€å½¼ã‚‰ã«ä¾é ¼ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + move_pods_q: "ç§ã®ç¨®å (アカウント) ã‚’ã‚ã‚‹ãƒãƒƒãƒ‰ã‹ã‚‰åˆ¥ã®ã‚‚ã®ã«ç§»å‹•ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + title: "アカウントã¨ãƒ‡ãƒ¼ã‚¿ã®ç®¡ç†" + aspects: + change_aspect_of_post_a: "ã„ã„ãˆã€‚ã—ã‹ã—ã€ã‚ãªãŸã¯ã„ã¤ã§ã‚‚åŒã˜å†…容ã®æ–°ã—ã„投稿を作æˆã—ã¦ã€ãれを異ãªã‚‹ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«æŠ•ç¨¿ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + change_aspect_of_post_q: "何ã‹æŠ•ç¨¿ã—ãŸå¾Œã«ã€ãれを見るã“ã¨ãŒã§ãるアスペクトを変更ã§ãã¾ã™ã‹ï¼Ÿ" + contacts_know_aspect_a: "ã„ã„ãˆã€‚ã©ã®ã‚ˆã†ãªå ´åˆã‚‚ã€å½¼ã‚‰ãŒã‚¢ã‚¹ãƒšã‚¯ãƒˆã®åå‰ã‚’見るã“ã¨ã¯ã§ãã¾ã›ã‚“。" + contacts_know_aspect_q: "ç§ã®é€£çµ¡å…ˆã¯ã€ç§ãŒå…¥ã‚Œã¦ã„るアスペクトãŒåˆ†ã‹ã‚Šã¾ã™ã‹ï¼Ÿ" + contacts_visible_a: "ã“ã®ã‚ªãƒ—ションをãƒã‚§ãƒƒã‚¯ã™ã‚‹ã¨ã€ãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‹ã‚‰ã®é€£çµ¡å…ˆã¯ã€ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã®ã€Œé€£çµ¡å…ˆã€ã‚¿ãƒ–ã§ã€ãã®ä¸ã«ã„ã‚‹ä»–ã®äººã‚’å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションをé¸æŠžã™ã‚‹ã“ã¨ãŒæœ€å–„ãªã®ã¯ã€ãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆå†…ã®ã™ã¹ã¦ã®é€£çµ¡å…ˆãŒãŠäº’ã„を知ã£ã¦ã„ã‚‹å ´åˆã®ã¿ã§ã™ã€‚ãŸã¨ãˆã°ã€ã‚¢ã‚¹ãƒšã‚¯ãƒˆãŒæ‰€å±žã™ã‚‹ã‚¯ãƒ©ãƒ–や社会用ã®ã‚‚ã®ã§ã‚ã‚‹å ´åˆã§ã™ã€‚彼らã¯ã¾ã 呼ã°ã‚ŒãŸã‚¢ã‚¹ãƒšã‚¯ãƒˆã¯è¦‹ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。" + contacts_visible_q: "「ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ãƒ¡ãƒ³ãƒãƒ¼ä¸€è¦§ã‚’メンãƒãƒ¼ã¸å…¬é–‹ã™ã‚‹ã€ã¯ã©ã†ã„ã†æ„味ã§ã™ã‹ï¼Ÿ" + delete_aspect_a: "ストリームビューã‹ã‚‰ã‚µã‚¤ãƒ‰ãƒãƒ¼ã«ã‚る「マイ アスペクトã€ã‚’クリックã—ã¦ã€å‰Šé™¤ã—ãŸã„アスペクトã®æ¨ªã«ã‚る鉛ç†ã‚¢ã‚¤ã‚³ãƒ³ã‚’クリックã™ã‚‹ã‹ã€é€£çµ¡å…ˆã®ãƒšãƒ¼ã‚¸ã«ç§»å‹•ã—ã€é–¢é€£ã™ã‚‹ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’é¸æŠžã—ã¾ã™ã€‚次ã«ã€ãƒšãƒ¼ã‚¸ã®å³ä¸Šã«ã‚るゴミ箱ã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’クリックã—ã¾ã™ã€‚" + delete_aspect_q: "アスペクトを削除ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + person_multiple_aspects_a: "ã¯ã„。連絡先ã®ãƒšãƒ¼ã‚¸ã«ç§»å‹•ã—ã¦ã€ã€Œç§ã®é€£çµ¡å…ˆã€ã‚’クリックã—ã¦ãã ã•ã„。ãã‚Œãžã‚Œã®é€£çµ¡å…ˆã«å¯¾ã—ã¦ã€å³å´ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’使用ã—ã¦ã€å¸Œæœ›ã™ã‚‹æ•°ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’è¿½åŠ (ã¾ãŸã¯ãã“ã‹ã‚‰å‰Šé™¤) ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã¾ãŸã¯ã€å½¼ã‚‰ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã§ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚»ãƒ¬ã‚¯ã‚¿ãƒ¼ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ã€æ–°ã—ã„アスペクトã«è¿½åŠ (ã¾ãŸã¯ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‹ã‚‰å‰Šé™¤) ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã¾ãŸã€ã‚¹ãƒˆãƒªãƒ¼ãƒ ã§è¦‹ã‚‹ã“ã¨ãŒã§ãる彼らã®åå‰ã®ä¸Šã«ãƒã‚¤ãƒ³ã‚¿ã‚’移動ã™ã‚‹ã ã‘ã§ã€ã€Œãƒ›ãƒãƒ¼ã‚«ãƒ¼ãƒ‰ã€ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã™ããã“ã«ã‚るアスペクトを変更ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + person_multiple_aspects_q: "複数ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«äººã‚’è¿½åŠ ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + post_multiple_aspects_a: "ã¯ã„。投稿を作æˆã—ã¦ã„ã‚‹ã¨ãã«ã€ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚»ãƒ¬ã‚¯ã‚¿ãƒ¼ãƒœã‚¿ãƒ³ã‚’使用ã—ã¦ã€ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’é¸æŠžã¾ãŸã¯é¸æŠžã‚’解除ã—ã¾ã™ã€‚ 「全ã¦ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã€ãŒãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®è¨å®šã§ã™ã€‚ã‚ãªãŸã®æŠ•ç¨¿ã¯ã€é¸æŠžã—ãŸã™ã¹ã¦ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã¾ãŸã€ã‚µã‚¤ãƒ‰ãƒãƒ¼ã§æŠ•ç¨¿ã—ãŸã„アスペクトをé¸æŠžã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚投稿ã™ã‚‹ã¨ãã«å·¦å´ã®ãƒªã‚¹ãƒˆã§é¸æŠžã—ãŸã‚¢ã‚¹ãƒšã‚¯ãƒˆã¯ã€æ–°ã—ã„投稿ã®ä½œæˆã‚’始ã‚ã‚‹ã¨ãã€è‡ªå‹•çš„ã«ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚»ãƒ¬ã‚¯ã‚¿ãƒ¼ã§é¸æŠžã•ã‚Œã¾ã™ã€‚" + post_multiple_aspects_q: "一度ã«è¤‡æ•°ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«å¯¾ã—ã¦ã‚³ãƒ³ãƒ†ãƒ³ãƒ„を投稿ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + remove_notification_a: "ã„ã„ãˆã€‚ã™ã§ã«å½¼ã‚‰ã¨å…±æœ‰ã—ã¦ã„ã‚‹ã¨ãã€ã•ã‚‰ã«å¤šãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«å½¼ã‚‰ã‚’è¿½åŠ ã™ã‚‹å ´åˆã‚‚通知ã•ã‚Œã¾ã›ã‚“。" + remove_notification_q: "誰ã‹ã‚’ã‚るアスペクトã‹ã‚‰ã€ã¾ãŸã¯ã™ã¹ã¦ã®ãƒžã‚¤ アスペクトã‹ã‚‰å‰Šé™¤ã—ãŸå ´åˆã€ã“ã‚Œã¯å½¼ã‚‰ã«é€šçŸ¥ã•ã‚Œã¾ã™ã‹ï¼Ÿ" + rename_aspect_a: "ストリームビューã‹ã‚‰ã‚µã‚¤ãƒ‰ãƒãƒ¼ã«ã‚る「マイ アスペクトã€ã‚’クリックã—ã¦ã€åå‰ã‚’変更ã—ãŸã„アスペクトã®æ¨ªã«ã‚る鉛ç†ã‚¢ã‚¤ã‚³ãƒ³ã‚’クリックã™ã‚‹ã‚‹ã‹ã€é€£çµ¡å…ˆã®ãƒšãƒ¼ã‚¸ã«ç§»å‹•ã—ã€é–¢é€£ã™ã‚‹ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’é¸æŠžã—ã¾ã™ã€‚次ã«ã€ã“ã®ãƒšãƒ¼ã‚¸ã®ä¸€ç•ªä¸Šã«ã‚るアスペクトåã®æ¨ªã«ã‚る編集アイコンをクリックã—ã¦ã€åå‰ã‚’変更ã—ã¦ã€Œæ›´æ–°ã€ã‚’押ã—ã¾ã™ã€‚" + rename_aspect_q: "アスペクトã®åå‰ã‚’変更ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + restrict_posts_i_see_a: "ã¯ã„。サイドãƒãƒ¼ã«ã‚る「マイ アスペクトã€ã‚’クリックã—ã¦ã€ãã®å¾Œãƒªã‚¹ãƒˆã®å€‹ã€…ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’クリックã—ã¦ã€é¸æŠžã¾ãŸã¯é¸æŠžã‚’解除ã—ã¾ã™ã€‚é¸æŠžã•ã‚ŒãŸã‚¢ã‚¹ãƒšã‚¯ãƒˆã®äººã«ã‚ˆã£ã¦è¡Œã‚ã‚ŒãŸæŠ•ç¨¿ã ã‘ãŒã‚ãªãŸã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚" + restrict_posts_i_see_q: "ç§ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ 内ã®æŠ•ç¨¿ã‚’ã€ç‰¹å®šã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‹ã‚‰ã ã‘ã®ã‚‚ã®ã«åˆ¶é™ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + title: "アスペクト" + what_is_an_aspect_a: "アスペクトã¯ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã®é€£çµ¡å…ˆã‚’グループ化ã™ã‚‹æ–¹æ³•ã§ã™ã€‚アスペクトã¯ã€ã‚ãªãŸãŒä¸–ç•Œã«è¦‹ã›ã‚‹é¡”ã®ä¸€ã¤ã§ã™ã€‚ãã‚Œã¯ä»•äº‹ä¸ã®é¡”ã§ã‚ã£ãŸã‚Šã€ã¾ãŸã‚ãªãŸã®å®¶æ—ã«å‘ã‘ã¦ã„ã‚‹é¡”ã§ã‚ã£ãŸã‚Šã€ã¾ãŸã‚ãªãŸãŒæ‰€å±žã™ã‚‹ã‚¯ãƒ©ãƒ–ã§ãŠå‹é”ã«å‘ã‘ã‚‹é¡”ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。" + what_is_an_aspect_q: "アスペクトã¨ã¯ä½•ã§ã™ã‹ï¼Ÿ" + who_sees_post_a: "é™å®šå…¬é–‹ã®æŠ•ç¨¿ã‚’è¡Œã†å ´åˆã€æŠ•ç¨¿ã‚’è¡Œã†å‰ã«ã‚¢ã‚¹ãƒšã‚¯ãƒˆ (複数ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«è¡Œã‚ã‚ŒãŸå ´åˆã¯ãれらã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆ) ã«é…ç½®ã—ãŸäººã«ã ã‘表示ã•ã‚Œã¾ã™ã€‚アスペクトã«ã„ãªã„連絡先ã¯æŠ•ç¨¿ã‚’見る方法ãŒã‚ã‚Šã¾ã›ã‚“。é™å®šå…¬é–‹ã®æŠ•ç¨¿ã¯ã€ã‚ãªãŸã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ä¸€ã¤ã«é…ç½®ã•ã‚Œã¦ã„ãªã„人ã«ã¯è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。" + who_sees_post_q: "アスペクトã«æŠ•ç¨¿ã™ã‚‹ã¨ã€èª°ãŒãれを見ã¾ã™ã‹ï¼Ÿ" + chat: + add_contact_roster_a: "ã¾ãšã€äººãŒã„るアスペクトã®ä¸€ã¤ã§ãƒãƒ£ãƒƒãƒˆã‚’有効ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã“れを行ã†ã«ã¯ã€%{contacts_page}ã«ç§»å‹•ã—ã€å¸Œæœ›ã™ã‚‹ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’é¸æŠžã—ã¦ã€ãƒãƒ£ãƒƒãƒˆã‚¢ã‚¤ã‚³ãƒ³ã‚’クリックã—ã¦ã€ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ãƒãƒ£ãƒƒãƒˆã‚’有効ã«ã—ã¦ãã ã•ã„。 %{toggle_privilege}ã€ã‚ãªãŸãŒå¥½ã‚€å ´åˆã€ã€Œãƒãƒ£ãƒƒãƒˆã€ã¨å‘¼ã°ã‚Œã‚‹ç‰¹æ®Šãªã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’作æˆã—ã¦ã€ãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«ãƒãƒ£ãƒƒãƒˆã—ãŸã„äººã‚’è¿½åŠ ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚一度ã“れを行ã†ã¨ã€ãƒãƒ£ãƒƒãƒˆã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ã‚§ã‚¤ã‚¹ã‚’é–‹ã„ã¦ã€ãƒãƒ£ãƒƒãƒˆã—ãŸã„人をé¸æŠžã—ã¾ã™ã€‚" + add_contact_roster_q: "ダイアスãƒãƒ©*ã§èª°ã‹ã¨ãƒãƒ£ãƒƒãƒˆã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + contacts_page: "連絡先ページ" + title: "ãƒãƒ£ãƒƒãƒˆ" + faq: "よãã‚る質å•" + foundation_website: "ダイアスãƒãƒ©*財団ã®ã‚¦ã‚§ãƒ–サイト" + getting_help: + get_support_a_faq: "Wikiã§%{faq}ページをãŠèªã¿ãã ã•ã„" + get_support_a_hashtag: "ダイアスãƒãƒ©*ã®å…¬é–‹æŠ•ç¨¿ã§ %{question} ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã‚’使用ã—ã¦è³ªå•ã—ã¦ãã ã•ã„" + get_support_a_irc: "%{irc}ã§å‚åŠ ã—ã¦ãã ã•ã„ (ライブãƒãƒ£ãƒƒãƒˆ)" + get_support_a_tutorials: "%{tutorials}を確èªã—ã¦ãã ã•ã„" + get_support_a_website: "%{link}ã‚’ã”覧ãã ã•ã„" + get_support_a_wiki: "%{link}を検索ã—ã¦ãã ã•ã„" + get_support_q: "ã“ã®FAQã§ã€ç§ã®è³ªå•ãŒç”ãˆã‚‰ã‚Œã¦ã„ãªã„å ´åˆã¯ã©ã†ã™ã‚Œã°ã„ã„ã§ã™ã‹ï¼Ÿä»–ã«ã©ã“ã‹ã§ã‚µãƒãƒ¼ãƒˆã‚’å—ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + getting_started_a: "ã‚ãªãŸã¯é‹ãŒã„ã„ã§ã™ã。プãƒã‚¸ã‚§ã‚¯ãƒˆã‚µã‚¤ãƒˆã® %{tutorial_series} を試ã—ã¦ã¿ã¦ãã ã•ã„。登録ã®æ‰‹é †ã‚’一æ©ãšã¤èª¬æ˜Žã—ã¦ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã«ã¤ã„ã¦çŸ¥ã‚‹å¿…è¦ãŒã‚ã‚‹ã™ã¹ã¦ã®åŸºæœ¬çš„ãªã“ã¨ã‚’æ•™ãˆã¦ãã‚Œã¾ã™ã€‚" + getting_started_q: "助ã‘ã¦ï¼å§‹ã‚ã‚‹ãŸã‚ã«ã„ãã¤ã‹ã®åŸºæœ¬çš„ãªæ‰‹åŠ©ã‘ãŒå¿…è¦ã§ã™ï¼" + title: "ヘルプã®è¡¨ç¤º" + getting_started_tutorial: "「ã¯ã˜ã‚ã«ã€ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ« シリーズ" + here: "ã“ã“" irc: "IRC" + keyboard_shortcuts: + keyboard_shortcuts_a1: "ストリームビューã§ã¯ã€æ¬¡ã®ã‚ーボードショートカットを使用ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™:" + keyboard_shortcuts_li1: "j – 次ã®æŠ•ç¨¿ã¸ã‚¸ãƒ£ãƒ³ãƒ—" + keyboard_shortcuts_li2: "k – å‰ã®æŠ•ç¨¿ã¸ã‚¸ãƒ£ãƒ³ãƒ—" + keyboard_shortcuts_li3: "c – ç¾åœ¨ã®æŠ•ç¨¿ã«ã‚³ãƒ¡ãƒ³ãƒˆ" + keyboard_shortcuts_li4: "l – ç¾åœ¨ã®æŠ•ç¨¿ã«ã„ã„ãï¼" + keyboard_shortcuts_li5: "r – ç¾åœ¨ã®æŠ•ç¨¿ã‚’å†å…±æœ‰" + keyboard_shortcuts_li6: "m – ç¾åœ¨ã®æŠ•ç¨¿ã‚’展開" + keyboard_shortcuts_li7: "o – ç¾åœ¨ã®æŠ•ç¨¿å†…ã®æœ€åˆã®ãƒªãƒ³ã‚¯ã‚’é–‹ã" + keyboard_shortcuts_li8: "Ctrl+Enter – 書ã„ã¦ã„るメッセージをé€ä¿¡" + keyboard_shortcuts_q: "ã©ã®ã‚ーボードショートカットãŒåˆ©ç”¨ã§ãã¾ã™ã‹ï¼Ÿ" + title: "ã‚ーボードショートカット" markdown: "マークダウン" + mentions: + how_to_mention_a: "「@ã€è¨˜å·ã‚’入力ã—ã¦ã€å½¼ã‚‰ã®åå‰ã®å…¥åŠ›ã‚’始ã‚ã¾ã™ã€‚より簡å˜ã«é¸æŠžã§ãるよã†ã«ã€ãƒ‰ãƒãƒƒãƒ—ダウンメニューãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚アスペクトã«è¿½åŠ ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã®ã¿ãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã‚ã‚‹ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。" + how_to_mention_q: "投稿を作るã¨ãã«ã€èª°ã‹ã«ãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + mention_in_comment_a: "ã„ã„ãˆã€ç¾åœ¨ã¯ã§ãã¾ã›ã‚“。" + mention_in_comment_q: "コメントã®èª°ã‹ã«ãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + see_mentions_a: "ã¯ã„ã€ã‚ãªãŸã®ãƒ›ãƒ¼ãƒ ページã®å·¦å´ã®åˆ—ã§ã€Œ@メンションã€ã‚’クリックã—ã¾ã™ã€‚" + see_mentions_q: "ç§ãŒãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã•ã‚ŒãŸæŠ•ç¨¿ã‚’å‚ç…§ã™ã‚‹æ–¹æ³•ã¯ã‚ã‚Šã¾ã™ã‹ï¼Ÿ" + title: "メンション" + what_is_a_mention_a: "メンションã¯ã€æŠ•ç¨¿ã«è¡¨ç¤ºã•ã‚Œã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã¸ã®ãƒªãƒ³ã‚¯ã§ã™ã€‚誰ã‹ãŒãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã•ã‚Œã‚‹ã¨ã€å½¼ã‚‰ã¯æŠ•ç¨¿ã¸ã®æ³¨æ„ã‚’å–šèµ·ã™ã‚‹é€šçŸ¥ã‚’å—ä¿¡ã—ã¾ã™ã€‚" + what_is_a_mention_q: "「メンションã€ã¨ã¯ä½•ã§ã™ã‹ï¼Ÿ" + miscellaneous: + back_to_top_a: "ã¯ã„。ページを下ã«ã‚¹ã‚¯ãƒãƒ¼ãƒ«ã—ãŸå¾Œã€ãƒ–ラウザウィンドウã®å³ä¸‹ã«è¡¨ç¤ºã•ã‚Œã‚‹ç°è‰²ã®çŸ¢å°ã‚’クリックã—ã¦ãã ã•ã„。" + back_to_top_q: "下ã«ã‚¹ã‚¯ãƒãƒ¼ãƒ«ã—ãŸå¾Œã«ã€ãƒšãƒ¼ã‚¸ã®å…ˆé ã«æˆ»ã‚‹ãŸã‚ã®ç°¡å˜ãªæ–¹æ³•ã¯ã‚ã‚Šã¾ã™ã‹ï¼Ÿ" + diaspora_app_a: "コミュニティã®ãƒ¡ãƒ³ãƒãƒ¼ã«ã‚ˆã£ã¦é–‹ç™ºä¸ã®AndroidアプリãŒã„ãã¤ã‹ã‚ã‚Šã¾ã—ãŸã€‚一部ã¯é•·æœŸã«æ”¾æ£„ã•ã‚ŒãŸãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆã®ãŸã‚ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã®ç¾åœ¨ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ã†ã¾ã機能ã—ã¾ã›ã‚“。ç¾æ™‚点ã§ã¯ã“れらã®ã‚¢ãƒ—リã«å¤šãを期待ã—ãªã„ã§ãã ã•ã„。 iOS用ã®ã‚¢ãƒ—リã¯ç¾åœ¨ã‚ã‚Šã¾ã›ã‚“。ã¾ã 完全ãªæ©Ÿèƒ½ã‚’æŒã£ã¦ã„ã¾ã›ã‚“ãŒã€ã™ã¹ã¦ã®ãƒ‡ãƒã‚¤ã‚¹ã§ã†ã¾ã動作ã™ã‚‹ã¯ãšã®ãƒ¢ãƒã‚¤ãƒ«ç‰ˆã®ã‚µã‚¤ãƒˆã‚’デザインã—ã¾ã—ãŸã®ã§ã€ãŠä½¿ã„ã®æºå¸¯ç«¯æœ«ã‹ã‚‰ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹æœ€è‰¯ã®æ–¹æ³•ã¯ã€ãƒ–ラウザを利用ã—ã¦ãã ã•ã„。" + diaspora_app_q: "Android ã‚„ iOS 用ã®ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*アプリã¯ã‚ã‚Šã¾ã™ã‹ï¼Ÿ" + photo_albums_a: "ã„ã„ãˆã€ç¾åœ¨ã¯ã‚ã‚Šã¾ã›ã‚“。ã—ã‹ã—ã€ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã®å†™çœŸã‚¿ãƒ–ã®ä¸‹ã§ã€äººã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã—ãŸå†™çœŸã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + photo_albums_q: "フォトアルãƒãƒ やビデオアルãƒãƒ ã¯ã‚ã‚Šã¾ã™ã‹ï¼Ÿ" + subscribe_feed_a: "ã¯ã„。ã—ã‹ã—ã€ã“ã‚Œã¯ã¾ã æ´—ç·´ã•ã‚ŒãŸæ©Ÿèƒ½ã§ã¯ãªãã€çµæžœã®å½¢å¼ã¯ã¾ã ã‹ãªã‚Šãƒ©ãƒ•ã§ã™ã€‚ã¨ã«ã‹ã試ã—ã¦ã¿ãŸã„å ´åˆã¯ã€èª°ã‹ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã€ãŠä½¿ã„ã®ãƒ–ラウザã§ãƒ•ã‚£ãƒ¼ãƒ‰ãƒœã‚¿ãƒ³ã‚’クリックã™ã‚‹ã‹ã€ãƒ•ã‚£ãƒ¼ãƒ‰ãƒªãƒ¼ãƒ€ãƒ¼ã«ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã® URL (例 https://podname.org/people/somenumber) をコピーã—ã¦è²¼ã‚Šä»˜ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚çµæžœã®ãƒ•ã‚£ãƒ¼ãƒ‰ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯æ¬¡ã®ã‚ˆã†ã«ãªã‚Šã¾ã™: https://podname.org/public/username.atom - ダイアスãƒãƒ©* 㯠RSS ã§ã¯ãªã Atom を使用ã—ã¦ã„ã¾ã™" + subscribe_feed_q: "誰ã‹ã®å…¬é–‹ã®æŠ•ç¨¿ã‚’フィードリーダーã§è³¼èªã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + title: "ãã®ä»–" + pods: + find_people_a: "å‹é”をダイアスãƒãƒ©*ã«å‚åŠ ã™ã‚‹ã‚ˆã†ã«æ‹›å¾…ã—ãŸã„å ´åˆã¯ã€ã‚µã‚¤ãƒ‰ãƒãƒ¼ã®æ‹›å¾…リンクã¾ãŸã¯ãƒ¡ãƒ¼ãƒ«ãƒªãƒ³ã‚¯ã‚’使用ã—ã¾ã™ã€‚#ã‚¿ã‚° をフォãƒãƒ¼ã—ã¦ã€ã‚ãªãŸãŒèˆˆå‘³ã®ã‚ã‚‹ã‚‚ã®ã‚’共有ã™ã‚‹ä»–ã®äººã‚’発見ã—㦠ã€ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«ãã®èˆˆå‘³ãŒã‚ã‚‹ã‚‚ã®ã®æŠ•ç¨¿è€…ã‚’è¿½åŠ ã—ã¾ã™ã€‚公開ã®æŠ•ç¨¿ã§ #åˆã‚㦠ã¨å«ã‚“ã§ãã ã•ã„。" + find_people_q: "ãƒãƒƒãƒ‰ã«å‚åŠ ã—ãŸã°ã‹ã‚Šã§ã™ã€‚ã©ã®ã‚ˆã†ã«å…±æœ‰ã™ã‚‹äººã‚’見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + title: "ãƒãƒƒãƒ‰" + use_search_box_a: "ã‚ãªãŸãŒå½¼ã‚‰ã®å®Œå…¨ãªãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©* ID (例 username@podname.org) を知ã£ã¦ã„ã‚‹å ´åˆã¯ã€ãれを検索ã—ã¦è¦‹ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã‚ãªãŸãŒåŒã˜ãƒãƒƒãƒ‰ä¸Šã«ã„ã‚‹å ´åˆã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼åã ã‘ã§æ¤œç´¢ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚別ã®æ–¹æ³•ã¨ã—ã¦ã¯ã€å½¼ã‚‰ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«å (ç”»é¢ä¸Šã«è¡¨ç¤ºã•ã‚Œã‚‹åå‰) ã«ã‚ˆã£ã¦æ¤œç´¢ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚検索ãŒæœ€åˆã«å‹•ä½œã—ãªã„å ´åˆã¯ã€ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。" + use_search_box_q: "検索ボックスを使用ã—ã¦ç‰¹å®šã®å€‹äººã‚’見ã¤ã‘る方法ã¯ï¼Ÿ" + what_is_a_pod_a: "ãƒãƒƒãƒ‰ã¯ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ソフトウェアを実行ã—ã¦ã„るサーãƒãƒ¼ã§ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æŽ¥ç¶šã—ã¾ã™ã€‚ 「ãƒãƒƒãƒ‰ã€ã¯ã€ç¨®åを入れãŸæ¤æœ¨é‰¢ã®æ¯”å–©ã§ã€ã‚µãƒ¼ãƒãƒ¼ãŒå¤šæ•°ã®ãƒ¦ãƒ¼ã‚¶ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’å«ã‚“ã§ã„る様åã§ã™ã€‚多ãã®ç•°ãªã£ãŸãƒãƒƒãƒ‰ãŒã‚ã‚Šã¾ã™ã€‚ã‚ãªãŸã¯ä»–ã®ãƒãƒƒãƒ‰ã‹ã‚‰å‹é”ã‚’è¿½åŠ ã—ã¦ã€é€šä¿¡ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚別ã®ãƒãƒƒãƒ‰ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’é–‹è¨ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“ï¼ä¸€ã¤ã§å分ã§ã™ - ã“ã®ã‚ˆã†ã«ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ãƒãƒƒãƒ‰ã¯ãƒ¡ãƒ¼ãƒ«ãƒ—ãƒãƒã‚¤ãƒ€ãƒ¼ã¨åŒæ§˜ã«è€ƒãˆã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚公開ãƒãƒƒãƒ‰ã€ãƒ—ライベートãƒãƒƒãƒ‰ãŒã‚ã‚Šã€å°‘ã—ã®åŠªåŠ›ã§ã‚ãªãŸã‚‚独自ã«å®Ÿè¡Œã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚" + what_is_a_pod_q: "ãƒãƒƒãƒ‰ã¨ã¯ä½•ã§ã™ã‹ï¼Ÿ" + posts_and_posting: + char_limit_services_a: "投稿を少ãªã„æ–‡å—æ•°ã«åˆ¶é™ã™ã‚‹å¿…è¦ãŒã‚ã‚‹å ´åˆ (Twitter ã®å ´åˆã¯ 140ã€Tumblr ã®å ´åˆã¯ 1000)ã€ãŠã‚ˆã³ãã®ã‚µãƒ¼ãƒ“スã®ã‚¢ã‚¤ã‚³ãƒ³ãŒãƒã‚¤ãƒ©ã‚¤ãƒˆã•ã‚Œã¦ã„ã‚‹ã¨ãã«ã¯ã€ä½¿ç”¨ã™ã‚‹ãŸã‚ã«æ®‹ã£ã¦ã„ã‚‹æ–‡å—æ•°ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚投稿ãŒãã®åˆ¶é™ã‚ˆã‚Šã‚‚é•·ã„å ´åˆã§ã‚‚ã€ãã®ã‚µãƒ¼ãƒ“スã«æŠ•ç¨¿ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ãŒã€ãれらã®ã‚µãƒ¼ãƒ“スã¨ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*上ã®æŠ•ç¨¿ã¸ã®ãƒªãƒ³ã‚¯ã§ãƒ†ã‚ストã¯åˆ‡ã‚Šæ¨ã¦ã‚‰ã‚Œã¾ã™ã€‚" + char_limit_services_q: "å°‘ãªã„æ–‡å—æ•°ã®ææºã‚µãƒ¼ãƒ“スã§æŠ•ç¨¿ã‚’共有ã—ã¦ã„ã‚‹å ´åˆã¯ï¼Ÿ" + character_limit_a: "65,535æ–‡å—。Twitter よりも 65,395 æ–‡å—以上多ã„ã§ã™! ;)" + character_limit_q: "投稿ã®æ–‡å—数制é™ã¯ã„ãã¤ã§ã™ã‹ï¼Ÿ" + embed_multimedia_a: "投稿ã®ä¸ã«ã€æ™®é€šã« URL (例. http://www.youtube.com/watch?v=nnnnnnnnnnn ) を貼り付ã‘ã‚‹ã ã‘ã§ã€ãƒ“デオやオーディオãŒè‡ªå‹•çš„ã«åŸ‹ã‚è¾¼ã¾ã‚Œã¾ã™ã€‚サãƒãƒ¼ãƒˆã•ã‚Œã¦ã„るサイトã¯æ¬¡ã®ã‚ˆã†ãªã‚‚ã®ãŒã‚ã‚Šã¾ã™: YouTubeã€Vimeoã€SoundCloudã€Flickrã€ãªã©ã€‚ダイアスãƒãƒ©*ã¯ã€ã“ã®æ©Ÿèƒ½ã®ãŸã‚ã«oEmbedを使用ã—ã¦ã„ã¾ã™ã€‚ç§ãŸã¡ã¯ã€å¸¸ã«ã‚ˆã‚Šå¤šãã®ãƒ¡ãƒ‡ã‚£ã‚¢ã‚½ãƒ¼ã‚¹ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚常ã«ã€ã‚·ãƒ³ãƒ—ルã«ã€å®Œå…¨ãªãƒªãƒ³ã‚¯ã§æŠ•ç¨¿ã™ã‚‹ã“ã¨ã‚’忘れãªã„ã§ãã ã•ã„ - çŸç¸®ãƒªãƒ³ã‚¯ã§ã¯ãªãã€ãƒ™ãƒ¼ã‚¹URLã®å¾Œã®ã‚ªãƒšãƒ¬ãƒ¼ã‚¿ãƒ¼ã§ã‚‚ãªã - プレビューを見るãŸã‚ã€æŠ•ç¨¿å¾Œã«ãƒšãƒ¼ã‚¸ã‚’æ›´æ–°ã™ã‚‹å‰ã«å°‘ã—時間を置ãã¾ã™ã€‚" + embed_multimedia_q: "投稿ã«ãƒ“デオã€ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªã€ã¾ãŸã¯ä»–ã®ãƒžãƒ«ãƒãƒ¡ãƒ‡ã‚£ã‚¢ã‚³ãƒ³ãƒ†ãƒ³ãƒ„を埋ã‚込む方法ã¯ï¼Ÿ" + format_text_a: "%{markdown} ã¨å‘¼ã°ã‚Œã‚‹ç°¡ç•¥åŒ–ã—ãŸã‚·ã‚¹ãƒ†ãƒ を使用ã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ã€‚å…¨ã¦ã®ãƒžãƒ¼ã‚¯ãƒ€ã‚¦ãƒ³æ§‹æ–‡ã‚’ %{here} ã§å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚共有ã™ã‚‹å‰ã«ã€ã‚ãªãŸã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒã©ã®ã‚ˆã†ã«è¦‹ãˆã‚‹ã‹ã‚’å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã®ã§ã€ãƒ—レビューボタンã¯ã“ã“ã§ã¯æœ¬å½“ã«å½¹ã«ç«‹ã¡ã¾ã™ã€‚" + format_text_q: "自分ã®æŠ•ç¨¿å†…ã®ãƒ†ã‚ストã®æ›¸å¼ (太å—ã€æ–œä½“ãªã©) ã‚’è¨å®šã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + hide_posts_a: "投稿ã®å…ˆé ã«ãƒžã‚¦ã‚¹ã‚’移動ã™ã‚‹ã¨ã€X ãŒå³å´ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ãれをクリックã™ã‚‹ã¨ã€æŠ•ç¨¿ã‚’éžè¡¨ç¤ºã«ã—ã¦ã€ãã‚Œã«é–¢ã™ã‚‹é€šçŸ¥ã‚’ミュートã—ã¾ã™ã€‚ãれを投稿ã—ãŸäººã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã‚’訪å•ã™ã‚‹ã¨ã€ã¾ã 投稿を見るã“ã¨ãŒã§ãã¾ã™ã€‚" + hide_posts_q: "投稿をéžè¡¨ç¤ºã«ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + image_text: "ç”»åƒãƒ†ã‚スト" + image_url: "ç”»åƒ URL" + insert_images_a: "å°ã•ãªã‚«ãƒ¡ãƒ©ã‚¢ã‚¤ã‚³ãƒ³ã‚’クリックã—ã¦ã€æŠ•ç¨¿ã«ç”»åƒã‚’挿入ã—ã¾ã™ã€‚ã‚‚ã†ä¸€åº¦ã‚«ãƒ¡ãƒ©ã‚¢ã‚¤ã‚³ãƒ³ã‚’押ã—ã¦åˆ¥ã®å†™çœŸã‚’è¿½åŠ ã—ãŸã‚Šã€è¤‡æ•°ã®å†™çœŸã‚’é¸æŠžã—ã¦ä¸€åº¦ã«ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + insert_images_comments_a1: "コメントã«ã€ç”»åƒã‚’アップãƒãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ãŒã€æ¬¡ã®ãƒžãƒ¼ã‚¯ãƒ€ã‚¦ãƒ³ã‚³ãƒ¼ãƒ‰" + insert_images_comments_a2: "を使用ã—ã¦ã€ã‚³ãƒ¡ãƒ³ãƒˆãªã‚‰ã³ã«æŠ•ç¨¿ã«ã‚¦ã‚§ãƒ–ã‹ã‚‰ç”»åƒã‚’挿入ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + insert_images_comments_q: "コメントã«ç”»åƒã‚’挿入ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + insert_images_q: "投稿ã«ç”»åƒã‚’挿入ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + post_location_a: "公開者ã®ã‚«ãƒ¡ãƒ©ã®æ¨ªã®ãƒ”ンアイコンをクリックã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€OpenStreetMap ã‹ã‚‰ã‚ãªãŸã®å ´æ‰€ã‚’挿入ã—ã¾ã™ã€‚ã‚ãªãŸã®å ´æ‰€ã‚’編集ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ - ã‚ãªãŸãŒã„る都市ã§ã¯ãªãã€ç‰¹å®šã®ä½æ‰€ã‚’å«ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + post_location_q: "投稿ã«è‡ªåˆ†ã®å ´æ‰€ã‚’è¿½åŠ ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + post_notification_a: "投稿ã®å³ä¸Šã«ã‚ã‚‹ X ã®æ¨ªã«ãƒ™ãƒ«ã®ã‚¢ã‚¤ã‚³ãƒ³ãŒã‚ã‚Šã¾ã™ã€‚ã“れをクリックã—ã¦ã€ãã®æŠ•ç¨¿ã®é€šçŸ¥ã‚’有効ã¾ãŸã¯ç„¡åŠ¹ã«ã—ã¾ã™ã€‚" + post_notification_q: "投稿ã«é–¢ã™ã‚‹é€šçŸ¥ã‚’å–å¾—ã™ã‚‹ã€ã¾ãŸã¯é€šçŸ¥ã‚’åœæ¢ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + post_poll_a: "グラフã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’クリックã—ã¦ã€æŠ•ç¥¨ã‚’生æˆã—ã¾ã™ã€‚質å•ã¨ã€å°‘ãªãã¨ã‚‚ 2 ã¤ã®ç”ãˆã‚’入力ã—ã¾ã™ã€‚ã™ã¹ã¦ã®äººãŒã‚ãªãŸã®æŠ•ç¥¨ã«å‚åŠ ã§ãるよã†ã«ã—ãŸã„å ´åˆã¯ã€æŠ•ç¨¿ã‚’公開ã«ã™ã‚‹ã“ã¨ã‚’忘れãªã„ã§ãã ã•ã„。" + post_poll_q: "ç§ã®æŠ•ç¨¿ã«æŠ•ç¥¨ã‚’è¿½åŠ ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + post_report_a: "ã‚ãªãŸã®ãƒãƒƒãƒ‰ç®¡ç†è€…ã«å ±å‘Šã™ã‚‹ã«ã¯ã€æŠ•ç¨¿ã®å³ä¸Šã«ã‚ã‚‹è¦å‘Šä¸‰è§’å½¢ã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’クリックã—ã¾ã™ã€‚ダイアãƒã‚°ãƒœãƒƒã‚¯ã‚¹ã§ã“ã®æŠ•ç¨¿ã‚’å ±å‘Šã™ã‚‹ãŸã‚ã®ç†ç”±ã‚’入力ã—ã¦ãã ã•ã„。" + post_report_q: "攻撃的ãªæŠ•ç¨¿ã‚’å ±å‘Šã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + size_of_images_a: "ã„ã„ãˆã€‚ストリームã¾ãŸã¯ã‚·ãƒ³ã‚°ãƒ«ãƒã‚¹ãƒˆãƒ“ューã«åˆã‚ã›ã¦ç”»åƒã¯è‡ªå‹•çš„ã«ãƒªã‚µã‚¤ã‚ºã•ã‚Œã¾ã™ã€‚ マークダウン記法ã¯ã€ç”»åƒã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ãŸã‚ã®ã‚³ãƒ¼ãƒ‰ã‚’æŒã£ã¦ã„ã¾ã›ã‚“。" + size_of_images_q: "投稿やコメント内ã®ç”»åƒã®ã‚µã‚¤ã‚ºã‚’カスタマイズã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + stream_full_of_posts_a1: "ã‚ãªãŸã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã¯ã€3 種類ã®æŠ•ç¨¿ã§æ§‹æˆã•ã‚Œã¦ã„ã¾ã™:" + stream_full_of_posts_li1: "ã‚ãªãŸã¨å…±æœ‰ã—ã¦ã„る人々ã«ã‚ˆã‚‹æŠ•ç¨¿ã¯ 2 種類ã‚ã‚Šã¾ã™: 公開ã®æŠ•ç¨¿ã¨ã€ã‚ãªãŸãŒå«ã¾ã‚Œã‚‹ã‚¢ã‚¹ãƒšã‚¯ãƒˆã¨å…±æœ‰ã—ãŸé™å®šå…¬é–‹ã®æŠ•ç¨¿ã€‚ã“れらã®æŠ•ç¨¿ã‚’ã‚ãªãŸã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‹ã‚‰å‰Šé™¤ã™ã‚‹ã«ã¯ã€å˜ã«ãã®äººã¨ã®å…±æœ‰ã‚’æ¢ã‚ã¾ã™ã€‚" + stream_full_of_posts_li2: "ã‚ãªãŸãŒãƒ•ã‚©ãƒãƒ¼ã—ã¦ã„ã‚‹ã‚¿ã‚°ã‚’å«ã‚€å…¬é–‹ã®æŠ•ç¨¿ã€‚ã“れらを削除ã™ã‚‹ã«ã¯ã€ãã®ã‚¿ã‚°ã®ãƒ•ã‚©ãƒãƒ¼ã‚’æ¢ã‚ã¾ã™ã€‚" + stream_full_of_posts_li3: "コミュニティスãƒãƒƒãƒˆãƒ©ã‚¤ãƒˆã«è¨˜è¼‰ã•ã‚Œã¦ã„る人々ã«ã‚ˆã‚‹å…¬é–‹ã®æŠ•ç¨¿ã€‚ã“れらã¯è¨å®šã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚¿ãƒ–ã§ã€ã‚ªãƒ—ション「ストリームã«ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã‚¹ãƒãƒƒãƒˆãƒ©ã‚¤ãƒˆã‚’表示?ã€ã®ãƒã‚§ãƒƒã‚¯ã‚’オフã«ã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦é™¤å¤–ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + stream_full_of_posts_q: "ãªãœç§ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ãŒã€çŸ¥ã‚‰ãªã„人や共有ã—ã¦ã„ãªã„人ã‹ã‚‰ã®æŠ•ç¨¿ã§ã„ã£ã±ã„ãªã®ã§ã™ã‹ï¼Ÿ" + title: "投稿" + private_posts: + can_comment_a: "éžå…¬é–‹ã®æŠ•ç¨¿ã‚’è¡Œã†å‰ã«ãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«é…ç½®ã•ã‚Œã¦ã„ãŸã€ãƒã‚°ã‚¤ãƒ³ã—ã¦ã„るダイアスãƒãƒ©*ユーザーã®ã¿ãŒãã‚Œã«ã‚³ãƒ¡ãƒ³ãƒˆã¾ãŸã¯ã„ã„ãï¼ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + can_comment_q: "éžå…¬é–‹ã®æŠ•ç¨¿ã«ã€èª°ãŒã‚³ãƒ¡ãƒ³ãƒˆã¾ãŸã¯ã„ã„ãï¼ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + can_reshare_a: "誰もã„ã¾ã›ã‚“。éžå…¬é–‹ã®æŠ•ç¨¿ã¯å†å…±æœ‰ã§ãã¾ã›ã‚“。ã—ã‹ã—ã€ãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆå†…ã®ãƒã‚°ã‚¤ãƒ³ã—ã¦ã„るダイアスãƒãƒ©*ユーザーã¯ã€æ½œåœ¨çš„ã«ã‚³ãƒ”ーãŠã‚ˆã³è²¼ã‚Šä»˜ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãれらã®äººã€…ã‚’ä¿¡é ¼ã™ã‚‹ã‹ã©ã†ã‹ã¯ã‚ãªãŸæ¬¡ç¬¬ã§ã™ï¼" + can_reshare_q: "誰ãŒç§ã®éžå…¬é–‹ã®æŠ•ç¨¿ã‚’å†å…±æœ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + see_comment_a: "投稿を共有ã•ã‚ŒãŸäºº (å…ƒã®æŠ•ç¨¿è€…ã«ã‚ˆã£ã¦é¸æŠžã•ã‚ŒãŸã‚¢ã‚¹ãƒšã‚¯ãƒˆã«ã„る人) ã®ã¿ã€ãã®ã‚³ãƒ¡ãƒ³ãƒˆã‚„ã„ã„ãï¼ã‚’見るã“ã¨ãŒã§ãã¾ã™ã€‚ " + see_comment_q: "ç§ãŒéžå…¬é–‹ã®æŠ•ç¨¿ã«ã‚³ãƒ¡ãƒ³ãƒˆã¾ãŸã¯ã„ã„ãï¼ã—ãŸã¨ãã€èª°ãŒãれを見るã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + title: "éžå…¬é–‹ã®æŠ•ç¨¿" + who_sees_post_a: "éžå…¬é–‹ã®æŠ•ç¨¿ã‚’è¡Œã†å‰ã«ãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«é…ç½®ã•ã‚Œã¦ã„ãŸã€ãƒã‚°ã‚¤ãƒ³ã—ã¦ã„るダイアスãƒãƒ©*ユーザーã®ã¿ãŒãれを見るã“ã¨ãŒã§ãã¾ã™ã€‚" + who_sees_post_q: "アスペクトã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’投稿ã™ã‚‹ã¨ (例 éžå…¬é–‹ã®æŠ•ç¨¿)ã€èª°ãŒãれを見るã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + private_profiles: + title: "éžå…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«" + whats_in_profile_a: "ã™ã¹ã¦ã®ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã‚’完了ã—ã¦ã„ã‚‹å ´åˆã€ã‚ãªãŸã®éžå…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã«ã¯ã€ç•¥æ´ã€å ´æ‰€ã€æ€§åˆ¥ã€èª•ç”Ÿæ—¥ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚ã“ã®æƒ…å ±ã¯ã™ã¹ã¦ã‚ªãƒ—ションã§ã™ - ãれをæä¾›ã™ã‚‹ã‹ã©ã†ã‹ã¯ã‚ãªãŸæ¬¡ç¬¬ã§ã™ã€‚ã‚ãªãŸã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«è¿½åŠ ã—ãŸãƒã‚°ã‚¤ãƒ³ãƒ¦ãƒ¼ã‚¶ãƒ¼ã ã‘ãŒã€ã‚ãªãŸã®éžå…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’見るã“ã¨ãŒã§ãã¾ã™ã€‚彼らãŒã‚ãªãŸã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã¨ã€å½¼ã‚‰ãŒå«ã¾ã‚Œã¦ã„るアスペクトã«å¯¾ã—ã¦è¡Œã‚ã‚ŒãŸéžå…¬é–‹ã®æŠ•ç¨¿ã‚‚ã€ã‚ãªãŸã®å…¬é–‹ã®æŠ•ç¨¿ã«æ··ã˜ã£ã¦è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚" + whats_in_profile_q: "ç§ã®éžå…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã«ã¯ä½•ãŒã‚ã‚Šã¾ã™ã‹ï¼Ÿ" + who_sees_profile_a: "ã‚ãªãŸã¨å…±æœ‰ã—ã¦ã„ã‚‹ã™ã¹ã¦ã®ãƒã‚°ã‚¤ãƒ³ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ (ã‚ãªãŸã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ä¸€ã¤ã«å½¼ã‚‰ã‚’è¿½åŠ ã—ã¦ã„ã‚‹ã¨ã„ã†æ„味)。ã—ã‹ã—ã€ã‚ãªãŸã‚’フォãƒãƒ¼ã—ã¦ã„ã¦ã‚‚ã€ã‚ãªãŸãŒãƒ•ã‚©ãƒãƒ¼ã—ã¦ã„ãªã„人ã¯ã€ã‚ãªãŸã®å…¬é–‹æƒ…å ±ãŒè¡¨ç¤ºã•ã‚Œã‚‹ã ã‘ã§ã™ã€‚" + who_sees_profile_q: "誰ãŒç§ã®éžå…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’見ã¾ã™ã‹ï¼Ÿ" + who_sees_updates_a: "ã‚ãªãŸã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«ã„る誰もãŒã€ã‚ãªãŸã®éžå…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã¸ã®å¤‰æ›´ã‚’見ã¦ã„ã¾ã™ã€‚ " + who_sees_updates_q: "ç§ã®éžå…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã¸ã®æ›´æ–°ã‚’誰ãŒè¦‹ã¾ã™ã‹ï¼Ÿ" + public_posts: + can_comment_reshare_like_a: "ã™ã¹ã¦ã®ãƒã‚°ã‚¤ãƒ³ã—ã¦ã„るダイアスãƒãƒ©*ユーザーãŒã‚³ãƒ¡ãƒ³ãƒˆã—ãŸã‚Šã€å†å…±æœ‰ã—ãŸã‚Šã€ã„ã„ãï¼ã‚’ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + can_comment_reshare_like_q: "誰ãŒã€ç§ã®å…¬é–‹ã®æŠ•ç¨¿ã‚’コメントã—ãŸã‚Šã€å†å…±æœ‰ã€ã„ã„ãï¼ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + deselect_aspect_posting_a: "アスペクトã®é¸æŠžã‚’解除ã—ã¦ã‚‚ã€å…¬é–‹ã®æŠ•ç¨¿ã«ã¯å½±éŸ¿ã‚’与ãˆã¾ã›ã‚“。公開ã•ã‚Œã¦ã€ã‚ãªãŸã®é€£çµ¡å…ˆã®ã™ã¹ã¦ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚特定ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«ã®ã¿æŠ•ç¨¿ãŒè¦‹ãˆã‚‹ã‚ˆã†ã«ã™ã‚‹ã«ã¯ã€å…¬é–‹è€…ã®ä¸‹ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚»ãƒ¬ã‚¯ã‚¿ãƒ¼ã‹ã‚‰ãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’é¸æŠžã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚" + deselect_aspect_posting_q: "公開ã®æŠ•ç¨¿ã‚’è¡Œã†ã¨ãã«ã€1 ã¤ã¾ãŸã¯è¤‡æ•°ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®é¸æŠžã‚’解除ã—ãŸå ´åˆã¯ã©ã†ãªã‚Šã¾ã™ã‹ï¼Ÿ" + find_public_post_a: "ã‚ãªãŸã®å…¬é–‹ã®æŠ•ç¨¿ã¯ã€ã‚ãªãŸã‚’フォãƒãƒ¼ã—ã¦ã„る誰ã‹ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã‚ãªãŸãŒå…¬é–‹ã®æŠ•ç¨¿ã« #ã‚¿ã‚° ã‚’å«ã‚ãŸå ´åˆã€ãã®ã‚¿ã‚°ã‚’フォãƒãƒ¼ã—ã¦ã„ã‚‹ã™ã¹ã¦ã®äººãŒè‡ªåˆ†ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã§ã‚ãªãŸã®æŠ•ç¨¿ã‚’見ã¤ã‘ã¾ã™ã€‚ã™ã¹ã¦ã®å…¬é–‹ã®æŠ•ç¨¿ã¯ã€ãƒã‚°ã‚¤ãƒ³ã—ã¦ã„ãªã„å ´åˆã§ã‚‚ã€èª°ã§ã‚‚閲覧ã™ã‚‹ã“ã¨ãŒã§ãる特定㮠URL ã‚‚æŒã£ã¦ã„ã¾ã™ - ãã®ãŸã‚ã€å…¬é–‹ã®æŠ•ç¨¿ã¯ Twitterã€ãƒ–ãƒã‚°ã€ãªã©ã‹ã‚‰ç›´æŽ¥ãƒªãƒ³ã‚¯ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚公開ã®æŠ•ç¨¿ã¯ã€æ¤œç´¢ã‚¨ãƒ³ã‚¸ãƒ³ã«ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã•ã‚Œã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚" + find_public_post_q: "ç§ã®å…¬é–‹ã®æŠ•ç¨¿ã‚’ä»–ã®äººã¯ã©ã®ã‚ˆã†ã«è¦‹ã¤ã‘ã¾ã™ã‹ï¼Ÿ" + see_comment_reshare_like_a: "公開ã®æŠ•ç¨¿ã®ã‚³ãƒ¡ãƒ³ãƒˆã€ã„ã„ãï¼ã€ãŠã‚ˆã³å†å…±æœ‰ã‚‚ã¾ãŸã€å…¬é–‹ã•ã‚Œã¾ã™ã€‚ã™ã¹ã¦ã®ãƒã‚°ã‚¤ãƒ³ã—ã¦ã„るダイアスãƒãƒ©*ユーザーã¨ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Šã®èª°ã§ã‚‚公開ã®æŠ•ç¨¿ã¨ã‚ãªãŸã®ã‚„ã‚Šå–りを見るã“ã¨ãŒã§ãã¾ã™ã€‚" + see_comment_reshare_like_q: "ç§ãŒå…¬é–‹ã®æŠ•ç¨¿ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ãŸã‚Šã€å†å…±æœ‰ã€ã„ã„ãï¼ã—ãŸã¨ãã€èª°ãŒãれを見るã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + title: "公開ã®æŠ•ç¨¿" + who_sees_post_a: "インターãƒãƒƒãƒˆã‚’使ã£ã¦ã„る誰もãŒã‚ãªãŸãŒå…¬é–‹ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã—ãŸæŠ•ç¨¿ã‚’å‚ç…§ã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚‹ã®ã§ã€ã‚ãªãŸã®æŠ•ç¨¿ã‚’本当ã«å…¬é–‹ã«ã—ãŸã„ã‹ã‚’確èªã—ã¦ãã ã•ã„。世界ã«æ‰‹ã‚’å·®ã—伸ã¹ã‚‹ç´ 晴らã—ã„方法ã§ã™ã€‚" + who_sees_post_q: "公開ã§ä½•ã‹ã‚’投稿ã™ã‚‹ã¨ã€èª°ãŒãれを見るã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + public_profiles: + title: "公開プãƒãƒ•ã‚£ãƒ¼ãƒ«" + what_do_tags_do_a: "人々ãŒã‚ãªãŸã®ã“ã¨ã‚’知るã®ã«å½¹ç«‹ã¡ã¾ã™ã€‚ã“れら特定ã®ã‚¿ã‚°ãƒšãƒ¼ã‚¸ã®å·¦å´ã«ã€å…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã§ãれらをæŒã£ã¦ã„ã‚‹ä»–ã®èª°ã‹ã¨ä¸€ç·’ã«ã€ã‚ãªãŸã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«å†™çœŸã‚‚表示ã•ã‚Œã¾ã™ã€‚" + what_do_tags_do_q: "公開プãƒãƒ•ã‚£ãƒ¼ãƒ«ä¸Šã®ã‚¿ã‚°ã¯ä½•ã‚’ã—ã¾ã™ã‹ï¼Ÿ" + whats_in_profile_a: "ã™ã¹ã¦ã®ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã‚’完了ã—ã¦ã„ã‚‹å ´åˆã€å…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã«ã¯ã€ã‚ãªãŸã®åå‰ã€ã‚ãªãŸè‡ªèº«ã‚’説明ã™ã‚‹ãŸã‚ã«é¸ã¶ 5 ã¤ã®ã‚¿ã‚°ã€ã‚ãªãŸã®å†™çœŸãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚ã“ã®æƒ…å ±ã¯ã™ã¹ã¦ã‚ªãƒ—ションã§ã™ - ãれをæä¾›ã™ã‚‹ã‹ã©ã†ã‹ã¯ã‚ãªãŸæ¬¡ç¬¬ã§ã™ã€‚ã‚ãªãŸãŒå¥½ããªã‚ˆã†ã«ç‰¹å®šå¯èƒ½ã¾ãŸã¯åŒ¿åã§ã€ã“ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«æƒ…å ±ã‚’ä½œã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã‚ãªãŸã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã¯ã€ã‚ãªãŸãŒè¡Œã£ãŸã™ã¹ã¦ã®å…¬é–‹ã®æŠ•ç¨¿ã‚‚表示ã—ã¦ã„ã¾ã™ã€‚" + whats_in_profile_q: "ç§ã®å…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã«ã¯ä½•ãŒã‚ã‚Šã¾ã™ã‹ï¼Ÿ" + who_sees_profile_a: "ã™ã¹ã¦ã®ãƒã‚°ã‚¤ãƒ³ã—ãŸãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ユーザーã ã‘ã§ãªãã€ã‚ˆã‚Šåºƒãインターãƒãƒƒãƒˆã‹ã‚‰è¦‹ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã‚Œãžã‚Œã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã¯ã€ç›´æŽ¥ URL ãŒã‚ã‚‹ã®ã§ã€å¤–部サイトã‹ã‚‰ç›´æŽ¥ãƒªãƒ³ã‚¯ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã‚Œã¯ã€æ¤œç´¢ã‚¨ãƒ³ã‚¸ãƒ³ã«ã‚ˆã£ã¦ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã•ã‚Œã‚‹ã“ã¨ã‚‚ã‚ã‚Šã¾ã™ã€‚" + who_sees_profile_q: "誰ãŒç§ã®å…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’見ã¦ã„ã¾ã™ã‹ï¼Ÿ" + who_sees_updates_a: "ã‚ãªãŸã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã¨ã€èª°ã§ã‚‚更新を見るã“ã¨ãŒã§ãã¾ã™ã€‚" + who_sees_updates_q: "誰ãŒç§ã®å…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã¸ã®æ›´æ–°ã‚’見ã¦ã„ã¾ã™ã‹ï¼Ÿ" + resharing_posts: + reshare_private_post_aspects_a: "ã„ã„ãˆã€‚éžå…¬é–‹ã®æŠ•ç¨¿ã‚’å†å…±æœ‰ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。ã“ã‚ŒãŒã€ç‰¹å®šã®ã‚°ãƒ«ãƒ¼ãƒ—ã®äººã€…ã¨ã®ã¿ãれを共有ã—ãŸã€å…ƒã®æŠ•ç¨¿è€…ã®æ„å‘ã‚’å°Šé‡ã™ã‚‹ã“ã¨ã§ã™ã€‚" + reshare_private_post_aspects_q: "éžå…¬é–‹ã®æŠ•ç¨¿ã‚’ã€é¸æŠžã—ãŸã‚¢ã‚¹ãƒšã‚¯ãƒˆã«å†å…±æœ‰ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + reshare_public_post_aspects_a: "ã„ã„ãˆã€‚公開ã®æŠ•ç¨¿ã‚’å†å…±æœ‰ã™ã‚‹ã¨ã€ãã‚Œã¯è‡ªå‹•çš„ã«ã‚ãªãŸã®å…¬é–‹ã®æŠ•ç¨¿ã®ä¸€ã¤ã«ãªã‚Šã¾ã™ã€‚ ãれを特定ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã¨å…±æœ‰ã™ã‚‹ã«ã¯ã€æ–°ã—ã„é™å®šå…¬é–‹ã®æŠ•ç¨¿ã«æŠ•ç¨¿ã®å†…容をコピーãŠã‚ˆã³è²¼ã‚Šä»˜ã‘ã—ã¾ã™ã€‚" + reshare_public_post_aspects_q: "公開ã®æŠ•ç¨¿ã‚’ã€é¸æŠžã—ãŸã‚¢ã‚¹ãƒšã‚¯ãƒˆã«å†å…±æœ‰ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + title: "投稿ã®å†å…±æœ‰" + sharing: + add_to_aspect_a1: "エイミーãŒãƒ™ãƒ³ã‚’アスペクトã«è¿½åŠ ã—ã€ãƒ™ãƒ³ã¯ (ã¾ã ) エイミーをアスペクトã«è¿½åŠ ã—ã¦ã„ãªã„ã¨ã—ã¾ã—ょã†:" + add_to_aspect_a2: "ã“ã‚Œã¯éžå¯¾ç§°ã®å…±æœ‰ã¨ã—ã¦çŸ¥ã‚‰ã‚Œã¦ã„ã¾ã™ã€‚ã‚‚ã—ã€ãƒ™ãƒ³ã‚‚ã¾ãŸã€ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«ã‚¨ã‚¤ãƒŸãƒ¼ã‚’è¿½åŠ ã™ã‚‹ã¨ã€ãŠäº’ã„ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã«ã‚¨ã‚¤ãƒŸãƒ¼ã¨ãƒ™ãƒ³ã®ä¸¡æ–¹å…¬é–‹ã®æŠ•ç¨¿ã‚„関連ã™ã‚‹éžå…¬é–‹ã®æŠ•ç¨¿ãŒè¡¨ç¤ºã•ã‚Œã€ç›¸äº’共有ã«ãªã‚‹ã§ã—ょã†ã€‚ãã—ã¦ã€ã‚¨ã‚¤ãƒŸãƒ¼ã¯ãƒ™ãƒ³ã®éžå…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã§ã—ょã†ã€‚ãã—ã¦ã€å½¼ã‚‰ã¯ãŠäº’ã„ã«éžå…¬é–‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’é€ä¿¡ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã§ã—ょã†ã€‚" + add_to_aspect_li1: "ベンã¯ã€ã‚¨ã‚¤ãƒŸãƒ¼ãŒãƒ™ãƒ³ã¨ã€Œå…±æœ‰ã‚’開始ã—ãŸã€ã¨ã„ã†é€šçŸ¥ã‚’å—ã‘å–ã‚Šã¾ã™ã€‚" + add_to_aspect_li2: "エイミーã¯å½¼å¥³ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã«ã€ãƒ™ãƒ³ã®å…¬é–‹ã®æŠ•ç¨¿ã®è¡¨ç¤ºãŒå§‹ã¾ã‚Šã¾ã™ã€‚" + add_to_aspect_li3: "エイミーã¯ã€ãƒ™ãƒ³ã®éžå…¬é–‹ã®æŠ•ç¨¿ã¯è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。" + add_to_aspect_li4: "ベンã¯ã€å½¼ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã«ã‚¨ã‚¤ãƒŸãƒ¼ã®å…¬é–‹ã¾ãŸã¯éžå…¬é–‹ã®æŠ•ç¨¿ã¯è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。" + add_to_aspect_li5: "ベンãŒã‚¨ã‚¤ãƒŸãƒ¼ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã«ç§»å‹•ã—ãŸå ´åˆã€å½¼ã«ã¯ã€ã‚¨ã‚¤ãƒŸãƒ¼ãŒå½¼ã‚’é…ç½®ã—ã¦ã„るアスペクトã«è¡Œã£ãŸéžå…¬é–‹ã®æŠ•ç¨¿ (ã¨åŒæ§˜ã«ã€èª°ã§ã‚‚見るã“ã¨ãŒã§ãる彼女ã®å…¬é–‹ã®æŠ•ç¨¿) ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚" + add_to_aspect_li6: "ベンã¯ã‚¨ã‚¤ãƒŸãƒ¼ã®éžå…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ« (ç•¥æ´ã€å ´æ‰€ã€æ€§åˆ¥ã€èª•ç”Ÿæ—¥) を見るã“ã¨ãŒã§ãã¾ã™ã€‚" + add_to_aspect_li7: "エイミーã¯ã€ãƒ™ãƒ³ã®é€£çµ¡å…ˆãƒšãƒ¼ã‚¸ã®ã€Œè‡ªåˆ†ã ã‘ã«å…±æœ‰ã€ã®ä¸‹ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚" + add_to_aspect_li8: "エイミーもベンを@メンションã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚" + add_to_aspect_q: "ç§ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ä¸€ã¤ã«èª°ã‹ã‚’è¿½åŠ ã™ã‚‹ã¨ã€ã¾ãŸã¯èª°ã‹ãŒå½¼ã‚‰ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ä¸€ã¤ã«ç§ã‚’è¿½åŠ ã™ã‚‹ã¨ã€ã©ã†ãªã‚Šã¾ã™ã‹ï¼Ÿ" + list_not_sharing_a: "ã„ã„ãˆã€‚ã—ã‹ã—ã€å½¼ã‚‰ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã‚’訪å•ã—ã¦ã€ãã®äººãŒã‚ãªãŸã¨å…±æœ‰ã—ã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚’確èªã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®å ´åˆã€å½¼ã‚‰ãŒé…ç½®ã—ãŸã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’示ã™ãƒœã‚¿ãƒ³ãŒç·‘色ã«ãªã‚Šã€ãªã„å ´åˆã¯ã€ãã‚ŒãŒç°è‰²ã«ãªã‚‹ã§ã—ょã†ã€‚" + list_not_sharing_q: "ç§ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ä¸€ã¤ã«è¿½åŠ ã—ãŸäººã§ã€ãã®äººã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«ç§ã‚’è¿½åŠ ã—ã¦ã„ãªã„人ã®ãƒªã‚¹ãƒˆã¯ã‚ã‚Šã¾ã™ã‹ï¼Ÿ" + only_sharing_a: "ã“れらã¯ã€è‡ªåˆ†ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ä¸€ã¤ã«ã‚ãªãŸã‚’è¿½åŠ ã—ãŸäººã§ã™ãŒã€ã‚ãªãŸã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ã„ãšã‚Œã«ã‚‚ (ã¾ã ) ã„ãªã„人ã§ã™ã€‚言ã„æ›ãˆã‚Œã°ã€å½¼ã‚‰ã¯ã‚ãªãŸã¨å…±æœ‰ã—ã¦ã„ã¾ã™ãŒã€ã‚ãªãŸã¯å½¼ã‚‰ã¨å…±æœ‰ã—ã¦ã„ã¾ã›ã‚“: 彼らをã€ã‚ãªãŸã‚’「フォãƒãƒ¼ã—ã¦ã„ã‚‹ã€äººã¨è€ƒãˆã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã‚ãªãŸãŒã‚¢ã‚¹ãƒšã‚¯ãƒˆã«å½¼ã‚‰ã‚’è¿½åŠ ã—ãŸå ´åˆã€ãã®å¾Œã€ã€Œè‡ªåˆ†ã ã‘ã«å…±æœ‰ã€ã§ã¯ãªãアスペクトã®ä¸‹ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚上記をå‚ç…§ã—ã¦ãã ã•ã„。" + only_sharing_q: "ç§ã®é€£çµ¡å…ˆãƒšãƒ¼ã‚¸ã®ã€Œè‡ªåˆ†ã ã‘ã«å…±æœ‰ã€ã®ä¸‹ã«ãƒªã‚¹ãƒˆã•ã‚Œã¦ã„る人ã¯èª°ã§ã™ã‹ï¼Ÿ" + see_old_posts_a: "ã„ã„ãˆã€‚彼らã¯ã€ãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã¸ã®æ–°ã—ã„投稿ã®ã¿ã‚’見るã“ã¨ãŒã§ãã¾ã™ã€‚彼ら (ãŠã‚ˆã³ä»–ã®èª°ã§ã‚‚) ã‚ãªãŸã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã§ã‚ãªãŸã®å¤ã„公開ã®æŠ•ç¨¿ã‚’見るã“ã¨ãŒã§ãã€ã¾ãŸã€å½¼ã‚‰ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã§ã‚‚ãれらを見るã“ã¨ãŒã§ãã¾ã™ã€‚" + see_old_posts_q: "ç§ãŒèª°ã‹ã‚’アスペクトã«è¿½åŠ ã™ã‚‹ã¨ã€å½¼ã‚‰ã¯ç§ãŒã™ã§ã«ãã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«æŠ•ç¨¿ã—ã¦ã„ã‚‹å¤ã„投稿を見るã“ã¨ãŒã§ãã¾ã™ã‹ï¼Ÿ" + sharing_notification_a: "誰ã‹ãŒã‚ãªãŸã¨å…±æœ‰ã‚’始ã‚ã‚‹ãŸã³ã«ã€ã‚ãªãŸã¯é€šçŸ¥ã‚’å—ä¿¡ã™ã‚‹ã¯ãšã§ã™ã€‚" + sharing_notification_q: "誰ã‹ãŒç§ã¨å…±æœ‰ã‚’始ã‚ãŸã¨ãã€ã©ã®ã‚ˆã†ã«ç§ãŒãれを知りã¾ã™ã‹ï¼Ÿ" + title: "共有" + tags: + filter_tags_a: "ã“ã‚Œã¯ã€ã¾ã 直接ダイアスãƒãƒ©*を通ã—ã¦åˆ©ç”¨ã§ãã¾ã›ã‚“ãŒã€ã„ãã¤ã‹ã® %{third_party_tools} ãŒã“れをæä¾›ã™ã‚‹ãŸã‚ã«ä½œæˆã•ã‚Œã¦ã„ã¾ã™ã€‚" + filter_tags_q: "ç§ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‹ã‚‰ã„ãã¤ã‹ã®ã‚¿ã‚°ã‚’フィルター/除外ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + followed_tags_a: "タグを検索ã—ãŸå¾Œã«ã€ã‚¿ã‚°ã®ãƒšãƒ¼ã‚¸ã®ä¸Šéƒ¨ã«ã‚るボタンをクリックã—ã¦ã€ãã®ã‚¿ã‚°ã‚’「フォãƒãƒ¼ã€ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãã®å¾Œã€å·¦å´ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã§ãƒ•ã‚©ãƒãƒ¼ã—ãŸã‚¿ã‚°ã®ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚フォãƒãƒ¼ã—ãŸã‚¿ã‚°ã®ã„ãšã‚Œã‹ã‚’クリックã™ã‚‹ã¨ã€ãã®ã‚¿ã‚°ã®ãƒšãƒ¼ã‚¸ã«ç§»å‹•ã—ã¦ã€ãã®ã‚¿ã‚°ã‚’å«ã‚€æœ€è¿‘ã®æŠ•ç¨¿ã‚’見るã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚#フォãƒãƒ¼ã—ãŸã‚¿ã‚°ã‚’クリックã™ã‚‹ã¨ã€ã‚ãªãŸãŒãƒ•ã‚©ãƒãƒ¼ã—ãŸã‚¿ã‚°ã®ã„ãšã‚Œã‹ã‚’å«ã‚€æŠ•ç¨¿ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ を見るã“ã¨ãŒã§ãã¾ã™ã€‚" + followed_tags_q: "「#フォãƒãƒ¼ã—ãŸã‚¿ã‚°ã€ã¨ã¯ä½•ã§ã™ã‹ã€ã‚¿ã‚°ã‚’フォãƒãƒ¼ã™ã‚‹æ–¹æ³•ã¯ï¼Ÿ" + people_tag_page_a: "公開プãƒãƒ•ã‚£ãƒ¼ãƒ«ã§è‡ªåˆ†è‡ªèº«ã‚’説明ã™ã‚‹ãŸã‚ã«ã€ãã®ã‚¿ã‚°ã‚’記載ã—ã¦ã„る人ã§ã™ã€‚" + people_tag_page_q: "タグページã®å·¦å´ã«è¨˜è¼‰ã•ã‚Œã¦ã„る人ã¯èª°ã§ã™ã‹ï¼Ÿ" + tags_in_comments_a: "コメントã«è¿½åŠ ã•ã‚ŒãŸã‚¿ã‚°ã¯ã€ã‚¿ã‚°ã®ãƒšãƒ¼ã‚¸ã¸ã®ãƒªãƒ³ã‚¯ã¨ã—ã¦è¡¨ç¤ºã•ã‚Œã¾ã™ãŒã€ãã®æŠ•ç¨¿ (ã¾ãŸã¯ã‚³ãƒ¡ãƒ³ãƒˆ) ãŒã€ãã®ã‚¿ã‚°ã®ãƒšãƒ¼ã‚¸ã«è¡¨ç¤ºã•ã‚Œã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。ã“ã‚Œã¯æŠ•ç¨¿ã®ä¸ã®ã‚¿ã‚°ã«å¯¾ã—ã¦ã®ã¿æ©Ÿèƒ½ã—ã¾ã™ã€‚" + tags_in_comments_q: "コメントã€ã¾ãŸã¯æŠ•ç¨¿ã®ä¸ã«ã‚¿ã‚°ã‚’入れるã“ã¨ã¯ã§ãã¾ã™ã‹ï¼Ÿ" + title: "ã‚¿ã‚°" + what_are_tags_for_a: "ã‚¿ã‚°ã¯ã€é€šå¸¸ãƒˆãƒ”ックã”ã¨ã«ã€æŠ•ç¨¿ã‚’分類ã™ã‚‹æ–¹æ³•ã§ã™ã€‚タグを検索ã™ã‚‹ã¨ã€è¡¨ç¤ºã™ã‚‹æ¨©é™ã‚’æŒã£ã¦ã„ã‚‹ã‚¿ã‚°ã®ã€å…¬é–‹ã¨éžå…¬é–‹ã®ä¸¡æ–¹ã®ã™ã¹ã¦ã®æŠ•ç¨¿ã‚’表示ã—ã¾ã™ã€‚ã“ã‚Œã¯ã€ç‰¹å®šã®ãƒˆãƒ”ックã«èˆˆå‘³ã‚’æŒã£ã¦ã„る人々ã«ã€ãã‚Œã«é–¢ã™ã‚‹å…¬é–‹ã®æŠ•ç¨¿ã‚’見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãるよã†ã«ã—ã¾ã™ã€‚" + what_are_tags_for_q: "ã‚¿ã‚°ã¯ä½•ã®ãŸã‚ã§ã™ã‹ï¼Ÿ" + third_party_tools: "サードパーティーã®ãƒ„ール" + title_header: "ヘルプ" tutorial: "ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«" + tutorials: "ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«" wiki: "wiki" - hide: "éš ã™" + home: + default: + be_who_you_want_to_be: "ã‚ãªãŸãŒãªã‚ŠãŸã„人ã«ãªã‚‹" + be_who_you_want_to_be_info: "多ãã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¯ã€ã‚ãªãŸãŒå®Ÿåを使用ã™ã‚‹ã“ã¨ã‚’主張ã—ã¦ã„ã¾ã™ã€‚ダイアスãƒãƒ©*ã¯ãã†ã§ã¯ã‚ã‚Šã¾ã›ã‚“。ã“ã“ã§ã¯ã€ã‚ãªãŸãŒãªã‚ŠãŸã„人をé¸ã‚“ã§ã€è‡ªåˆ†è‡ªèº«ã«ã¤ã„ã¦ãŸãã•ã‚“ã€ã‚ã‚‹ã„ã¯å°‘ã—ã ã‘ã€ã‚ãªãŸãŒæœ›ã‚€ã‚ˆã†ã«å…±æœ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã‚ãªãŸãŒä»–ã®äººã¨å¯¾è©±ã™ã‚‹æ–¹æ³•ã¯ã€æœ¬å½“ã«ã‚ãªãŸæ¬¡ç¬¬ã§ã™ã€‚" + byline: "ã‚ãªãŸãŒã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ«ã—ã¦ã„るオンラインソーシャルã®ä¸–ç•Œ" + choose_your_audience: "観客をé¸æŠž" + choose_your_audience_info: "ダイアスãƒãƒ©*ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã¯ã€ã‚ãªãŸãŒå¸Œæœ›ã™ã‚‹äººãŸã¡ã¨ã ã‘共有ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã‚ãªãŸãŒå¥½ããªã‚ˆã†ã«å…¬é–‹ã«ã‚‚éžå…¬é–‹ã«ã‚‚ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚世界ä¸ã¨é¢ç™½ã„写真をã€ã¾ãŸã¯è¦ªã—ã„å‹äººã¨ã ã‘æ·±ã„秘密を共有ã—ã¾ã™ã€‚ã‚ãªãŸãŒã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ«ã—ã¾ã™ã€‚" + headline: "%{pod_name}ã«ã‚ˆã†ã“ã" + own_your_data: "ã‚ãªãŸè‡ªèº«ã®ãƒ‡ãƒ¼ã‚¿ã‚’所有ã™ã‚‹" + own_your_data_info: "多ãã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¯ã‚ãªãŸã®ãƒ‡ãƒ¼ã‚¿ã‚’使用ã—ã¦ã€ã‚ãªãŸã®ã‚„ã‚Šå–りを分æžã™ã‚‹ã“ã¨ã§ãŠé‡‘を稼ãŽã¾ã™ã€‚ãã—ã¦ã€ã“ã®æƒ…å ±ã‚’ä½¿ç”¨ã—ã¦ã€ç‰©ã‚’宣ä¼ã—ã¾ã™ã€‚ダイアスãƒãƒ©*ã¯ã€ã‚ãªãŸãŒä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨æŽ¥ç¶šã—ã¦ã€å…±æœ‰ã™ã‚‹ã“ã¨ã‚’å¯èƒ½ã«ã™ã‚‹ä»¥å¤–ã®ç›®çš„ã®ãŸã‚ã«ã€ã‚ãªãŸã®ãƒ‡ãƒ¼ã‚¿ã‚’使用ã—ã¾ã›ã‚“。" + podmin: + admin_panel: "管ç†è€…用パãƒãƒ«" + byline: "インターãƒãƒƒãƒˆã‚’変更ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚セットアップを始ã‚ã¾ã™ã‹ï¼Ÿ" + configuration_info: "ãŠå¥½ã¿ã®ãƒ†ã‚ストエディタ㧠%{database_path} 㨠%{diaspora_path} ã‚’é–‹ã„ã¦ã€æ…Žé‡ã«ãƒ¬ãƒ“ューã—ã¦ãã ã•ã„。広範囲ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ã¦ã„ã¾ã™ã€‚" + configure_your_pod: "ã‚ãªãŸã®ãƒãƒƒãƒ‰ã‚’è¨å®š" + contact_irc: "IRCã§ç§ãŸã¡ã«é€£çµ¡" + contribute: "貢献ã™ã‚‹" + contribute_info: "ダイアスãƒãƒ©*ã‚’ã•ã‚‰ã«è‰¯ãã™ã‚‹ãŸã‚ï¼ä½•ã‹ãƒã‚°ã‚’見ã¤ã‘ãŸå ´åˆã¯ã€%{report_bugs}ã—ã¦ãã ã•ã„。" + create_an_account: "アカウントã®ä½œæˆ" + create_an_account_info: "æ–°ã—ã„アカウント㮠%{sign_up_link}。" + faq_for_podmins: "ç§ãŸã¡ã®wikiã«ãƒãƒƒãƒ‰ãƒ¡ãƒ³ãƒ†ãƒŠãƒ³ã‚¹è€…å‘ã‘ã®FAQ" + getting_help: "ヘルプã®è¡¨ç¤º" + getting_help_info: "ã„ãã¤ã‹ã®è¿½åŠ ã®ãƒ’ントやã€ã‚³ãƒ„ã€æœ€ã‚‚一般的ãªå•é¡Œã®è§£æ±ºç–ãªã©ã€%{faq}を記載ã—ã¦ã„ã¾ã™ã€‚ã¾ãŸã€ãŠæ°—軽ã«%{irc}ã—ã¦ãã ã•ã„。" + headline: "よã†ã“ãã€å‹é”。" + make_yourself_an_admin: "ã‚ãªãŸè‡ªèº«ã‚’管ç†è€…ã«ã™ã‚‹" + make_yourself_an_admin_info: "%{wiki}ã§æ‰‹é †ã‚’見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãƒã‚°ã‚¤ãƒ³ã—ã¦ã„ã‚‹å ´åˆã¯ã€ãƒ˜ãƒƒãƒ€ãƒ¼ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã«ã€Œç®¡ç†è€…ã€ã®ãƒªãƒ³ã‚¯ãŒè¿½åŠ ã•ã‚Œã‚‹ã¯ãšã§ã™ã€‚ã‚ãªãŸã®ãƒãƒƒãƒ‰ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼æ¤œç´¢ã‚„統計ã®ã‚ˆã†ãªã‚‚ã®ãŒã§ãã¾ã™ã€‚ã‚ãªãŸã®ãƒãƒƒãƒ‰ã®é‹ç”¨é¢ã§ã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€%{admin_panel}ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ãã ã•ã„。" + report_bugs: "ãã‚Œã‚’å ±å‘Š" + update_instructions: "ダイアスãƒãƒ©* wikiã®æ›´æ–°æ‰‹é †" + update_your_pod: "ãƒãƒƒãƒ‰ã‚’æ›´æ–°" + update_your_pod_info: "%{update_instructions}を見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + invitation_codes: + not_valid: "ãã®æ‹›å¾…コードã¯ã€ã‚‚ã¯ã‚„有効ã§ã¯ã‚ã‚Šã¾ã›ã‚“" invitations: a_facebook_user: "Facebookユーザー" check_token: not_found: "招待トークンãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。" create: - already_contacts: "æ—¢ã«é€£çµ¡å…ˆã¨ã—ã¦ç™»éŒ²ã—ã¦ã„ã¾ã™ã€‚" - already_sent: "æ—¢ã«æ‹›å¾…ã—ã¾ã—ãŸã€‚" empty: "å°‘ãªãã¨ã‚‚1ã¤ã®Eメールアドレスを入力ã—ã¦ãã ã•ã„。" no_more: "招待権ãŒã‚‚ã†æ®‹ã£ã¦ã„ã¾ã›ã‚“。" - own_address: "自分自身ã«æ‹›å¾…状をé€ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“" + note_already_sent: "招待状ã¯ã™ã§ã«ã«é€ä¿¡ã—ã¾ã—ãŸ: %{emails}" rejected: "次ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸï¼š" sent: "次ã®äººã€…ã«æ‹›å¾…ã‚’é€ä¿¡ã—ã¾ã—ãŸï¼š" - edit: - accept_your_invitation: "招待をå—ã‘ã‚‹" - your_account_awaits: "アカウントをãŠå¾…ã¡ã—ã¦ã„ã¾ã™!" new: - already_invited: "招待済ã¿" - aspect: "アスペクト" - check_out_diaspora: "ダイアスãƒãƒ©ã‚’ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã™ã‚‹!" + codes_left: + other: "ã“ã®ã‚³ãƒ¼ãƒ‰ã§æ‹›å¾…ã¯æ®‹ã‚Š %{count}" + zero: "ã“ã®ã‚³ãƒ¼ãƒ‰ã§æ‹›å¾…ã¯æ®‹ã£ã¦ã„ã¾ã›ã‚“" comma_separated_plz: "コンマ区切りã§è¤‡æ•°ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’入力ã§ãã¾ã™ã€‚" - if_they_accept_info: "招待を承諾ã—ã¦ãã‚ŒãŸå ´åˆã€æ‹›å¾…時ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚" invite_someone_to_join: "知りåˆã„をダイアスãƒãƒ©ï¼Šã«æ‹›å¾…ã—ã¾ã—ょã†ï¼" language: "言語" - personal_message: "個人メッセージ" - resend: "å†é€ã™ã‚‹" + paste_link: "å‹é”ã¨ã“ã®ãƒªãƒ³ã‚¯ã‚’共有ã—ã¦ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã«æ‹›å¾…ã™ã‚‹ã‹ã€ç›´æŽ¥ãƒªãƒ³ã‚¯ã‚’メールã§é€ã‚Šã¾ã™ã€‚" send_an_invitation: "招待をé€ä¿¡ã™ã‚‹" - send_invitation: "招待をé€ä¿¡ã™ã‚‹" sending_invitation: "招待をé€ä¿¡ä¸..." - to: "宛先:" layouts: application: back_to_top: "トップã«æˆ»ã‚‹" + be_excellent: "ãŠäº’ã„ã«ç´ 晴らã—ã„関係ã§ã‚ã‚Šã¾ã—ょã†ï¼ ♥" powered_by: "POWERED BY DIASPORA*" public_feed: "%{name}ã•ã‚“ã®å…¬é–‹ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©ãƒ•ã‚£ãƒ¼ãƒ‰" source_package: "ソースコードã®ãƒ‘ッケージをダウンãƒãƒ¼ãƒ‰ã™ã‚‹" - toggle: "æºå¸¯ã‚µã‚¤ãƒˆã‚’切替ãˆã‚‹" + statistics_link: "ãƒãƒƒãƒ‰ã®çµ±è¨ˆ" + toggle: "æºå¸¯ã‚µã‚¤ãƒˆã®åˆ‡ã‚Šæ›¿ãˆ" whats_new: "æ›´æ–°å±¥æ´" - your_aspects: "アスペクト" header: - admin: "管ç†" - blog: "ブãƒã‚°" code: "ソース" - login: "ãƒã‚°ã‚¤ãƒ³" logout: "ãƒã‚°ã‚¢ã‚¦ãƒˆ" profile: "プãƒãƒ•ã‚£ãƒ¼ãƒ«" - recent_notifications: "最近ã®é€šçŸ¥" settings: "è¨å®š" - view_all: "ã™ã¹ã¦è¦‹ã‚‹" - likes: - likes: - people_dislike_this: - few: "ã“ã‚ŒãŒå«Œã„ãªäººï¼š%{count}人" - many: "ã“ã‚ŒãŒå«Œã„ãªäººï¼š%{count}人" - one: "ã“ã‚ŒãŒå«Œã„ãªäººï¼š1人" - other: "ã“ã‚ŒãŒå«Œã„ãªäººï¼š%{count}人" - two: "%{count} dislikes" - zero: "ã“ã‚ŒãŒå«Œã„ãªäººï¼š0人" - people_like_this: - few: "ã“ã‚ŒãŒå¥½ããªäººï¼š%{count}人" - many: "ã“ã‚ŒãŒå¥½ããªäººï¼š%{count}人" - one: "ã“ã‚ŒãŒå¥½ããªäººï¼š1人" - other: "ã“ã‚ŒãŒå¥½ããªäººï¼š%{count}人" - two: "%{count} likes" - zero: "ã“ã‚ŒãŒå¥½ããªäººï¼š0人" - people_like_this_comment: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" + toggle_navigation: "ナビゲーションã®åˆ‡ã‚Šæ›¿ãˆ" limited: "é™å®šå…¬é–‹" more: "続ã" - next: "次ã¸" no_results: "çµæžœãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" notifications: also_commented: few: "%{actors} also commented on %{post_author}'s %{post_link}." many: "%{actors} also commented on %{post_author}'s %{post_link}." one: "%{actors} also commented on %{post_author}'s %{post_link}." - other: "%{actors} also commented on %{post_author}'s %{post_link}." + other: "%{actors}ã•ã‚“ã¯%{post_author}ã•ã‚“ã®æŠ•ç¨¿%{post_link}もコメントã—ã¾ã—ãŸã€‚" two: "%{actors} also commented on %{post_author}'s %{post_link}." - zero: "%{actors} also commented on %{post_author}'s %{post_link}." + zero: "%{actors}ã•ã‚“ã¯%{post_author}ã•ã‚“ã®æŠ•ç¨¿%{post_link}もコメントã—ã¾ã—ãŸã€‚" also_commented_deleted: few: "%{actors} commented on a deleted post." many: "%{actors} commented on a deleted post." one: "%{actors} commented on a deleted post." - other: "%{actors} commented on a deleted post." + other: "%{actors}ã•ã‚“ãŒå‰Šé™¤ã•ã‚ŒãŸæŠ•ç¨¿ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ã¾ã—ãŸã€‚" two: "%{actors} commented on a deleted post." - zero: "%{actors} commented on a deleted post." + zero: "%{actors}ã•ã‚“ãŒå‰Šé™¤ã•ã‚ŒãŸæŠ•ç¨¿ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ã¾ã—ãŸã€‚" comment_on_post: few: "%{actors} commented on your %{post_link}." many: "%{actors} commented on your %{post_link}." one: "%{actors} commented on your %{post_link}." - other: "%{actors} commented on your %{post_link}." + other: "%{actors}ã•ã‚“ãŒæŠ•ç¨¿%{post_link}ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ã¾ã—ãŸã€‚" two: "%{actors} commented on your %{post_link}." - zero: "%{actors} commented on your %{post_link}." - helper: - new_notifications: - few: "æ–°ç€é€šçŸ¥%{count}件" - many: "æ–°ç€é€šçŸ¥%{count}件" - one: "æ–°ç€é€šçŸ¥1件" - other: "æ–°ç€é€šçŸ¥%{count}件" - two: "%{count} new notifications" - zero: "æ–°ç€é€šçŸ¥ç„¡ã—" + zero: "%{actors}ã•ã‚“ãŒæŠ•ç¨¿%{post_link}ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ã¾ã—ãŸã€‚" index: + all_notifications: "ã™ã¹ã¦ã®é€šçŸ¥" + also_commented: "コメントも" and: "åˆã¯" and_others: few: "and %{count} others" many: "and %{count} others" one: "and one more" - other: "and %{count} others" + other: "ãã—ã¦ä»–ã« %{count} 人" two: "and %{count} others" - zero: "and nobody else" + zero: "ãã—ã¦ä»–ã«ã¯ã„ã¾ã›ã‚“" + comment_on_post: "投稿ã«ã‚³ãƒ¡ãƒ³ãƒˆ" + liked: "ã„ã„ãï¼ã—ã¾ã—ãŸ" mark_all_as_read: "全件を既èªã«ã™ã‚‹" + mark_all_shown_as_read: "表示をã™ã¹ã¦æ—¢èªã¨ã—ã¦ãƒžãƒ¼ã‚¯" mark_read: "æ—¢èªã«ã™ã‚‹" mark_unread: "未èªã«ã™ã‚‹" + mentioned: "メンションã•ã‚Œã¾ã—ãŸ" + no_notifications: "ã¾ã 通知ã¯ä½•ã‚‚ã‚ã‚Šã¾ã›ã‚“" notifications: "通知" + reshared: "å†å…±æœ‰ã—ã¾ã—ãŸ" show_all: "全件表示" show_unread: "未開å°ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示" started_sharing: "共有を開始ã—ã¾ã—ãŸ" @@ -355,207 +667,272 @@ ja: few: "%{actors} has just liked your %{post_link}." many: "%{actors} has just liked your %{post_link}." one: "%{actors} has just liked your %{post_link}." - other: "%{actors} has just liked your %{post_link}." + other: "%{actors}ã•ã‚“ãŒæŠ•ç¨¿%{post_link}ã«ã„ã„ãï¼ã—ã¾ã—ãŸã€‚" two: "%{actors} has just liked your %{post_link}." - zero: "%{actors} has just liked your %{post_link}." + zero: "%{actors}ã•ã‚“ãŒæŠ•ç¨¿%{post_link}ã«ã„ã„ãï¼ã—ã¾ã—ãŸã€‚" liked_post_deleted: few: "%{actors} liked your deleted post." many: "%{actors} liked your deleted post." one: "%{actors} liked your deleted post." - other: "%{actors} liked your deleted post." + other: "%{actors}ã•ã‚“ãŒå‰Šé™¤ã•ã‚ŒãŸæŠ•ç¨¿ã«ã„ã„ãï¼ã—ã¾ã—ãŸã€‚" two: "%{actors} liked your deleted post." - zero: "%{actors} liked your deleted post." + zero: "%{actors}ã•ã‚“ãŒå‰Šé™¤ã•ã‚ŒãŸæŠ•ç¨¿ã«ã„ã„ãï¼ã—ã¾ã—ãŸã€‚" mentioned: few: "%{actors} has mentioned you in a %{post_link}." many: "%{actors} has mentioned you in a %{post_link}." one: "%{actors} has mentioned you in a %{post_link}." - other: "%{actors} has mentioned you in a %{post_link}." + other: "%{actors}ã•ã‚“ãŒ%{post_link}ã§ã‚ãªãŸã«ãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã—ã¾ã—ãŸã€‚" two: "%{actors} has mentioned you in a %{post_link}." - zero: "%{actors} has mentioned you in a %{post_link}." + zero: "%{actors}ã•ã‚“ãŒ%{post_link}ã§ã‚ãªãŸã«ãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã—ã¾ã—ãŸã€‚" mentioned_deleted: few: "%{actors} mentioned you in a deleted post." many: "%{actors} mentioned you in a deleted post." one: "%{actors} mentioned you in a deleted post." - other: "%{actors} mentioned you in a deleted post." + other: "%{actors}ã•ã‚“ãŒå‰Šé™¤ã•ã‚ŒãŸæŠ•ç¨¿ã§ã‚ãªãŸã«ãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã—ã¾ã—ãŸã€‚" two: "%{actors} mentioned you in a deleted post." - zero: "%{actors} mentioned you in a deleted post." + zero: "%{actors}ã•ã‚“ãŒå‰Šé™¤ã•ã‚ŒãŸæŠ•ç¨¿ã§ã‚ãªãŸã«ãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã—ã¾ã—ãŸã€‚" post: "(投稿ã§ï¼‰" private_message: few: "%{actors} sent you a message." many: "%{actors} sent you a message." one: "%{actors} sent you a message." - other: "%{actors} sent you a message." + other: "%{actors}ã•ã‚“ãŒã€ã‚ãªãŸã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’é€ä¿¡ã—ã¾ã—ãŸã€‚" two: "%{actors} sent you a message." - zero: "%{actors} sent you a message." + zero: "%{actors}ã•ã‚“ãŒã€ã‚ãªãŸã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’é€ä¿¡ã—ã¾ã—ãŸã€‚" reshared: few: "%{actors} has reshared your %{post_link}." many: "%{actors} has reshared your %{post_link}." one: "%{actors} has reshared your %{post_link}." - other: "%{actors} has reshared your %{post_link}." + other: "%{actors}ã•ã‚“ãŒæŠ•ç¨¿%{post_link}ã‚’å†å…±æœ‰ã—ã¾ã—ãŸã€‚" two: "%{actors} has reshared your %{post_link}." - zero: "%{actors} has reshared your %{post_link}." + zero: "%{actors}ã•ã‚“ãŒæŠ•ç¨¿%{post_link}ã‚’å†å…±æœ‰ã—ã¾ã—ãŸã€‚" reshared_post_deleted: few: "%{actors} reshared your deleted post." many: "%{actors} reshared your deleted post." one: "%{actors} reshared your deleted post." - other: "%{actors} reshared your deleted post." + other: "%{actors}ã•ã‚“ãŒå‰Šé™¤ã•ã‚ŒãŸæŠ•ç¨¿ã‚’å†å…±æœ‰ã—ã¾ã—ãŸã€‚" two: "%{actors} reshared your deleted post." - zero: "%{actors} reshared your deleted post." + zero: "%{actors}ã•ã‚“ãŒå‰Šé™¤ã•ã‚ŒãŸæŠ•ç¨¿ã‚’å†å…±æœ‰ã—ã¾ã—ãŸã€‚" started_sharing: few: "%{actors} started sharing with you." many: "%{actors} started sharing with you." one: "%{actors} started sharing with you." - other: "%{actors} started sharing with you." + other: "%{actors}ã•ã‚“ãŒã€ã‚ãªãŸã¨å…±æœ‰ã‚’始ã‚ã¾ã—ãŸã€‚" two: "%{actors} started sharing with you." - zero: "%{actors} started sharing with you." + zero: "%{actors}ã•ã‚“ãŒã€ã‚ãªãŸã¨å…±æœ‰ã‚’始ã‚ã¾ã—ãŸã€‚" notifier: + a_limited_post_comment: "ã‚ãªãŸãŒç¢ºèªã™ã‚‹ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã®åˆ¶é™å…¬é–‹ã®æŠ•ç¨¿ã«æ–°ã—ã„コメントãŒã‚ã‚Šã¾ã™ã€‚" a_post_you_shared: "投稿" + a_private_message: "ã‚ãªãŸãŒç¢ºèªã™ã‚‹ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã®æ–°ã—ã„éžå…¬é–‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒã‚ã‚Šã¾ã™ã€‚" + also_commented: + limited_subject: "ã‚ãªãŸãŒã‚³ãƒ¡ãƒ³ãƒˆã—ãŸæŠ•ç¨¿ã«æ–°ã—ã„コメントãŒã‚ã‚Šã¾ã™" click_here: "ã“ã“をクリック" comment_on_post: + limited_subject: "ã‚ãªãŸã®æŠ•ç¨¿ã®ä¸€ã¤ã«æ–°ã—ã„コメントãŒã‚ã‚Šã¾ã™" reply: "返信ã¾ãŸã¯%{name}ã•ã‚“ã®æŠ•ç¨¿ã‚’見る >" confirm_email: - click_link: "To activate your new e-mail address %{unconfirmed_email}, please click this link:" - subject: "Please activate your new e-mail address %{unconfirmed_email}" + click_link: "æ–°ã—ã„メールアドレス %{unconfirmed_email} を有効ã«ã™ã‚‹ãŸã‚ã«ã€ã“ã®ãƒªãƒ³ã‚¯ã‚’クリックã—ã¦ãã ã•ã„:" + subject: "æ–°ã—ã„メールアドレス %{unconfirmed_email} を有効ã«ã—ã¦ãã ã•ã„" email_sent_by_diaspora: "ã“ã®Eメールã¯%{pod_name}ã‹ã‚‰é€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚ã‚‚ã—ã“ã®ã‚ˆã†ãªEメールã®å—ä¿¡ã‚’æ‹’å¦ã—ãŸã„å ´åˆã¯ã€" + export_email: + body: |- + %{name} ã•ã‚“ã€ã“ã‚“ã«ã¡ã¯ã€‚ + + データを処ç†ã—ã€ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ã™ã‚‹æº–å‚™ãŒã§ãã¾ã—㟠[ã“ã®ãƒªãƒ³ã‚¯](%{url})。 + + 敬具 + + ダイアスãƒãƒ©* メールãƒãƒœãƒƒãƒˆï¼ + subject: "%{name}ã•ã‚“ã€å€‹äººãƒ‡ãƒ¼ã‚¿ã®ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ã®æº–å‚™ãŒã§ãã¾ã—ãŸã€‚" + export_failure_email: + body: |- + %{name}ã•ã‚“ã€ã“ã‚“ã«ã¡ã¯ + + 個人データã®ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ã®å‡¦ç†ä¸ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ + ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„ï¼ + + 申ã—訳ã‚ã‚Šã¾ã›ã‚“。 + + ダイアスãƒãƒ©* メールãƒãƒœãƒƒãƒˆï¼ + subject: "%{name} ã•ã‚“ã€ç”³ã—訳ã‚ã‚Šã¾ã›ã‚“。データã«å•é¡ŒãŒã‚ã‚Šã¾ã—ãŸ" + export_photos_email: + body: |- + %{name} ã•ã‚“ã€ã“ã‚“ã«ã¡ã¯ + + 写真ãŒå‡¦ç†ã•ã‚Œã€ãƒ€ã‚¦ãƒ³ãƒãƒ¼ãƒ‰ã™ã‚‹æº–å‚™ãŒã§ãã¾ã—㟠[ã“ã®ãƒªãƒ³ã‚¯](%{url})。 + + 敬具 + + ダイアスãƒãƒ©* メールãƒãƒœãƒƒãƒˆï¼ + subject: "%{name} ã•ã‚“ã€å†™çœŸã‚’ダウンãƒãƒ¼ãƒ‰ã™ã‚‹æº–å‚™ãŒã§ãã¾ã—ãŸ" + export_photos_failure_email: + body: |- + %{name} ã•ã‚“ã€ã“ã‚“ã«ã¡ã¯ + + ダウンãƒãƒ¼ãƒ‰ã®ãŸã‚ã«å†™çœŸã‚’処ç†ã—ã¦ã„ã‚‹é–“ã«ã€å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ + ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„ï¼ + + 申ã—訳ã‚ã‚Šã¾ã›ã‚“ + + ダイアスãƒãƒ©* メールãƒãƒœãƒƒãƒˆï¼ + subject: "%{name} ã•ã‚“ã€å†™çœŸã«å•é¡ŒãŒã‚ã‚Šã¾ã—ãŸ" hello: "%{name}ã•ã‚“ã€ã“ã‚“ã«ã¡ã¯ï¼" + invite: + message: |- + ã“ã‚“ã«ã¡ã¯ï¼ + %{diaspora_id}ã•ã‚“ã«ã‚ˆã£ã¦ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã«æ‹›å¾…ã•ã‚Œã¾ã—ãŸï¼ + + ã“ã®ãƒªãƒ³ã‚¯ã‚’クリックã—ã¦ã¯ã˜ã‚ã¾ã—ょㆠ+ + [%{invite_url}][1] + + ã™ã§ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ãŠæŒã¡ã®å ´åˆã¯ã€é€£çµ¡å…ˆã«%{diaspora_id}ã‚’è¿½åŠ ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ + + 親愛ãªã‚‹ + + ダイアスãƒãƒ©* メールãƒãƒœãƒƒãƒˆï¼ + + 追伸: 念ã®ãŸã‚ã«ã€(ã¾ã ) ダイアスãƒãƒ©* ã‚’ã”å˜ã˜ãªã„ã¨ã—ãŸã‚‰ã€[ã“ã“][2] ãŒãã®ç”ãˆã§ã™ï¼ + + [1]: %{invite_url} + [2]: %{diasporafoundation_url} invited_you: "%{name}ã•ã‚“ãŒãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã«æ‹›å¾…ã—ã¦ã„ã¾ã™ã€‚" liked: liked: "%{name} has just liked your post: " + limited_post: "%{name} ã•ã‚“ãŒã€ã‚ãªãŸã®é™å®šå…¬é–‹ã®æŠ•ç¨¿ã«ã„ã„ãï¼ã—ã¾ã—ãŸ" view_post: "投稿を見る >" mentioned: - mentioned: "ã•ã‚“ã¯æŠ•ç¨¿ã§ã‚ãªãŸã‚’メンションã—ã¾ã—ãŸã€‚" + limited_post: "ã‚ãªãŸã¯é™å®šå…¬é–‹ã®æŠ•ç¨¿ã§ãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã•ã‚Œã¾ã—ãŸã€‚" subject: "%{name}ã•ã‚“ã¯ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©ï¼Šã§ã‚ãªãŸã‚’メンションã—ã¾ã—ãŸã€‚" private_message: reply_to_or_view: "ã“ã®ä¼šè©±ã«è¿”ä¿¡ã€ã¾ãŸã¯è¡¨ç¤º >" + subject: "ã‚ãªãŸã«æ–°ã—ã„éžå…¬é–‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒã‚ã‚Šã¾ã™" + remove_old_user: + body: |- + ã“ã‚“ã«ã¡ã¯ã€ + + ã‚ãªãŸã¯ %{after_days} 日間アカウントを使用ã•ã‚Œã¦ã„ãªã„よã†ã§ã™ã€‚ã‚‚ã¯ã‚„ã€%{pod_url} ã‚’ã”希望ã•ã‚Œã¦ã„ãªã„よã†ã«æ€ã‚ã‚Œã¾ã™ã€‚アクティブãªãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã“ã®ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ãƒãƒƒãƒ‰ã‹ã‚‰æœ€é«˜ã®ãƒ‘フォーマンスを得られるよã†ã«ã™ã‚‹ãŸã‚ã€ç§ãŸã¡ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‹ã‚‰ä¸è¦ãªã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã—ょã†ã‹ã€‚ + + ã‚ãªãŸãŒãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*コミュニティã®ä¸€éƒ¨ã«ç•™ã¾ã‚ŠãŸã„ã¨ã”希望ã®å ´åˆã€ç§ãŸã¡ã¯ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ç¶æŒã™ã‚‹ã“ã¨ã‚’æ“è¿Žã—ã¾ã™ã€‚ + + ã‚ãªãŸãŒã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ç¶æŒã—ãŸã„å ´åˆã€å¿…è¦ãªã“ã¨ã¯ã€%{remove_after} å‰ã«ã€ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹ã“ã¨ã ã‘ã§ã™ã€‚サインインã—ãŸã‚‰ã€å°‘ã—時間をã¨ã£ã¦ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã‚’ãªãŒã‚ã¦ã¿ã¦ãã ã•ã„。ã‚ãªãŸãŒæœ€å¾Œã«ã”覧ã«ãªã£ã¦ã‹ã‚‰ã€ãŸãã•ã‚“変更ã•ã‚Œã¦ã„ã¾ã™ã€‚ãã—ã¦ã‚ãªãŸã¯ç§ãŸã¡ãŒè¡Œã£ãŸæ”¹å–„ã‚’æ°—ã«å…¥ã£ã¦ã„ãŸã ã‘ã‚‹ã“ã¨ã¨æ€ã„ã¾ã™ã€‚ã„ãã¤ã‹ã® #ã‚¿ã‚° をフォãƒãƒ¼ã—ã¦ã€ãŠå¥½ããªã‚³ãƒ³ãƒ†ãƒ³ãƒ„を見ã¤ã‘ã¦ãã ã•ã„。 + + ã“ã“ã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¦ãã ã•ã„: %{login_url}ã€‚ã‚µã‚¤ãƒ³ã‚¤ãƒ³æƒ…å ±ã‚’å¿˜ã‚Œã¦ã—ã¾ã£ãŸå ´åˆã¯ã€ãã®ãƒšãƒ¼ã‚¸ã®ãƒªãƒžã‚¤ãƒ³ãƒ€ãƒ¼ã§å°‹ãã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ + + å†ã³ãŠä¼šã„ã™ã‚‹ã“ã¨ã‚’望んã§ã€ + + ダイアスãƒãƒ©* メールãƒãƒœãƒƒãƒˆï¼ + subject: "éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–ã®ãŸã‚ã€ã‚ãªãŸã®ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯é™¤å¤–ã®ãƒ•ãƒ©ã‚°ãŒä»˜ã‘られã¦ã„ã¾ã™" report_email: + body: |- + ã“ã‚“ã«ã¡ã¯ã€‚ + + ID %{id} ã® %{type} ã¯æ”»æ’ƒçš„ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã•ã‚Œã¾ã—ãŸã€‚ + + ç†ç”±: %{reason} + + [%{url}][1] + + å¯èƒ½ãªé™ã‚Šæ—©ã確èªã—ã¦ãã ã•ã„! + + + 敬具 + + ダイアスãƒãƒ©* メールãƒãƒœãƒƒãƒˆ! + + [1]: %{url} subject: "%{type}ãŒæ–°ã—ã攻撃的ã ã¨ãƒžãƒ¼ã‚¯ã•ã‚Œã¾ã—ãŸ" + type: + comment: "コメント" + post: "投稿" reshared: - reshared: "%{name} just reshared your post" + reshared: "%{name}ã•ã‚“ãŒã‚ãªãŸã®æŠ•ç¨¿ã‚’å†å…±æœ‰ã—ã¾ã—ãŸ" view_post: "投稿を見る >" single_admin: admin: "ダイアスãƒãƒ©ï¼Šç®¡ç†è€…" subject: "ダイアスãƒãƒ©ï¼Šã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®é‡è¦ãªãŠçŸ¥ã‚‰ã›ï¼š" started_sharing: sharing: "ã‚ãªãŸã¸ã®å…±æœ‰ã‚’開始ã—ã¦ã„ã¾ã™!" - subject: "%{name} has started sharing with you on Diaspora*" + subject: "%{name}ã•ã‚“ãŒãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã§ã‚ãªãŸã¨å…±æœ‰ã‚’始ã‚ã¾ã—ãŸ" view_profile: "%{name}ã•ã‚“ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’見る" thanks: "ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚" to_change_your_notification_settings: "通知è¨å®šã‚’変更ã—ã¾ã™" nsfw: "NSFW (è·å ´ã§ã®é–²è¦§æ³¨æ„)" ok: "了解" - or: "ã¾ãŸã¯" - password: "パスワード" - password_confirmation: "パスワード確èª" people: - add_contact_small: - add_contact_from_tag: "ã‚¿ã‚°ã‚ˆã‚Šé€£çµ¡å…ˆã‚’è¿½åŠ ã™ã‚‹" - aspect_list: - edit_membership: "アスペクト所属を編集ã™ã‚‹" - helper: - is_sharing: "%{name}ã•ã‚“ãŒã‚ãªãŸã«å…±æœ‰ã—ã¦ã„ã¾ã™" - results_for: "%{params}ã®æ¤œç´¢çµæžœ" + add_contact: + invited_by: "ã‚ãªãŸã®æ‹›å¾…者ã¯" index: + couldnt_find_them: "見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã‹ï¼Ÿ" looking_for: "ã‚¿ã‚°%{tag_link}ã®ä»˜ã„ãŸæŠ•ç¨¿ã‚’ãŠæŽ¢ã—ã§ã™ã‹?" no_one_found: "…1人も見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" no_results: "何ã‹ã‚’検索ã—ãªã„ã¨ã„ã‘ã¾ã›ã‚“。" results_for: "検索çµæžœï¼š" + search_handle: "å‹é”を見ã¤ã‘ã‚‹ãŸã‚ã«å½¼ã‚‰ã®ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©* ID (username@pod.tld) を使用ã—ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。" searching: "検索ä¸ã§ã™ã€‚ã‚‚ã†ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„..." - one: "1人ã®é€£çµ¡å…ˆ" - other: "%{count}人ã®é€£çµ¡å…ˆ" + send_invite: "ã¾ã 見ã¤ã‹ã‚Šã¾ã›ã‚“ã‹ï¼Ÿæ‹›å¾…ã‚’é€ä¿¡ã—ã¾ã—ょã†ï¼" person: - add_contact: "é€£çµ¡å…ˆã‚’è¿½åŠ ã™ã‚‹" - already_connected: "æ—¢ã«ã¤ãªãŒã£ã¦ã„ã¾ã™" - pending_request: "共有ã®æ‰¿èªå¾…ã¡" thats_you: "ã‚ãªãŸè‡ªèº«ã§ã™ï¼" profile_sidebar: bio: "ç•¥æ´" born: "誕生日" - edit_my_profile: "プãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’編集ã™ã‚‹" gender: "性別" - in_aspects: "アスペクトã§" location: "所在地" - remove_contact: "連絡先を削除ã™ã‚‹" - remove_from: "%{name}ã•ã‚“ã‚’%{aspect}ã‹ã‚‰é™¤å¤–ã—ã¾ã™ã‹ã€‚" show: closed_account: "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯å‰Šé™¤ã•ã‚Œã¦ã„ã¾ã™" does_not_exist: "å˜åœ¨ã—ãªã„連絡先ã§ã™ï¼" has_not_shared_with_you_yet: "%{name}ã•ã‚“ã¯ã¾ã ã‚ãªãŸã«ã©ã®æŠ•ç¨¿ã‚‚共有ã—ã¦ã„ã¾ã›ã‚“ï¼" - ignoring: "%{name}ã•ã‚“ã‹ã‚‰ã®å…¨ã¦ã®æŠ•ç¨¿ã‚’無視ã—ã¦ã„ã¾ã™ã€‚" - incoming_request: "%{name}ã•ã‚“ã¯å…±æœ‰ã®è¨±å¯ã‚’求ã‚ã¦ã„ã¾ã™" - mention: "メンション" - message: "メッセージ" - not_connected: "ã“ã®é€£çµ¡å…ˆã¨å…±æœ‰ã—ã¦ã„ã¾ã›ã‚“" - recent_posts: "最近ã®æŠ•ç¨¿" - recent_public_posts: "最近ã®å…¬é–‹æŠ•ç¨¿" - return_to_aspects: "アスペクトページã«æˆ»ã‚‹" - see_all: "å…¨ã¦è¡¨ç¤º" - start_sharing: "共有を開始ã™ã‚‹" - to_accept_or_ignore: "承諾ã™ã‚‹ã‹ç„¡è¦–ã™ã‚‹ã‹æ±ºã‚ã¦ä¸‹ã•ã„。" - sub_header: - edit: "編集" - you_have_no_tags: "ã‚¿ã‚°ãŒã‚ã‚Šã¾ã›ã‚“" - webfinger: - fail: "%{handle}ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" - zero: "連絡先無ã—" photos: - comment_email_subject: "%{name}ã•ã‚“ã®å†™çœŸ" create: integrity_error: "写真ã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸã€‚確ã‹ã«ç”»åƒãƒ•ã‚¡ã‚¤ãƒ«ã ã£ãŸã®ã§ã—ょã†ã‹ã€‚" runtime_error: "写真ã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸã€‚シートベルトã¯ã—ã£ã‹ã‚Šã¨ãŠç· ã‚ã§ã—ょã†ã‹ã€‚" type_error: "写真ã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸã€‚確ã‹ã«ç”»åƒãƒ•ã‚¡ã‚¤ãƒ«ã‚’添付ã—ã¾ã—ãŸã‹ã€‚" destroy: notice: "写真を削除ã—ã¾ã—ãŸã€‚" - edit: - editing: "編集ä¸" - new: - back_to_list: "一覧ã«æˆ»ã‚‹" - new_photo: "æ–°ã—ã„写真" - post_it: "投稿ã™ã‚‹ï¼" new_photo: empty: "{file}ã¯ç©ºã§ã™ã€‚å–り除ã„ã¦ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ãªãŠã—ã¦ãã ã•ã„。" invalid_ext: "{file}ã®ãƒ•ã‚¡ã‚¤ãƒ«åã¯ä¸æ£ã§ã™ã€‚{extensions}以外ã®æ‹¡å¼µåã¯ä½¿ãˆã¾ã›ã‚“。" size_error: "{file}ã¯å¤§ãã™ãŽã¾ã™ã€‚ファイルサイズã®ä¸Šé™ã¯{sizeLimit}ã§ã™ã€‚" new_profile_photo: - or_select_one_existing: "ã¾ãŸã¯æ—¢å˜ã®%{photos}ã‹ã‚‰ä¸€æžšé¸ã‚“ã§ãã ã•ã„" upload: "æ–°ã—ã„プãƒãƒ•ã‚£ãƒ¼ãƒ«å†™çœŸã‚’アップãƒãƒ¼ãƒ‰ã™ã‚‹ï¼" - photo: - view_all: "%{name}ã®å†™çœŸã‚’ã™ã¹ã¦ã¿ã‚‹" show: - collection_permalink: "コレクションã®ãƒ‘ーマリンク" - delete_photo: "写真を削除ã™ã‚‹" - edit: "編集" - edit_delete_photo: "写真ã®èª¬æ˜Žã‚’編集ã™ã‚‹ï¼å†™çœŸã‚’削除ã™ã‚‹" - make_profile_photo: "プãƒãƒ•ã‚£ãƒ¼ãƒ«å†™çœŸã«ã™ã‚‹" show_original_post: "å…ƒã®æŠ•ç¨¿ã‚’表示ã™ã‚‹" - update_photo: "写真を更新ã™ã‚‹" - update: - error: "写真ã®ç·¨é›†ã«å¤±æ•—ã—ã¾ã—ãŸã€‚" - notice: "写真ã®æ›´æ–°ã«æˆåŠŸã—ã¾ã—ãŸã€‚" + polls: + votes: + other: "ã“ã‚Œã¾ã§ %{count} ã®æŠ•ç¥¨" + zero: "ã“ã‚Œã¾ã§ %{count} ã®æŠ•ç¥¨" posts: presenter: title: "%{name}ã•ã‚“ã‹ã‚‰ã®æŠ•ç¨¿" show: - destroy: "削除" - not_found: "ã”ã‚ã‚“ãªã•ã„。ãŠæŽ¢ã—ã®æŠ•ç¨¿ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" - permalink: "パーマリンク" + forbidden: "ã“ã®æ“作ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“" + location: "%{location} ã‹ã‚‰æŠ•ç¨¿" photos_by: few: "%{count} photos by %{author}" many: "%{count} photos by %{author}" one: "One photo by %{author}" - other: "%{count} photos by %{author}" + other: "%{author}ã•ã‚“ã®å†™çœŸ%{count}æžš" two: "Two photos by %{author}" - zero: "No photos by %{author}" + zero: "%{author}ã•ã‚“ã®å†™çœŸã¯ã‚ã‚Šã¾ã›ã‚“" reshare_by: "%{author}ã•ã‚“ãŒå†å…±æœ‰" - previous: "å‰ã¸" privacy: "プライãƒã‚·ãƒ¼" - privacy_policy: "プライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼" profile: "プãƒãƒ•ã‚£ãƒ¼ãƒ«" profiles: edit: allow_search: "ダイアスãƒãƒ©å†…ã®æ¤œç´¢ã‚’許å¯ã—ã¾ã™" - edit_profile: "プãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’編集ã™ã‚‹" + basic: "ç§ã®åŸºæœ¬ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«" + basic_hint: "ã‚ãªãŸã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«å†…ã®ã™ã¹ã¦ã®é …ç›®ã¯çœç•¥å¯èƒ½ã§ã™ã€‚ã‚ãªãŸã®åŸºæœ¬çš„ãªãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã¯ã€å¸¸ã«å…¬é–‹ã•ã‚Œã¾ã™ã€‚" + extended: "ç§ã®æ‹¡å¼µãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«" + extended_hint: "スイッãƒã‚’クリックã—ã¦ã€ã‚ãªãŸã®æ‹¡å¼µãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒ‡ãƒ¼ã‚¿ã®è¡¨ç¤ºã‚’è¨å®šã—ã¾ã™ã€‚公開ã¯ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆã«è¡¨ç¤ºã•ã‚Œã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚é™å®šå…¬é–‹ã¯ã€ã‚ãªãŸã¨å…±æœ‰ã™ã‚‹äººã ã‘ã«ã“ã®æƒ…å ±ãŒè¡¨ç¤ºã•ã‚Œã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚" + extended_visibility_text: "ã‚ãªãŸã®æ‹¡å¼µãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã®è¡¨ç¤º:" first_name: "å" last_name: "姓" + limited: "é™å®šå…¬é–‹" + nsfw_check: "ç§ãŒå…±æœ‰ã™ã‚‹ã™ã¹ã¦ã®ã‚‚ã®ã‚’ NSFW ã¨ã—ã¦ãƒžãƒ¼ã‚¯" + nsfw_explanation: "NSFW (「閲覧注æ„ã€) ã¯ã€ä»•äº‹ä¸ã«è¦‹ã‚‹ã®ã«é©ã—ãªã„å¯èƒ½æ€§ãŒã‚るコンテンツã®ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*自主管ç†ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£æ¨™æº–ã§ã™ã€‚é »ç¹ã«ã“ã®ã‚ˆã†ãªç´ æを共有ã™ã‚‹å ´åˆã€ãれらを表示ã™ã‚‹ã“ã¨ã‚’é¸æŠžã—ãªã„é™ã‚Šã€ã‚ãªãŸãŒå…±æœ‰ã™ã‚‹ã™ã¹ã¦ã®ã‚‚ã®ãŒäººã€…ã®ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‹ã‚‰è¡¨ç¤ºã•ã‚Œãªã„よã†ã«ã€ã“ã®ã‚ªãƒ—ションをãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„。" + nsfw_explanation2: "ã“ã®ã‚ªãƒ—ションをé¸æŠžã—ãªã„å ´åˆã€ã“ã®ã‚ˆã†ãªç´ æを共有ã™ã‚‹ãŸã³ã« #nsfw ã‚¿ã‚°ã‚’è¿½åŠ ã—ã¦ãã ã•ã„。" + public: "公開" + settings: "プãƒãƒ•ã‚£ãƒ¼ãƒ«ã®è¨å®š" update_profile: "プãƒãƒ•ã‚£ãƒ¼ãƒ«æ›´æ–°" your_bio: "ç•¥æ´" your_birthday: "誕生日" @@ -563,8 +940,6 @@ ja: your_location: "所在地" your_name: "姓å" your_photo: "写真" - your_private_profile: "éžå…¬é–‹ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«" - your_public_profile: "公開プãƒãƒ•ã‚£ãƒ¼ãƒ«" your_tags: "自分を表ã™ï¼•ã¤ã®#ã‚¿ã‚°" your_tags_placeholder: "例:#diaspora #kaji #nyanko #ongaku" update: @@ -575,257 +950,270 @@ ja: few: "%{count} reactions" many: "%{count} reactions" one: "1 reaction" - other: "%{count} reactions" + other: "%{count} リアクション" two: "%{count} reactions" - zero: "0 reactions" + zero: "0 リアクション" registrations: closed: "ã“ã®ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©ï¼Šãƒãƒƒãƒ‰ã§ã¯æ–°è¦ç™»éŒ²ã‚’å—ã‘付ã‘ã¦ã„ã¾ã›ã‚“。" create: success: "ダイアスãƒãƒ©ã®æ–°è¦ç™»éŒ²ãŒå®Œäº†ã—ã¾ã—ãŸï¼" - edit: - cancel_my_account: "アカウント登録をå–り消ã™" - edit: "%{name}を編集ã™ã‚‹" - leave_blank: "(変更ã—ãŸããªã„å ´åˆã¯ç©ºç™½ã®ã¾ã¾ã«ã—ã¦ãã ã•ã„)" - password_to_confirm: "(確èªã®ãŸã‚ã€ç¾ãƒ‘スワードも必è¦ã§ã™ï¼‰" - unhappy: "何ã‹ã”ä¸æº€ã§ã™ã‹ã€‚" - update: "æ›´æ–°" + invalid_invite: "æä¾›ã•ã‚ŒãŸæ‹›å¾…リンクã¯ã€ã‚‚ã¯ã‚„有効ã§ã¯ã‚ã‚Šã¾ã›ã‚“ï¼" new: - create_my_account: "Create my account" email: "メール" enter_email: "メールアドレスを入力ã—ã¦ãã ã•ã„。" enter_password: "パスワードを入力ã—ã¦ãã ã•ã„。" enter_password_again: "ã‚‚ã†ä¸€åº¦åŒã˜ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。" enter_username: "ユーザåã‚’é¸æŠžã—ã¦ãã ã•ã„。(åŠè§’英数å—ã¨ã‚¢ãƒ³ãƒ€ãƒ¼ãƒãƒ¼ã®ã¿ï¼‰" password: "パスワード" + password_confirmation: "パスワードã®ç¢ºèª" sign_up: "登録" - sign_up_message: "Social Networking with a <3" + submitting: "é€ä¿¡ä¸..." + terms: "アカウントを作æˆã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ã€ã‚ãªãŸã¯%{terms_link}ã«åŒæ„ã—ã¾ã™ã€‚" + terms_link: "利用è¦ç´„" username: "ユーザå" - requests: - create: - sending: "é€ä¿¡ä¸" - sent: "共有リクエストをé€ä¿¡ã—ã¾ã—ãŸã€‚%{name}ã•ã‚“ã¯æ¬¡å›žã®ãƒã‚°ã‚¤ãƒ³æ™‚ã«è¦‹ã‚‹ã§ã—ょã†ã€‚" - destroy: - error: "アスペクトをé¸æŠžã—ã¦ä¸‹ã•ã„。" - ignore: "共有リクエストを無視ã—ã¾ã—ãŸã€‚" - success: "ç¾åœ¨å…±æœ‰ã—ã¦ã„ã¾ã™ã€‚" - helper: - new_requests: - few: "新リクエスト%{count}件ï¼" - many: "新リクエスト%{count}件ï¼" - one: "新リクエストï¼" - other: "新リクエスト%{count}件ï¼" - two: "%{count} new requests!" - zero: "新リクエスト無ã—" - manage_aspect_contacts: - existing: "ç¾åœ¨ã®é€£çµ¡å…ˆ" - manage_within: "次ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®é€£çµ¡å…ˆã‚’管ç†ï¼š" - new_request_to_person: - sent: "é€ä¿¡ã—ã¾ã—ãŸï¼" + report: + comment_label: "<b>コメント</b>:<br>%{data}" + confirm_deletion: "é …ç›®ã‚’å‰Šé™¤ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ" + delete_link: "é …ç›®ã‚’å‰Šé™¤" + not_found: "<u>投稿/コメントã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ユーザーã«ã‚ˆã£ã¦å‰Šé™¤ã•ã‚ŒãŸã‚ˆã†ã§ã™ï¼</u>" + post_label: "<b>投稿</b>: %{title}" + reason_label: "ç†ç”±: %{text}" + reported_label: "<b>å ±å‘Šè€…</b> %{person}" + reported_user_details: "å ±å‘Šãƒ¦ãƒ¼ã‚¶ãƒ¼ã®è©³ç´°" + review_link: "レビュー済ã¨ã—ã¦ãƒžãƒ¼ã‚¯" + status: + destroyed: "投稿ãŒç ´å£Šã•ã‚Œã¾ã—ãŸ" + failed: "何ã‹å•é¡ŒãŒã‚ã‚Šã¾ã™" + title: "å ±å‘Šã®æ¦‚è¦" reshares: + comment_email_subject: "%{author}ã®æŠ•ç¨¿ã®%{resharer}ã®å†å…±æœ‰" reshare: - reshare: - few: "%{count} Reshares" - many: "%{count} Reshares" - one: "1 Reshare" - other: "%{count} Reshares" - two: "%{count} reshares" - zero: "Reshare" - reshare_confirmation: "Reshare %{author} - %{text}?" - reshare_original: "Reshare orignial" - show_original: "Show Original" + deleted: "å…ƒã®æŠ•ç¨¿ã¯ä½œè€…ã«ã‚ˆã£ã¦å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚" + reshare_confirmation: "%{author}ã•ã‚“ã®æŠ•ç¨¿ã‚’å†å…±æœ‰ã—ã¾ã™ã‹?" + reshared_via: "...ã§å†å…±æœ‰" search: "検索" services: create: + already_authorized: "ダイアスãƒãƒ© id %{diaspora_id} ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ %{service_name} アカウントã§ã™ã§ã«èªè¨¼ã•ã‚Œã¦ã„ã¾ã™ã€‚" failure: "èªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚" + read_only_access: "アクセスレベルã¯èªã¿å–り専用ã§ã™ã€‚後ã§å†èªè¨¼ã—ã¦ã¿ã¦ãã ã•ã„" success: "èªè¨¼ã«æˆåŠŸã—ã¾ã—ãŸã€‚" destroy: success: "èªè¨¼ã‚’削除ã™ã‚‹ã®ã«æˆåŠŸã—ã¾ã—ãŸã€‚" failure: error: "サービスã¸æŽ¥ç¶šä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚" - finder: - no_friends: "Facebookã®å‹é”ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" - service_friends: "%{service}ã®å‹ã ã¡" index: + connect: "接続" disconnect: "切æ–" edit_services: "サービスを編集ã™ã‚‹" logged_in_as: "ãƒã‚°ã‚¤ãƒ³æ¸ˆã¿ãƒ¦ãƒ¼ã‚¶å:" + no_services_available: "ã“ã®ãƒãƒƒãƒ‰ã§åˆ©ç”¨å¯èƒ½ãªã‚µãƒ¼ãƒ“スã¯ã‚ã‚Šã¾ã›ã‚“。" + not_logged_in: "ç¾åœ¨ãƒã‚°ã‚¤ãƒ³ã—ã¦ã„ã¾ã›ã‚“。" really_disconnect: "%{service}ã‹ã‚‰åˆ‡æ–ã—ã¾ã™ã‹ã€‚" - inviter: - click_link_to_accept_invitation: "招待を承諾ã™ã‚‹ã«ã¯ã“ã®ãƒªãƒ³ã‚¯ã«ã‚¯ãƒªãƒƒã‚¯ã—ã¦ãã ã•ã„。" - join_me_on_diaspora: "ダイアスãƒãƒ©ï¼Šã«å‚åŠ ã—ã¾ã›ã‚“ã‹ã€‚" - remote_friend: - invite: "招待" - resend: "å†é€" + services_explanation: "サードパーティã®å…±æœ‰ã‚µãƒ¼ãƒ“スã«æŽ¥ç¶šã™ã‚‹ã¨ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã«æ›¸ããªãŒã‚‰ãれらã«æŠ•ç¨¿ã‚’公開ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + share_to: "%{provider}ã«å…±æœ‰" + title: "ææºã‚µãƒ¼ãƒ“スを管ç†ã™ã‚‹" + provider: + facebook: "Facebook" + tumblr: "Tumblr" + twitter: "Twitter" + wordpress: "WordPress" settings: "è¨å®š" - share_visibilites: - update: - post_hidden_and_muted: "%{name}ã•ã‚“ã®æŠ•ç¨¿ã¯éžå…¬é–‹ã§ã€é€šçŸ¥ã‚‚ã•ã‚Œã¾ã›ã‚“。" - see_it_on_their_profile: "ã‚‚ã—ã“ã®æŠ•ç¨¿ã®æ›´æ–°ã‚’ã¿ãŸã‘ã‚Œã°ã€%{name}ã•ã‚“ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒšãƒ¼ã‚¸ã‚’訪れã¦ãã ã•ã„。" shared: - add_contact: - add_new_contact: "æ–°ã—ã„é€£çµ¡å…ˆã‚’è¿½åŠ ã™ã‚‹" - create_request: "ダイアスãƒãƒ©ã®ãƒãƒ³ãƒ‰ãƒ«åã§æ¤œç´¢" - diaspora_handle: "diaspora@handle.org" - enter_a_diaspora_username: "ダイアスãƒãƒ©ã®ãƒ¦ãƒ¼ã‚¶åを入力ã—ã¦ãã ã•ã„。" - know_email: "メールアドレスをã”å˜ã˜ãªã‚‰æ‹›å¾…ã—ã¾ã—ょã†ï¼" - your_diaspora_username_is: "ã‚ãªãŸã®ãƒãƒ³ãƒ‰ãƒ«åã¯%{diaspora_handle}ã§ã™ã€‚" aspect_dropdown: - add_to_aspect: "Add to aspect" + mobile_row_checked: "%{name} (削除)" + mobile_row_unchecked: "%{name} (è¿½åŠ )" toggle: few: "In %{count} aspects" many: "In %{count} aspects" one: "In %{count} aspect" - other: "In %{count} aspects" + other: "%{count} ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã§" two: "In %{count} aspects" - zero: "Add to aspect" - contact_list: - all_contacts: "å…¨ã¦ã®é€£çµ¡å…ˆ" - footer: - logged_in_as: "%{name}ã¨ã—ã¦ãƒã‚°ã‚¤ãƒ³æ¸ˆ" - your_aspects: "アスペクト" + zero: "%{count} ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã§" invitations: by_email: "メールã§" - dont_have_now: "ç¾åœ¨ã€æ‹›å¾…権ãŒæ®‹ã£ã¦ã„ã¾ã›ã‚“。少々ãŠå¾…ã¡ä¸‹ã•ã„。" - from_facebook: "Facebookã‹ã‚‰" - invitations_left: "(残り%{count}回)" - invite_someone: "誰ã‹ã‚’招待ã™ã‚‹" invite_your_friends: "知りåˆã„を検索ã™ã‚‹" invites: "招待" - invites_closed: "ç¾åœ¨ã“ã®ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©ãƒãƒƒãƒ‰ã¸ã®æ‹›å¾…ã‚’ç· ã‚切らã›ã¦é ‚ã„ã¦ã„ã¾ã™" share_this: "ã“ã®ãƒªãƒ³ã‚¯ã‚’メールやブãƒã‚°ã€ãŠæ°—ã«å…¥ã‚Šã®SNSã§å…±æœ‰ã—ã¾ã—ょã†!" - notification: - new: "%{from}ã•ã‚“ã‹ã‚‰æ–°ã—ã„%{type}" public_explain: atom_feed: "Atom フィード" + control_your_audience: "観客をコントãƒãƒ¼ãƒ«" logged_in: "%{service}ã¸ãƒã‚°ã‚¤ãƒ³ã—ã¾ã—ãŸã€‚" manage: "ææºã‚µãƒ¼ãƒ“スを管ç†ã™ã‚‹" + new_user_welcome_message: "ã‚ãªãŸã®æŠ•ç¨¿ã‚’分類ã—ã€ã‚ãªãŸãŒèˆˆå‘³ãŒã‚ã‚‹ã‚‚ã®ã‚’共有ã™ã‚‹äººã‚’見ã¤ã‘ã‚‹ãŸã‚ã«ã€#ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚° を使用ã—ã¾ã™ã€‚ @メンション ã§ç´ 晴らã—ã„人々を呼ã³å‡ºã—ã¾ã™" outside: "公開投稿ã¯ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©å¤–ã®äººã«ã‚‚表示ã•ã‚Œã¾ã™ã€‚" share: "共有" title: "ææºã‚µãƒ¼ãƒ“スをè¨å®šã™ã‚‹" + visibility_dropdown: "ã“ã®ãƒ‰ãƒãƒƒãƒ—ダウンを使用ã—ã¦ã€æŠ•ç¨¿ã®è¡¨ç¤ºã‚’変更ã—ã¾ã™ã€‚ (ã“ã®æœ€åˆã®1ã¤ã‚’公開ã™ã‚‹ã“ã¨ã‚’ã”æ案ã—ã¾ã™ã€‚)" publisher: - all: "ã™ã¹ã¦" - all_contacts: "å…¨ã¦ã®é€£çµ¡å…ˆ" discard_post: "æŠ•ç¨¿ã‚’ç ´æ£„ã™ã‚‹" + formatWithMarkdown: "%{markdown_link} を使用ã—ã¦ã€æŠ•ç¨¿ã®æ›¸å¼ã‚’æ•´ãˆã‚‹ã“ã¨ãŒã§ãã¾ã™" get_location: "ä½ç½®æƒ…å ±ã‚’å–å¾—ã™ã‚‹" - make_public: "公開ã«ã™ã‚‹" new_user_prefill: hello: "ã“ã‚“ã«ã¡ã¯ã¿ãªã•ã‚“。ç§ã¯%{new_user_tag}ã§ã™ã€‚ " - i_like: "I'm interested in %{tags}." - post_a_message_to: "%{aspect}ã«æŠ•ç¨¿ã™ã‚‹" + i_like: "%{tags} ã«èˆˆå‘³ãŒã‚ã‚Šã¾ã™ã€‚ " + invited_by: "ã”招待ã‚ã‚ŠãŒã¨ã†ã€ " + newhere: "åˆã‚ã¦" + poll: + add_a_poll: "æŠ•ç¥¨ã‚’è¿½åŠ " posting: "投稿ä¸" - preview: "プレビュー" - publishing_to: "公開先:" + remove_location: "å ´æ‰€ã‚’å‰Šé™¤" share: "共有" - share_with: "共有先:" upload_photos: "写真をアップãƒãƒ¼ãƒ‰" whats_on_your_mind: "ã„ã¾ä½•ã‚’考ãˆã¦ã„る?" - reshare: - reshare: "å†å…±æœ‰" stream_element: - dislike: "ã“れ嫌ã„ï¼" - hide_and_mute: "Hide and Mute" - ignore_user: "%{name}ã•ã‚“を無視ã™ã‚‹" - like: "ã“れ好ãï¼" - show: "表示" - unlike: "ã“れ好ãï¼ã‚’å–り消ã™" - via: "via %{link}" - viewable_to_anyone: "ã“ã®æŠ•ç¨¿ã¯ã‚¦ã‚§ãƒ–上ã®èª°ã‹ã‚‰ã§ã‚‚見るã“ã¨ãŒã§ãã¾ã™ã€‚" + via: "%{link} ã§" + via_mobile: "モãƒã‚¤ãƒ«ã§" + simple_captcha: + label: "ボックスã«ã‚³ãƒ¼ãƒ‰ã‚’入力ã—ã¦ãã ã•ã„:" + message: + default: "秘密ã®ã‚³ãƒ¼ãƒ‰ãŒç”»åƒã¨ä¸€è‡´ã—ã¾ã›ã‚“ã§ã—ãŸ" + failed: "人間ã®æ¤œè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸ" + user: "秘密ã®ç”»åƒã¨ã‚³ãƒ¼ãƒ‰ãŒç•°ãªã£ã¦ã„ã¾ã—ãŸ" + placeholder: "ç”»åƒã®å€¤ã‚’入力ã—ã¦ãã ã•ã„" + statistics: + active_users_halfyear: "アクティブユーザー数 åŠå¹´" + active_users_monthly: "アクティブユーザー数 月" + closed: "クãƒãƒ¼ã‚ºæ¸ˆ" + disabled: "使用ä¸å¯" + enabled: "利用å¯èƒ½" + local_comments: "ãƒãƒ¼ã‚«ãƒ«ã‚³ãƒ¡ãƒ³ãƒˆ" + local_posts: "ãƒãƒ¼ã‚«ãƒ«æŠ•ç¨¿" + name: "åå‰" + network: "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" + open: "オープン" + registrations: "登録" + services: "サービス" + total_users: "åˆè¨ˆãƒ¦ãƒ¼ã‚¶ãƒ¼æ•°" + version: "ãƒãƒ¼ã‚¸ãƒ§ãƒ³" status_messages: create: success: "%{names}ã‚’å‚ç…§ã™ã‚‹ã®ã«æˆåŠŸã—ã¾ã—ãŸã€‚" - destroy: - failure: "投稿を削除ã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸã€‚" - helper: - no_message_to_display: "表示ã™ã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒã‚ã‚Šã¾ã›ã‚“。" new: mentioning: "%{person}ã•ã‚“ã®ãƒ¡ãƒ³ã‚·ãƒ§ãƒ³" - too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" + too_long: |- + %{count} æ–‡å—未満ã§ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’作æˆã—ã¦ãã ã•ã„。 + 今 %{current_length} æ–‡å—ã§ã™ stream_helper: - hide_comments: "コメントをéžè¡¨ç¤ºã«ã™ã‚‹" - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" + no_more_posts: "ストリームã®çµ‚ã‚ã‚Šã«é”ã—ã¾ã—ãŸã€‚" + no_posts_yet: "ã¾ã 投稿ã¯ã‚ã‚Šã¾ã›ã‚“。" streams: + activity: + title: "マイ アクティビティ" aspects: - title: "Your Aspects" + title: "マイ アスペクト" + aspects_stream: "アスペクト" + comment_stream: + title: "コメントã—ãŸæŠ•ç¨¿" community_spotlight_stream: "コミュニティスãƒãƒƒãƒˆãƒ©ã‚¤ãƒˆ" followed_tag: add_a_tag: "ã‚¿ã‚°ã‚’è¿½åŠ ã™ã‚‹" follow: "フォãƒãƒ¼" title: "フォãƒãƒ¼ã—ãŸã‚¿ã‚°" followed_tags_stream: "フォãƒãƒ¼ã—ãŸã‚¿ã‚°" + like_stream: + title: "ストリームã€ã„ã„ãï¼" + mentioned_stream: "@メンション" mentions: - title: "Your Mentions" + title: "@メンション" + multi: + title: "ストリーム" + public: + title: "公開アクティビティ" tags: title: "ã‚¿ã‚°%{tags}ã®ä»˜ã„ãŸæŠ•ç¨¿" tag_followings: - create: - failure: "Failed to follow: #%{name}" - none: "空白タグã¯ãƒ•ã‚©ãƒãƒ¼ã§ãã¾ã›ã‚“" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" + manage: + no_tags: "ã‚ãªãŸã¯ä½•ã®ã‚¿ã‚°ã‚‚フォãƒãƒ¼ã—ã¦ã„ã¾ã›ã‚“。" + title: "フォãƒãƒ¼ã—ãŸã‚¿ã‚°ã®ç®¡ç†" tags: + name_too_long: "%{count} æ–‡å—未満ã§ã‚¿ã‚°åを作æˆã—ã¦ãã ã•ã„。 今 %{current_length} æ–‡å—ã§ã™" show: follow: "#%{tag}をフォãƒãƒ¼ã™ã‚‹" - following: "#%{tag}をフォãƒãƒ¼ä¸" none: "空ã®ã‚¿ã‚°ã¯å˜åœ¨ã—ã¾ã›ã‚“ï¼" stop_following: "#%{tag}ã®ãƒ•ã‚©ãƒãƒ¼ã‚’ä¸æ¢ã™ã‚‹" - terms_and_conditions: "利用è¦ç´„" - undo: "å…ƒã«æˆ»ã™" + tagged_people: + other: "%{count} 人㌠%{tag} ã§ã‚¿ã‚°ä»˜ã‘ã—ã¦ã„ã¾ã™" + zero: "誰も %{tag} ã§ã‚¿ã‚°ä»˜ã‘ã—ã¦ã„ã¾ã›ã‚“" username: "ユーザå" users: confirm_email: - email_confirmed: "E-Mail %{email} activated" - email_not_confirmed: "E-Mail could not be activated. Wrong link?" + email_confirmed: "メール %{email} を有効ã«ã—ã¾ã—ãŸ" + email_not_confirmed: "メールを有効ã«ã§ãã¾ã›ã‚“。リンクãŒé–“é•ã£ã¦ã„ã¾ã›ã‚“ã‹ï¼Ÿ" destroy: no_password: "アカウントã®ä½¿ç”¨ã‚’åœæ¢ã™ã‚‹ãŸã‚ã«ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。" success: "アカウントã¯ãƒãƒƒã‚¯ã•ã‚Œã¾ã—ãŸã€‚ アカウントを削除ã™ã‚‹ã«ã¯20分程度ã‹ã‹ã‚Šã¾ã™ã€‚ ダイアスãƒãƒ©ã‚’ãŠè©¦ã—ã„ãŸã ãã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚" wrong_password: "パスワードãŒä¸€è‡´ã—ã¾ã›ã‚“。" edit: also_commented: "ä»–ã®äººã‚‚連絡先ã®æŠ•ç¨¿ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ãŸã¨ã" - auto_follow_back: "Automatically follow back if a someone follows you" + auto_follow_aspect: "ã‚ãªãŸãŒè‡ªå‹•çš„ã«å…±æœ‰ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆ:" + auto_follow_back: "ã‚ãªãŸã¨å…±æœ‰ã‚’始ã‚ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨ã€è‡ªå‹•çš„ã«å…±æœ‰" change: "変更" + change_color_theme: "色ã®ãƒ†ãƒ¼ãƒžã‚’変更" change_email: "Change E-Mail" change_language: "言語変更" change_password: "パスワード変更" character_minimum_expl: "å°‘ãªãã¨ã‚‚6å—以上ã§ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã‚“。" close_account: + dont_go: "è¡Œã‹ãªã„ã§ãã ã•ã„ï¼" lock_username: "ユーザーåã¯ãƒãƒƒã‚¯ã•ã‚Œã¾ã™ã€‚ã“ã®ãƒãƒƒãƒ‰ä¸Šã§ã€åŒã˜IDã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’作るã“ã¨ã¯ã§ãã¾ã›ã‚“。" - what_we_delete: "We delete all of your posts, profile data, as soon as humanly possible. Your comments will hang around, but be associated with your Diaspora Handle." + locked_out: "ã‚ãªãŸã¯ã‚µã‚¤ãƒ³ã‚¢ã‚¦ãƒˆã—ã€ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯å‰Šé™¤ã•ã‚Œã‚‹ã¾ã§ãƒãƒƒã‚¯ã‚¢ã‚¦ãƒˆã•ã‚Œã¾ã™ã€‚" + make_diaspora_better: "ã“ã“ã‹ã‚‰é›¢ã‚Œãªã„ã§ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã‚’ã•ã‚‰ã«è‰¯ãã™ã‚‹æ‰‹åŠ©ã‘ã‚’ã—ã¦ãã ã•ã„。本当ã«é›¢ã‚ŒãŸã„å ´åˆã¯ã€ã—ã‹ã—ã€æ¬¡ã«èµ·ã“ã‚‹ã“ã¨ã¯:" + mr_wiggles: "ウィグルæ°ã¯ã€ã‚ãªãŸãŒè¡Œãã®ã‚’見ã¦æ‚²ã—ã‚€ã§ã—ょã†" + no_turning_back: "後戻りã¯ã§ãã¾ã›ã‚“ï¼ç¢ºä¿¡ã—ã¦ã„ã‚‹å ´åˆã¯ã€ä»¥ä¸‹ã«ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。" + what_we_delete: "ã§ãã‚‹ã ã‘æ—©ãã‚ãªãŸã®æŠ•ç¨¿ã‚„プãƒãƒ•ã‚£ãƒ¼ãƒ«ãƒ‡ãƒ¼ã‚¿ã‚’ã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã€‚ä»–ã®äººã®æŠ•ç¨¿ã¸ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯ã€ã¾ã 表示ã•ã‚Œã¾ã™ãŒã€ãれらã¯ã‚ãªãŸã®åå‰ã§ã¯ãªãダイアスãƒãƒ©*番å·ã«é–¢é€£ä»˜ã‘られã¾ã™ã€‚" close_account_text: "アカウントを削除ã™ã‚‹" comment_on_post: "自分ã®æŠ•ç¨¿ã«ã‚³ãƒ¡ãƒ³ãƒˆãŒã‚ã£ãŸã¨ã" current_password: "ç¾åœ¨ã®ãƒ‘スワード" - download_photos: "写真をダウンãƒãƒ¼ãƒ‰ã™ã‚‹" + current_password_expl: "サインインã—ã¦ã„ã‚‹ã‚‚ã®..." + download_export: "マイ プãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’ダウンãƒãƒ¼ãƒ‰" + download_export_photos: "写真をダウンãƒãƒ¼ãƒ‰ã™ã‚‹" edit_account: "アカウント編集" - email_awaiting_confirmation: "We have sent you an activation link to %{unconfirmed_email}. Till you follow this link and activate the new address, we will continue to use your original address %{email}." + email_awaiting_confirmation: "有効化ã®ãƒªãƒ³ã‚¯ã‚’ %{unconfirmed_email} ã«é€ä¿¡ã—ã¾ã—ãŸã€‚ ã“ã®ãƒªãƒ³ã‚¯ã«å¾“ã£ã¦ã€æ–°ã—ã„アドレスを有効ã«ã™ã‚‹ã¾ã§ã€å…ƒã®ã‚¢ãƒ‰ãƒ¬ã‚¹ %{email} を使ã„続ã‘ã¾ã™ã€‚" export_data: "データ出力" + export_in_progress: "ç¾åœ¨ã€ãƒ‡ãƒ¼ã‚¿ã‚’処ç†ã—ã¦ã„ã¾ã™ã€‚ã—ã°ã‚‰ãã—ã¦ã‹ã‚‰ã€æˆ»ã£ã¦ç¢ºèªã—ã¦ãã ã•ã„。" + export_photos_in_progress: "ç¾åœ¨ã€å†™çœŸã‚’処ç†ã—ã¦ã„ã¾ã™ã€‚ã—ã°ã‚‰ãã—ã¦ã‹ã‚‰ã€æˆ»ã£ã¦ç¢ºèªã—ã¦ãã ã•ã„。" following: "フォãƒãƒ¼è¨å®š" - getting_started: "æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼è¨å®š" + last_exported_at: "(最終更新 %{timestamp})" + liked: "誰ã‹ãŒã‚ãªãŸã®æŠ•ç¨¿ã‚’ã„ã„ãï¼ã—ã¾ã—ãŸ" mentioned: "投稿ã«è‡ªåˆ†ãŒãƒ¡ãƒ³ã‚·ãƒ§ãƒ³ã•ã‚ŒãŸã¨ã" new_password: "æ–°ã—ã„パスワード" private_message: "éžå…¬é–‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒå±Šã„ãŸã¨ã" receive_email_notifications: "通知メールã®é€ä¿¡è¨å®š" + request_export: "マイ プãƒãƒ•ã‚£ãƒ¼ãƒ«ã®ãƒ‡ãƒ¼ã‚¿ã‚’リクエスト" + request_export_photos: "写真をリクエスト" + request_export_photos_update: "写真を更新" + request_export_update: "マイ プãƒãƒ•ã‚£ãƒ¼ãƒ«ã®ãƒ‡ãƒ¼ã‚¿ã‚’æ›´æ–°" + reshared: "誰ã‹ãŒã‚ãªãŸã®æŠ•ç¨¿ã‚’å†å…±æœ‰ã—ã¾ã—ãŸ" + show_community_spotlight: "ストリームã«ã€Œã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã‚¹ãƒãƒƒãƒˆãƒ©ã‚¤ãƒˆã€ã‚’表示" + show_getting_started: "「ã¯ã˜ã‚ã«ã€ã®ãƒ’ントを表示" + someone_reported: "誰ã‹ãŒå ±å‘Šã‚’é€ä¿¡" + started_sharing: "誰ã‹ãŒã‚ãªãŸã¨å…±æœ‰ã‚’始ã‚ã¾ã—ãŸ" + stream_preferences: "ストリームè¨å®š" your_email: "メールアドレス" + your_email_private: "ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¦‹ã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“" your_handle: "ダイアスãƒãƒ©ã®ãƒ¦ãƒ¼ã‚¶å" getting_started: + awesome_take_me_to_diaspora: "ç´ æ™´ã‚‰ã—ã„ï¼ç§ã‚’ダイアスãƒãƒ©*ã«é€£ã‚Œã¦ã£ã¦" + community_welcome: "ã‚ãªãŸã«åŠ ã‚ã£ã¦ã„ãŸã ã„ã¦ã€ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©*ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¯å¹¸ã›ã§ã™ï¼" + connect_to_facebook: "ダイアスãƒãƒ©*ã« %{link} ã—ã¦ç‰©äº‹ã‚’スピードアップã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã‚ãªãŸã®åå‰ã¨å†™çœŸã‚’引ã£å¼µã‚Šã€ã‚¯ãƒã‚¹ãƒã‚¹ãƒˆã‚’有効ã«ã—ã¾ã™ã€‚" connect_to_facebook_link: "Facebookアカウントã¨ã®é€£æº" + hashtag_explanation: "ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚°ã¯ã‚ãªãŸãŒè©±ã—åˆã†ã“ã¨ã€ã‚ãªãŸã®èˆˆå‘³ãŒã‚ã‚‹ã“ã¨ã«ãƒ•ã‚©ãƒãƒ¼ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ダイアスãƒãƒ©*ã§æ–°ã—ã„人を見ã¤ã‘ã‚‹ãŸã‚ã®ç´ 晴らã—ã„方法ã§ã‚‚ã‚ã‚Šã¾ã™ã€‚" hashtag_suggestions: "#art, #movies, #gif ãªã©ã®ã‚ˆã†ãªã‚¿ã‚°ã‚’フォãƒãƒ¼ã—ã¦ã¿ã¾ã—ょã†ã€‚" - saved: "ä¿å˜ã—ã¾ã—ãŸï¼" + well_hello_there: "ã‚„ã‚ã€ã“ã‚“ã«ã¡ã¯ï¼" what_are_you_in_to: "何ã«èˆˆå‘³ãŒã‚ã‚Šã¾ã™ã‹?" who_are_you: "ã‚ãªãŸã¯èª°ã§ã™ã‹ï¼Ÿ" privacy_settings: ignored_users: "無視ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼" + no_user_ignored_message: "ç¾åœ¨ã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’無視ã—ã¦ã„ã¾ã›ã‚“" stop_ignoring: "無視を解除ã™ã‚‹" + strip_exif: "アップãƒãƒ¼ãƒ‰ã—ãŸç”»åƒã‹ã‚‰å ´æ‰€ã€ä½œæˆè€…ã€ã‚«ãƒ¡ãƒ©ãƒ¢ãƒ‡ãƒ«ãªã©ã®ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ã‚’除去ã™ã‚‹ (推奨)" title: "プライãƒã‚·ãƒ¼è¨å®š" public: does_not_exist: "ユーザå「%{username}ã€ã¯å˜åœ¨ã—ã¾ã›ã‚“。" update: + color_theme_changed: "色ã®ãƒ†ãƒ¼ãƒžã‚’æ£å¸¸ã«å¤‰æ›´ã—ã¾ã—ãŸã€‚" + color_theme_not_changed: "色ã®ãƒ†ãƒ¼ãƒžã‚’変更ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚" email_notifications_changed: "メール通知ã®è¨å®šã‚’変更ã—ã¾ã—ãŸã€‚" follow_settings_changed: "フォãƒãƒ¼ã®è¨å®šã‚’変更ã—ã¾ã—ãŸã€‚" follow_settings_not_changed: "フォãƒãƒ¼ã®è¨å®šã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸã€‚" @@ -837,13 +1225,6 @@ ja: settings_updated: "è¨å®šãŒæ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚" unconfirmed_email_changed: "E-Mail Changed. Needs activation." unconfirmed_email_not_changed: "E-Mail Change Failed" - webfinger: - fetch_failed: "%{profile_url} ã®webfingerプãƒãƒ•ã‚£ãƒ¼ãƒ«ã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸã€‚" - hcard_fetch_failed: "%{account}ã®hcardå–å¾—ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚" - no_person_constructed: "ã“ã®hcardã‹ã‚‰é€£çµ¡å…ˆäººã‚’生æˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" - not_enabled: "%{account}ã®ãƒãƒƒãƒ‰ã§ã¯webfingerãŒç„¡åŠ¹ã«ãªã£ã¦ã„るよã†ã§ã™ã€‚" - xrd_fetch_failed: "%{account}ã®xrdå–å¾—ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚" - welcome: "よã†ã“ã!" will_paginate: next_label: "次㸠»" previous_label: "« å‰ã¸" \ No newline at end of file diff --git a/config/locales/diaspora/ka.yml b/config/locales/diaspora/ka.yml index 7923d4b84d9488d0ab82cc20f383b0659df7a256..ad0f0222454904c684fa4613285ece305561f1b1 100644 --- a/config/locales/diaspora/ka.yml +++ b/config/locales/diaspora/ka.yml @@ -6,10 +6,7 @@ ka: _applications: "áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ”ბი" - _comments: "კáƒáƒ›áƒ”ნტáƒáƒ ები" _contacts: "კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბი" - _home: "სáƒáƒ®áƒšáƒ˜" - _photos: "ფáƒáƒ¢áƒáƒ”ბი" _services: "მáƒáƒ›áƒ¡áƒáƒ®áƒ£áƒ ებები" account: "áƒáƒœáƒ’áƒáƒ იში" activerecord: @@ -44,13 +41,7 @@ ka: stats: 50_most: "50 ყველáƒáƒ–ე პáƒáƒžáƒ£áƒšáƒáƒ ული თáƒáƒ’ი" tag_name: "თáƒáƒ’ი: <b>%{name_tag}</b> Count: <b>%{count_tag}</b>" - ago: "%{time} წინ" all_aspects: "ყველრáƒáƒ¡áƒžáƒ”ქტი" - application: - helper: - unknown_person: "უცნáƒáƒ‘ი áƒáƒ“áƒáƒ›áƒ˜áƒáƒœáƒ˜" - video_title: - unknown: "ვიდეáƒáƒ¡ სáƒáƒ—áƒáƒ£áƒ ი უცნáƒáƒ‘იáƒ" are_you_sure: "დáƒáƒ წმუნებული ხáƒáƒ თ?" are_you_sure_delete_account: "დáƒáƒ წმუნებული ხáƒáƒ თ რáƒáƒ› თქვენი áƒáƒœáƒ’áƒáƒ იშის დáƒáƒ®áƒ£áƒ ვრგსურთ? áƒáƒ›áƒ˜áƒ¡ დáƒáƒ‘რუნებრშეუძლებელიáƒ!" aspect_memberships: @@ -64,17 +55,9 @@ ka: success: "კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜ წáƒáƒ მáƒáƒ¢áƒ”ბით დáƒáƒ”მáƒáƒ¢áƒ áƒáƒ¡áƒžáƒ”ქტში." aspect_listings: add_an_aspect: "+ áƒáƒ¡áƒžáƒ”ქტის დáƒáƒ›áƒáƒ¢áƒ”ბáƒ" - deselect_all: "ყველრმáƒáƒœáƒ˜áƒ¨áƒ•áƒœáƒ˜áƒ¡ მáƒáƒ®áƒ¡áƒœáƒ" - edit_aspect: "%{name}-ს რედáƒáƒ¥áƒ¢áƒ˜áƒ ებáƒ" - select_all: "ყველáƒáƒ¡ áƒáƒ ჩევáƒ" aspect_stream: stay_updated: "იყáƒáƒ•áƒ˜ ინფáƒáƒ მირებული" stay_updated_explanation: "შენ გვერდზე áƒáƒ ის შენი კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბი, ტáƒáƒ’ები რáƒáƒ›áƒšáƒ”ბსáƒáƒª მიყვები დრპáƒáƒ¡áƒ¢áƒ”ბი სáƒáƒ–áƒáƒ’áƒáƒ“áƒáƒ”ბის კრეáƒáƒ¢áƒ˜áƒ£áƒšáƒ˜ წევრებისგáƒáƒœ." - contacts_not_visible: "áƒáƒ› áƒáƒ¡áƒžáƒ”ქტებში áƒáƒ სებული კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბი ვერშეძლებენ ერთმáƒáƒœáƒ”თის დáƒáƒœáƒáƒ®áƒ•áƒáƒ¡." - contacts_visible: "áƒáƒ› áƒáƒ¡áƒžáƒ”ქტში áƒáƒ სებული კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბი შეძლებენ ერთმáƒáƒœáƒ”თის დáƒáƒœáƒáƒ®áƒ•áƒáƒ¡." - create: - failure: "áƒáƒ¡áƒžáƒ”ქტის შექმნრჩáƒáƒ˜áƒ¨áƒáƒšáƒ" - success: "თქვენი áƒáƒ®áƒáƒšáƒ˜ áƒáƒ¡áƒžáƒ”ქტი %{name} შეიქმნáƒ" destroy: failure: "%{name} ცáƒáƒ იელი áƒáƒ áƒáƒ ის დრმáƒáƒ¡ ვერწáƒáƒ¨áƒšáƒ˜áƒ—." success: "%{name} წáƒáƒ მáƒáƒ¢áƒ”ბით წáƒáƒ˜áƒ¨áƒáƒšáƒ." @@ -82,22 +65,13 @@ ka: aspect_list_is_not_visible: "áƒáƒ¡áƒžáƒ”ქტის სირდáƒáƒ›áƒáƒšáƒ£áƒšáƒ˜áƒ áƒáƒ› áƒáƒ¡áƒžáƒ”ქტში მყáƒáƒ¤áƒ—áƒáƒ—ვის." aspect_list_is_visible: "áƒáƒ¡áƒžáƒ”ქტის სირხილულირáƒáƒ› áƒáƒ¡áƒžáƒ”ქტში მყáƒáƒ¤áƒ—áƒáƒ—ვის" confirm_remove_aspect: "დáƒáƒ წმუნებული ხáƒáƒ თ რáƒáƒ› áƒáƒ› áƒáƒ¡áƒžáƒ”ქტის წáƒáƒ¨áƒšáƒ გსურთ?" - make_aspect_list_visible: "გáƒáƒ®áƒ“ნენ áƒáƒ› áƒáƒ¡áƒžáƒ”ქტში áƒáƒ სებული კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბი ერთმáƒáƒœáƒ”თისთვის ხილულნი?" - remove_aspect: "áƒáƒ› áƒáƒ¡áƒžáƒ”ქტის წáƒáƒ¨áƒšáƒ" rename: "გáƒáƒ“áƒáƒ ქმევáƒ" update: "გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ" updating: "ნáƒáƒ®áƒšáƒ“ებáƒ" index: - diaspora_id: - content_1: "თქვენი Diaspora-ს ID áƒáƒ ის:" - content_2: "გáƒáƒ£áƒ–იáƒáƒ ეთ ის ნებისმიერáƒáƒ“áƒáƒ›áƒ˜áƒáƒœáƒ¡ დრის შეძლებს თქვენს პáƒáƒ•áƒœáƒáƒ¡ Diaspora-ზე." - heading: "Diaspora ID" donate: "ფულის შეწირვáƒ" - handle_explanation: "This is your diaspora id. Like an email address, you can give this to people to reach you." help: do_you: "თქვენ:" - email_feedback: "%{link} თქვენი უკუკáƒáƒ•áƒ¨áƒ˜áƒ ი, თუ გსურთ" - email_link: "ელ-ფáƒáƒ¡áƒ¢áƒ" feature_suggestion: "... გáƒáƒ¥áƒ•áƒ— %{link} რჩევáƒ?" find_a_bug: "... იპáƒáƒ•áƒ”თ %{link}?" have_a_question: "გáƒáƒáƒ¥áƒ•áƒ¡ %{link}?" @@ -111,24 +85,14 @@ ka: follow: "გáƒáƒ§áƒ”ვი %{link} დრმიესáƒáƒšáƒ›áƒ” áƒáƒáƒ®áƒáƒš დიáƒáƒ¡áƒžáƒáƒ áƒ*-ს მáƒáƒ›áƒ®áƒ›áƒáƒ ებლებს" learn_more: "მეტის გáƒáƒ’ებáƒ" title: "მიესáƒáƒšáƒ›áƒ” áƒáƒ®áƒáƒš მáƒáƒ›áƒ®áƒ›áƒáƒ ებლებს" - no_contacts: "áƒáƒ áƒáƒ ის კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბი" - no_tags: "მáƒáƒ«áƒ”ბნე ტáƒáƒ’ი რáƒáƒ› გáƒáƒ§áƒ•áƒ” მáƒáƒ¡" - people_sharing_with_you: "ხáƒáƒšáƒ®áƒ˜, რáƒáƒ›áƒ”ლიც áƒáƒ–იáƒáƒ ებს შენთáƒáƒœ" - post_a_message: "დáƒáƒ¬áƒ”რე მესიჯი >>" services: content: "დიáƒáƒ¡áƒžáƒáƒ áƒáƒ¨áƒ˜ შეგიძლირდáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ დე შემდეგ სერვისებს:" heading: "სერვისებთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ ებáƒ" - unfollow_tag: "შეწყვიტე გáƒáƒ§áƒáƒšáƒ #%{tag}" - new: - create: "შექმნáƒ" - name: "სáƒáƒ®áƒ”ლი (ხედáƒáƒ•áƒ— მხáƒáƒšáƒáƒ“ თქვენ)" no_contacts_message: community_spotlight: "ყურáƒáƒ“ღების ცენტრში" or_spotlight: "áƒáƒœ თქვენ შეგიძლიáƒáƒ— გáƒáƒáƒ–იáƒáƒ áƒáƒ— %{link}-ის გáƒáƒ›áƒáƒ§áƒ”ნებით" try_adding_some_more_contacts: "თქვენ შეგიძლიáƒáƒ— მáƒáƒ«áƒ”ბნáƒáƒ— áƒáƒœ მáƒáƒ˜áƒ¬áƒ•áƒ˜áƒáƒ— მეტი კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜." you_should_add_some_more_contacts: "თქვენ უნდრდáƒáƒáƒ›áƒáƒ¢áƒáƒ— მეტი კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜!" - no_posts_message: - start_talking: "ჯერáƒáƒ áƒáƒ•áƒ˜áƒ¡ áƒáƒ áƒáƒ¤áƒ”რი áƒáƒ უთქვáƒáƒ›áƒ¡!" seed: acquaintances: "ნáƒáƒªáƒœáƒáƒ‘ები" family: "áƒáƒ¯áƒáƒ®áƒ˜" @@ -137,7 +101,6 @@ ka: update: failure: "თქვენს áƒáƒ¡áƒžáƒ”ქტს, %{name}, áƒáƒ¥áƒ•áƒ¡ ძáƒáƒšáƒ˜áƒáƒœ დიდი სáƒáƒ®áƒ”ლი დრáƒáƒ შეიძლებრმისი შენáƒáƒ®áƒ•áƒ" success: "თქვენი áƒáƒ¡áƒžáƒ”ქტი, %{name}, წáƒáƒ მáƒáƒ¢áƒ”ბით დáƒáƒ ედáƒáƒ¥áƒ¢áƒ˜áƒ დáƒ." - back: "უკáƒáƒœ" blocks: create: failure: "მე áƒáƒ ვáƒáƒ˜áƒ’ნáƒáƒ ებ áƒáƒ› მáƒáƒ›áƒ®áƒ›áƒáƒ ებელს  #evasion" @@ -146,21 +109,14 @@ ka: explanation: "გáƒáƒ›áƒáƒáƒ¥áƒ•áƒ”ყნე დიáƒáƒ¡áƒžáƒáƒ áƒáƒ–ე ნებისმიერი áƒáƒ“გილიდáƒáƒœ áƒáƒ› ბმულის ჩáƒáƒœáƒ˜áƒ¨áƒ•áƒœáƒ˜áƒ— =>%{link}." heading: "სáƒáƒœáƒ˜áƒ¨áƒœáƒ”" post_something: "გáƒáƒ›áƒáƒáƒ¥áƒ•áƒ”ყნე დიáƒáƒ¡áƒžáƒáƒ áƒáƒ–ე" - post_success: "გáƒáƒ›áƒáƒ¥áƒ•áƒ”ყნდáƒ! იხურებáƒ!" cancel: "გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ" comments: new_comment: comment: "კáƒáƒ›áƒ”ნტáƒáƒ ი" commenting: "დáƒáƒ™áƒáƒ›áƒ”ნტáƒáƒ ებáƒ" - one: "1 კáƒáƒ›áƒ”ნტáƒáƒ ი" - other: "%{count} კáƒáƒ›áƒ”ნტáƒáƒ ი" - zero: "კáƒáƒ›áƒ”ნტáƒáƒ ები áƒáƒ áƒáƒ ის" contacts: - create: - failure: "კáƒáƒ›áƒ”ნáƒáƒ¢áƒáƒ ის შექმნრვერმáƒáƒ®áƒ”რხდáƒ" index: add_a_new_aspect: "დáƒáƒáƒ›áƒáƒ¢áƒ” áƒáƒ®áƒáƒšáƒ˜ áƒáƒ¡áƒžáƒ”ქტი" - add_to_aspect: "%{name} დáƒáƒáƒ›áƒáƒ¢áƒ” კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბში" all_contacts: "ყველრკáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜" community_spotlight: "სáƒáƒ–áƒáƒ’áƒáƒ“áƒáƒ”ბის ყურáƒáƒ“ღების ცენტრში" my_contacts: "ჩემი კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბი" @@ -169,29 +125,16 @@ ka: only_sharing_with_me: "áƒáƒ–იáƒáƒ ებს მხáƒáƒšáƒáƒ“ ჩემთáƒáƒœ" start_a_conversation: "დáƒáƒ˜áƒ¬áƒ§áƒ” სáƒáƒ£áƒ‘áƒáƒ ი" title: "კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბი" - your_contacts: "შენი კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბი" - sharing: - people_sharing: "ხáƒáƒšáƒ®áƒ˜, რáƒáƒ›áƒ”ლიც áƒáƒ–იáƒáƒ ებს შენთáƒáƒœ:" spotlight: community_spotlight: "Community Spotlight" conversations: create: fail: "áƒáƒ áƒáƒ¡áƒ¬áƒáƒ ი წერილი" sent: "წერილი გáƒáƒ’ზáƒáƒ•áƒœáƒ˜áƒšáƒ˜áƒ" - helper: - new_messages: - few: "%{count} new messages" - many: "%{count} new messages" - one: "1 new messages" - other: "%{count} new messages" - two: "%{count} new messages" - zero: "No new messages" index: inbox: "შემáƒáƒ¡áƒ£áƒšáƒ˜" - no_conversation_selected: "სáƒáƒ£áƒ‘áƒáƒ ი áƒáƒ áƒáƒ ის მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜" no_messages: "წერილები áƒáƒ áƒáƒ ის" new: - abandon_changes: "áƒáƒ მáƒáƒ•áƒáƒ®áƒ“ინრცვლილებáƒ?" send: "გáƒáƒ’ზáƒáƒ•áƒœáƒ" sending: "იგზáƒáƒ•áƒœáƒ”ბáƒ..." subject: "თემáƒ" @@ -210,36 +153,20 @@ ka: error_messages: helper: correct_the_following_errors_and_try_again: "გáƒáƒ›áƒáƒáƒ¡áƒ¬áƒáƒ ეთ შემდეგი შეცდáƒáƒ›áƒ”ბი დრხელáƒáƒ®áƒšáƒ ცáƒáƒ“ეთ." - invalid_fields: "áƒáƒ áƒáƒ¡áƒ¬áƒáƒ ი ველები" fill_me_out: "შევსებáƒ" find_people: "იპáƒáƒ•áƒ”თ áƒáƒ“áƒáƒ›áƒ˜áƒáƒœáƒ”ბი áƒáƒœ #ტეგები" - hide: "დáƒáƒ›áƒáƒšáƒ•áƒ" invitations: a_facebook_user: "Facebook-ის მáƒáƒ›áƒ®áƒ›áƒáƒ ებელი" check_token: not_found: "მáƒáƒ¬áƒ•áƒ”ვრáƒáƒ áƒáƒ ის ნáƒáƒžáƒáƒ•áƒœáƒ˜" create: - already_contacts: "თქვენ უკვე დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ ებული ხáƒáƒ თ áƒáƒ› პირáƒáƒ•áƒœáƒ”ბáƒáƒ¡áƒ—áƒáƒœ" - already_sent: "თქვენ უკვე მáƒáƒ˜áƒ¬áƒ•áƒ˜áƒ”თ ეს პირáƒáƒ•áƒœáƒ”ბáƒ" no_more: "თქვენ áƒáƒ›áƒáƒ’ეწურáƒáƒ— მáƒáƒ¡áƒáƒ¬áƒ•áƒ”ვები." - own_address: "თქვენ áƒáƒ შეგიძლიáƒáƒ— მáƒáƒ¡áƒáƒ¬áƒ•áƒ”ვის გáƒáƒ’ზáƒáƒ•áƒœáƒ სáƒáƒ™áƒ£áƒ—áƒáƒ მისáƒáƒ›áƒáƒ თზე." rejected: "შემდეგ ელ-ფáƒáƒ¡áƒ¢áƒ”ბს áƒáƒ¥áƒ•áƒ— პრáƒáƒ‘ლემáƒ: " sent: "მáƒáƒ¡áƒáƒ¬áƒ•áƒ”ვები გáƒáƒ’ზáƒáƒ•áƒœáƒ˜áƒšáƒ˜áƒ: " - edit: - accept_your_invitation: "მიიღე შენი მáƒáƒ¬áƒ•áƒ”ვáƒ" - your_account_awaits: "თქვენი მáƒáƒ¡áƒáƒ¬áƒ•áƒ”ვი გელáƒáƒ“ებáƒáƒ—!" new: - already_invited: "შემდეგ ხáƒáƒšáƒ®áƒ¡ áƒáƒ მიუღირთქვენი მáƒáƒ¬áƒ•áƒ”ვáƒ:" - aspect: "áƒáƒ¡áƒžáƒ”ქტი" - check_out_diaspora: "შეáƒáƒ›áƒáƒ¬áƒ›áƒ” დიáƒáƒ¡áƒžáƒáƒ áƒ!" - if_they_accept_info: "თუ მáƒáƒ¬áƒ•áƒ”ვáƒáƒ¡ მიიღებენ, ისინი დáƒáƒ”მáƒáƒ¢áƒ”ბიáƒáƒœ იმ áƒáƒ¡áƒžáƒ”ქტში რáƒáƒ›áƒ”ლშიც თქვენ მáƒáƒ˜áƒ¬áƒ•áƒ˜áƒ”თ." invite_someone_to_join: "მáƒáƒ˜áƒ¬áƒ•áƒ˜áƒ” ვინმე რáƒáƒ› შემáƒáƒ£áƒ”რთდეს დიáƒáƒ¡áƒžáƒáƒ áƒáƒ¡!" language: "ენáƒ" - personal_message: "პირáƒáƒ“ი წერილი" - resend: "ხელáƒáƒ®áƒšáƒ გáƒáƒ’ზáƒáƒ•áƒœáƒ" send_an_invitation: "მáƒáƒ¬áƒ•áƒ”ვის გáƒáƒ’ზáƒáƒ•áƒœáƒ" - send_invitation: "მáƒáƒ¬áƒ•áƒ”ვის გáƒáƒ’ზáƒáƒ•áƒœáƒ" - to: "ვის" layouts: application: back_to_top: "დáƒáƒ¡áƒáƒ¬áƒ§áƒ˜áƒ¡áƒ¨áƒ˜ დáƒáƒ‘რუნებáƒ" @@ -247,39 +174,13 @@ ka: public_feed: "Public Diaspora Feed for %{name}" toggle: "გáƒáƒ®áƒ“ი მáƒáƒ‘ილური" whats_new: "რრáƒáƒ ის áƒáƒ®áƒáƒšáƒ˜?" - your_aspects: "შენი áƒáƒ¡áƒžáƒ”ქტები" header: - admin: "áƒáƒ“მინისტრáƒáƒ¢áƒáƒ ი" - blog: "ბლáƒáƒ’ი" code: "კáƒáƒ“ი" - login: "შესვლáƒ" logout: "გáƒáƒ›áƒáƒ¡áƒ•áƒšáƒ" profile: "პრáƒáƒ¤áƒ˜áƒšáƒ˜" - recent_notifications: "ბáƒáƒšáƒ შეტყáƒáƒ‘ინებები" settings: "პáƒáƒ áƒáƒ›áƒ”ტრები" - view_all: "ყველáƒáƒ¡ ჩვენებáƒ" - likes: - likes: - people_dislike_this: - few: "%{count} dislikes" - many: "%{count} dislikes" - one: "%{count} dislike" - other: "%{count} dislikes" - two: "%{count} dislikes" - zero: "no dislikes" - people_like_this: - other: "%{count} მáƒáƒ¬áƒáƒœáƒ”ბáƒ" - zero: "no likes" - people_like_this_comment: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" limited: "შეზღუდული" more: "მეტი" - next: "შემდეგი" no_results: "შედეგი ვერმáƒáƒ˜áƒ«áƒ”ბნáƒ" notifications: also_commented: @@ -303,14 +204,6 @@ ka: other: "%{actors} commented on your %{post_link}." two: "%{actors} commented on your %{post_link}." zero: "%{actors} commented on your %{post_link}." - helper: - new_notifications: - few: "%{count} new notifications" - many: "%{count} new notifications" - one: "1 new notification" - other: "%{count} new notifications" - two: "%{count} new notifications" - zero: "No new notifications" index: and: "დáƒ" and_others: @@ -393,7 +286,6 @@ ka: liked: "%{name} მáƒáƒ˜áƒ¬áƒáƒœáƒ შენი პáƒáƒ¡áƒ¢áƒ˜" view_post: "პáƒáƒ¡áƒ¢áƒ˜áƒ¡ ნáƒáƒ®áƒ•áƒ >" mentioned: - mentioned: "გáƒáƒ®áƒ¡áƒ”ნრპáƒáƒ¡áƒ¢áƒ¨áƒ˜:" subject: "%{name} გáƒáƒ®áƒ¡áƒ”ნრდიáƒáƒ¡áƒžáƒáƒ áƒáƒ¨áƒ˜*" private_message: reply_to_or_view: "უპáƒáƒ¡áƒ£áƒ®áƒ” áƒáƒœ ნáƒáƒ®áƒ” ეს სáƒáƒ£áƒ‘áƒáƒ ი >" @@ -411,98 +303,40 @@ ka: to_change_your_notification_settings: "რáƒáƒ› შეცვáƒáƒšáƒáƒ— თქვენი შეტყáƒáƒ‘ინების პáƒáƒ áƒáƒ›áƒ”ტრები" nsfw: "18+" ok: "OK" - or: "áƒáƒœ" - password: "პáƒáƒ áƒáƒšáƒ˜" - password_confirmation: "პáƒáƒ áƒáƒšáƒ˜áƒ¡ დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებáƒ" people: - add_contact_small: - add_contact_from_tag: "დáƒáƒáƒ›áƒáƒ¢áƒ” კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜ თáƒáƒ’იდáƒáƒœ" - aspect_list: - edit_membership: "edit aspect membership" - helper: - results_for: " რეზულტáƒáƒ¢áƒ˜ %{params}-სთვის" index: looking_for: "ეძებ %{tag_link} დáƒáƒ—áƒáƒ’ულ პáƒáƒ¡áƒ¢áƒ”ბს?" no_one_found: "...დრვერáƒáƒ•áƒ˜áƒœ ვერმáƒáƒ˜áƒ«áƒ”ბნáƒ." no_results: "რáƒáƒ›áƒ” უნდრმáƒáƒ«áƒ”ბნáƒ!" results_for: "მáƒáƒ«áƒ”ბნე რეზულტáƒáƒ¢áƒ”ბი" - one: "1 პერსáƒáƒœáƒ" - other: "%{count} áƒáƒ“áƒáƒ›áƒ˜áƒáƒœáƒ¡" person: - add_contact: "დáƒáƒáƒ›áƒáƒ¢áƒ” კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜" - already_connected: "უკვე დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ ებულიáƒ" - pending_request: "მიმდინáƒáƒ ე მáƒáƒ—ხáƒáƒ•áƒœáƒ" thats_you: "ეს შენ ხáƒáƒ !" profile_sidebar: bio: "ბიáƒáƒ’რáƒáƒ¤áƒ˜áƒ" born: "დáƒáƒ‘áƒáƒ“ების დღე" - edit_my_profile: "ჩემი პრáƒáƒ¤áƒ˜áƒšáƒ˜áƒ¡ რედáƒáƒ¥áƒ¢áƒ˜áƒ ებáƒ" gender: "სქესი" - in_aspects: "áƒáƒ¡áƒžáƒ”ქტებში" location: "მდებáƒáƒ ეáƒáƒ‘áƒ" - remove_contact: "კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜áƒ¡ áƒáƒ›áƒáƒ¨áƒšáƒ" - remove_from: "áƒáƒ›áƒáƒ¨áƒšáƒ %{name} %{aspect}-დáƒáƒœ?" show: closed_account: "ეს áƒáƒœáƒ’áƒáƒ იში დáƒáƒ®áƒ£áƒ ულიáƒ." does_not_exist: "პირáƒáƒ•áƒœáƒ”ბრáƒáƒ áƒáƒ სებáƒáƒ‘ს!" has_not_shared_with_you_yet: "%{name} áƒáƒ áƒáƒ¥áƒ•áƒ¡ პáƒáƒ¡áƒ¢áƒ”ბი შენთáƒáƒœ გáƒáƒ–იáƒáƒ ებული" - ignoring: "იგნáƒáƒ ირებáƒáƒ¡ უკეთებთ %{name}-ის ყველრპáƒáƒ¡áƒ¢áƒ¡" - incoming_request: "%{name} wants to share with you" - mention: "ხსენებáƒ" - message: "შეტყáƒáƒ‘ინებáƒ" - not_connected: "áƒáƒ áƒáƒ–იáƒáƒ ებთ áƒáƒ› პერსáƒáƒœáƒáƒ¡áƒ—áƒáƒœ" - recent_posts: "áƒáƒ®áƒáƒšáƒ˜ პáƒáƒ¡áƒ¢áƒ”ბი" - recent_public_posts: "ბáƒáƒšáƒ სáƒáƒ¯áƒáƒ რპáƒáƒ¡áƒ¢áƒ”ბი" - return_to_aspects: "დáƒáƒ‘რუნდით თქვენი áƒáƒ¡áƒžáƒ”ქტების გვერდზე" - see_all: "ყველáƒáƒ¡ ნáƒáƒ®áƒ•áƒ" - start_sharing: "დáƒáƒ˜áƒ¬áƒ§áƒ” გáƒáƒ–იáƒáƒ ებáƒ" - to_accept_or_ignore: "რáƒáƒ› დáƒáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒáƒ— áƒáƒœ უáƒáƒ ყáƒáƒ— ის" - sub_header: - add_some: "დáƒáƒáƒ›áƒáƒ¢áƒ”" - edit: "რედáƒáƒ¥áƒ¢áƒ˜áƒ ებáƒ" - you_have_no_tags: "შენ áƒáƒ გáƒáƒ¥áƒ•áƒ¡ თáƒáƒ’ები!" - webfinger: - fail: "ბáƒáƒ“იში, ვერვიპáƒáƒ•áƒ”თ %{handle}." - zero: "áƒáƒ áƒáƒ ის ხáƒáƒšáƒ®áƒ˜" photos: - comment_email_subject: "%{name}-ის სურáƒáƒ—ი" create: integrity_error: "ფáƒáƒ¢áƒáƒ¡ áƒáƒ¢áƒ•áƒ˜áƒ თვრვერმáƒáƒ®áƒ”რხდáƒ. დáƒáƒ წმუნებული ხáƒáƒ რáƒáƒ› სურáƒáƒ—იáƒ?" runtime_error: "ფáƒáƒ¢áƒáƒ¡ áƒáƒ¢áƒ•áƒ˜áƒ თვრვერმáƒáƒ®áƒ”რხდáƒ. დáƒáƒ წმუნებული ხáƒáƒ რáƒáƒ› უსáƒáƒ¤áƒ თხáƒáƒ”ბის ღვედები შეკრული გáƒáƒ¥áƒ•áƒ¡?" type_error: "ფáƒáƒ¢áƒáƒ¡ áƒáƒ¢áƒ•áƒ˜áƒ თვრვერმáƒáƒ®áƒ”რხდáƒ. დáƒáƒ წმუნებული ხáƒáƒ რáƒáƒ› სურáƒáƒ—ი დáƒáƒáƒ›áƒáƒ¢áƒ”?" destroy: notice: "სურáƒáƒ—ი წáƒáƒ¨áƒšáƒ˜áƒšáƒ˜áƒ." - edit: - editing: "შესწáƒáƒ ებáƒ" - new: - back_to_list: "სიáƒáƒ¨áƒ˜ დáƒáƒ‘რუნებáƒ" - new_photo: "áƒáƒ®áƒáƒšáƒ˜ ფáƒáƒ¢áƒ" - post_it: "გáƒáƒ›áƒáƒáƒ¥áƒ•áƒ”ყნე!" new_photo: empty: "{file} áƒáƒ ის ცáƒáƒ იელი, გთხáƒáƒ•áƒ— áƒáƒ˜áƒ ჩიáƒáƒ— ფáƒáƒ˜áƒšáƒ”ბი მის გáƒáƒ ეშე" invalid_ext: "{file} áƒáƒ¥áƒ•áƒ¡ áƒáƒ áƒáƒ¡áƒ¬áƒáƒ ი გáƒáƒ¤áƒáƒ თáƒáƒ”ბáƒ. მხáƒáƒšáƒáƒ“ {extensions} გáƒáƒ¤áƒáƒ თáƒáƒ”ბები áƒáƒ ის დáƒáƒ¨áƒ•áƒ”ბული." size_error: "{file} ზáƒáƒ›áƒáƒ–ე დიდიáƒ, მáƒáƒ¥áƒ¡áƒ˜áƒ›áƒáƒšáƒ£áƒ ი ზáƒáƒ›áƒ áƒáƒ ის {sizeLimit}." new_profile_photo: - or_select_one_existing: "áƒáƒœ áƒáƒ˜áƒ ჩიეთ უკვე áƒáƒ სებული %{photos}" upload: "áƒáƒ®áƒáƒšáƒ˜ პრáƒáƒ¤áƒ˜áƒšáƒ˜áƒ¡ ფáƒáƒ¢áƒáƒ¡ áƒáƒ¢áƒ•áƒ˜áƒ თვáƒ!" - photo: - view_all: "დáƒáƒáƒ—ვáƒáƒ იელე %{name}-ს ყველრფáƒáƒ¢áƒ" show: - collection_permalink: "პერმáƒáƒ‘მულის კáƒáƒšáƒ”ქციáƒ" - delete_photo: "სურáƒáƒ—ის წáƒáƒ¨áƒšáƒ" - edit: "რედáƒáƒ¥áƒ¢áƒ˜áƒ ებáƒ" - edit_delete_photo: "ფáƒáƒ¢áƒáƒ¡ áƒáƒ¦áƒ¬áƒ”რის რედáƒáƒ¥áƒ¢áƒ˜áƒ ებრ/ ფáƒáƒ¢áƒáƒ¡ წáƒáƒ¨áƒšáƒ" - make_profile_photo: "დáƒáƒáƒ§áƒ”ნე სურáƒáƒ—ი პრáƒáƒ¤áƒ˜áƒšáƒ–ე" show_original_post: "áƒáƒ იგინáƒáƒšáƒ˜ პáƒáƒ¡áƒ¢áƒ˜áƒ¡ ჩვენებáƒ" - update_photo: "სურáƒáƒ—ის გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ" - update: - error: "ფáƒáƒ¢áƒáƒ¡ რედáƒáƒ¥áƒ¢áƒ˜áƒ ებრვერმáƒáƒ®áƒ”რხდáƒ." - notice: "ფáƒáƒ¢áƒ წáƒáƒ მáƒáƒ¢áƒ”ბით გáƒáƒœáƒáƒ®áƒšáƒ“áƒ." posts: show: - destroy: "წáƒáƒ¨áƒšáƒ" - not_found: "ბáƒáƒ“იში, ვერვიპáƒáƒ•áƒ”თ მáƒáƒ—ხáƒáƒ•áƒœáƒ˜áƒšáƒ˜ პáƒáƒ¡áƒ¢áƒ˜." - permalink: "პერმáƒáƒ‘მული" photos_by: few: "%{count} photos by %{author}" many: "%{count} photos by %{author}" @@ -511,14 +345,11 @@ ka: two: "Two photos by %{author}" zero: "No photos by %{author}" reshare_by: "თáƒáƒ•áƒ˜áƒ“áƒáƒœ გáƒáƒ›áƒáƒ¥áƒ•áƒ”ყნებრby %{author}" - previous: "წინáƒ" privacy: "კáƒáƒœáƒ¤áƒ˜áƒ“ენციáƒáƒšáƒ£áƒ áƒáƒ‘áƒ" - privacy_policy: "კáƒáƒœáƒ¤áƒ˜áƒ“ენციáƒáƒšáƒ£áƒ áƒáƒ‘ის პáƒáƒšáƒ˜áƒ¢áƒ˜áƒ™áƒ" profile: "პრáƒáƒ¤áƒ˜áƒšáƒ˜" profiles: edit: allow_search: "მიეცეს ხáƒáƒšáƒ®áƒ¡ დიáƒáƒ¡áƒžáƒáƒ áƒáƒ¨áƒ˜ თქვენი მáƒáƒ«áƒ”ბნის სáƒáƒ¨áƒ£áƒáƒšáƒ”ბáƒ" - edit_profile: "პრáƒáƒ¤áƒ˜áƒšáƒ˜áƒ¡ რედáƒáƒ¥áƒ¢áƒ˜áƒ ებáƒ" first_name: "სáƒáƒ®áƒ”ლი" last_name: "გვáƒáƒ ი" update_profile: "პრáƒáƒ¤áƒ˜áƒšáƒ˜áƒ¡ გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ" @@ -528,8 +359,6 @@ ka: your_location: "თქვენი მდებáƒáƒ ეáƒáƒ‘áƒ" your_name: "თქვენი სáƒáƒ®áƒ”ლი" your_photo: "თქვენი ფáƒáƒ¢áƒ" - your_private_profile: "თქვენი პირáƒáƒ“ი პრáƒáƒ¤áƒ˜áƒšáƒ˜" - your_public_profile: "თქვენი სáƒáƒ¯áƒáƒ რპრáƒáƒ¤áƒ˜áƒšáƒ˜" your_tags: "áƒáƒ¦áƒ¬áƒ”რეთ თქვენი თáƒáƒ•áƒ˜ 5 სიტყვით" your_tags_placeholder: "მáƒáƒ›áƒ¬áƒáƒœáƒ¡ #ფილმები #კáƒáƒ¢áƒ”ბი #მáƒáƒ’ზáƒáƒ£áƒ áƒáƒ‘რ# მáƒáƒ¡áƒ¬áƒáƒ•áƒšáƒ”ბელი #მáƒáƒ“რიდი" update: @@ -547,61 +376,19 @@ ka: closed: "რეგისტრáƒáƒªáƒ˜áƒ დáƒáƒ®áƒ£áƒ ულირდიáƒáƒ¡áƒžáƒáƒ áƒáƒ¡ áƒáƒ› პáƒáƒ“ზე." create: success: "თქვენ შეუერთდით დიáƒáƒ¡áƒžáƒáƒ áƒáƒ¡!" - edit: - cancel_my_account: "ჩემი áƒáƒœáƒ’áƒáƒ იშის გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ" - edit: "%{name}-ს რედáƒáƒ¥áƒ¢áƒ˜áƒ ებáƒ" - leave_blank: "(დáƒáƒ¢áƒáƒ•áƒ” ცáƒáƒ იელი თუ áƒáƒ გინდრმისი შეცვლáƒ)" - password_to_confirm: "(ჩვენ თქვენი მიმდინáƒáƒ ე პáƒáƒ áƒáƒšáƒ˜ ცვილელების დáƒáƒ¡áƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებლáƒáƒ“ გვáƒáƒ˜áƒ დებáƒ)" - unhappy: "Unhappy?" - update: "გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ" new: - create_my_account: "შექმენი ჩემი áƒáƒœáƒ’áƒáƒ იში!" enter_email: "შეიყვáƒáƒœáƒ”თ ელ-ფáƒáƒ¡áƒ¢áƒ" enter_password: "შეიყვáƒáƒœáƒ”თ პáƒáƒ áƒáƒšáƒ˜ (მინიმუმ 6 სიმბáƒáƒšáƒ)" enter_password_again: "შეივყáƒáƒœáƒ”თ იგივე პáƒáƒ áƒáƒšáƒ˜ რáƒáƒª წინáƒáƒ–ე" enter_username: "áƒáƒ˜áƒ ჩიე მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლი (მხáƒáƒšáƒáƒ“ áƒáƒ¡áƒáƒ”ბი, ციფრები დრტირე)" - join_the_movement: "შეუერთდი მáƒáƒ«áƒ áƒáƒáƒ‘áƒáƒ¡!" password: "პáƒáƒ áƒáƒšáƒ˜" - sign_up_message: "სáƒáƒªáƒ˜áƒáƒšáƒ£áƒ ი ქსელი ♥-ით" username: "მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლი" - requests: - create: - sending: "იგზáƒáƒ•áƒœáƒ”ბáƒ..." - sent: "შენ ითხáƒáƒ•áƒ” %{name}-თáƒáƒœ გáƒáƒ–იáƒáƒ ებáƒ. ის ნáƒáƒ®áƒáƒ•áƒ¡ თხáƒáƒ•áƒœáƒáƒ¡ რáƒáƒ“ესáƒáƒª შევრდიáƒáƒ¡áƒžáƒáƒ áƒáƒ¨áƒ˜." - destroy: - error: "áƒáƒ˜áƒ ჩიეთ áƒáƒ¡áƒžáƒ”ქტი!" - ignore: "იგნáƒáƒ ირებული კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბის თხáƒáƒ•áƒœáƒ”ბი." - success: "áƒáƒ®áƒšáƒ áƒáƒ–იáƒáƒ ებ." - helper: - new_requests: - few: "%{count} new requests!" - many: "%{count} new requests!" - one: "new request!" - other: "%{count} new requests!" - two: "%{count} new requests!" - zero: "no new requests" - manage_aspect_contacts: - existing: "áƒáƒ სებული კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბი" - manage_within: "კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბის მáƒáƒ თვáƒ" - new_request_to_person: - sent: "გáƒáƒ’ზáƒáƒ•áƒœáƒ˜áƒáƒšáƒ˜áƒ!" reshares: comment_email_subject: "%{resharer}'s reshare of %{author} პáƒáƒ¡áƒ¢áƒ˜" - create: - failure: "მáƒáƒ®áƒ“რშეცდáƒáƒ›áƒ áƒáƒ› პáƒáƒ¡áƒ¢áƒ˜áƒ¡ თáƒáƒ•áƒ˜áƒ“áƒáƒœ გáƒáƒ–იáƒáƒ ებისáƒáƒ¡." reshare: deleted: "áƒáƒ იგინáƒáƒšáƒ˜ პáƒáƒ¡áƒ¢áƒ˜ წáƒáƒ¨áƒšáƒ˜áƒšáƒ˜áƒ áƒáƒ•áƒ¢áƒáƒ ის მიერ." - reshare: - few: "%{count} reshares" - many: "%{count} reshares" - one: "1 reshare" - other: "%{count} reshares" - two: "%{count} reshares" - zero: "Reshare" reshare_confirmation: "გსურს %{author}-ს პáƒáƒ¡áƒ¢áƒ˜áƒ¡ თáƒáƒ•áƒ˜áƒ“áƒáƒœ გáƒáƒ–იáƒáƒ ებáƒ?" - reshare_original: "áƒáƒ იგინáƒáƒšáƒ˜áƒ¡ თáƒáƒ•áƒ˜áƒ“áƒáƒœ გáƒáƒ–იáƒáƒ ებáƒ" reshared_via: "თáƒáƒ•áƒ˜áƒ“áƒáƒœ გáƒáƒ–იáƒáƒ ებáƒ" - show_original: "áƒáƒ იგინáƒáƒšáƒ˜áƒ¡ ჩვენებáƒ" search: "ძებნáƒ" services: create: @@ -612,36 +399,14 @@ ka: success: "áƒáƒ£áƒ¢áƒ”ნტიფიკáƒáƒªáƒ˜áƒ წáƒáƒ მáƒáƒ¢áƒ”ბით წáƒáƒ˜áƒ¨áƒáƒšáƒ" failure: error: "მáƒáƒ®áƒ“რშეცდáƒáƒ›áƒ áƒáƒ› სერვისთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ ებისáƒáƒ¡" - finder: - no_friends: "ვერცერთი ფეისბუქის მეგáƒáƒ‘áƒáƒ ი ვერიქნრნáƒáƒžáƒáƒ•áƒœáƒ˜" - service_friends: "%{service} მეგáƒáƒ‘რები" index: disconnect: "გáƒáƒ›áƒáƒ¡áƒ•áƒšáƒ" edit_services: "სერვისის დáƒáƒ›áƒáƒ¢áƒ”ბáƒ" logged_in_as: "შესული ხáƒáƒ რáƒáƒ’áƒáƒ ც" really_disconnect: "გáƒáƒ›áƒáƒ•áƒ˜áƒ“ე %{service} ?" - inviter: - click_link_to_accept_invitation: "მიყევით ბმულს რáƒáƒ› დáƒáƒ—áƒáƒœáƒ®áƒ›áƒ“ეთ მáƒáƒ¬áƒ•áƒ”ვáƒáƒ¡" - join_me_on_diaspora: "შემáƒáƒ›áƒ˜áƒ”რთდი დიáƒáƒ¡áƒžáƒáƒ áƒáƒ–ე*" - remote_friend: - invite: "მáƒáƒ¬áƒ•áƒ”ვáƒ" - not_on_diaspora: "ჯერáƒáƒ ხáƒáƒ თ დიáƒáƒ¡áƒžáƒáƒ áƒáƒ–ე?" - resend: "ხელáƒáƒ®áƒšáƒ გáƒáƒ’ზáƒáƒ•áƒœáƒ" settings: "პáƒáƒ áƒáƒ›áƒ”ტრები" - share_visibilites: - update: - post_hidden_and_muted: "%{name} პáƒáƒ¡áƒ¢áƒ”ბი დáƒáƒ›áƒáƒšáƒ£áƒšáƒ˜áƒ დრგáƒáƒœáƒáƒ®áƒšáƒ”ბები გáƒáƒ›áƒáƒ თული" - see_it_on_their_profile: "თუ გინდრგáƒáƒœáƒáƒ®áƒšáƒ”ბების ნáƒáƒ®áƒ•áƒ, ეწვიე %{name} გვერდს" shared: - add_contact: - add_new_contact: "დáƒáƒáƒ›áƒáƒ¢áƒ” áƒáƒ®áƒáƒšáƒ˜ კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜" - create_request: "მáƒáƒ«áƒ”ბნე დიáƒáƒ¡áƒžáƒáƒ áƒáƒ¡ სáƒáƒ®áƒ”ლით" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "შეიყვáƒáƒœáƒ”თ დიáƒáƒ¡áƒžáƒáƒ áƒáƒ¡ მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლი:" - know_email: "იცი მáƒáƒ—ი ელ-ფáƒáƒ¡áƒ¢áƒ? მáƒáƒ˜áƒ¬áƒ•áƒ˜áƒ” ისინი" - your_diaspora_username_is: "თქვენი დიáƒáƒ¡áƒžáƒáƒ áƒáƒ¡ მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლი áƒáƒ ის: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜áƒ¡ დáƒáƒ›áƒáƒ¢áƒ”ბáƒ" toggle: few: "In %{count} aspects" many: "In %{count} aspects" @@ -649,23 +414,11 @@ ka: other: "In %{count} aspects" two: "In %{count} aspects" zero: "Add contact" - contact_list: - all_contacts: "ყველრკáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜" - footer: - logged_in_as: "შემáƒáƒ¡áƒ£áƒšáƒ˜ ხáƒáƒ რáƒáƒ’áƒáƒ ც %{name}" - your_aspects: "შენი áƒáƒ¡áƒžáƒ”ქტები" invitations: by_email: "ელ-ფáƒáƒ¡áƒ¢áƒ˜áƒ—" - dont_have_now: "თქვენ áƒáƒ გáƒáƒ¥áƒ•áƒ— áƒáƒ ცერთი áƒáƒ®áƒšáƒ, მეტი მáƒáƒ¡áƒáƒ¬áƒ•áƒ”ვები იქნებრმáƒáƒšáƒ”!" - from_facebook: "ფეისბუქიდáƒáƒœ" - invitations_left: "დáƒáƒ ჩრ%{count}" - invite_someone: "მáƒáƒ˜áƒ¬áƒ•áƒ˜áƒ” ვინმე" invite_your_friends: "მáƒáƒ˜áƒ¬áƒ•áƒ˜áƒ”თ თქვენი მეგáƒáƒ‘რები" invites: "მáƒáƒ¡áƒáƒ¬áƒ•áƒ”ვები" - invites_closed: "áƒáƒ› მáƒáƒ›áƒ”ნტისთვის მáƒáƒ¬áƒ•áƒ”ვრდáƒáƒ®áƒ£áƒ ულირდიáƒáƒ¡áƒžáƒáƒ áƒáƒ¡ áƒáƒ› პáƒáƒ“ზე" share_this: "გáƒáƒáƒ–იáƒáƒ ე ეს ბმული ელ-ფáƒáƒ¡áƒ¢áƒ˜áƒ—, ბლáƒáƒ’ით áƒáƒœ სáƒáƒ§áƒ•áƒáƒ ელი სáƒáƒªáƒ˜áƒáƒšáƒ£áƒ ი ქსელით!" - notification: - new: "áƒáƒ®áƒáƒšáƒ˜ {from}%{type} from %{from}" public_explain: atom_feed: "Atom feed" control_your_audience: "áƒáƒ™áƒáƒœáƒ¢áƒ áƒáƒšáƒ” შენი áƒáƒ£áƒ“იენციáƒ" @@ -677,59 +430,27 @@ ka: title: "Set up connected services" visibility_dropdown: "გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნე ჩáƒáƒ›áƒáƒ¡áƒáƒ¨áƒšáƒ”ლი მენიუ რáƒáƒ› áƒáƒ˜áƒ ჩირვის ექნებრპáƒáƒ¡áƒ¢áƒ˜áƒ¡ ნáƒáƒ®áƒ•áƒ˜áƒ¡ სáƒáƒ¨áƒ£áƒáƒšáƒ”ბრ(ჩვენ გირჩევთ რáƒáƒ› პირველი პáƒáƒ¡áƒ¢áƒ˜ იყáƒáƒ¡ სáƒáƒ®áƒáƒšáƒ®áƒ)" publisher: - all: "ყველáƒ" - all_contacts: "ყველრკáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜" discard_post: "წáƒáƒ¨áƒáƒšáƒ” პáƒáƒ¡áƒ¢áƒ˜" - make_public: "გáƒáƒáƒ¡áƒáƒ¯áƒáƒ áƒáƒ•áƒ”" new_user_prefill: hello: "ყველáƒáƒ¡ მáƒáƒ’ესáƒáƒšáƒ›áƒ”ბით, მე ვáƒáƒ #%{new_user_tag}. " i_like: "მე მáƒáƒ˜áƒœáƒ¢áƒ”რესებს %{tags}. " invited_by: "მáƒáƒ“ლáƒáƒ‘რმáƒáƒ¬áƒ•áƒ”ვისთვის, " newhere: "áƒáƒ®áƒáƒšáƒ˜" - post_a_message_to: "დáƒáƒžáƒáƒ¡áƒ¢áƒ” შეტყáƒáƒ‘ინებáƒ%{aspect}" posting: "დáƒáƒžáƒáƒ¡áƒ¢áƒ•áƒ" share: "გáƒáƒ–იáƒáƒ ებáƒ" - share_with: "გáƒáƒáƒ–იáƒáƒ ე ვინმესთáƒáƒœ" upload_photos: "ფáƒáƒ¢áƒáƒ”ბის áƒáƒ¢áƒ•áƒ˜áƒ თვáƒ" whats_on_your_mind: "რáƒáƒ¡ ფიქრáƒáƒ‘ ?" - reshare: - reshare: "თáƒáƒ•áƒ˜áƒ“áƒáƒœ გáƒáƒ–იáƒáƒ ებáƒ" stream_element: - connect_to_comment: "დáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ დი áƒáƒ› მáƒáƒ›áƒ®áƒ›áƒáƒ ებელს რáƒáƒ› ნáƒáƒ®áƒ მისი პáƒáƒ¡áƒ¢áƒ”ბი" - currently_unavailable: "კáƒáƒ›áƒ”ნტáƒáƒ ის გáƒáƒ™áƒ”თებრáƒáƒ› მáƒáƒ›áƒ”ნტისთვის შეუძლებელიáƒ" - dislike: "áƒáƒ მáƒáƒ›áƒ¬áƒáƒœáƒ¡" - hide_and_mute: "დáƒáƒ›áƒáƒšáƒ” პáƒáƒ¡áƒ¢áƒ˜" - ignore_user: "გáƒáƒ£áƒ™áƒ”თე იგნáƒáƒ ირებრ%{name}" - ignore_user_description: "წáƒáƒ•áƒ¨áƒáƒšáƒ მáƒáƒ›áƒ®áƒ›áƒáƒ ებელი ყველრáƒáƒ¡áƒžáƒ”ქტიდáƒáƒœ?" - like: "მáƒáƒ›áƒ¬áƒáƒœáƒ¡" - nsfw: "ეს პáƒáƒ¡áƒ¢áƒ˜ მისმრáƒáƒ•áƒ¢áƒáƒ მრმáƒáƒœáƒ˜áƒ¨áƒœáƒ რáƒáƒ’áƒáƒ ც 18+. %{link}" - shared_with: "გáƒáƒ–იáƒáƒ ებულირ: %{aspect_names}" - show: "ჩვენებáƒ" - unlike: "áƒáƒ¦áƒáƒ მáƒáƒ›áƒ¬áƒáƒœáƒ¡" via: "via %{link}" - viewable_to_anyone: "áƒáƒ› პáƒáƒ¡áƒ¢áƒ˜áƒ¡ ნáƒáƒ®áƒ•áƒ შეუძლირყველáƒáƒ¡ ინტერნეტში" status_messages: create: success: "წáƒáƒ მáƒáƒ¢áƒ”ბით áƒáƒ¦áƒœáƒ˜áƒ¨áƒœáƒ”: %{names}" - helper: - no_message_to_display: "áƒáƒ áƒáƒ ის მესიჯები." new: mentioning: "Mentioning: %{person}" too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - hide_comments: "დáƒáƒ›áƒáƒšáƒ” ყველრკáƒáƒ›áƒ”ნáƒáƒ¢áƒáƒ ი" - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: aspects: title: "Your Aspects" - terms_and_conditions: "ვáƒáƒ“ები დრპირáƒáƒ‘ები" - undo: "დáƒáƒ‘რუნებáƒ?" username: "მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლი" users: destroy: @@ -743,13 +464,11 @@ ka: character_minimum_expl: "უნდრშეიცáƒáƒ•áƒ“ეს მინიმუმ ექვს სიმბáƒáƒšáƒáƒ¡" close_account: dont_go: "ჰეი, გთხáƒáƒ• áƒáƒ წáƒáƒ®áƒ•áƒ˜áƒ“ე!" - if_you_want_this: "თუ მáƒáƒ თლრგსურთ áƒáƒ›áƒ˜áƒ¡ გáƒáƒ™áƒ”თებáƒ, ჩáƒáƒ¬áƒ”რეთ თქვენი პáƒáƒ áƒáƒšáƒ˜ ქვემáƒáƒ— დრდáƒáƒáƒ¬áƒ™áƒáƒžáƒ£áƒœáƒ”თ ღილáƒáƒ™áƒ¡ \"áƒáƒœáƒ’áƒáƒ იშის დáƒáƒ®áƒ£áƒ ვáƒ\"" locked_out: "თქვენ გáƒáƒ›áƒáƒ®áƒ•áƒáƒšáƒ— დრთქვენი áƒáƒœáƒ’áƒáƒ იში დáƒáƒ˜áƒ‘ლáƒáƒ™áƒ”ბáƒ" what_we_delete: "We delete all of your posts, profile data, as soon as humanly possible. Your comments will hang around, but be associated with your Diaspora Handle." close_account_text: "áƒáƒœáƒ’áƒáƒ იშის დáƒáƒ®áƒ£áƒ ვáƒ" current_password: "მიმდინáƒáƒ ე პáƒáƒ áƒáƒšáƒ˜" current_password_expl: "რáƒáƒ›áƒšáƒ˜áƒ—áƒáƒª შემáƒáƒ“იხáƒáƒ თ..." - download_photos: "ჩემი სურáƒáƒ—ების გáƒáƒ“მáƒáƒ¬áƒ”რáƒ" edit_account: "áƒáƒœáƒ’áƒáƒ იშის რედáƒáƒ¥áƒ¢áƒ˜áƒ ებáƒ" new_password: "áƒáƒ®áƒáƒšáƒ˜ პáƒáƒ áƒáƒšáƒ˜" show_community_spotlight: "გსურთ რეკáƒáƒ›áƒ”ნდებული მáƒáƒ›áƒ®áƒ›áƒáƒ ებლების ნáƒáƒ®áƒ•áƒ ნáƒáƒ™áƒáƒ“ში?" @@ -764,5 +483,4 @@ ka: language_changed: "ენრშიეცვáƒáƒšáƒ" language_not_changed: "ენის შეცვლრვერმáƒáƒ®áƒ”რხდáƒ" password_changed: "პáƒáƒ áƒáƒšáƒ˜ შეიცვáƒáƒšáƒ. თქვენ áƒáƒ®áƒšáƒ უკვე შეგიძლიáƒáƒ— თქვენი áƒáƒ®áƒáƒšáƒ˜ პáƒáƒ áƒáƒšáƒ˜áƒ— შესვლáƒ" - unconfirmed_email_not_changed: "ელ-ფáƒáƒ¡áƒ¢áƒ˜áƒ¡ შეცვლრვერმáƒáƒ®áƒ”რხდáƒ" - welcome: "მáƒáƒ’ესáƒáƒšáƒ›áƒ”ბით!" \ No newline at end of file + unconfirmed_email_not_changed: "ელ-ფáƒáƒ¡áƒ¢áƒ˜áƒ¡ შეცვლრვერმáƒáƒ®áƒ”რხდáƒ" \ No newline at end of file diff --git a/config/locales/diaspora/kk.yml b/config/locales/diaspora/kk.yml index 7c04dd53d39efc3a0a4988b1617f88bef937cf0c..02091da7d5958a9dbcbaf6c4f7affa2ff0cac2df 100644 --- a/config/locales/diaspora/kk.yml +++ b/config/locales/diaspora/kk.yml @@ -5,17 +5,12 @@ kk: - _comments: "ТүÑініктемелер" _contacts: "БайланыÑтар" - _home: "Үйге" - _photos: "Суреттер" _services: "Қызмет атқарулар" _statistics: "СтатиÑтикаÑÑ‹" account: "ЕÑепшот" are_you_sure: "СенімдіÑіз бе?" aspects: - aspect_listings: - select_all: "Барлықты таңдап ал" edit: rename: "Ðтын өзгерту" update: "жаңала" @@ -24,18 +19,13 @@ kk: help: tag_bug: "қате" tag_question: "Ñұрақ" - new: - create: "жаÑау" seed: family: "ЖанұÑ" friends: "доÑтар" work: "жұмыÑ" - back: "Ðртқа" comments: new_comment: comment: "Ñ‚Ò¯Ñініктеме" - one: "1 Ñ‚Ò¯Ñініктеме" - zero: "Ñ‚Ò¯Ñініктемелер жоқ" conversations: new: subject: "тақырып" @@ -43,20 +33,14 @@ kk: delete: "Өшіру" invitations: new: - aspect: "ÐÑпектіÑÑ–" language: "тіл" - to: "Үшін" limited: "Шектеулі" more: "Көбірек" - next: "КелеÑÑ–" no_results: "Ðәтижелер табылмады" notifications: index: no_notifications: "Сізде әлі ешқандай хабарландыруларды жоқ." ok: "ЖÐҚСЫ" - or: "немеÑе" - password: "ҚұпиÑÑөз" - previous: "Ðлдыңғы" public: "Қоғамдық" search: "Іздеу" settings: "Құрал Ñаймандар" @@ -73,6 +57,4 @@ kk: services: "Қызмет атқарулар" total_users: "Жалпы пайдаланушылар" version: "ÐÒ±Ñқа" - terms_and_conditions: "Шарт және шарттар" - username: "Қолданушының аты" - welcome: "Қош келдіңіз!" \ No newline at end of file + username: "Қолданушының аты" \ No newline at end of file diff --git a/config/locales/diaspora/kn.yml b/config/locales/diaspora/kn.yml index ae7f35c0ed20bf396a46ebf16413f68a063a2c64..0b07609c32cb59685a2419116e20e17813d385cd 100644 --- a/config/locales/diaspora/kn.yml +++ b/config/locales/diaspora/kn.yml @@ -6,10 +6,7 @@ kn: _applications: "ಅನà³à²µà²¯à²¿à²¸à³à²µà²¿à²•à³†à²—ಳà³" - _comments: "ಪà³à²°à²¤à²¿à²•à³à²°à²¿à²¯à³†à²—ಳà³" _contacts: "ಸಂಪರà³à²•à²—ಳà³" - _home: "ಮತà³à²¤à²·à³à²Ÿà³" - _photos: "à²à²¾à²µà²šà²¿à²¤à³à²°à²—ಳà³" _services: "ಸೇವೆಗಳà³" account: "ಖಾತೆ" activerecord: @@ -33,30 +30,18 @@ kn: all_aspects: "ಎಲà³à²²à²¾ ಅಂಶಗಳà³" are_you_sure: "ನೀವೠಖಚಿತವಾಗಿರà³à²µà²¿à²°à²¾?" are_you_sure_delete_account: "ನೀವೠನಿಮà³à²® ಖಾತೆಯನà³à²¨à³ ಮà³à²šà³à²šà²²à³ ಬಯಸà³à²µà²¿à²°à²¾? ಇದನà³à²¨à³ ರದà³à²¦à³à²ªà²¡à²¿à²¸à²²à³ ಸಾಧà³à²¯à²µà²¿à²²à³à²²!" - back: "ಹಿಂದೆ" delete: "ಅಳಿಸà³" email: "ಇಮೇಲà³" fill_me_out: "ತà³à²‚ಬಿಸಿ" find_people: "ಜನರನà³à²¨à³ ಹà³à²¡à³à²•à²¿ ಅಥವಾ #ಟà³à²¯à²¾à²—à³à²—ಳà³" limited: "ಸೀಮಿತ" more: "ಮತà³à²¤à²·à³à²Ÿà³" - next: "ನಂತರ" no_results: "ಫಲಿತಾಂಶಗಳೠಪತà³à²¤à³†à²¯à²¾à²—ಿಲà³à²²" nsfw: "ಎನೠಎಸೠಎಫೠಡಬೣಯೂ" ok: "ಒಪà³à²ªà²¿à²—ೆ" - or: "ಅಥವಾ" - password: |- - - ಸಂಜà³à²žà³† - password_confirmation: "ಸಂಜà³à²žà³† ದೃಢೀಕರಣ" - previous: "ಹಿಂದಿನ" privacy: "ಖಾಸಗಿತನ" - privacy_policy: "ಗೌಪà³à²¯à²¤à²¾ ನೀತಿ" profile: "ಸà³à²µà²µà²¿à²µà²°" public: "ಲೋಕಪà³à²°à²¸à²¿à²¦à³à²§" search: "ಹà³à²¡à³à²•à³" settings: "ಸೆಟà³à²Ÿà²¿à²‚ಗà³à²—ಳà³" - terms_and_conditions: "ನಿಯಮಗಳೠಮತà³à²¤à³ ಷರತà³à²¤à³à²—ಳà³" - undo: "ಮೇಲಕà³à²•à³†" - username: "ಬಳಕೆದಾರಹೆಸರà³" - welcome: "ಸà³à²µà²¾à²—ತ" \ No newline at end of file + username: "ಬಳಕೆದಾರಹೆಸರà³" \ No newline at end of file diff --git a/config/locales/diaspora/ko.yml b/config/locales/diaspora/ko.yml index 29a1f0421c81d45c7053a0256eaa7ba3c7231247..b39326befcff1daf81fe0b01054f97688398e57f 100644 --- a/config/locales/diaspora/ko.yml +++ b/config/locales/diaspora/ko.yml @@ -6,11 +6,8 @@ ko: _applications: "ì• í”Œë¦¬ì¼€ì´ì…˜" - _comments: "댓글" _contacts: "컨íƒ" _help: "ë„움ë§" - _home: "처ìŒ" - _photos: "사진" _services: "서비스" account: "ê³„ì •" activerecord: @@ -86,13 +83,7 @@ ko: other: "ì´ë²ˆ 주 새 ì‚¬ìš©ìž ìˆ˜: %{count}" zero: "ì´ë²ˆ 주 새 ì‚¬ìš©ìž ìˆ˜: ì—†ìŒ" current_server: "현재 서버 ë‚ ì§œëŠ” %{date}입니다." - ago: "%{time} ì „" all_aspects: "ëª¨ë“ ì• ìŠ¤íŽ™" - application: - helper: - unknown_person: "ì•Œ 수 없는 사람" - video_title: - unknown: "ì•Œ 수 없는 비디오 ì œëª©" are_you_sure: "확실합니까?" are_you_sure_delete_account: "ê³„ì •ì„ ì—†ì• ë ¤ëŠ”ê²Œ 확실합니까? ëŒì´í‚¬ 수 없습니다!" aspect_memberships: @@ -106,18 +97,10 @@ ko: success: "컨íƒì„ ì• ìŠ¤íŽ™ì— ì„±ê³µì 으로 추가했습니다." aspect_listings: add_an_aspect: "+ ì• ìŠ¤íŽ™ 추가" - deselect_all: "ì„ íƒ í•´ì œ" - edit_aspect: "%{name} ê³ ì¹˜ê¸°" - select_all: "ëª¨ë‘ ì„ íƒ" aspect_stream: make_something: "ë”ê°€ 만들어보세요" stay_updated: "ìµœì‹ ìœ¼ë¡œ ìœ ì§€í•˜ê¸°" stay_updated_explanation: "ë‚´ 주 ìŠ¤íŠ¸ë¦¼ì€ ë‚´ 컨íƒ, ë‚´ê°€ 팔로우한 태그, ê·¸ë¦¬ê³ ë””ì•„ìŠ¤í¬ë¼ ì»¤ë®¤ë‹ˆí‹°ì˜ ë…ì°½ì ì¸ êµ¬ì„±ì›ë“¤ì´ ê³µìœ í•œ 게시물로 채워집니다." - contacts_not_visible: "ì´ ì• ìŠ¤íŽ™ì— ìžˆëŠ” ì‚¬ëžŒë“¤ì´ ì„œë¡œë¥¼ ë³¼ 수 없습니다." - contacts_visible: "ì´ ì• ìŠ¤íŽ™ì— ìžˆëŠ” ì‚¬ëžŒë“¤ì´ ì„œë¡œë¥¼ ë³¼ 수 있습니다." - create: - failure: "ì• ìŠ¤íŽ™ ìƒì„± 실패." - success: "ë‚˜ì˜ ìƒˆ %{name} ì• ìŠ¤íŽ™ì´ ë§Œë“¤ì–´ì¡ŒìŠµë‹ˆë‹¤" destroy: failure: "%{name} ì• ìŠ¤íŽ™ì´ ë¹„ì–´ìžˆì§€ ì•Šì•„ 지울 수 없습니다." success: "%{name} ì• ìŠ¤íŽ™ì„ ì„±ê³µì 으로 ì§€ì› ìŠµë‹ˆë‹¤." @@ -125,24 +108,15 @@ ko: aspect_list_is_not_visible: "ì• ìŠ¤íŽ™ì˜ ë‹¤ë¥¸ 사람들ì—게 ì• ìŠ¤íŽ™ 목ë¡ì„ 숨ê¹ë‹ˆë‹¤." aspect_list_is_visible: "ì• ìŠ¤íŽ™ì˜ ë‹¤ë¥¸ 사람들ì—게 ì• ìŠ¤íŽ™ 목ë¡ì„ 보입니다." confirm_remove_aspect: "ì´ ì• ìŠ¤íŽ™ì„ ì§€ìš°ë ¤ëŠ”ê²Œ 확실합니까?" - make_aspect_list_visible: "ì´ ì• ìŠ¤íŽ™ì˜ ì»¨íƒì´ 서로 ë³¼ 수 있게 í• ê¹Œìš”?" - remove_aspect: "ì´ ì• ìŠ¤íŽ™ 지우기" rename: "ì´ë¦„ 바꾸기" update: "ê°±ì‹ " updating: "ê°±ì‹ ì¤‘" index: - diaspora_id: - content_1: "ë‚´ 디아스í¬ë¼ ì•„ì´ë””:" - content_2: "ë‚´ ì•„ì´ë””를 주면 ëˆ„êµ¬ë“ ì§€ 디아스í¬ë¼ì—ì„œ ë‚ ì°¾ì„수 있습니다." - heading: "디아스í¬ë¼ ì•„ì´ë””" donate: "기부" - handle_explanation: "디아스í¬ë¼ ì•„ì´ë””는 ì´ë©”ì¼ ì£¼ì†Œì²˜ëŸ¼ 내게 ì—°ë½í•˜ê³ 싶어하는 사람들ì—게 건낼 수 있습니다." help: any_problem: "ë¬¸ì œê°€ 있나요?" contact_podmin: "ë‚´ 팟 관리ìžì—게 문ì˜í•˜ê¸°" do_you: "해시태그:" - email_feedback: "%{link}: ì´ë©”ì¼ë¡œ 보낼 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤" - email_link: "ì´ë©”ì¼" feature_suggestion: "%{link}: ì œì•ˆí•´ì£¼ì„¸ìš”!" find_a_bug: "%{link}: 버그를 ë³´ê³ í•´ì£¼ì„¸ìš”!" have_a_question: "%{link}: 물어보세요!" @@ -154,31 +128,20 @@ ko: tag_question: "질문" tutorial_link_text: "간단 설명서" introduce_yourself: "ë‚´ 스트림입니다. ìžê¸°ì†Œê°œ 어때요?" - keep_diaspora_running: "ì •ê¸° 후ì›ìœ¼ë¡œ 디아스í¬ë¼ ê°œë°œì„ ë¹ ë¥´ê²Œ ìœ ì§€í•´ì£¼ì„¸ìš”!" keep_pod_running: "%{pod} íŒŸì´ ë¹ ë¥´ê²Œ ë™ìž‘í•˜ê³ ì„œë²„ì™€ 디아스í¬ë¼ íŒ€ì´ ë§ˆì‹œëŠ” 커피를 ì‚´ 수 있ë„ë¡ ì •ê¸°í›„ì›ì„ í•´ 주세요!" new_here: follow: "%{link} 태그를 팔로우해서 디아스í¬ë¼*ì˜ ìƒˆ 사용ìžë¥¼ 맞으세요!" learn_more: "ìžì„¸ížˆ" title: "새 사용ìžë¥¼ 맞으세요" - no_contacts: "ì»¨íƒ ì—†ìŒ" - no_tags: "+ 태그를 찾아 팔로우하세요" - people_sharing_with_you: "나와 ê³µìœ í•˜ëŠ” 사람들" - post_a_message: "새 게시물 ê³µìœ >>" services: content: "다ìŒì˜ 여러 서비스를 디아스í¬ë¼ì— ì—°ê²°í• ìˆ˜ 있습니다:" heading: "서비스를 연결하세요" - unfollow_tag: "#%{tag} 태그 팔로우 멈추기" welcome_to_diaspora: "%{name}님, 디아스í¬ë¼ì— ì˜¤ì‹ ê±¸ 환ì˜í•©ë‹ˆë‹¤!" - new: - create: "만들기" - name: "ì´ë¦„(나만 ë³¼ 수 있습니다)" no_contacts_message: community_spotlight: "커뮤니티 스í¬íŠ¸ë¼ì´íŠ¸" or_spotlight: "%{link}와 ê³µìœ í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤" try_adding_some_more_contacts: "ë” ë§Žì€ ì»¨íƒì„ 찾거나 ì´ˆëŒ€í• ìˆ˜ 있습니다." you_should_add_some_more_contacts: "컨íƒì„ 좀 ë” ì¶”ê°€í•˜ì„¸ìš”!" - no_posts_message: - start_talking: "ì•„ì§ ë”ê°€ ë§í•œ ì‚¬ëžŒì´ ì—†ìŠµë‹ˆë‹¤!" seed: acquaintances: "지ì¸" family: "가족" @@ -187,7 +150,6 @@ ko: update: failure: "%{name} ì• ìŠ¤íŽ™ì€ ì´ë¦„ì´ ë„ˆë¬´ 길어 ì €ìž¥í• ìˆ˜ 없습니다." success: "%{name} ì• ìŠ¤íŽ™ì„ ì„±ê³µì 으로 ê³ ì³¤ìŠµë‹ˆë‹¤." - back: "ëŒì•„가기" blocks: create: failure: "ê·¸ 사용ìžë¥¼ ë¬´ì‹œí• ìˆ˜ 없었습니다. #evasion" @@ -198,21 +160,14 @@ ko: explanation: "ì´ ë§í¬ë¥¼ ë¶ë§ˆí¬ë¡œ 추가하면 ì–´ë””ì„œë“ ë””ì•„ìŠ¤í¬ë¼ì— ê²Œì‹œí• ìˆ˜ 있습니다 => %{link}." heading: "ë¶ë§ˆí´ë¦¿" post_something: "디아스í¬ë¼ì— 게시하기" - post_success: "ì˜¬ë ¸ìŠµë‹ˆë‹¤! 닫힙니다!" cancel: "취소" comments: new_comment: comment: "댓글 달기" commenting: "댓글 다는 중···" - one: "댓글 í•œ ê°œ" - other: "댓글 %{count}ê°œ" - zero: "댓글 ì—†ìŒ" contacts: - create: - failure: "컨íƒì„ 만들 수 없습니다" index: add_a_new_aspect: "새 ì• ìŠ¤íŽ™ 추가" - add_to_aspect: "%{name} ì• ìŠ¤íŽ™ì— ì»¨íƒ ì¶”ê°€" all_contacts: "ëª¨ë“ ì»¨íƒ" community_spotlight: "커뮤니티 스í¬íŠ¸ë¼ì´íŠ¸" my_contacts: "ë‚´ 컨íƒ" @@ -221,36 +176,20 @@ ko: only_sharing_with_me: "나와만 ê³µìœ í•˜ê³ ìžˆëŠ” 사람들" start_a_conversation: "대화를 시작하세요" title: "컨íƒ" - your_contacts: "ë‚´ 컨íƒ" - sharing: - people_sharing: "나와 ê³µìœ í•˜ëŠ” 사람들:" spotlight: community_spotlight: "커뮤니티 스í¬íŠ¸ë¼ì´íŠ¸" suggest_member: "íšŒì› ì œì•ˆ" conversations: - conversation: - participants: "참여ìž" create: fail: "ìœ íš¨í•˜ì§€ ì•Šì€ ìª½ì§€" no_contact: "컨íƒë¶€í„° 추가하세요!" sent: "쪽지를 보냈습니다" - helper: - new_messages: - few: "새 쪽지 %{count}ê°œ" - many: "새 쪽지 %{count}ê°œ" - one: "새 쪽지 í•œ ê°œ" - other: "새 쪽지 %{count}ê°œ" - two: "새 쪽지 %{count}ê°œ" - zero: "새 쪽지 ì—†ìŒ" index: conversations_inbox: "대화 - ìˆ˜ì‹ í•¨" - create_a_new_conversation: "새 대화" inbox: "쪽지함" new_conversation: "새로운 대화" - no_conversation_selected: "대화를 ê³ ë¥´ì§€ 않았습니다" no_messages: "쪽지 ì—†ìŒ" new: - abandon_changes: "ë³€ê²½ì„ í¬ê¸°í• 까요?" send: "보내기" sending: "보내는 중···" subject: "ì œëª©" @@ -269,9 +208,6 @@ ko: error_messages: helper: correct_the_following_errors_and_try_again: "ì•„ëž˜ì˜ ì—러를 ì •ì •í•œ ë’¤ 다시 ì‹œë„하ì‹ì‹œì˜¤." - invalid_fields: "ìœ íš¨í•˜ì§€ ì•Šì€ í•ëª©" - login_try_again: "<a href='%{login_link}'>로그ì¸</a> ë’¤ 다시 ì‹œë„해주세요." - post_not_public: "공개 ê²Œì‹œë¬¼ì´ ì•„ë‹™ë‹ˆë‹¤!" fill_me_out: "채워주세요" find_people: "사람ì´ë‚˜ #태그 를 찾아보세요" help: @@ -304,43 +240,26 @@ ko: tutorial: "ë”°ë¼í•˜ê¸°" tutorials: "간단 설명서" wiki: "위키" - hide: "숨기기" - invitation_codes: - excited: "%{name}ë‹˜ì´ ë‚˜ë¥¼ ê¸°ë‹¤ë¦¬ê³ ìžˆìŠµë‹ˆë‹¤." invitations: a_facebook_user: "페ì´ìŠ¤ë¶ 사욤ìž" check_token: not_found: "초대장 í† í°ì„ ì°¾ì„ ìˆ˜ 없습니다" create: - already_contacts: "ì´ ì‚¬ëžŒê³¼ ì´ë¯¸ ì—°ê²°ë˜ì–´ 있습니다" - already_sent: "ì´ë¯¸ 초대한 사람입니다." empty: "ì´ë©”ì¼ ì£¼ì†Œë¥¼ í•œ ê°œ ì´ìƒ ìž…ë ¥í•´ì£¼ì„¸ìš”." no_more: "가진 ì´ˆëŒ€ìž¥ì´ ì—†ìŠµë‹ˆë‹¤." note_already_sent: "ì´ë¯¸ %{emails} 주소로 ì´ˆëŒ€ìž¥ì„ ë³´ëƒˆìŠµë‹ˆë‹¤." - own_address: "ë‚´ ì´ë©”ì¼ ì£¼ì†Œë¡œ ì´ˆëŒ€ìž¥ì„ ë³´ë‚¼ 수 없습니다." rejected: "ì•„ëž˜ì˜ ì´ë©”ì¼ ì£¼ì†ŒëŠ” ë¬¸ì œê°€ 있습니다: " sent: "ì´ˆëŒ€ìž¥ì„ %{emails} 주소로 보냈습니다." - edit: - accept_your_invitation: "초대 승ë½í•˜ê¸°" - your_account_awaits: "ë‚´ ê³„ì •ì´ ê¸°ë‹¤ë¦¬ê³ ìžˆìŠµë‹ˆë‹¤!" new: - already_invited: "ë‚´ 초대를 수ë½í•˜ì§€ ì•Šì€ ì‚¬ëžŒë“¤:" - aspect: "ì• ìŠ¤íŽ™" - check_out_diaspora: "디아스í¬ë¼ë¥¼ ì¨ë³´ì„¸ìš”!" codes_left: other: "ì´ ì½”ë“œì— ì´ˆëŒ€ìž¥ %{count}ê°œ 남았습니다" zero: "ì´ ì½”ë“œì— ë‚¨ì€ ì´ˆëŒ€ìž¥ì´ ì—†ìŠµë‹ˆë‹¤" comma_separated_plz: "쉼표로 구분하여 여러 ì´ë©”ì¼ ì£¼ì†Œë¥¼ ë„£ì„ ìˆ˜ 있습니다." - if_they_accept_info: "수ë½í•œ 친구는 ì´ˆëŒ€í–ˆë˜ ì• ìŠ¤íŽ™ì— ì¶”ê°€ë©ë‹ˆë‹¤." invite_someone_to_join: "다ì´ìŠ¤í¬ë¼ì— 친구를 초대하세요!" language: "언어" paste_link: "ì´ ë§í¬ë¥¼ 친구들ì—게 ê³µìœ í•´ì„œ 디아스í¬ë¼*ë¡œ 초대하거나, ì´ë©”ì¼ë¡œ ì§ì ‘ 보내세요." - personal_message: "쪽지" - resend: "다시 보내기" send_an_invitation: "초대장 보내기" - send_invitation: "초대장 보내기" sending_invitation: "초대장 ì „ì†¡ì¤‘" - to: "받는ì´" layouts: application: back_to_top: "맨 위로 ëŒì•„가기" @@ -349,32 +268,13 @@ ko: source_package: "소스코드 패키지 다운로드" toggle: "모바ì¼" whats_new: "새로운 ì " - your_aspects: "ë‚´ ì• ìŠ¤íŽ™" header: - admin: "관리ìž" - blog: "블로그" code: "코드" - help: "ë„움" - login: "로그ì¸" logout: "로그아웃" profile: "프로필" - recent_notifications: "최근 알림" settings: "ì„¤ì •" - view_all: "ëª¨ë‘ ë³´ê¸°" - likes: - likes: - people_dislike_this: - other: "%{count}ëª…ì´ ì‹«ì–´í•©ë‹ˆë‹¤" - zero: "ì‹«ì–´ìš” ì—†ìŒ" - people_like_this: - other: "%{count}ëª…ì´ ì¢‹ì•„í•©ë‹ˆë‹¤" - zero: "좋아요 ì—†ìŒ" - people_like_this_comment: - other: "%{count}ëª…ì´ ì¢‹ì•„í•©ë‹ˆë‹¤" - zero: "좋아요 ì—†ìŒ" limited: "ì œí•œë¨" more: "ë”" - next: "다ìŒ" no_results: "ê²°ê³¼ ì—†ìŒ" notifications: also_commented: @@ -386,14 +286,6 @@ ko: comment_on_post: other: "%{actors}ë‹˜ì´ ë‚´ %{post_link}ì— ëŒ“ê¸€ì„ ë‹¬ì•˜ìŠµë‹ˆë‹¤." zero: "%{actors}ë‹˜ì´ ë‚´ %{post_link}ì— ëŒ“ê¸€ì„ ë‹¬ì•˜ìŠµë‹ˆë‹¤." - helper: - new_notifications: - few: "새 알림 %{count}ê°œ" - many: "새 알림 %{count}ê°œ" - one: "새 알림 í•œ ê°œ" - other: "새 알림 %{count}ê°œ" - two: "새 알림 %{count}ê°œ" - zero: "새 알림 ì—†ìŒ" index: and: "ê·¸ë¦¬ê³ " and_others: @@ -455,7 +347,6 @@ ko: zero: "%{actors}ë‹˜ì´ ë‚˜ì™€ ê³µìœ ë¥¼ 시작했습니다." notifier: a_post_you_shared: "게시물" - accept_invite: "디아스í¬ë¼* 초대를 수ë½í•˜ì„¸ìš”!" click_here: "여기를 í´ë¦" comment_on_post: reply: "%{name}ë‹˜ì˜ ê²Œì‹œë¬¼ì— ëŒ“ê¸€ 달기 >" @@ -484,7 +375,6 @@ ko: liked: "%{name}ë‹˜ì´ ë‚´ ê²Œì‹œë¬¼ì„ ì¢‹ì•„í•©ë‹ˆë‹¤:" view_post: "게시물 보기 >" mentioned: - mentioned: "ë‹˜ì´ ê²Œì‹œë¬¼ì—ì„œ 나를 멘션했습니다:" subject: "%{name}ë‹˜ì´ ë””ì•„ìŠ¤í¬ë¼*ì—ì„œ 나를 멘션했습니다" private_message: reply_to_or_view: "ì´ ìª½ì§€ 답장 ë˜ëŠ” 보기 >" @@ -505,104 +395,45 @@ ko: to_change_your_notification_settings: "하세요" nsfw: "ìœ í•´ë§¤ì²´" ok: "확ì¸" - or: "ë˜ëŠ”" - password: "암호" - password_confirmation: "암호 확ì¸" people: add_contact: invited_by: "나를 초대한 사람:" - add_contact_small: - add_contact_from_tag: "태그ì—ì„œ ì»¨íƒ ì¶”ê°€" - aspect_list: - edit_membership: "ì†í•œ ì• ìŠ¤íŽ™ ê³ ì¹˜ê¸°" - helper: - results_for: "%{params} ê²°ê³¼" index: looking_for: "%{tag_link} 태그가 달린 ê²Œì‹œë¬¼ì„ ì°¾ê³ ìžˆë‚˜ìš”?" no_one_found: "검색 결과가 없습니다" no_results: "검색 결과가 없습니다" results_for: "검색 ê²°ê³¼:" searching: "검색중입니다, ìž ì‹œë§Œ ê¸°ë‹¤ë ¤ì£¼ì‹ì‹œì˜¤Â·Â·Â·" - one: "í•œ 명" - other: "%{count}명" person: - add_contact: "ì»¨íƒ ì¶”ê°€" - already_connected: "ì´ë¯¸ ì—°ê²°ë˜ì—ˆìŠµë‹ˆë‹¤" - pending_request: "ì´ë¯¸ ìš”ì²í–ˆìŠµë‹ˆë‹¤" thats_you: "바로 나!" profile_sidebar: bio: "ìžê¸°ì†Œê°œ" born: "ìƒë…„ì›”ì¼" - edit_my_profile: "프로필 ê³ ì¹˜ê¸°" gender: "성별" - in_aspects: "ì†í•œ ì• ìŠ¤íŽ™:" location: "위치" - photos: "사진" - remove_contact: "ì»¨íƒ ì§€ìš°ê¸°" - remove_from: "%{aspect}ì—ì„œ %{name}ë‹˜ì„ ì§€ìš¸ê¹Œìš”?" show: closed_account: "없어진 ê³„ì •ìž…ë‹ˆë‹¤." does_not_exist: "없는 사람입니다!" has_not_shared_with_you_yet: "%{name}ë‹˜ì€ ì•„ì§ ë‚˜ì™€ ì•„ë¬´ê²ƒë„ ê³µìœ í•˜ì§€ 않았습니다!" - ignoring: "%{name}ë‹˜ì˜ ëª¨ë“ ê²Œì‹œë¬¼ì„ ë¬´ì‹œí•˜ê³ ìžˆìŠµë‹ˆë‹¤." - incoming_request: "%{name}ë‹˜ì´ ë‚˜ì™€ ê³µìœ í•˜ê¸¸ ì›í•©ë‹ˆë‹¤" - mention: "멘션" - message: "쪽지" - not_connected: "ì—´ê²°ë˜ì§€ ì•Šì€ ì‚¬ëžŒìž…ë‹ˆë‹¤" - recent_posts: "최근 게시물" - recent_public_posts: "최근 공개 게시물" - return_to_aspects: "ì• ìŠ¤íŽ™ 페ì´ì§€ë¡œ ëŒì•„ê°€" - see_all: "ëª¨ë‘ ë³´ê¸°" - start_sharing: "ê³µìœ ì‹œìž‘" - to_accept_or_ignore: "ìˆ˜ë½ ë˜ëŠ” 무시하기." - sub_header: - add_some: "추가하기" - edit: "ê³ ì¹˜ê¸°" - you_have_no_tags: "태그가 없습니다!" - webfinger: - fail: "%{handle} í•¸ë“¤ì„ ì°¾ì„ ìˆ˜ 없습니다." - zero: "ì—†ìŒ" photos: - comment_email_subject: "%{name}ë‹˜ì˜ ì‚¬ì§„" create: integrity_error: "사진 ì—…ë¡œë“œí• ìˆ˜ 없습니다. ì´ë¯¸ì§€ê°€ 맞습니까?" runtime_error: "ì‚¬ì§„ì„ ì—…ë¡œë“œí• ìˆ˜ 없습니다. ì•ˆì „ë²¨íŠ¸ë¥¼ 확ì¸í•˜ì…¨ìŠµë‹ˆê¹Œ?" type_error: "사진 업로드 실패. ì´ë¯¸ì§€ë¥¼ 추가하지 않았습니다." destroy: notice: "ì‚¬ì§„ì„ ì§€ì› ìŠµë‹ˆë‹¤." - edit: - editing: "ê³ ì¹˜ëŠ” 중" - new: - back_to_list: "목ë¡ìœ¼ë¡œ ëŒì•„가기" - new_photo: "새 사진" - post_it: "올리기!" new_photo: empty: "{file} 파ì¼ì€ 빈 파ì¼ìž…니다. ì´ íŒŒì¼ë§Œ ë¹¼ê³ ë‹¤ì‹œ ì‹œë„하세요." invalid_ext: "{file} 파ì¼ì€ ìœ íš¨í•˜ì§€ ì•Šì€ í˜•ì‹ìž…니다. {extensions} 형ì‹ì˜ 파ì¼ì„ ì˜¬ë ¤ì£¼ì„¸ìš”." size_error: "{file} 파ì¼ì´ {sizeLimit} 보다 í½ë‹ˆë‹¤" new_profile_photo: - or_select_one_existing: "ì´ë¯¸ ì˜¬ë ¤ë‘” 사진 ê°€ìš´ë° ê³ ë¥¼ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤ %{photos}" upload: "새 프로필 사진 업로드하기!" - photo: - view_all: "%{name}ë‹˜ì˜ ëª¨ë“ ì‚¬ì§„ 보기" show: - collection_permalink: "사진집 ì˜êµ¬ì£¼ì†Œ" - delete_photo: "사진 지우기" - edit: "ê³ ì¹˜ê¸°" - edit_delete_photo: "사진 설명 ê³ ì¹˜ê¸° / 사진 지우기" - make_profile_photo: "프로필 사진 만들기" show_original_post: "ì›ëž˜ 게시물 보기" - update_photo: "사진 ì—…ë°ì´íŠ¸" - update: - error: "사진 ê³ ì¹˜ê¸° 실패." - notice: "ì‚¬ì§„ì„ ì„±ê³µì 으로 ì—…ë°ì´íŠ¸í–ˆìŠµë‹ˆë‹¤." posts: presenter: title: "%{name}ë‹˜ì˜ ê²Œì‹œë¬¼" show: - destroy: "지우기" - not_found: "해당 ê²Œì‹œë¬¼ì„ ì°¾ì„ ìˆ˜ 없습니다." - permalink: "ì˜êµ¬ ë§í¬" photos_by: few: "%{author}ë‹˜ì˜ ì‚¬ì§„ %{count}장" many: "%{author}ë‹˜ì˜ ì‚¬ì§„ %{count}장" @@ -611,14 +442,11 @@ ko: two: "%{author}ë‹˜ì˜ ì‚¬ì§„ ë‘ ìž¥" zero: "%{author}ë‹˜ì˜ ì‚¬ì§„ ì—†ìŒ" reshare_by: "%{author}ë‹˜ì´ ìž¬ê³µìœ " - previous: "ì´ì „" privacy: "ê°œì¸ì •ë³´ë³´í˜¸" - privacy_policy: "ê°œì¸ì •ë³´ë³´í˜¸ì •ì±…" profile: "프로필" profiles: edit: allow_search: "디아스í¬ë¼ì—ì„œ ì‚¬ëžŒë“¤ì´ ë‚˜ë¥¼ ê²€ìƒ‰í• ìˆ˜ 있ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤" - edit_profile: "프로필 ìˆ˜ì •" first_name: "ì´ë¦„" last_name: "성" update_profile: "프로필 ì—…ë°ì´íŠ¸" @@ -628,8 +456,6 @@ ko: your_location: "위치" your_name: "ì´ë¦„" your_photo: "ë‚´ 사진" - your_private_profile: "ê°œì¸ í”„ë¡œí•„" - your_public_profile: "공개 프로필" your_tags: "ë‚±ë§ 5개로 나를 표현하세요" your_tags_placeholder: "예) #movies #kittens #travel #teacher #newyork" update: @@ -647,70 +473,28 @@ ko: closed: "우리 디아스í¬ë¼ íŒ“ì€ ê°€ìž…ì´ ë‹«í˜€ìžˆìŠµë‹ˆë‹¤." create: success: "디아스í¬ë¼ì— 가입ë˜ì—ˆìŠµë‹ˆë‹¤!" - edit: - cancel_my_account: "취소" - edit: "%{name} ê³ ì¹˜ê¸°" - leave_blank: "(바꾸지 ì•Šìœ¼ë ¤ë©´ 비워ë‘세요)" - password_to_confirm: "(암호를 ë°”ê¾¸ë ¤ë©´ ì›ëž˜ 암호가 필요합니다)" - unhappy: "무슨 ë¬¸ì œë¼ë„?" - update: "ê°±ì‹ í•˜ê¸°" invalid_invite: "ë‚´ê°€ ì œê³µí•œ 초대 ë§í¬ê°€ ë” ì´ìƒ ìœ íš¨í•˜ì§€ 않습니다!" new: - create_my_account: "ë‚´ ê³„ì • 만들기!" email: "ì´ë©”ì¼" enter_email: "ì´ë©”ì¼ ì£¼ì†Œë¥¼ ìž…ë ¥í•˜ì„¸ìš”" enter_password: "암호를 ìž…ë ¥í•˜ì„¸ìš” (최소 여섯 ìž)" enter_password_again: "암호를 다시 ìž…ë ¥í•˜ì„¸ìš”" enter_username: "ì‚¬ìš©ìž ì´ë¦„ì„ ê³ ë¥´ì„¸ìš” (로마ìž, ì•„ë¼ë¹„ì•„ 숫ìž, 밑줄 문ìž_ 만)" - join_the_movement: "합류하세요!" password: "암호" password_confirmation: "암호 확ì¸" sign_up: "가입" - sign_up_message: "소셜 네트워í¬â™¡" username: "ì‚¬ìš©ìž ì´ë¦„" report: delete_link: "í•ëª© ì‚ì œ" status: failed: "오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤" title: "ë³´ê³ ì„œ 개요" - requests: - create: - sending: "ê³µìœ ë¥¼ ìš”ì²í•˜ê³ 있습니다." - sent: "%{name}님ì—게 ê³µìœ ë¥¼ ìš”ì²í–ˆìŠµë‹ˆë‹¤. ìƒëŒ€ë°©ì´ 디아스í¬ë¼ì— 로그ì¸í•˜ë©´ ë³¼ê²ë‹ˆë‹¤." - destroy: - error: "ì• ìŠ¤íŽ™ì„ ê³¨ë¼ì£¼ì„¸ìš”!" - ignore: "ì»¨íƒ ìš”ì²ì´ 무시ë˜ì—ˆìŠµë‹ˆë‹¤." - success: "ê³µìœ í•˜ê³ ìžˆìŠµë‹ˆë‹¤." - helper: - new_requests: - few: "ìš”ì²ì´ %{count}ê°œ 들어왔습니다!" - many: "ìš”ì²ì´ %{count}ê°œ 들어왔습니다!" - one: "ìš”ì²ì´ í•œ ê°œ 들어왔습니다!" - other: "ìš”ì²ì´ %{count}ê°œ 들어왔습니다!" - two: "새 ìš”ì²ì´ %{count}ê°œ 있습니다!" - zero: "ìš”ì² ì—†ìŒ" - manage_aspect_contacts: - existing: "기존 컨íƒ" - manage_within: "ì»¨íƒ ê´€ë¦¬í•˜ê¸°:" - new_request_to_person: - sent: "보냈습니다." reshares: comment_email_subject: "%{resharer}ë‹˜ì´ ìž¬ê³µìœ í•œ %{author}ë‹˜ì˜ ê²Œì‹œë¬¼" - create: - failure: "ì´ ê²Œì‹œë¬¼ì„ ìž¬ê³µìœ í•˜ëŠ”ë° ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤." reshare: deleted: "ì›ëž˜ ê²Œì‹œë¬¼ì´ ì§€ì›Œì¡ŒìŠµë‹ˆë‹¤." - reshare: - few: "ìž¬ê³µìœ %{count}번" - many: "ìž¬ê³µìœ %{count}번" - one: "ìž¬ê³µìœ í•œ 번" - other: "ìž¬ê³µìœ %{count}번" - two: "ìž¬ê³µìœ %{count}ê°œ" - zero: "ìž¬ê³µìœ " reshare_confirmation: "%{author}ë‹˜ì˜ %{text} ê²Œì‹œë¬¼ì„ ìž¬ê³µìœ í•˜ì‹œê² ìŠµë‹ˆê¹Œ?" - reshare_original: "ì›ë³¸ ìž¬ê³µìœ " reshared_via: "ìž¬ê³µìœ via" - show_original: "ì›ë³¸ 보기" search: "검색" services: create: @@ -721,58 +505,23 @@ ko: success: "ì¸ì¦ì„ 성공ì 으로 ì§€ì› ìŠµë‹ˆë‹¤." failure: error: "서비스 연결중 ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤." - finder: - fetching_contacts: "디아스í¬ë¼ê°€ %{service} ì¹œêµ¬ë“¤ì„ ì±„ìš°ê³ ìžˆìŠµë‹ˆë‹¤. 몇 분 ë’¤ì— ë‹¤ì‹œ 확ì¸í•´ì£¼ì„¸ìš”." - no_friends: "페ì´ìŠ¤ë¶ 친구를 ì°¾ì„ ìˆ˜ 없습니다." - service_friends: "%{service} 친구" index: disconnect: "ëŠê¸°" edit_services: "서비스 ì„¤ì •" logged_in_as: "ë¡œê·¸ì¸ ì¤‘: " really_disconnect: "%{service} 서비스를 ëŠìœ¼ì‹œê² 습니까?" services_explanation: "서비스 ì—°ê²°ë¡œ 디아스í¬ë¼ì— ë‚´ ê²Œì‹œë¬¼ì„ ë‚¨ê¸°ë©´ì„œ 해당 서비스ì—ë„ ê°™ì´ ê²Œì‹œí• ìˆ˜ 있습니다." - inviter: - click_link_to_accept_invitation: "초대를 수ë½í•˜ë ¤ë©´ ì´ ë§í¬ë¥¼ ë”°ë¼ê°€ì„¸ìš”" - join_me_on_diaspora: "디아스í¬ë¼*ì—ì„œ 만나요!" - remote_friend: - invite: "초대하기" - not_on_diaspora: "ì•„ì§ ë””ì•„ìŠ¤í¬ë¼ì— 없습니다" - resend: "다시 보내기" settings: "ì„¤ì •" - share_visibilites: - update: - post_hidden_and_muted: "%{name}ë‹˜ì˜ ê²Œì‹œë¬¼ì´ ê°ì¶°ì¡ŒìŠµë‹ˆë‹¤. 앞으로 ì•Œë¦¼ì´ ë˜ì§€ 않습니다." - see_it_on_their_profile: "%{name}ë‹˜ì˜ í”„ë¡œí•„ 페ì´ì§€ë¥¼ 방문하면 ì´ ê²Œì‹œë¬¼ì˜ ìµœì‹ ìƒíƒœë¥¼ ë³¼ 수 있습니다." shared: - add_contact: - add_new_contact: "새 ì»¨íƒ ì¶”ê°€" - create_request: "디아스í¬ë¼ ì•„ì´ë””ë¡œ 찾기" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "디아스í¬ë¼ ì‚¬ìš©ìž ì´ë¦„ì„ ìž…ë ¥í•˜ì„¸ìš”:" - know_email: "ì´ë©”ì¼ ì£¼ì†Œë¥¼ 알면 ì´ˆëŒ€í• ìˆ˜ 있습니다!" - your_diaspora_username_is: "ë‚´ 디아스í¬ë¼ ì‚¬ìš©ìž ì´ë¦„: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "ì»¨íƒ ì¶”ê°€" toggle: other: "ì• ìŠ¤íŽ™ %{count}ê°œ" zero: "ì»¨íƒ ì¶”ê°€" - contact_list: - all_contacts: "ëª¨ë“ ì»¨íƒ" - footer: - logged_in_as: "%{name}ë¡œ 로그ì¸ì¤‘" - your_aspects: "ë‚´ ì• ìŠ¤íŽ™" invitations: by_email: "ì´ë©”ì¼ ì´ˆëŒ€" - dont_have_now: "ì§€ê¸ˆì€ ì´ˆëŒ€í• ìˆ˜ 없습니다." - from_facebook: "페ì´ìŠ¤ë¶ì—ì„œ 찾기" - invitations_left: "%{count}통 남ìŒ" - invite_someone: "초대하기" invite_your_friends: "ì¹œêµ¬ë“¤ì„ ì´ˆëŒ€í•˜ì„¸ìš”" invites: "초대" - invites_closed: "ì´ ë””ì•„ìŠ¤í¬ë¼ëŠ” 초대가 닫혀있습니다." share_this: "ì´ ë§í¬ë¥¼ ì´ë©”ì¼, 블로그, ë˜ëŠ” ì¦ê²¨ì“°ëŠ” 소셜 네트워í¬ë¥¼ 통해 ê³µìœ í•˜ì„¸ìš”" - notification: - new: "%{from}ë‹˜ì˜ ìƒˆ %{type}" public_explain: atom_feed: "Atom 구ë…" control_your_audience: "ë³´ì¼ ì‚¬ëžŒ ì œì–´í•˜ê¸°" @@ -784,11 +533,8 @@ ko: title: "서비스 ì„¤ì •" visibility_dropdown: "ì´ ë“œë¡ë‹¤ìš´ 메뉴로 ê²Œì‹œë¬¼ì´ ëˆ„êµ¬ì—게 ë³´ì¼ì§€ 바꿉니다. (첫 ê²Œì‹œë¬¼ì€ ê³µê°œë¡œ í• ê²ƒì„ ê¶Œí•©ë‹ˆë‹¤.)" publisher: - all: "모ë‘" - all_contacts: "ëª¨ë“ ì»¨íƒ" discard_post: "게시물 ì‚ì œ" get_location: "위치 ê°€ì ¸ì˜¤ê¸°" - make_public: "공개하기" new_user_prefill: hello: "반갑습니다! #%{new_user_tag} 했습니다." i_like: "ì œ 관심사는 %{tags} 입니다." @@ -796,53 +542,20 @@ ko: newhere: "새로가입" poll: add_a_poll: "설문 추가" - add_poll_answer: "ì„ íƒ ì‚¬í• ì¶”ê°€" - question: "질문" - post_a_message_to: "%{aspect} ì• ìŠ¤íŽ™ì— ë©”ì‹œì§€ 게시하기" posting: "올리는 중···" - preview: "미리보기" - publishing_to: "올릴 ê³³: " remove_location: "위치 ì‚ì œ" share: "ê³µìœ " - share_with: "ê³µìœ í•˜ê¸°: " upload_photos: "사진 올리기" whats_on_your_mind: "무슨 ìƒê°í•´ìš”?" - reshare: - reshare: "ìž¬ê³µìœ " stream_element: - connect_to_comment: "ì´ ì‚¬ìš©ìžì˜ ê²Œì‹œë¬¼ì— ëŒ“ê¸€ì„ ë‹¬ê³ ì‹¶ë‹¤ë©´ 컨íƒìœ¼ë¡œ 추가하세요" - currently_unavailable: "ì§€ê¸ˆì€ ëŒ“ê¸€ì„ ë‹¬ 수 없습니다" - dislike: "싪어요" - hide_and_mute: "ê²Œì‹œë¬¼ì„ ìˆ¨ê¸°ê³ ì•Œë¦¼ ë„기" - ignore_user: "%{name}님 무시하기" - ignore_user_description: "ì´ ì‚¬ìš©ìžë¥¼ 무시한 ë’¤ ëª¨ë“ ì• ìŠ¤íŽ™ì—ì„œ ì§€ìš°ì‹œê² ìŠµë‹ˆê¹Œ?" - like: "좋아요" - nsfw: "ì´ ê²Œì‹œë¬¼ì€ ê²Œì‹œì¸ì´ ìœ í•´ë§¤ì²´ë¡œ ì§€ì •í–ˆìŠµë‹ˆë‹¤. %{link}" - shared_with: "ê³µìœ ëœ ì• ìŠ¤íŽ™: %{aspect_names}" - show: "보기" - unlike: "좋아요 취소" via: "%{link}ì—ì„œ" via_mobile: "via 모바ì¼" - viewable_to_anyone: "ì´ ê²Œì‹œë¬¼ì€ ì›¹ì˜ ëˆ„êµ¬ë“ ì§€ ë³¼ 수 있습니다" status_messages: create: success: "%{names}ë‹˜ì„ ì„±ê³µì 으로 멘션했습니다." - destroy: - failure: "ê²Œì‹œë¬¼ì„ ì§€ìš¸ 수 없습니다." - helper: - no_message_to_display: "í‘œì‹œí• ê²Œì‹œë¬¼ì´ ì—†ìŠµë‹ˆë‹¤." new: mentioning: "%{person}ë‹˜ì„ ë©˜ì…˜í•©ë‹ˆë‹¤" too_long: "{\"other\"=>\"ìƒíƒœ 메시지를 %{count}ìžë³´ë‹¤ ì 게 줄여주세요\", \"zero\"=>\"ìƒíƒœ 메시지를 %{count}ìžë³´ë‹¤ ì 게 줄여주세요\"}" - stream_helper: - hide_comments: "ëª¨ë“ ëŒ“ê¸€ 숨기기" - show_comments: - few: "댓글 %{count}ê°œ ë” ë³´ê¸°" - many: "댓글 %{count}ê°œ ë” ë³´ê¸°" - one: "댓글 í•œ ê°œ ë” ë³´ê¸°" - other: "댓글 %{count}ê°œ ë” ë³´ê¸°" - two: "댓글 ë‘ ê°œ ë” ë³´ê¸°" - zero: "ëŒ“ê¸€ì´ ë” ì—†ìŠµë‹ˆë‹¤" streams: activity: title: "ë‚´ 활ë™" @@ -868,22 +581,11 @@ ko: title: "공개 활ë™" tags: title: "태그: %{tags}" - tag_followings: - create: - failure: "#%{name}님 팔로우를 실패하였습니다. ì´ë¯¸ íŒ”ë¡œìš°í•˜ê³ ìžˆìŠµë‹ˆê¹Œ?" - none: "빈 태그는 íŒ”ë¡œìš°í• ìˆ˜ 없습니다!" - success: "만세! ì´ì œ #%{name} 태그를 팔로우합니다." - destroy: - failure: "#%{name}님 팔로우 멈추기를 실패하였습니다. ì´ë¯¸ 팔로우를 ë©ˆì·„ì„ ìˆ˜ 있습니다." - success: "아아···. ë” ì´ìƒ #%{name}ë‹˜ì„ íŒ”ë¡œìš°í•˜ì§€ 않습니다." tags: show: follow: "#%{tag} 태그 팔로우하기" - following: "#%{tag} 태그 팔로우중" none: "빈 태그는 존재하지 않습니다!" stop_following: "#%{tag} 태그 팔로우 멈추기" - terms_and_conditions: "ì´ìš©ì•½ê´€" - undo: "ëŒì´í‚¤ê² 습니까?" username: "ì‚¬ìš©ìž ì´ë¦„" users: confirm_email: @@ -904,7 +606,6 @@ ko: character_minimum_expl: "6ìž ì´ìƒ" close_account: dont_go: "ì œë°œ 가지 마세요!" - if_you_want_this: "ì •ë§ë¡œ ì—†ì• ê³ ì‹¶ë‹¤ë©´ 암호를 ìž…ë ¥í•œ ë’¤ ì•„ëž˜ì˜ 'ê³„ì • ì—†ì• ê¸°'를 í´ë¦í•˜ì„¸ìš”." lock_username: "다시 ê°€ìž…í• ë•Œë¥¼ 위해 ì‚¬ìš©ìž ì´ë¦„ì„ ìž ê¸‰ë‹ˆë‹¤." locked_out: "로그아웃 ëœ ë’¤ ë‚´ ê³„ì •ì´ ìž ê¹ë‹ˆë‹¤." make_diaspora_better: "ë– ë‚˜ëŠ” 것 ëŒ€ì‹ ë” ë‚˜ì€ ë””ì•„ìŠ¤í¬ë¼ë¥¼ 만들 수 있ë„ë¡ ë„와주ì‹ì‹œì˜¤. ë– ë‚˜ê³ ì‹¶ë‹¤ë©´, 다ìŒì— 무슨 ì¼ì´ ì¼ì–´ë‚˜ëŠ”지 ì•Œë ¤ë“œë¦¬ê² ìŠµë‹ˆë‹¤." @@ -915,12 +616,10 @@ ko: comment_on_post: "ë‚´ ê²Œì‹œë¬¼ì— ëŒ“ê¸€ì´ ë‹¬ë ¸ì„ ë•Œ" current_password: "ì›ëž˜ 암호" current_password_expl: "로그ì¸í• ë•Œ ì¼ë˜ 암호" - download_photos: "ë‚´ 사진 다운로드" edit_account: "ê³„ì • ê³ ì¹˜ê¸°" email_awaiting_confirmation: "%{unconfirmed_email} ë¡œ 활성화 ë§í¬ë¥¼ 보냈습니다. ì´ ë§í¬ë¥¼ ë”°ë¼ ìƒˆ 주소를 활성화하기 ì „ê¹Œì§€ëŠ” ì›ëž˜ ì´ë©”ì¼ ì£¼ì†Œ %{email} 를 사용합니다." export_data: "ìžë£Œ 뽑아내기" following: "팔로우 ì„¤ì •" - getting_started: "새 ì‚¬ìš©ìž í™˜ê²½ ì„¤ì •" liked: "누군가가 ë‚´ ê²Œì‹œë¬¼ì„ ì¢‹ì•„í• ë•Œ" mentioned: "ë‚´ê°€ 멘션ë˜ì—ˆì„ ë•Œ" new_password: "새 암호" @@ -940,7 +639,6 @@ ko: connect_to_facebook_link: "페ì´ìŠ¤ë¶ ê³„ì •ì„ ì—°ê²°í•˜ë©´" hashtag_explanation: "해시태그로 ë‚´ ê´€ì‹¬ì‚¬ì— ëŒ€í•´ ë§í•˜ê±°ë‚˜ íŒ”ë¡œìš°í• ìˆ˜ 있습니다. 디아스í¬ë¼ì—ì„œ 새로운 ì‚¬ëžŒë“¤ì„ ì°¾ì„ ìˆ˜ 있는 ë˜ í•˜ë‚˜ì˜ í›Œë¥í•œ 방법입니다." hashtag_suggestions: "#art, #movies, #gif ê°™ì€ íƒœê·¸ë¥¼ 팔로우해보세요." - saved: "ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤!" well_hello_there: "ìž, 어서오ì‹ì‹œì˜¤!" what_are_you_in_to: "ë˜ ì¢‹ì•„í•´ìš”?" who_are_you: "ëˆ„êµ¬ì‹œì£ ?" @@ -962,13 +660,6 @@ ko: settings_updated: "ì„¤ì •ì„ ê³ ì³¤ìŠµë‹ˆë‹¤" unconfirmed_email_changed: "ì´ë©”ì¼ì„ ê³ ì³¤ìŠµë‹ˆë‹¤. 활성화가 필요합니다." unconfirmed_email_not_changed: "ì´ë©”ì¼ ê³ ì¹˜ê¸° 실패" - webfinger: - fetch_failed: "%{profile_url} 웹핑거 프로필 ì—°ë™ì— 실패했습니다." - hcard_fetch_failed: "%{account}ì˜ hcard ì—°ë™ì— ë¬¸ì œê°€ 있습니다." - no_person_constructed: "ì´ hcard로부터 ì•„ë¬´ë„ ë§Œë“¤ì–´ì§€ì§€ 않았습니다." - not_enabled: "웹핑거가 %{account}ì˜ í˜¸ìŠ¤íŠ¸ì—ì„œ 활성화 ëœ ê²ƒ 같지 않습니다." - xrd_fetch_failed: "%{account} ê³„ì •ìœ¼ë¡œë¶€í„° xrd를 ê°€ì ¸ì˜¤ëŠ” ê²ƒì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤." - welcome: "환ì˜í•©ë‹ˆë‹¤!" will_paginate: next_label: "ë‹¤ìŒ »" previous_label: "« ì´ì „" \ No newline at end of file diff --git a/config/locales/diaspora/lt.yml b/config/locales/diaspora/lt.yml index 413d0ea3eb3fd2dd7848fd97d30663aa611e932c..8d56031ce02c1091c51654d05aa53b6ef27ba128 100644 --- a/config/locales/diaspora/lt.yml +++ b/config/locales/diaspora/lt.yml @@ -6,10 +6,7 @@ lt: _applications: "Programos" - _comments: "Komentarai" _contacts: "Kontaktai" - _home: "Pradžia" - _photos: "Nuotraukos" _services: "Paslaugos" account: "Paskyra" activerecord: @@ -40,13 +37,7 @@ lt: username: invalid: "Neteisingas. Galima naudoti tik raides, skaiÄius ir apatinį brÅ«kÅ¡nelį_" taken: "Užimtas" - ago: "%{time} prieÅ¡" all_aspects: "Visos kategorijos" - application: - helper: - unknown_person: "Nežinomas asmuo" - video_title: - unknown: "Netinkamas video įraÅ¡o tipas." are_you_sure: "Ar jÅ«s įsitikinÄ™s?" are_you_sure_delete_account: "Ar JÅ«s įsitikinÄ™s, kad norite iÅ¡trinti savo paskyrÄ…? Å io veiksmo negalÄ—site atÅ¡aukti!" aspect_memberships: @@ -60,17 +51,9 @@ lt: success: "Kontaktas sÄ—kmingai priskirtas kategorijai." aspect_listings: add_an_aspect: "PridÄ—ti kategorijÄ…" - deselect_all: "Nepasirinkti nieko" - edit_aspect: "Redaguoti %{name}" - select_all: "Pasirinkti viskÄ…" aspect_stream: stay_updated: "Sekite naujienas" stay_updated_explanation: "JÅ«sų pagrindiniame sraute galite rasti visus savo kontaktus, JÅ«sų sekamas žymes, ir iÅ¡radingų bendruomenÄ—s narių įraÅ¡us." - contacts_not_visible: "Å ios kategorijos kontaktai negalÄ—s matyti vienas kito." - contacts_visible: "Å ios kategorijos kontaktai galÄ—s matyti vienas kitÄ…." - create: - failure: "Kategorijos sukurti nepavyko." - success: "Nauja kategorija %{name} sukurta." destroy: failure: "%{name} negali bÅ«ti paÅ¡alintas, nes nÄ—ra tuÅ¡Äias." success: "%{name} sÄ—kmingai paÅ¡alintas." @@ -78,21 +61,13 @@ lt: aspect_list_is_not_visible: "Kategorijų sÄ…raÅ¡o nemato kiti esantys Å¡ioje kategorijoje" aspect_list_is_visible: "Kategorijų sÄ…raÅ¡as matomas kietiems esantiems Å¡ioje kategorijoje" confirm_remove_aspect: "Ar tikrai norite iÅ¡trinti Å¡iÄ… kategorijÄ…?" - make_aspect_list_visible: "Ar leisti Å¡ios kategorijos kontaktams matyti vienas kitÄ…?" - remove_aspect: "IÅ¡trinti kategorijÄ…" rename: "Pervardinti" update: "Atnaujinti" updating: "Atnaujinama..." index: - diaspora_id: - content_1: "JÅ«sų unikalus Diaspora ID:" - content_2: "Jo pagalba Jus galima surasti Diaspora tinkle." - heading: "Unikalus Diaspora ID" donate: "Aukoti dabar" - handle_explanation: "Tai tavo unikalus numeris Diaspora tinkle. Jis, kaip ir el. paÅ¡to adresas, leidžia kitiems žmonÄ—ms surasti Jus tinkle." help: do_you: "Ar:" - email_feedback: "%{link} JÅ«sų atsiliepimai" feature_suggestion: "... galite pasiÅ«lyti %{link}?" find_a_bug: "...randate %{link}?" have_a_question: "... turite %{link}?" @@ -106,25 +81,15 @@ lt: follow: "Sekti %{link} ir pasveikinti naujus tinklapio Diaspora* vartotojus!" learn_more: "Sužinoti daugiau" title: "Pasveikinkite naujus vartotojus" - no_contacts: "Kontaktų nÄ—ra" - no_tags: "No tags" - people_sharing_with_you: "ŽmonÄ—s dalijasi su jumis" - post_a_message: "ParaÅ¡yti žinutÄ™" services: content: "JÅ«s galite prijungti Å¡ias paslaugas prie savo Diaspora tinklapio:" heading: "Prijungti paslaugas" - unfollow_tag: "Sustabdyti sekimÄ… #%{tag}" welcome_to_diaspora: "Sveiki atvykÄ™ į tinklapį Diaspora, %{name}!" - new: - create: "Sukurti" - name: "Vardas (matomas tik Jums)" no_contacts_message: community_spotlight: "BendruomenÄ—s dÄ—mesio centre" or_spotlight: "Arba galite dalintis su %{link}" try_adding_some_more_contacts: "JÅ«s galite ieÅ¡koti arba pakviesti daugiau žmonių." you_should_add_some_more_contacts: "PridÄ—kite daugiau kontaktų!" - no_posts_message: - start_talking: "Dar niekas nepasisakÄ—. PradÄ—kite pokalbį pats!" seed: acquaintances: "Pažintys" family: "Å eima" @@ -133,26 +98,18 @@ lt: update: failure: "Kategorijos %{name} pavadinimas yra per ilgas." success: "Kategorija %{name} sÄ—kmingai pakeista." - back: "Atgal" bookmarklet: explanation: "Paskelbkite tinkle Diaspora %{link} paspausdami Å¡iÄ… nuorodÄ… => %{link}" heading: "Diaspora žymelÄ—s" post_something: "Paskelbti Diaspora" - post_success: "Ä®raÅ¡as iÅ¡siųstas!" cancel: "AtÅ¡aukti" comments: new_comment: comment: "Komentuoti" commenting: "SiunÄiamas komentaras..." - one: "1 komentaras" - other: "%{count} komentarų" - zero: "Komentarų nÄ—ra" contacts: - create: - failure: "Nepavyko sukurti kontakto" index: add_a_new_aspect: "Sukurti kategorijÄ…" - add_to_aspect: "PridÄ—ti kontaktus į kategorijÄ… %{name}" all_contacts: "Visi kontaktai" community_spotlight: "BendruomenÄ—s dÄ—mesio centre" my_contacts: "Mano kontaktai" @@ -161,27 +118,16 @@ lt: only_sharing_with_me: "Tik tie, kurie su manimi dalijasi" start_a_conversation: "PradÄ—ti pokalbį" title: "Kontaktai" - your_contacts: "JÅ«sų kontaktai" - sharing: - people_sharing: "ŽmonÄ—s dalijasi su jumis:" spotlight: community_spotlight: "BendruomenÄ—s dÄ—mesio centre" conversations: create: fail: "Netinkamas praneÅ¡imas" sent: "PraneÅ¡imas iÅ¡siųstas" - helper: - new_messages: - few: "%{count} nauji praneÅ¡imai" - one: "1 naujas praneÅ¡imas" - other: "%{count} naujų praneÅ¡imų" - zero: "NÄ—ra naujų praneÅ¡imų" index: inbox: "Gauta" - no_conversation_selected: "Nepasirinktas joks pokalbis" no_messages: "NÄ—ra praneÅ¡imų" new: - abandon_changes: "Atsisakyti pakeitimų?" send: "Siųsti" sending: "SiunÄiama..." subject: "Tema" @@ -199,36 +145,20 @@ lt: error_messages: helper: correct_the_following_errors_and_try_again: "IÅ¡taisykite Å¡ias klaidas ir bandykite vÄ—l." - invalid_fields: "Neteisingai suvesta" fill_me_out: "Užpildykite" find_people: "Rasti žmones arba žymes" - hide: "SlÄ—pti" invitations: a_facebook_user: "Facebook vartotojas" check_token: not_found: "Pakvietimo raktas nerastas" create: - already_contacts: "Å is žmogus jau yra jÅ«sų kontaktuose" - already_sent: "Å iam žmogui pakvietimÄ… jau siuntÄ—te" no_more: "Daugiau pakvietimų neturi." - own_address: "JÅ«s negalite siųsti pakvietimo sau." rejected: "Å ie el. paÅ¡to adresai neveikÄ—: " sent: "Pakvietimas iÅ¡siųstas." - edit: - accept_your_invitation: "Patvirtinti kvietimÄ…" - your_account_awaits: "JÅ«sų paskyra tikrinama!" new: - already_invited: "Already invited" - aspect: "Kategorija" - check_out_diaspora: "Užeik į tinklÄ… Diaspora!" - if_they_accept_info: "Kvietimus priÄ—mÄ™ žmonÄ—s bus pridÄ—ti prie kategorijos į kuriÄ… kvietÄ—te." invite_someone_to_join: "Pakviesk kÄ… nors prisijungti prie Diasporos!" language: "Kalba" - personal_message: "AsmeninÄ— žinutÄ—" - resend: "Siųsti dar kartÄ…" send_an_invitation: "Nusiųsk kvietimÄ…" - send_invitation: "Siųsti kvietimÄ…" - to: "Kam" layouts: application: back_to_top: "Ä® viršų" @@ -236,37 +166,13 @@ lt: public_feed: "VieÅ¡as atsiliepimas apie Diaspora %{name}" toggle: "toggle mobile site" whats_new: "Kas naujo?" - your_aspects: "JÅ«sų kategorijos" header: - admin: "Administruoti" - blog: "blog'as" code: "kodas" - login: "prisijungti" logout: "atsijungti" profile: "profile" - recent_notifications: "Siųsti įspÄ—jimÄ… dar kartÄ…" settings: "settings" - view_all: "Rodyti viskÄ…" - likes: - likes: - people_dislike_this: - few: "%{count} žmonÄ—s nemÄ—gsta" - one: "1 žmogus nemÄ—gsta" - other: "%{count} žmonių nemÄ—gsta" - zero: "NÄ—ra nemÄ—gstanÄių" - people_like_this: - few: "%{count} žmonių mÄ—gta" - one: "1 žmogus mÄ—gsta" - other: "%{count} žmonių mÄ—gsta" - zero: "Niekam nepatiko" - people_like_this_comment: - few: "%{count} mÄ—gsta" - one: "%{count} mÄ—gsta" - other: "%{count} mÄ—gsta" - zero: "niekas nemÄ—gsta" limited: "Ribotas" more: "Daugiau" - next: "Sekantis" no_results: "Nieko nerasta" notifications: also_commented: @@ -284,12 +190,6 @@ lt: one: "%{actors} pakomentavo JÅ«sų %{post_link}." other: "%{actors} pakomentavo JÅ«sų %{post_link}." zero: "%{actors} pakomentavo JÅ«sų %{post_link}." - helper: - new_notifications: - few: "%{count} nauji įspÄ—jimai" - one: "1 naujas įspÄ—jimas" - other: "%{count} naujų įspÄ—jimų" - zero: "nÄ—ra naujų įspÄ—jimų" index: and: "ir" and_others: @@ -354,7 +254,6 @@ lt: liked: "%{name} has just liked your post: " view_post: "parodyti įraÅ¡Ä…" mentioned: - mentioned: "paminÄ—jo Jus įraÅ¡e:" subject: "%{name} paminÄ—jo Jus Diaspora* tinkle" private_message: reply_to_or_view: "AtraÅ¡yti arba parodyti pokalbį" @@ -372,62 +271,26 @@ lt: to_change_your_notification_settings: "kad pakeisti savo įspÄ—jimų nustatymus" nsfw: "Nesaugus" ok: "Gerai" - or: "arba" - password: "Slaptažodis" - password_confirmation: "Slaptažodžio patvirtinimas" people: - helper: - results_for: " \"%{params}\" rezultatai" index: no_one_found: "... ir nieko nepavyko rasti." no_results: "Labas! Nieko nerasta." results_for: "ieÅ¡koti rezultatų pagal" - one: "1 person" - other: "%{count} people" person: - add_contact: "pridÄ—ti kontaktÄ…" - already_connected: "Jau prisijungtas" - pending_request: "laukiamas praÅ¡ymas" thats_you: "tai tu!" profile_sidebar: bio: "biografija" born: "gimimo data" - edit_my_profile: "Redaguoti mano profilį" gender: "lytis" - in_aspects: "aspektuose" - remove_contact: "paÅ¡alinti kontaktÄ…" - remove_from: "Ar paÅ¡alinti kontaktÄ… \"%{name}\" iÅ¡ aspekto \"%{aspect}\"?" show: does_not_exist: "Asmuo neegzistuoja!" - incoming_request: "JÅ«s gavote pakvietimÄ… iÅ¡ Å¡io asmens." - not_connected: "You are not connected with this person" - return_to_aspects: "Grįžti į aspektų puslapį" - to_accept_or_ignore: "priimti arba ignoruoti." - zero: "no people" photos: destroy: notice: "Nuotrauka paÅ¡alinta." - edit: - editing: "Redagavimas" - new: - back_to_list: "Atgal į sÄ…raÅ¡Ä…" - new_photo: "Nauja nuotrauka" - post_it: "paskelbti!" new_photo: empty: "{file} yra tuÅ¡Äias, pasirink failus iÅ¡ naujo." invalid_ext: "{file} turi neteisingÄ… galÅ«nÄ™. Yra leidžiamos tik {extensions}." size_error: "{file} yra per didelis, maksimalus failo dydis yra {sizeLimit}." - photo: - view_all: "rodyti visas nuotraukas, kurias įkÄ—lÄ— %{name}" - show: - delete_photo: "PaÅ¡alinti nuotraukÄ…" - edit: "redaguoti" - edit_delete_photo: "Redaguoti nuotraukos apraÅ¡ymÄ… / paÅ¡alinti nuotraukÄ…" - make_profile_photo: "padaryti profilio nuotraukÄ…" - update_photo: "Atnaujinti nuotraukÄ…" - update: - error: "Nuotraukos atnaujinti nepavyko." - notice: "Nuotrauka atnaujinta sÄ—kmingai." posts: show: photos_by: @@ -435,9 +298,7 @@ lt: one: "%{author} nuotrauka" other: "%{count} %{author} nuotraukų" zero: "NÄ—ra %{author} nuotraukų" - previous: "Ankstesnis" privacy: "Privatumas" - privacy_policy: "Privatumo politika" profile: "Anketa" profiles: edit: @@ -453,48 +314,14 @@ lt: closed: "Naujų paskyrų kÅ«rimas Å¡iame Diasporos serveryje yra uždarytas." create: success: "Prisijungei prie Diasporos!" - edit: - cancel_my_account: "AtÅ¡aukti mano paskyrÄ…" - edit: "Redaguoti %{name}" - leave_blank: "(palik tuÅ¡ÄiÄ…, jei nenori pakeisti)" - password_to_confirm: "(tavo slaptažodis reikalingas, kad patvirtintume pakeitimus)" - unhappy: "Nesmagu?" - update: "Atnaujinimas" new: - create_my_account: "Create my account" enter_email: "Enter an e-mail" enter_password: "Ä®veskite slaptažodį" enter_password_again: "Ä®veskite tÄ… patį slaptažodį kaip ir anksÄiau" enter_username: "Pasirinkite naudotojo vardÄ… (naudokite tik raides, skaiÄius ir pabraukimus)" - sign_up_message: "Social Networking with a <3" - requests: - create: - sending: "SiunÄiama" - destroy: - error: "Pasirink aspektÄ…!" - ignore: "Ignoruotas praÅ¡ymas draugauti." - success: "Susidraugavai." - helper: - new_requests: - few: "%{count} nauji praÅ¡ymai!" - one: "naujas praÅ¡ymas!" - other: "%{count} naujų praÅ¡ymų!" - zero: "nÄ—ra naujų praÅ¡ymų" - manage_aspect_contacts: - existing: "Egzistuojantys kontaktai" - manage_within: "Valdyti kontaktus ties" - new_request_to_person: - sent: "iÅ¡siųsta!" reshares: reshare: - reshare: - few: "%{count} pasidalino" - one: "1 pasidalino" - other: "%{count} pasidalino" - zero: "Niekas nepasidalino" reshare_confirmation: "Reshare %{author} - %{text}?" - reshare_original: "Reshare orignial" - show_original: "Show Original" search: "PaieÅ¡ka" services: create: @@ -505,79 +332,34 @@ lt: disconnect: "atjungti" logged_in_as: "sujungta su" really_disconnect: "atjungti %{service}?" - inviter: - click_link_to_accept_invitation: "Click this link to accept your invitation" settings: "Nustatymai" shared: - add_contact: - create_request: "Rask pagal Diaspora naudotojo vardÄ…" - diaspora_handle: "diaspora@handle.org" - enter_a_diaspora_username: "Ä®veskite naudotojo vardÄ…:" - your_diaspora_username_is: "Tavo Diaspora tinklo naudotojo vardas yra: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Add to aspect" toggle: few: "%{count} kategorijose" one: "%{count} kategorijoje" other: "%{count} kategorijų" zero: "PridÄ—ti kontaktÄ… prie kategorijos" - contact_list: - all_contacts: "Visi kontaktai" invitations: by_email: "by Email" - dont_have_now: "Tu neturi jokių pakvietimų dabar, taÄiau netrukus gausi daugiau!" - invitations_left: "(liko %{count})" - invite_someone: "Pakviesk kÄ… nors" - invites_closed: "Invites are currently closed on this Diaspora seed" - notification: - new: "Naujas %{type} iÅ¡ naudotojo \"%{from}\"" public_explain: logged_in: "Prisijungta į %{service}" manage: "valdyti prijungtus tinklus" outside: "VieÅ¡os žinutÄ—s bus matomos kitiems už Diasporos ribų." title: "Tu ketini skelbti vieÅ¡Ä… žinutÄ™!" publisher: - all: "viskas" - all_contacts: "visi kontaktai" - make_public: "pavieÅ¡inti" new_user_prefill: i_like: "I'm interested in %{tags}." - post_a_message_to: "ParaÅ¡yti žinutÄ™ į aspektÄ… \"%{aspect}\"" posting: "RaÅ¡oma..." share: "Skelbti" - share_with: "Skelbti aspekte \"%{aspect}\"" whats_on_your_mind: "what's on your mind?" - reshare: - reshare: "Skelbti papildomai" - stream_element: - dislike: "I dislike this" - hide_and_mute: "Hide and Mute" - like: "I like this" status_messages: - helper: - no_message_to_display: "ŽinuÄių nÄ—ra." too_long: "{\"few\"=>\"Sutrumpinkite savo statuso praneÅ¡imÄ… %{count} ženklais\", \"one\"=>\"Sutrumpinkite savo statuso praneÅ¡imÄ… %{count} ženklu\", \"other\"=>\"Sutrumpinkite savo statuso praneÅ¡imÄ… %{count} ženklų\", \"zero\"=>\"Sutrumpinkite savo statuso praneÅ¡imÄ… %{count} ženklų\"}" - stream_helper: - hide_comments: "SlÄ—pti visus komentarus" - show_comments: - few: "Rodyti dar %{count} komentarus" - one: "Rodyti dar vienÄ… komentarÄ…" - other: "Rodyti dar %{count} komentarų" - zero: "Daugiau komentarų nÄ—ra" streams: aspects: title: "Your Aspects" mentions: title: "Your Mentions" - tag_followings: - create: - failure: "Failed to follow: #%{name}" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" - terms_and_conditions: "Nuostatos ir sÄ…lygos" - undo: "AtÅ¡aukti" username: "Vartotojo vardas" users: confirm_email: @@ -590,7 +372,6 @@ lt: change_password: "Keisti slaptažodį" close_account: what_we_delete: "We delete all of your posts, profile data, as soon as humanly possible. Your comments will hang around, but be associated with your Diaspora Handle." - download_photos: "atsisiųsti mano nuotraukas" email_awaiting_confirmation: "We have sent you an activation link to %{unconfirmed_email}. Till you follow this link and activate the new address, we will continue to use your original address %{email}." export_data: "Eksportuoti duomenis" new_password: "Naujas slaptažodis" @@ -606,7 +387,4 @@ lt: password_changed: "Slaptažodis pakeistas" password_not_changed: "Slaptažodžio pakeisti nepavyko" unconfirmed_email_changed: "E-Mail Changed. Needs activation." - unconfirmed_email_not_changed: "E-Mail Change Failed" - webfinger: - hcard_fetch_failed: "there was a problem fetching the hcard for #{@account}" - welcome: "Sveiki atvykÄ™!" \ No newline at end of file + unconfirmed_email_not_changed: "E-Mail Change Failed" \ No newline at end of file diff --git a/config/locales/diaspora/lv.yml b/config/locales/diaspora/lv.yml index 7f7d437fb4ab9b94ffa758201d86018e05b4d8b3..bb238389199b6826eac31135e80b69f4ced46e38 100644 --- a/config/locales/diaspora/lv.yml +++ b/config/locales/diaspora/lv.yml @@ -6,10 +6,7 @@ lv: _applications: "Lietotnes" - _comments: "KomentÄri" _contacts: "Kontakti" - _home: "MÄjÄs" - _photos: "FotogrÄfijas:" _services: "Servisi" account: "Konts" activerecord: @@ -36,13 +33,7 @@ lv: username: invalid: "nav derÄ«gs. Ir atļauti tikai burti, cipari un apakÅ¡svÄ«tras." taken: "ir aizņemts." - ago: "pirms %{time}" all_aspects: "Visas grupas" - application: - helper: - unknown_person: "nezinÄma persona" - video_title: - unknown: "Nenosaukts video" are_you_sure: "Vai esi pÄrliecinÄts?" are_you_sure_delete_account: "Vai tieÅ¡Äm vÄ“laties slÄ“gt savu kontu? To nevarÄ“s atjaunot!" aspect_memberships: @@ -55,14 +46,6 @@ lv: success: "Kontakts veiksmÄ«gi pievienots grupai." aspect_listings: add_an_aspect: "+ Pievienot grupu" - deselect_all: "AtlasÄ«t neko" - edit_aspect: "Labot %{name}" - select_all: "IzvÄ“lÄ“ties visus" - contacts_not_visible: "Kontakti Å¡ajÄ grupÄ nevarÄ“s viens otru redzÄ“s." - contacts_visible: "Kontakti Å¡ajÄ grupÄ varÄ“s viens otru redzÄ“t." - create: - failure: "Grupas izveide neizdevÄs." - success: "Grupa %{name} tika izveidota." destroy: failure: "%{name} nav tukÅ¡a un to nevar noņemt." success: "%{name} tika veiksmÄ«gi noņemta." @@ -70,18 +53,11 @@ lv: aspect_list_is_not_visible: "Kontakti Å¡ajÄ grupÄ neredz viens otru." aspect_list_is_visible: "Kontakti Å¡ajÄ grupÄ var redzÄ“t viens otru." confirm_remove_aspect: "Vai jÅ«s tieÅ¡Äm vÄ“laties dzÄ“st Å¡o grupu?" - make_aspect_list_visible: "ļaut kontaktiem Å¡ajÄ grupÄ viens otru redzÄ“t?" - remove_aspect: "DzÄ“st Å¡o grupu" rename: "pÄrsaukt" update: "atjaunot" updating: "atjauno" index: - diaspora_id: - content_1: "Tavs diaspora* ID:" - content_2: "Dod to citiem, lai viņi varÄ“tu tevi atrast diaspora* tÄ«klÄ." - heading: "diaspora* ID" donate: "Ziedot" - handle_explanation: "Å is ir tavs diaspora* ID. TÄ ir kÄ e-pasta adrese, kuru tu dod, lai cilvÄ“ki varÄ“tu ar tevi sazinÄties." help: do_you: "Ja tev ir:" feature_suggestion: "... %{link}?" @@ -97,16 +73,10 @@ lv: follow: "Seko %{link} un sveicini jaunos lietotÄjus diaspora*!" learn_more: "LasÄ«t vairÄk" title: "SveicinÄti, jaunie lietotÄji" - no_contacts: "Nav kontaktu" - no_tags: "+ Atrodi birku, kurai sekot" services: content: "Tu vari pieslÄ“gt Å¡Ädus servisus savam diaspora* profilam:" heading: "PieslÄ“gt servisus" - unfollow_tag: "Vairs nerÄdÄ«t %{tag}" welcome_to_diaspora: "Laipni lÅ«gti diaspora*, %{name}!" - new: - create: "Izveidot" - name: "Nosaukums (redzams tikai tev)" no_contacts_message: community_spotlight: "Kopienas uzmanÄ«bÄ" or_spotlight: "Vai arÄ« tu vari dalÄ«ties ar saiti %{link}" @@ -120,36 +90,23 @@ lv: update: failure: "Grupas %{name} nosaukums ir pÄrÄk garÅ¡, lai to saglabÄtu." success: "Grupa %{name} tika veiksmÄ«gi labota." - back: "Atpakaļ" cancel: "Atcelt" comments: new_comment: comment: "KomentÄ“t" commenting: "KomentÄ“..." - one: "1 komentÄrs" - other: "%{count} komentÄri" - zero: "nav komentÄru" contacts: - create: - failure: "NeizdevÄs izveidot kontaktu" index: add_a_new_aspect: "Pievienot jaunai grupai" all_contacts: "Visi kontakti" start_a_conversation: "SÄkt sarunu" title: "Kontakti" - your_contacts: "Tavi kontakti" conversations: create: sent: "Ziņa aizsÅ«tÄ«ta" - helper: - new_messages: - one: "1 jauna ziņa" - other: "%{count} jaunas ziņas" - zero: "Nav jaunu ziņu" index: inbox: "IenÄkoÅ¡Äs" new: - abandon_changes: "Atcelt izmaiņas?" send: "SÅ«tÄ«t" sending: "SÅ«ta..." subject: "Virsraksts" @@ -163,32 +120,20 @@ lv: error_messages: helper: correct_the_following_errors_and_try_again: "Izlabojiet sekojoÅ¡Äs kļūdas un mÄ“Ä£iniet vÄ“lreiz." - invalid_fields: "Nekorekti lauki" fill_me_out: "Aizpildi mani" find_people: "MeklÄ“t cilvÄ“kus vai #birkas" - hide: "SlÄ“pt" invitations: create: - already_sent: "Tu jau esi ielÅ«dzis Å¡o personu." sent: "IelÅ«gumi ir aizsÅ«tÄ«t: %{emails}" new: language: "Valoda" limited: "Ierobežota piekļuve" more: "VairÄk" - next: "nÄkamais" no_results: "Nekas netika atrasts." ok: "Labi" - or: "vai" - password: "Parole" - password_confirmation: "Paroles apstiprinÄjums" - previous: "iepriekÅ¡Ä“jais" privacy: "PrivÄtums" - privacy_policy: "PrivÄtuma politika" profile: "Profils" public: "Publisks" search: "MeklÄ“t" settings: "IestatÄ«jumi" - terms_and_conditions: "Noteikumi un nosacÄ«jumi" - undo: "Atsaukt" - username: "LietotÄjvÄrds" - welcome: "SveicinÄti!" \ No newline at end of file + username: "LietotÄjvÄrds" \ No newline at end of file diff --git a/config/locales/diaspora/mk.yml b/config/locales/diaspora/mk.yml index b5cfeb9f92230db414ee71376e791fd5371a0951..7dfd8096de7a9433ab8d7a00c49ca6e959841ef8 100644 --- a/config/locales/diaspora/mk.yml +++ b/config/locales/diaspora/mk.yml @@ -6,10 +6,7 @@ mk: _applications: "Ðпликации" - _comments: "Коментари" _contacts: "Контакти" - _home: "Дома" - _photos: "фотографии" _services: "СервиÑи" account: "КориÑничка Ñметка" activerecord: @@ -32,35 +29,21 @@ mk: username: invalid: "is invalid. We only allow letters, numbers, and underscores" taken: "е веќе иÑкориÑтено." - ago: "%{time} пред" all_aspects: "All aspects" - application: - helper: - unknown_person: "непозната личноÑÑ‚" - video_title: - unknown: "Ðепознат наÑлов на видео" are_you_sure: "Дали Ñте Ñигурни?" are_you_sure_delete_account: "Дали Ñте Ñигурни дека Ñакате да ја избришете вашата кориÑничка Ñметка? ПоÑле ова не можете да ја вратите." aspects: add_to_aspect: failure: "ÐеуÑпешно додавање на контактот во аÑпект." success: "УÑпешно додаден контактот во аÑпект." - aspect_listings: - edit_aspect: "Измени %{name}" - select_all: "Одбери ÑÑ" - create: - failure: "ÐеуÑпешно креирање на аÑпект." - success: "Вашиот нов аÑпект %{name} е креиран" destroy: success: "%{name} е отÑтранет уÑпешно." edit: - make_aspect_list_visible: "make aspect list visible?" rename: "реименувај" update: "ажурирај" updating: "ажурирање" index: donate: "Донирај" - handle_explanation: "Ова е вашето diaspora кориÑничко име. ИÑто како е-маил адреÑа, можете да го давате на луѓе за да Ñе Ñврзат Ñо ваÑ." help: do_you: "Дали" have_a_question: "...има %{link}" @@ -71,22 +54,14 @@ mk: tag_question: "#question" new_here: learn_more: "Ðаучи повеќе" - no_contacts: "Ðема контакти" - no_tags: "No tags" - new: - create: "Ðаправи" - name: "Name" no_contacts_message: try_adding_some_more_contacts: "You can search (top) or invite (right) more contacts." - no_posts_message: - start_talking: "Ðикој доÑега нема кажано ништо. Започни го разговорот!" seed: family: "Фамилија" friends: "Пријатели" work: "Работа" update: success: "Вашиот аÑпект, %{name}, беше уÑпешно уреден." - back: "Ðазад" bookmarklet: explanation: "%{link} from anywhere by bookmarking this link." heading: "Diaspora Bookmarklet" @@ -95,38 +70,20 @@ mk: new_comment: comment: "Коментар" commenting: "Коментирање..." - one: "1 коментар" - other: "%{count} коментари" - zero: "нема коментари" contacts: - create: - failure: "ÐеуÑпешно креирање на контакт" index: - add_to_aspect: "Add contacts to %{name}" all_contacts: "Сите контакти" my_contacts: "Мои контакти" no_contacts: "No contacts." no_contacts_message: "Провери %{community_spotlight}" start_a_conversation: "Започни разговор" title: "Контакти" - your_contacts: "Ваши контакти" - sharing: - people_sharing: "Луѓе што Ñподелуваат Ñо тебе:" conversations: create: fail: "Ðевалидна порака" sent: "Пораката е пратена" - helper: - new_messages: - few: "%{count} new messages" - many: "%{count} new messages" - one: "1 new messages" - other: "%{count} new messages" - two: "%{count} new messages" - zero: "no new messages" index: inbox: "Сандаче" - no_conversation_selected: "нема Ñелектирани разговори" no_messages: "нема пораки" new: send: "Прати" @@ -141,70 +98,30 @@ mk: error_messages: helper: correct_the_following_errors_and_try_again: "Поправете ги Ñледниве грешки и обидете Ñе повторно." - invalid_fields: "Ðевалидни полиња" fill_me_out: "Пополни ме" find_people: "Пронајди пријатели или #тагови" - hide: "Сокриј" invitations: a_facebook_user: "Facebook кориÑник" check_token: not_found: "Токенот за поканата не е пронајден" create: - already_contacts: "Веќе Ñте Ñе поврзале Ñо оваа личноÑÑ‚" - already_sent: "Веќе Ñте ја поканиле оваа личноÑÑ‚." no_more: "Ðемате повеќе покани." - own_address: "Ðе можете да иÑпратите покана на вашата адреÑа." rejected: "Следните е-маил адреÑи имаа проблем:" sent: "Поканите беа иÑпратени кон:" - edit: - accept_your_invitation: "Прифатија поканата" new: - already_invited: "Already invited" invite_someone_to_join: "Поканете некој да Ñе придружи на Diaspora!" language: "Јазик" - personal_message: "Лична порака" send_an_invitation: "ИÑпрати покана" - send_invitation: "ИÑпрати покана" - to: "До" layouts: application: toggle: "toggle mobile site" header: - admin: "админ" - blog: "блог" code: "код" - login: "најави Ñе" logout: "одјави Ñе" profile: "profile" - recent_notifications: "ПоÑледни извеÑтувања" settings: "settings" - view_all: "Види Ñе" - likes: - likes: - people_dislike_this: - few: "%{count} people disliked this" - many: "%{count} people disliked this" - one: "1 person disliked this" - other: "%{count} people disliked this" - two: "%{count} dislikes" - zero: "no people disliked this" - people_like_this: - few: "%{count} people liked this" - many: "%{count} people liked this" - one: "1 person liked this" - other: "%{count} people liked this" - two: "%{count} likes" - zero: "no people liked this" - people_like_this_comment: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" limited: "Ограничено" more: "Повеќе" - next: "Ñледно" no_results: "Ðема резултати" notifications: also_commented: @@ -228,14 +145,6 @@ mk: other: "%{actors} commented on your %{post_link}." two: "%{actors} commented on your %{post_link}." zero: "%{actors} commented on your %{post_link}." - helper: - new_notifications: - few: "%{count} new notifications" - many: "%{count} new notifications" - one: "1 new notifications" - other: "%{count} new notifications" - two: "%{count} new notifications" - zero: "no new notifications" index: and_others: few: "and %{count} others" @@ -315,58 +224,24 @@ mk: subject: "%{name} has started sharing with you on Diaspora*" nsfw: "За возраÑни" ok: "ОК" - or: "или" - password: "Лозинка" - password_confirmation: "Потврда на лозинка" people: - helper: - results_for: " резултати за %{params}" index: results_for: "резултати од пребарување за" - one: "1 person" - other: "%{count} people" person: - add_contact: "додај контакт" - already_connected: "Веќе поврзани" - pending_request: "преÑтоечко барање" thats_you: "тоа Ñи ти!" profile_sidebar: bio: "Биографија" born: "роденден" - edit_my_profile: "Уреди го мојот профил" gender: "пол" - in_aspects: "во аÑпекти" - remove_contact: "одÑтрани контакт" - remove_from: "ОдÑтрани %{name} од %{aspect}?" show: does_not_exist: "ЛичноÑта не поÑтои!" - incoming_request: "You have an incoming request from this person." - not_connected: "You are not connected with this person" - zero: "no people" photos: destroy: notice: "Сликата е избришана." - edit: - editing: "Уредување" - new: - back_to_list: "Ðазад кон лиÑта" - new_photo: "Ðова Ñлика" - post_it: "објави!" new_photo: empty: "{file} е празен, изберете датотеки без него." invalid_ext: "{file} има невалидна екÑтензија. Само овие {extensions} Ñе дозволени." size_error: "{file} е премногу голема, макÑимална големина на датотека е {sizeLimit}." - photo: - view_all: "погледни ги Ñите Ñлики на %{name}" - show: - delete_photo: "Избриши Ñлика" - edit: "уреди" - edit_delete_photo: "Уреди Ð¾Ð¿Ð¸Ñ Ð½Ð° Ñлика/избриши Ñлика" - make_profile_photo: "направи ја профил Ñлика" - update_photo: "Ðжурирај Ñлика" - update: - error: "ÐеуÑпешно уредување на Ñлика." - notice: "Ðжурирањето на Ñликата е уÑпешно." posts: show: photos_by: @@ -376,9 +251,7 @@ mk: other: "%{count} photos by %{author}" two: "Two photos by %{author}" zero: "No photos by %{author}" - previous: "претходно" privacy: "ПриватноÑÑ‚" - privacy_policy: "Политика за приватноÑÑ‚" profile: "Профил" profiles: edit: @@ -396,46 +269,11 @@ mk: closed: "РегиÑтрирањето е затворено." create: success: "Вие и Ñе придруживте на Diaspora!" - edit: - cancel_my_account: "Откажи ја мојата кориÑничка Ñметка" - edit: "Уреди %{name}" - leave_blank: "(оÑтавете го празно ако не Ñакате да го измените)" - password_to_confirm: "(потребна е вашата тековна лозинка за потврдување на измените)" - unhappy: "Ðезадоволни?" - update: "Ðжурирај" new: - create_my_account: "Create my account" enter_email: "Enter an e-mail" - sign_up_message: "Social Networking with a <3" - requests: - create: - sending: "ИÑпраќање" - destroy: - error: "Ве молиме изберете аÑпект!" - ignore: "Игнорирано контакт барање." - success: "Сега Ñте пријатели." - helper: - new_requests: - one: "ново барање!" - other: "%{count} нови барања!" - zero: "немате нови барања" - manage_aspect_contacts: - existing: "ПоÑтоечки контакти" - manage_within: "Менаџирај контакти во" - new_request_to_person: - sent: "иÑпратено!" reshares: reshare: - reshare: - few: "%{count} Reshares" - many: "%{count} Reshares" - one: "1 Reshare" - other: "%{count} Reshares" - two: "%{count} reshares" - zero: "Reshare" reshare_confirmation: "Reshare %{author} - %{text}?" - reshare_original: "Reshare orignial" - show_original: "Show Original" search: "Барај" services: create: @@ -446,17 +284,9 @@ mk: disconnect: "прекини" logged_in_as: "најавен како" really_disconnect: "прекини %{service}?" - inviter: - click_link_to_accept_invitation: "Click this link to accept your invitation" settings: "ПодеÑувања" shared: - add_contact: - create_request: "Ðајди Ñпоред Diaspora кориÑничко име" - diaspora_handle: "Diaspora кориÑничко име" - enter_a_diaspora_username: "ВнеÑи Diaspora кориÑничко име:" - your_diaspora_username_is: "Вашето Diaspora кориÑничко име е: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Add to aspect" toggle: few: "In %{count} aspects" many: "In %{count} aspects" @@ -466,61 +296,24 @@ mk: zero: "Add to aspect" invitations: by_email: "by Email" - dont_have_now: "Моментално немате права, но повеќе покани ќе дојдат наÑкоро!" - invitations_left: "(%{count} лево)" - invite_someone: "Покани некој" - invites_closed: "Invites are currently closed on this Diaspora seed" - notification: - new: "Ðов %{type} од %{from}" public_explain: logged_in: "најавен во %{service}" manage: "менаџирај ги поврзаните ÑервиÑи" outside: "Јавните пораки ќе бидат доÑтапни за Ñите кои Ñе надвор од Diaspora." title: "Ðа пат Ñте да иÑпратите јавна порака!" publisher: - all: "Ñите" - all_contacts: "Ñите контакти" - make_public: "направи јавен" new_user_prefill: i_like: "I'm interested in %{tags}." - post_a_message_to: "Додај порака во %{aspect}" posting: "Објавување..." share: "Сподели" - share_with: "Сподели Ñо %{aspect}" whats_on_your_mind: "what's on your mind?" - reshare: - reshare: "Сподели повторно" - stream_element: - dislike: "I dislike this" - hide_and_mute: "Hide and Mute" - like: "I like this" status_messages: - helper: - no_message_to_display: "Ðема пораки за прикажување." too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - hide_comments: "hide comments" - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: aspects: title: "Your Aspects" mentions: title: "Your Mentions" - tag_followings: - create: - failure: "Failed to follow: #%{name}" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" - terms_and_conditions: "УÑлови и правила" - undo: "Откажи" username: "КориÑничко име" users: confirm_email: @@ -533,7 +326,6 @@ mk: change_password: "Промени лозинка" close_account: what_we_delete: "We delete all of your posts, profile data, as soon as humanly possible. Your comments will hang around, but be associated with your Diaspora Handle." - download_photos: "Ñимни ги моите Ñлики" email_awaiting_confirmation: "We have sent you an activation link to %{unconfirmed_email}. Till you follow this link and activate the new address, we will continue to use your original address %{email}." export_data: "ИзнеÑи податоци" new_password: "Ðова лозинка" @@ -549,7 +341,4 @@ mk: password_changed: "Лозинката е променета" password_not_changed: "Промената на лозинка е неуÑпешна" unconfirmed_email_changed: "E-Mail Changed. Needs activation." - unconfirmed_email_not_changed: "E-Mail Change Failed" - webfinger: - hcard_fetch_failed: "there was a problem fetching the hcard for #{@account}" - welcome: "Добредојдовте!" \ No newline at end of file + unconfirmed_email_not_changed: "E-Mail Change Failed" \ No newline at end of file diff --git a/config/locales/diaspora/ml.yml b/config/locales/diaspora/ml.yml index cb7117cbc4a899c22fc5d03296a4a456f34601a9..fa2cfae7071417b206c66800ca6e3b89e903e0b2 100644 --- a/config/locales/diaspora/ml.yml +++ b/config/locales/diaspora/ml.yml @@ -6,11 +6,8 @@ ml: _applications: "à´ªàµà´°à´¯àµ‹à´—à´™àµà´™à´³àµâ€" - _comments: "à´…à´à´¿à´ªàµà´°à´¾à´¯à´™àµà´™à´³àµâ€" _contacts: "സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµâ€" _help: "സഹായം" - _home: "പൂമàµà´–à´‚" - _photos: "à´šà´¿à´¤àµà´°à´™àµà´™à´³àµâ€" _services: "സേവനങàµà´™à´³àµâ€" account: "à´…à´•àµà´•àµ—à´£àµà´Ÿàµ" activerecord: @@ -91,13 +88,7 @@ ml: other: "à´ˆ ആഴàµà´šà´¯à´¿à´²àµ† à´ªàµà´¤à´¿à´¯ ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµà´Ÿàµ† à´Žà´£àµà´£à´‚ : %{count}" zero: "à´ˆ ആഴàµà´šà´¯à´¿à´²àµ† à´ªàµà´¤à´¿à´¯ ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµà´Ÿàµ† à´Žà´£àµà´£à´‚ :à´’à´¨àµà´¨àµà´®à´¿à´²àµà´²" current_server: "നിലവിലàµà´³àµà´³ സെർവർ ദിവസം %{date} ആണàµ" - ago: "%{time} à´®àµà´¨àµâ€à´ªàµ" all_aspects: "à´Žà´²àµà´²à´¾ à´à´¾à´µà´™àµà´™à´³àµà´‚" - application: - helper: - unknown_person: "അറിയാതàµà´¤ à´µàµà´¯à´•àµà´¤à´¿" - video_title: - unknown: "ചലചàµà´šà´¿à´¤àµà´°à´¤àµà´¤à´¿à´¨àµà´±àµ† തലകàµà´•àµ†à´Ÿàµà´Ÿàµ അറിയിലàµà´²" are_you_sure: "താങàµà´•à´³àµâ€à´•àµà´•àµ ഉറപàµà´ªà´¾à´£àµ‹?" are_you_sure_delete_account: "താങàµà´•à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•à´£à´‚ à´Žà´¨àµà´¨àµ താങàµà´•àµ¾à´•àµà´•àµà´‰à´±à´ªàµà´ªà´¾à´£àµ‹?? à´ˆ à´ªàµà´°à´µàµƒà´¤àµà´¤à´¿ വീണàµà´Ÿàµ†à´Ÿàµà´•àµà´•à´¾àµ» കഴിയിലàµà´²!" aspect_memberships: @@ -111,18 +102,10 @@ ml: success: "വിജയകരമായി സമàµà´ªà´°àµâ€à´•àµà´•à´‚ പരിചയതàµà´¤à´¿à´²àµ‡à´•àµà´•àµ കൂടàµà´Ÿà´¿à´šàµ‡à´°àµâ€à´¤àµà´¤àµ." aspect_listings: add_an_aspect: "+ഒരൠപരിചയം ചേർകàµà´•àµà´•" - deselect_all: "à´’à´¨àµà´¨àµà´‚ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•à´¾à´¤à´¿à´°à´¿à´•àµà´•àµà´•" - edit_aspect: "%{name} തിരàµà´¤àµà´¤àµ" - select_all: "à´Žà´²àµà´²à´¾à´‚ തെരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•" aspect_stream: make_something: "à´Žà´¨àµà´¤àµ†à´™àµà´•à´¿à´²àµà´‚ സൃഷàµà´Ÿà´¿à´•àµà´•àµà´•" stay_updated: "മാറàµà´±à´™àµà´™à´³àµâ€ മനസàµà´¸à´¿à´²à´¾à´•àµà´•à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´•" stay_updated_explanation: "താങàµà´•à´³àµà´Ÿàµ† à´ªàµà´°à´§à´¾à´¨ à´¸àµà´Ÿàµà´°àµ€à´‚ നിറയെ താങàµà´•à´³àµà´Ÿàµ† സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµà´‚, താങàµà´•à´³àµâ€ പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨ ടാഗàµà´•à´³àµà´‚, കൂടàµà´Ÿà´¾à´¯àµà´®à´¯à´¿à´²àµ† സരàµâ€à´—àµà´—ാതàµà´®à´•à´¤à´¯àµà´³àµà´³ à´šà´¿à´² à´…à´‚à´—à´™àµà´™à´³àµà´Ÿàµ† പോസàµà´±àµà´±àµà´•à´³àµà´‚ ആണàµ." - contacts_not_visible: "à´ˆ പരിചയതàµà´¤à´¿à´²àµâ€à´ªàµà´ªàµ†à´Ÿàµà´Ÿ സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµâ€à´•àµà´•àµ പരസàµà´ªà´°à´‚ കാണാനàµâ€ സാധികàµà´•àµà´•à´¯à´¿à´²àµà´² " - contacts_visible: "à´ˆ പരിചയതàµà´¤à´¿à´²àµà´³àµà´³ സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµâ€à´•àµà´•àµ പരസàµà´ªà´°à´‚ കാണാനàµâ€ സാധികàµà´•àµà´¨àµà´¨à´¤à´¾à´£àµ." - create: - failure: "പരിചയം സൃഷàµà´Ÿà´¿à´•àµà´•à´²àµâ€ പരാജയപàµà´ªàµ†à´Ÿàµà´Ÿàµ." - success: "നിങàµà´™à´³àµà´Ÿàµ† à´ªàµà´¤à´¿à´¯ പരിചയം %{name} സൃഷàµà´Ÿà´¿à´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿàµ." destroy: failure: "%{name} à´¶àµà´¨àµà´¯à´®à´²àµà´²à´¾à´¤àµà´¤à´¤à´¿à´¨à´¾à´²àµâ€ നീകàµà´•à´¾à´¨à´¾à´•àµà´¨àµà´¨à´¿à´²àµà´²." success: "%{name} വിജയകരമായി നീകàµà´•à´‚ ചെയàµà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ." @@ -130,24 +113,15 @@ ml: aspect_list_is_not_visible: "പരിചയതàµà´¤à´¿à´¨àµà´±àµ† പടàµà´Ÿà´¿à´• പരിചയതàµà´¤à´¿à´²àµà´³àµà´³ മറàµà´±àµ‚à´³àµà´³à´µà´°à´¿à´²àµâ€à´¨à´¿à´¨àµà´¨àµà´‚ മറചàµà´šàµà´µà´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ" aspect_list_is_visible: "പരിചയപടàµà´Ÿà´¿à´• പരിചയതàµà´¤à´¿à´²àµà´³àµà´³à´µà´°àµâ€à´•àµà´•àµ ദൃശàµà´¯à´®à´¾à´£àµ." confirm_remove_aspect: "താങàµà´•à´³àµâ€à´•àµà´•àµ à´ˆ പരിചയം നീകàµà´•à´£à´®àµ†à´¨àµà´¨àµ ഉറപàµà´ªà´¾à´£àµ‹?" - make_aspect_list_visible: "പരിചയം ദൃശàµà´¯à´®à´¾à´•àµà´•àµà´•" - remove_aspect: "à´ˆ പരിചയം നീകàµà´•à´‚ ചെയàµà´¯àµà´•" rename: "പേരൠമാറàµà´±àµà´•" update: "à´ªàµà´¤àµà´•àµà´•àµà´•" updating: "à´ªàµà´¤àµà´•àµà´•àµà´¨àµà´¨àµ" index: - diaspora_id: - content_1: "നിങàµà´™à´³àµà´Ÿàµ† ഡയാസàµà´ªàµà´± à´à´¡à´¿:" - content_2: "ഇവ ആരàµâ€à´•àµà´•àµ കൊടàµà´•àµà´•àµà´¨àµà´¨àµà´µàµ‹ അവരàµâ€à´•àµà´•àµ നിങàµà´™à´³àµ† ഡയസàµà´ªàµà´±à´¯à´¿à´²àµâ€ à´•à´£àµà´Ÿàµà´ªà´¿à´Ÿà´¿à´•àµà´•à´¾à´¨à´¾à´•àµà´‚." - heading: "ഡയാസàµà´ªàµà´± à´à´¡à´¿" donate: "സംà´à´¾à´µà´¨" - handle_explanation: "ഇതൠതാങàµà´•à´³àµà´Ÿàµ† ഡയാസàµà´ªàµà´± à´à´¡à´¿à´¯à´¾à´£àµ. à´…à´³àµà´•à´³àµâ€à´•àµà´•àµ താങàµà´•à´³àµ† ബനàµà´§à´ªàµ†à´Ÿà´¾à´¨àµâ€ ഇതൠഇമെയിലàµâ€ പോലെ കൊടàµà´•àµà´•à´¾à´‚." help: any_problem: "à´Žà´¨àµà´¤àµ†à´™àµà´•à´¿à´²àµà´‚ à´ªàµà´°à´¶àµà´¨à´‚?" contact_podmin: "താങàµà´•à´³àµà´Ÿàµ† പോഡിനàµà´±àµ† കാരàµà´¯à´¨à´¿àµ¼à´µà´¾à´¹à´•à´¨àµ† ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´•" do_you: "നിങàµà´™àµ¾" - email_feedback: "താങàµà´•à´³àµâ€à´•àµà´•àµ താലàµâ€à´ªà´°àµà´¯à´®àµà´£àµà´Ÿàµ†à´™àµà´•à´¿à´²àµâ€ താങàµà´•à´³àµà´Ÿàµ† à´ªàµà´°à´¤à´¿à´•à´°à´£à´‚ %{link} അയകàµà´•àµ‚." - email_link: "ഈമെയിൽ" feature_suggestion: "%{link} നിരàµâ€à´¦àµà´¦àµ‡à´¶à´™àµà´™à´³àµâ€ à´Žà´¨àµà´¤àµ†à´™àµà´•à´¿à´²àµà´‚ ഉണàµà´Ÿàµ‹?" find_a_bug: "%{link} à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´•?" have_a_question: "%{link} ഉണàµà´Ÿàµ‹?" @@ -160,31 +134,20 @@ ml: tutorial_link_text: "പഠനോപകരണങàµà´™à´³àµâ€" tutorials_and_wiki: "%{tutorial} & %{wiki}: നിങàµà´™à´³àµà´Ÿàµ† ആദàµà´¯ à´šàµà´µà´Ÿàµà´•à´³àµâ€à´•àµà´•àµ സഹായം." introduce_yourself: "ഇതൠതാങàµà´•à´³àµà´Ÿàµ† à´¸àµà´Ÿàµà´°àµ€à´®à´¾à´£àµ. വനàµà´¨àµ à´¸àµà´µà´¯à´‚ പരിചയപàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµ‚." - keep_diaspora_running: "ഒരൠസംà´à´¾à´µà´¨à´¯à´¿à´²àµ‚ടെ ഡയസàµà´ªàµ‹à´± വികസനം വേഗതàµà´¤à´¿à´²à´¾à´•àµà´•àµà´•" keep_pod_running: "ഒരൠസംà´à´¾à´µà´¨ കൊണàµà´Ÿàµ %{pod} à´¸àµà´—മമായി à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´²àµà´‚ സെർവറàµà´•àµ¾ നിലനിർതàµà´¤àµà´¨àµà´¨à´¤à´¿à´²àµà´‚ സഹായികàµà´•àµà´•" new_here: follow: "%{link} പിനàµà´¤àµà´Ÿà´°àµâ€à´¨àµà´¨àµ à´ªàµà´¤à´¿à´¯ ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµ† ഡയസàµà´ªàµà´±à´¯à´¿à´²àµ‡à´•àµà´•àµ à´¸àµà´µà´¾à´—തം ചെയàµà´¯àµà´•!" learn_more: "കൂടàµà´¤à´²àµâ€ അറിയàµà´•" title: "à´ªàµà´¤à´¿à´¯ ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµ† à´¸àµà´µà´¾à´—തം ചെയàµà´¯àµà´•" - no_contacts: "സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³à´¿à´²àµà´²" - no_tags: "+ പിനàµà´¤àµà´Ÿà´°à´¾àµ» ഒരൠടാഗൠകണàµà´Ÿàµ†à´¤àµà´¤àµà´•" - people_sharing_with_you: "താങàµà´•à´³àµà´®à´¾à´¯à´¿ പങàµà´•à´¿à´Ÿàµà´¨àµà´¨ ആളàµà´•à´³àµâ€" - post_a_message: "ഒരൠസനàµà´¦àµ‡à´¶à´®à´¯à´¯àµà´•àµà´•àµà´• >>" services: content: "താഴെപàµà´ªà´±à´¯àµà´¨àµà´¨ സേവനങàµà´™à´³àµà´®à´¾à´¯à´¿ ബനàµà´§à´¿à´ªàµà´ªà´¿à´•àµà´•à´¾à´‚" heading: "സേവനങàµà´™àµ¾ ബനàµà´§à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´•" - unfollow_tag: "#%{tag} പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨à´¤àµ നിർതàµà´¤àµà´•" welcome_to_diaspora: "ഡയാസàµà´ªàµà´±à´¯à´¿à´²àµ‡à´•àµà´•àµ à´¸àµà´µà´—തം, %{name}!" - new: - create: "സൃഷàµà´Ÿà´¿à´•àµà´•àµ‚" - name: "പേരàµàµ" no_contacts_message: community_spotlight: "സാമൂഹിക à´ªàµà´°à´¾à´§à´¾à´¨àµà´¯à´‚" or_spotlight: "à´…à´²àµà´²àµ†à´™àµà´•à´¿à´²àµâ€ താങàµà´•à´³àµâ€à´•àµà´•àµ %{link} ഉപയോഗിചàµà´šàµ പങàµà´•à´¿à´Ÿà´¾à´µàµà´¨àµà´¨à´¤à´¾à´£àµ" try_adding_some_more_contacts: "താങàµà´•à´³àµâ€à´•àµà´•àµ കൂടàµà´¤à´²àµâ€ സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµ‡ തിരയàµà´•à´¯àµ‹ à´•àµà´·à´£à´¿à´•àµà´•àµà´•à´¯àµ‹ ചെയàµà´¯à´¾à´µàµà´¨àµà´¨à´¤à´¾à´£àµ." you_should_add_some_more_contacts: "താങàµà´•à´³àµâ€ à´•àµà´±à´šàµà´šàµà´•àµ‚à´Ÿà´¿ സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµâ€ ചേരàµâ€à´•àµà´•à´£à´‚!" - no_posts_message: - start_talking: "ആരàµà´‚ ഇതàµà´µà´°àµ† à´’à´¨àµà´¨àµà´‚ പറഞàµà´žà´¿à´²àµà´²!" seed: acquaintances: "പരിചയകàµà´•à´¾à´°àµâ€" family: "à´•àµà´Ÿàµà´‚ബം" @@ -193,7 +156,6 @@ ml: update: failure: "താങàµà´•à´³àµâ€ നലàµà´•à´¿à´¯ %{name} à´Žà´¨àµà´¨ പരിചയതàµà´¤à´¿à´¨àµà´±àµ† പേരൠഅനàµà´µà´¦à´¿à´¨àµ€à´¯à´®à´¾à´¯à´¤à´¿à´²àµà´‚ വലàµà´¤à´¾à´£àµ." success: "നിങàµà´™à´³àµà´Ÿàµ† പരിചയം, %{name}, വിജയകരമായി à´šà´¿à´Ÿàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿." - back: "പിനàµà´¨àµ‹à´Ÿàµà´Ÿàµ" blocks: create: failure: "I couldn't ignore that user. #evasion" @@ -205,21 +167,14 @@ ml: explanation: "എവിടെ നിനàµà´¨àµà´‚ ഡയാസàµà´ªàµà´±à´¯à´¿à´²àµ‡à´•àµà´•àµ à´•àµà´±à´¿à´ªàµà´ªà´¯à´¯àµà´•àµà´•àµà´µà´¾à´¨à´¾à´¯à´¿ à´ˆ ലിങàµà´•àµ à´¬àµà´•àµà´•àµà´®à´¾à´°àµâ€à´•àµà´•àµ ചെയàµà´¯àµà´• => %{link}." heading: "അടയാളകàµà´•àµà´±à´¿à´ªàµà´ªà´¾à´•àµà´•àµà´•" post_something: "ഡയാസàµà´ªàµà´±à´¯à´¿à´²àµ‡à´•àµà´•àµ à´•àµà´±à´¿à´ªàµà´ªà´¯à´¯àµà´•àµà´•àµà´•" - post_success: "à´•àµà´±à´¿à´ªàµà´ªà´¿à´Ÿàµà´Ÿàµ! à´…à´Ÿà´¯àµà´•àµà´•àµà´¨àµà´¨àµ!" cancel: "റദàµà´¦à´¾à´•àµà´•àµà´•" comments: new_comment: comment: "à´…à´à´¿à´ªàµà´°à´¾à´¯à´‚" commenting: "à´…à´à´¿à´ªàµà´°à´¾à´¯à´‚ രേഖപàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´¨àµà´¨àµ..." - one: "1 à´…à´à´¿à´ªàµà´°à´¾à´¯à´‚" - other: "%{count} à´…à´à´¿à´ªàµà´°à´¾à´¯à´™àµà´™à´³àµâ€" - zero: "à´…à´à´¿à´ªàµà´°à´¾à´¯à´™àµà´™à´³àµŠà´¨àµà´¨àµà´®à´¿à´²àµà´²." contacts: - create: - failure: "സമàµà´ªà´°àµâ€à´•àµà´•à´‚ ഉണàµà´Ÿà´¾à´•àµà´•à´¾à´¨à´¾à´•àµà´¨àµà´¨à´¿à´²àµà´²" index: add_a_new_aspect: "à´ªàµà´¤à´¿à´¯ പരിചയം ചേരàµâ€à´•àµà´•àµ‚" - add_to_aspect: "സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµâ€ %{name} പരിചയതàµà´¤à´¿à´²àµ‡à´•àµà´•àµ ചേരàµâ€à´•àµà´•àµà´•" all_contacts: "à´Žà´²àµà´²à´¾ സമàµà´ªà´°àµâ€à´•àµà´•à´µàµà´‚" community_spotlight: "സാമൂഹിക à´ªàµà´°à´¾à´§à´¾à´¨àµà´¯à´‚" my_contacts: "à´Žà´¨àµà´±àµ† സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµâ€" @@ -228,33 +183,18 @@ ml: only_sharing_with_me: "നിങàµà´™à´³àµà´®à´¾à´¯à´¿ മാതàµà´°à´‚ പങàµà´•àµ വചàµà´šà´¤àµ" start_a_conversation: "സംà´à´¾à´·à´£à´‚ ആരംà´à´¿à´•àµà´•àµ‚" title: "സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµâ€" - your_contacts: "നിങàµà´™à´³àµà´Ÿàµ† സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµâ€" - sharing: - people_sharing: "നിങàµà´™à´³àµà´®à´¾à´¯à´¿ പങàµà´•à´¿à´Ÿàµà´¨àµà´¨ à´¸àµà´¹àµƒà´¤àµà´¤àµà´•àµà´•àµ¾" spotlight: community_spotlight: "സാമൂഹിക à´ªàµà´°à´¾à´§à´¾à´¨àµà´¯à´‚" suggest_member: "ഒരൠഉപയോകàµà´¤àµà´¤à´¾à´µà´¿à´¨àµ† നിർദàµà´¦àµ‡à´¶à´¿à´•àµà´•àµà´•" conversations: - conversation: - participants: "à´…à´‚à´—à´™àµà´™àµ¾" create: fail: "സാധàµà´µà´²àµà´²à´¾à´¤àµà´¤ സനàµà´¦àµ‡à´¶à´‚" no_contact: "നമസàµà´•à´¾à´°à´‚, താങàµà´•àµ¾ ആദàµà´¯à´‚ ഒരൠബനàµà´§à´‚ ചേർകàµà´•à´£à´‚!" sent: "സനàµà´¦àµ‡à´¶à´‚ അയചàµà´šàµ." - helper: - new_messages: - few: "%{count} à´ªàµà´¤à´¿à´¯ സനàµà´¦àµ‡à´¶à´™àµà´™à´³àµâ€" - many: "%{count} à´ªàµà´¤à´¿à´¯ സനàµà´¦àµ‡à´¶à´™àµà´™à´³àµâ€" - one: "ഒരൠപàµà´¤à´¿à´¯ സനàµà´¦àµ‡à´¶à´‚" - other: "%{count} à´ªàµà´¤à´¿à´¯ സനàµà´¦àµ‡à´¶à´™àµà´™à´³àµâ€" - two: "%{count} new messages" - zero: "à´ªàµà´¤à´¿à´¯ സനàµà´¦àµ‡à´¶à´™àµà´™à´³à´¿à´²àµà´²" index: inbox: "ഇനàµâ€à´¬àµ‹à´•àµà´¸àµ" - no_conversation_selected: "സംവാദങàµà´™à´³àµŠà´¨àµà´¨àµà´‚ തിരഞàµà´žàµ†à´Ÿàµà´¤àµà´¤à´¿à´²àµà´²" no_messages: "സനàµà´¦àµ‡à´¶à´™àµà´™à´³àµŠà´¨àµà´¨àµà´®à´¿à´²àµà´²" new: - abandon_changes: "മാറàµà´±à´™àµà´™à´³àµâ€ ഉപേകàµà´·à´¿à´•àµà´•à´£àµ‹?" send: "അയകàµà´•àµ" sending: "അയയàµà´•àµà´•àµà´¨àµà´¨àµ..." subject: "വിഷയം" @@ -273,9 +213,6 @@ ml: error_messages: helper: correct_the_following_errors_and_try_again: "à´ˆ പിഴവàµà´•à´³àµâ€ പരിഹരിചàµà´š ശേഷം വീണàµà´Ÿàµà´‚ à´¶àµà´°à´®à´¿à´•àµà´•àµà´•." - invalid_fields: "അസാധàµà´µà´¾à´¯ à´•à´³àµà´³à´¿à´•à´³àµâ€" - login_try_again: "ദയവായി <a href='%{login_link}'>ലോഗിൻ ചെയàµà´¤à´¿à´Ÿàµà´Ÿàµ</a> വീണàµà´Ÿàµà´‚ à´¶àµà´°à´®à´¿à´•àµà´•àµà´•." - post_not_public: "താങàµà´•àµ¾ കാണാൻ à´¶àµà´°à´®à´¿à´•àµà´•àµà´¨àµà´¨ à´•àµà´±à´¿à´ªàµà´ªàµ പൊതàµà´¦àµ¼à´¶à´¨à´¤àµà´¤à´¿à´¨àµà´³àµà´³à´¤à´²àµà´²!" fill_me_out: "ഇതൠപൂരിപàµà´ªà´¿à´•àµà´•àµ‚" find_people: "ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµ†à´¯àµ‹ #tags -കളോ à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´•" help: @@ -410,45 +347,27 @@ ml: tutorial: "പഠനോപകരണങàµà´™à´³àµâ€" tutorials: "പഠനോപകരണങàµà´™à´³àµâ€" wiki: "വികàµà´•à´¿" - hide: "മറയàµà´•àµà´•àµà´•" - ignore: "അവഗണികàµà´•àµà´•" - invitation_codes: - excited: "%{name} താങàµà´•à´³àµ† ഇവിടെ à´•à´£àµà´Ÿà´¤à´¿àµ½ ആഹàµà´²à´¾à´¦à´¿à´•àµà´•àµà´¨àµà´¨àµ." invitations: a_facebook_user: "ഒരൠഫേസàµà´¬àµà´•àµà´•àµ ഉപയോകàµà´¤à´¾à´µàµ" check_token: not_found: "à´•àµà´·à´£à´¤àµà´¤à´¿à´¨àµà´±àµ† ടോകàµà´•à´£àµâ€ കാണàµà´¨àµà´¨à´¿à´²àµà´²" create: - already_contacts: "താങàµà´•à´³àµâ€ ഇതിനകം തനàµà´¨àµ† à´ˆ à´µàµà´¯à´•àµà´¤à´¿à´¯àµà´®à´¾à´¯à´¿ ബനàµà´§à´¿à´ªàµà´ªà´¿à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´•à´¯à´¾à´£àµ" - already_sent: "താങàµà´•à´³àµâ€ ഇതിനകം തനàµà´¨àµ† à´ˆ à´µàµà´¯à´•àµà´¤à´¿à´¯àµ† à´•àµà´·à´£à´¿à´šàµà´šàµ." empty: "ദയവായി à´•àµà´±à´žàµà´žà´¤àµ ഒരൠഈമെയിൽ വിലാസമെങàµà´•à´¿à´²àµà´‚ നൽകàµà´•" no_more: "താങàµà´•à´³àµâ€à´•àµà´•àµ ഇനി à´•àµà´·à´£à´™àµà´™à´³àµŠà´¨àµà´¨àµà´‚ ബാകàµà´•à´¿à´¯à´¿à´²àµà´²." note_already_sent: "à´•àµà´·à´£à´•àµà´•à´¤àµà´¤àµà´•àµ¾ à´®àµàµ»à´ªàµ‡ തനàµà´¨àµ† അയചàµà´šà´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ: %{emails}" - own_address: "നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´µà´¨àµà´¤à´‚ വിലാസതàµà´¤à´¿à´²àµ‡à´•àµà´•àµ à´•àµà´·à´£à´‚ അയകàµà´•à´¾à´¨àµâ€ സാധികàµà´•à´¿à´²àµà´²." rejected: "à´ˆ ഇമെയിലàµâ€ വിലാസങàµà´™à´³àµâ€à´•àµà´•àµ à´ªàµà´°à´¶àµà´¨à´™àµà´™à´³àµà´£àµà´Ÿàµ: " sent: "%{emails} ലേകàµà´•àµ à´•àµà´·à´£à´‚ അയചàµà´šàµ" - edit: - accept_your_invitation: "നിങàµà´™àµ¾à´•àµà´•àµà´³àµà´³ à´•àµà´·à´£à´‚ à´¸àµà´µàµ€à´•à´°à´¿à´•àµà´•àµà´•" - your_account_awaits: "താങàµà´•à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ കാതàµà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ!" new: - already_invited: "ഇപàµà´ªà´±à´¯àµà´¨àµà´¨ ആളàµâ€à´•àµà´•à´¾à´°àµâ€ നിങàµà´™à´³àµà´Ÿàµ† à´•àµà´·à´£à´‚ à´¸àµà´µàµ€à´•à´°à´¿à´šàµà´šà´¿à´Ÿàµà´Ÿà´¿à´²àµà´²." - aspect: "പരിചയം" - check_out_diaspora: "ഡയസàµà´ªàµà´± ഉപയോഗിചàµà´šàµà´¨àµ‹à´•àµà´•àµ!" codes_left: one: "à´ˆ à´•àµà´·à´£à´•àµà´•à´¤àµà´¤à´¿àµ½ ഒരൠകàµà´·à´£à´‚ ബാകàµà´•à´¿à´¯àµà´£àµà´Ÿàµ." other: "à´ˆ à´•àµà´·à´£à´•àµà´•à´¤àµà´¤à´¿àµ½ %{count} à´•àµà´·à´£à´™àµà´™àµ¾ ബാകàµà´•à´¿à´¯àµà´£àµà´Ÿàµ." zero: "à´ˆ à´•àµà´·à´£à´•àµà´•à´¤àµà´¤à´¿àµ½ à´•àµà´·à´£à´™àµà´™àµ¾ à´’à´¨àµà´¨àµà´‚ ബാകàµà´•à´¿à´¯à´¿à´²àµà´²" comma_separated_plz: "താങàµà´•à´³àµâ€à´•àµà´•àµ കോമാ ഉപയോഗിചàµà´šàµ à´’à´¨àµà´¨à´¿à´²àµâ€ കൂടൂതലàµâ€ ഇമെയിലàµâ€ വിലാസങàµà´™à´³àµâ€ ചേരàµâ€à´•àµà´•à´¾à´‚." - if_they_accept_info: "അവരàµâ€ അംഗീകരികàµà´•àµà´•à´¯à´¾à´£àµ†à´™àµà´•à´¿à´²àµâ€, അവരെ താങàµà´•à´³àµâ€ à´•àµà´·à´£à´¿à´šàµà´š പരിചയതàµà´¤à´¿à´²àµ‡à´¯àµà´•àµà´•àµ ചേരàµâ€à´•àµà´•àµà´‚." invite_someone_to_join: "ഡയാസàµà´ªàµà´±à´¯à´¿à´²àµâ€ ചേരാനàµâ€ ആരെയെങàµà´•à´¿à´²àµà´‚ à´•àµà´·à´£à´¿à´¯àµà´•àµà´•àµ!" language: "à´à´¾à´·" paste_link: "താങàµà´•à´³àµà´Ÿàµ† à´¸àµà´¹àµƒà´¤àµà´¤àµà´•àµà´•à´³àµ† ഡയസàµà´ªàµ‹à´±*യിലേകàµà´•àµ à´•àµà´·à´£à´¿à´•àµà´•à´¾àµ» à´ˆ ലിങàµà´•àµ അവരàµà´®à´¾à´¯à´¿ പങàµà´•àµà´µà´¯àµà´•àµà´•àµà´•, à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ അവർകàµà´•àµ à´ˆ ലിങàµà´•àµ നേരിടàµà´Ÿàµ ഈമെയിൽ അയയàµà´•àµà´•àµà´•." - personal_message: "à´µàµà´¯à´•àµà´¤à´¿à´ªà´°à´®à´¾à´¯ സനàµà´¦àµ‡à´¶à´‚" - resend: "വീണàµà´Ÿàµà´‚ അയയàµà´•àµà´•àµà´•" send_an_invitation: "ഒരൠകàµà´·à´£à´‚ അയയàµà´•àµà´•àµ" - send_invitation: "à´•àµà´·à´£à´‚ അയയàµà´•àµà´•àµ" sending_invitation: "à´•àµà´·à´£à´‚ അയയàµà´•àµà´•àµà´¨àµà´¨àµ" - to: "à´¸àµà´µàµ€à´•à´°àµâ€à´¤àµà´¤à´¾à´µàµ" layouts: application: back_to_top: "തിരികെ à´®àµà´•à´³à´¿à´²àµ‡à´•àµà´•àµ" @@ -457,35 +376,13 @@ ml: source_package: "സോഴàµà´¸àµ കോഡൠപൊതികàµà´•àµ†à´Ÿàµà´Ÿàµ സൂകàµà´·à´¿à´•àµà´•àµà´•" toggle: "മൊബൈലàµâ€ സൈറàµà´±à´¿à´²àµ‡à´•àµà´•àµ മാറàµà´•" whats_new: "à´ªàµà´¤à´¿à´¯à´¤àµ?" - your_aspects: "നിങàµà´™à´³àµà´Ÿàµ† പരിചയങàµà´™à´³àµâ€" header: - admin: "കാരàµà´¯à´¨à´¿àµ¼à´µà´¾à´¹à´•àµ»" - blog: "à´¬àµà´²àµ‹à´—àµ" code: "കോഡàµ" - help: "സഹായം" - login: "à´…à´•à´¤àµà´¤àµ à´•à´Ÿà´•àµà´•àµà´•" logout: "à´ªàµà´±à´¤àµà´¤àµ à´•à´Ÿà´•àµà´•àµ" profile: "à´ªàµà´°àµŠà´«àµˆà´²àµâ€" - recent_notifications: "à´…à´Ÿàµà´¤àµà´¤à´¿à´Ÿàµ†à´¯àµà´³àµà´³ അറിയിപàµà´ªàµà´•à´³àµâ€" settings: "à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™à´³àµâ€" - view_all: "à´Žà´²àµà´²à´¾à´‚ കാണàµà´•" - likes: - likes: - people_dislike_this: - one: "ഒരാളàµâ€ ഇതിഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨à´¿à´²àµà´²." - other: "%{count} പേരàµâ€ ഇതൠഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨à´¿à´²àµà´²" - zero: "ഇതൠഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿà´¾à´¤àµà´¤à´¤à´¾à´°àµà´®à´¿à´²àµà´²" - people_like_this: - one: "ഒരാളàµâ€ ഇതൠഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµ" - other: "%{count} ആളàµà´•à´³àµâ€ ഇതൠഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµ" - zero: "ആരàµà´‚ ഇതൠഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨à´¿à´²àµà´²." - people_like_this_comment: - one: "%{count} ഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿà´²àµâ€" - other: "%{count} ഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿà´²àµà´•à´³àµâ€" - zero: "ഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿà´²àµà´•à´³àµâ€ ഇലàµà´²" limited: "പരിമിതം" more: "കൂടàµà´¤à´²àµâ€" - next: "à´…à´Ÿàµà´¤àµà´¤à´¤àµ" no_results: "ഫലങàµà´™à´³àµŠà´¨àµà´¨àµà´‚ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¾à´¨à´¾à´¯à´¿à´²àµà´²." notifications: also_commented: @@ -499,14 +396,6 @@ ml: other: "%{actors} commented on a deleted post." two: "%{actors} commented on a deleted post." zero: "%{actors} commented on a deleted post." - helper: - new_notifications: - few: "%{count} new notifications" - many: "%{count} new notifications" - one: "1 new notifications" - other: "%{count} new notifications" - two: "%{count} new notifications" - zero: "No new notifications" index: and: "കൂടാതെ" and_others: @@ -568,7 +457,6 @@ ml: zero: "%{actors} reshared your deleted post." notifier: a_post_you_shared: "ഒരൠകàµà´±à´¿à´ªàµà´ªàµ." - accept_invite: "താങàµà´•à´³àµà´Ÿàµ† ഡയസàµà´ªàµ‹à´±* à´•àµà´·à´£à´‚ à´¸àµà´µàµ€à´•à´°à´¿à´•àµà´•àµà´•!" click_here: "ഇവിടെ ഞെകàµà´•àµà´•" comment_on_post: reply: "%{name} - à´¨àµà´±àµ† à´•àµà´±à´¿à´ªàµà´ªàµ കാണàµà´•à´¯àµ‹ അതിനൠമറàµà´ªà´Ÿà´¿ അയകàµà´•àµà´•à´¯àµ‹ ചെയàµà´¯àµà´• >" @@ -598,7 +486,6 @@ ml: liked: "%{name} നിങàµà´™à´³àµà´Ÿàµ† പോസàµà´±àµà´±àµ ഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµ" view_post: "à´•àµà´±à´¿à´ªàµà´ªàµ കാണàµà´• >" mentioned: - mentioned: "താങàµà´•à´³àµ† ഒരൠകàµà´±à´¿à´ªàµà´ªà´¿à´²àµâ€ സൂചിപàµà´ªà´¿à´šàµà´šàµ:" subject: "%{name} താങàµà´•à´³àµ† ഡയാസàµà´ªàµà´±à´¯à´¿à´²àµâ€* സൂചിപàµà´ªà´¿à´šàµà´šàµ" private_message: reply_to_or_view: "à´ˆ സംà´à´¾à´·à´£à´‚ കാണàµà´•à´¯àµ‹ മറàµà´ªà´Ÿà´¿ അയകàµà´•àµà´•à´¯àµ‹ ചെയàµà´¯àµà´• >" @@ -616,119 +503,55 @@ ml: to_change_your_notification_settings: "അറിയിപàµà´ªàµà´•à´³àµ†à´ªàµà´ªà´±àµà´±à´¿à´¯àµà´³àµà´³ സജàµà´œàµ€à´•à´°à´£à´™àµà´™à´³à´¿àµ½ മാറàµà´±à´‚ വരàµà´¤àµà´¤àµà´•" nsfw: "ജോലികàµà´•àµ à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´²àµà´²" ok: "ശരി" - or: "à´…à´²àµà´²àµ†à´™àµà´•à´¿à´²àµâ€" - password: "അടയാളവാകàµà´•àµ" - password_confirmation: "അടയാളവാകàµà´•àµ തിരàµâ€à´šàµà´šà´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´•" people: add_contact: invited_by: "താങàµà´•à´³àµ† à´•àµà´·à´£à´¿à´šàµà´šà´¤àµ" - add_contact_small: - add_contact_from_tag: "ടാഗിലàµâ€ നിനàµà´¨àµ സമàµà´ªà´°àµâ€à´•àµà´•à´‚ ചേരàµâ€à´•àµà´•àµà´•" - aspect_list: - edit_membership: "പരിചയതàµà´¤à´¿à´²àµ† à´…à´‚à´—à´¤àµà´µà´‚ തിരàµà´¤àµà´¤àµ" - helper: - is_not_sharing: "%{name} നിങàµà´™à´³àµà´®à´¾à´¯à´¿ പങàµà´•àµà´µàµ†à´¯àµà´•àµà´•àµà´¨àµà´¨à´¿à´²àµà´²." - is_sharing: "%{name} നിങàµà´™à´³àµà´®à´¾à´¯à´¿ പങàµà´•àµà´µàµ†à´¯àµà´•àµà´•àµà´¨àµà´¨àµ." - results_for: " %{params} à´¨àµà´±àµ† ഫലങàµà´™à´³àµâ€" index: looking_for: "%{tag_link} à´Žà´¨àµà´¨ ടാഗൠചേരàµâ€à´¤àµà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨ à´•àµà´±à´¿à´ªàµà´ªàµà´•à´³àµâ€à´•àµà´•à´¾à´¯à´¿ തിരയàµà´•à´¯à´¾à´£àµ‹?" no_one_found: "...പകàµà´·àµ‡, ഒരാളെയàµà´‚ à´•à´£àµà´Ÿàµà´ªà´¿à´Ÿà´¿à´šàµà´šà´¿à´²àµà´²." no_results: "താങàµà´•à´³àµâ€ à´Žà´¨àµà´¤à´¿à´¨àµ†à´™àµà´•à´¿à´²àµà´‚ വേണàµà´Ÿà´¿ തിരയേണàµà´Ÿà´¤àµà´£àµà´Ÿàµ." results_for: "വിവരങàµà´™à´³àµâ€à´•àµà´•à´¾à´¯à´¿ തെരയàµà´•" searching: "തിരഞàµà´žàµà´•àµŠà´£àµà´Ÿà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ, ദയവായി കാതàµà´¤à´¿à´°à´¿à´•àµà´•àµà´•..." - one: "ഒരാളàµâ€" - other: "%{count} ആളàµà´•à´³àµâ€" person: - add_contact: "സമàµà´ªà´°àµâ€à´•àµà´•à´‚ ചേരàµâ€à´•àµà´•àµà´•" - already_connected: "ഇപàµà´ªàµ‹à´³àµâ€ തനàµà´¨àµ† ബനàµà´§à´¿à´ªàµà´ªà´¿à´šàµà´šà´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ" - pending_request: "അപേകàµà´· ബാകàµà´•à´¿ നിലàµâ€à´•àµà´¨àµà´¨àµ" thats_you: "ഇതൠതാങàµà´•à´³à´¾à´£àµ!" profile_sidebar: bio: "à´¸àµà´µà´¯à´‚ വിവരണം" born: "ജനàµà´®à´¦à´¿à´¨à´‚" - edit_my_profile: "à´Žà´¨àµà´±àµ† à´ªàµà´°àµŠà´«àµˆà´²àµâ€ തിരàµà´¤àµà´¤àµà´•" gender: "ലിംഗം" - in_aspects: "പരിചയതàµà´¤à´¿à´²àµâ€" location: "à´¸àµà´¥à´²à´‚" - photos: "à´šà´¿à´¤àµà´°à´™àµà´™à´³àµâ€" - remove_contact: "സമàµà´ªà´°àµâ€à´•àµà´•à´‚ മാറàµà´±àµà´•" - remove_from: "%{name} നെ %{aspect} നിനàµà´¨àµ മാറàµà´±à´Ÿàµà´Ÿàµ‡?" show: closed_account: "à´ˆ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ പൂടàµà´Ÿà´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ." does_not_exist: "à´µàµà´¯à´•àµà´¤à´¿ നിലവിലിലàµà´²!" has_not_shared_with_you_yet: "%{name} has not shared any posts with you yet!" - ignoring: "നിങàµà´™à´³àµâ€ %{name} - ഇലàµâ€ നിനàµà´¨àµà´³àµà´³à´¾ à´Žà´²àµà´²à´¾ à´•àµà´±à´¿à´ªàµà´ªàµà´•à´³àµà´‚ അവഗണികàµà´•àµà´¨àµà´¨àµ." - incoming_request: "%{name} നിങàµà´™à´³àµà´®à´¾à´¯à´¿ പങàµà´•à´¿à´Ÿà´¾à´¨àµâ€ ആഗàµà´°à´¹à´¿à´•àµà´•àµà´¨àµà´¨àµ" - mention: "സൂചിപàµà´ªà´¿à´šàµà´šàµ" - message: "സനàµà´¦àµ‡à´¶à´‚" - not_connected: "താങàµà´•à´³àµâ€ %{name} à´¯àµà´®à´¾à´¯à´¿ പങàµà´•àµà´µàµ†à´¯àµà´•àµà´•àµà´¨àµà´¨à´¿à´²àµà´²" - recent_posts: "സമീപകാല à´•àµà´±à´¿à´ªàµà´ªàµà´•à´³àµâ€" - recent_public_posts: "സമീപകാല പൊതൠകàµà´±à´¿à´ªàµà´ªàµà´•à´³àµâ€" - return_to_aspects: "താങàµà´•à´³àµà´Ÿàµ† പരിചയം താളിലേയàµà´•àµà´•àµ തിരിചàµà´šàµ പോവàµà´•" - see_all: "à´Žà´²àµà´²à´¾à´‚ കാണàµ" - start_sharing: "പങàµà´•àµà´µà´šàµà´šàµ à´¤àµà´Ÿà´™àµà´™àµà´•" - to_accept_or_ignore: "à´¸àµà´µàµ€à´•à´°à´¿à´•àµà´•àµà´•à´¯àµ‹ à´¤àµà´¯à´œà´¿à´•àµà´•àµà´•à´¯àµ‹ ചെയàµà´¯à´¾à´¨àµâ€." - sub_header: - add_some: "à´Žà´¨àµà´¤àµ†à´™àµà´•à´¿à´²àµà´‚ ചേർകàµà´•àµ‚" - edit: "തിരàµà´¤àµà´¤àµà´•" - you_have_no_tags: "താങàµà´•à´³àµâ€à´•àµà´•àµ ഒരൠടാഗൠപോലàµà´®à´¿à´²àµà´²!" - webfinger: - fail: "à´•àµà´·à´®à´¿à´•àµà´•à´£à´‚, à´žà´™àµà´™à´³àµâ€à´•àµà´•àµ %{handle} à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¾à´¨à´¾à´¯à´¿à´²àµà´².." - zero: "ആളàµà´•à´³à´¿à´²àµà´²" photos: - comment_email_subject: "%{name}'s photo" create: integrity_error: "à´šà´¿à´¤àµà´°à´‚ à´…à´ªàµâ€Œà´²àµ‹à´¡àµ പരാജയപàµà´ªàµ†à´Ÿàµà´Ÿàµ. അതൠഒരൠചിതàµà´°à´‚ തനàµà´¨àµ†à´¯à´¾à´¯à´¿à´°àµà´¨àµà´¨àµ‹?" runtime_error: "à´šà´¿à´¤àµà´°à´‚ à´…à´ªàµâ€Œà´²àµ‹à´¡àµ പരാജയപàµà´ªàµ†à´Ÿàµà´Ÿàµ." type_error: "à´šà´¿à´¤àµà´°à´‚ à´…à´ªàµâ€Œà´²àµ‹à´¡àµ പരാജയപàµà´ªàµ†à´Ÿàµà´Ÿàµ.. താങàµà´•à´³àµâ€ ഒരൠചിതàµà´°à´‚ à´…à´ªàµâ€Œà´²àµ‹à´¡àµ ചെയàµà´¯à´¾à´¨àµâ€ തിരഞàµà´žàµ†à´Ÿàµà´¤àµà´¤à´¿à´°àµà´¨àµà´¨àµ‹?" destroy: notice: "à´šà´¿à´¤àµà´°à´‚ നീകàµà´•à´‚ ചെയàµà´¤àµ." - edit: - editing: "തിരàµà´¤àµà´¤àµà´¨àµà´¨àµ" - new: - back_to_list: "തിരിചàµà´šàµ പടàµà´Ÿà´¿à´•à´¯à´¿à´²àµ‡à´¯àµà´•àµà´•àµ" - new_photo: "à´ªàµà´¤à´¿à´¯ à´šà´¿à´¤àµà´°à´‚" - post_it: "à´•àµà´±à´¿à´•àµà´•àµ!" new_photo: empty: "{file} ശൂനàµà´¯à´®à´¾à´£àµ, അതലàµà´²à´¾à´¤àµà´¤ ഫയലàµà´•à´³àµâ€ ദയവായി വീണàµà´Ÿàµà´‚ തെരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•." invalid_ext: "{file} നൠതെറàµà´±à´¾à´¯ extension ആണàµ. {extensions} മാതàµà´°à´‚ à´…à´¨àµà´µà´¦à´¿à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ." size_error: "{file} വളരെ വലàµà´¤à´¾à´£àµ, കൂടിയ ഫയലàµâ€ വലിപàµà´ªà´‚ {sizeLimit} ആകàµà´¨àµà´¨àµ." new_profile_photo: - or_select_one_existing: "or select one from your already existing %{photos}" upload: "à´ªàµà´¤à´¿à´¯ à´ªàµà´°àµŠà´«àµˆà´²àµâ€ à´šà´¿à´¤àµà´°à´‚ ചേരàµâ€à´•àµà´•àµà´•!" - photo: - view_all: "%{name}à´¯àµà´Ÿàµ† à´Žà´²àµà´²à´¾ à´šà´¿à´¤àµà´°à´™àµà´™à´³àµà´‚ കാണàµà´•" show: - collection_permalink: "ശേഖരണതàµà´¤à´¿à´¨àµà´±àµ† à´¸àµà´¥à´¿à´°à´‚à´•à´£àµà´£à´¿" - delete_photo: "à´šà´¿à´¤àµà´°à´‚ നീകàµà´•àµà´•" - edit: "തിരàµà´¤àµà´¤àµà´•" - edit_delete_photo: "à´šà´¿à´¤àµà´°à´¤àµà´¤à´¿à´¨àµà´±àµ† വിവരണം തിരàµà´¤àµà´¤àµà´• / à´šà´¿à´¤àµà´°à´‚ നീകàµà´•à´‚ ചെയàµà´¯àµà´•" - make_profile_photo: "à´ªàµà´°àµŠà´«àµˆà´²àµâ€ à´šà´¿à´¤àµà´°à´‚ ഉണàµà´Ÿà´¾à´•àµà´•àµà´•" show_original_post: "Show original post" - update_photo: "à´šà´¿à´¤àµà´°à´‚ à´ªàµà´¤àµà´•àµà´•àµà´•" - update: - error: "à´šà´¿à´¤àµà´°à´‚ à´ªàµà´¤àµà´•àµà´•à´¾à´¨àµâ€ പറàµà´±àµà´¨àµà´¨à´¿à´²àµà´².." - notice: "à´šà´¿à´¤àµà´°à´‚ വിജയകരമായി à´ªàµà´¤àµà´•àµà´•à´¿." posts: presenter: title: "%{name}à´²àµâ€ നിനàµà´¨àµà´³àµà´³ à´•àµà´±à´¿à´ªàµà´ªàµ" show: - destroy: "Delete" - not_found: "Sorry, we couldn't find that post." - permalink: "permalink" photos_by: one: "%{author} à´²àµâ€ നിനàµà´¨àµà´‚ %{count} à´šà´¿à´¤àµà´°à´™àµà´™à´³àµâ€" other: "%{author} à´²àµâ€ നിനàµà´¨àµà´‚ %{count} à´šà´¿à´¤àµà´°à´™àµà´™à´³àµâ€" zero: "%{author} à´²àµâ€ നിനàµà´¨àµà´‚ ഒരൠചിതàµà´°à´‚" reshare_by: "Reshare by %{author}" - previous: "à´®àµàµ»à´ªà´¤àµà´¤àµ‡à´¤àµ" privacy: "à´¸àµà´µà´•à´¾à´°àµà´¯à´¤" - privacy_policy: "à´¸àµà´µà´•à´¾à´°àµà´¯à´¤à´¾à´¨à´¯à´‚" profile: "à´ªàµà´°àµŠà´«àµˆà´²àµâ€" profiles: edit: allow_search: "ഡയാസàµà´ªàµà´±à´¯àµà´•àµà´•à´•à´¤àµà´¤àµ മറàµà´±àµà´³àµà´³à´µà´°àµâ€ à´Žà´¨àµà´¨àµ† à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¾à´¨àµâ€ à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´•" - edit_profile: "à´ªàµà´°àµŠà´«àµˆà´²àµâ€ തിരàµà´¤àµà´¤àµà´•" first_name: "ആദàµà´¯ പേരàµ" last_name: "അവസാന പേരàµ" update_profile: "à´ªàµà´°àµŠà´«àµˆà´²àµâ€ à´ªàµà´¤àµà´•àµà´•àµà´•" @@ -738,8 +561,6 @@ ml: your_location: "താങàµà´•à´³àµà´Ÿàµ† à´¸àµà´¥à´²à´‚" your_name: "താങàµà´•à´³àµà´Ÿàµ† പേരàµ" your_photo: "താങàµà´•à´³àµà´Ÿàµ† à´šà´¿à´¤àµà´°à´‚" - your_private_profile: "താങàµà´•à´³àµà´Ÿàµ† à´¸àµà´µà´•à´¾à´°àµà´¯ à´ªàµà´°àµŠà´«àµˆà´²àµâ€ " - your_public_profile: "താങàµà´•à´³àµà´Ÿàµ† പൊതൠപàµà´°àµŠà´«àµˆà´²àµâ€ " your_tags: "Describe yourself in 5 words" your_tags_placeholder: "like #movies #kittens #travel #teacher #newyork" update: @@ -754,62 +575,23 @@ ml: closed: "à´ˆ ഡയാസàµà´ªàµà´± പോഡിലàµâ€ ചേരàµà´¨àµà´¨à´¤àµ à´…à´Ÿà´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ." create: success: "താങàµà´•à´³àµâ€ ഡയസàµà´ªàµ‹à´±à´¯à´¿à´²àµâ€ ചേരàµâ€à´¨àµà´¨à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ!" - edit: - cancel_my_account: "à´Žà´¨àµà´±àµ† à´…à´•àµà´•àµŒà´£àµà´Ÿàµ റദàµà´¦à´¾à´•àµà´•àµ" - edit: "%{name} തിരàµà´¤àµà´¤àµ" - leave_blank: "(മാറàµà´±àµ‡à´£àµà´Ÿàµ†à´™àµà´•à´¿à´²àµâ€ à´’à´´à´¿à´šàµà´šàµ തനàµà´¨àµ† ഇടàµà´•)" - password_to_confirm: "(മാറàµà´±à´™àµà´™à´³àµâ€ à´¸àµà´¥à´¿à´°à´¿à´•à´°à´¿à´•àµà´•à´¾à´¨àµâ€ വേണàµà´Ÿà´¿ താങàµà´•à´³àµà´Ÿàµ† നിലവിലàµà´³àµà´³ രഹസàµà´¯à´µà´¾à´•àµà´•àµ ആവശàµà´¯à´®àµà´£àµà´Ÿàµ)" - unhappy: "സനàµà´¤àµ‹à´·à´®à´¾à´¯à´¿à´²àµà´²?" - update: "à´ªàµà´¤àµà´•àµà´•àµ" invalid_invite: "താങàµà´•àµ¾ നൽകിയ à´•àµà´·à´£à´•àµà´•à´¤àµà´¤àµ സാധàµà´µà´²àµà´²!" new: - create_my_account: "à´Žà´¨àµà´±àµ† à´…à´•àµà´•àµŒà´£àµà´Ÿàµ സൃഷàµà´Ÿà´¿à´•àµà´•àµ‚!" email: "ഈമെയിൽ" enter_email: "Enter an email" enter_password: "അടയാളവാകàµà´•àµ നലàµâ€à´•àµà´• (ആറൠഅകàµà´·à´°à´®àµ†à´™àµà´•à´¿à´²àµà´‚)" enter_password_again: "അടയാളവാകàµà´•àµ വീണàµà´Ÿàµà´‚ നലàµâ€à´•àµà´•" enter_username: "ഉപà´à´¾à´•àµà´¤àµƒ നാമം തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´• (à´…à´•àµà´·à´°à´™àµà´™à´³àµà´‚ സംഖàµà´¯à´•à´³àµà´‚ à´…à´£àµà´Ÿà´°àµâ€ à´¸àµà´•àµ‹à´±àµà´‚ മാതàµà´°à´‚)" - join_the_movement: "Join the movement!" password: "രഹസàµà´¯à´µà´¾à´•àµà´•àµ" password_confirmation: "രഹസàµà´¯à´µà´¾à´•àµà´•àµ ഉറപàµà´ªà´¾à´•àµà´•àµ½" sign_up: "à´…à´‚à´—à´¤àµà´µà´®àµ†à´Ÿàµà´•àµà´•àµà´•" - sign_up_message: "Social Networking with a ♥" username: "ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚" - requests: - create: - sending: "അയയàµà´•àµà´•àµà´¨àµà´¨àµ" - sent: " %{name}-മായി പങàµà´•àµà´µà´¯àµà´•àµà´•à´¾à´¨àµâ€ താങàµà´•à´³àµâ€ അപേകàµà´·à´¿à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ. à´…à´Ÿàµà´¤àµà´¤ തവണ ഡയസàµà´ªàµ‹à´±à´¯à´¿à´²àµâ€ %{name} à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•àµà´®àµà´ªàµ‹à´³àµâ€ താങàµà´•à´³àµà´Ÿàµ† à´…à´àµà´¯à´°àµâ€à´¤àµà´¥à´¨ കാണàµà´¨àµà´¨à´¤à´¾à´£àµ." - destroy: - error: "ദയവായി ഒരൠപരിചയം തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•!" - ignore: "സമàµà´ªà´°àµâ€à´•àµà´• à´…à´àµà´¯à´°àµâ€à´¤àµà´¥à´¨ അവഗണിചàµà´šàµ." - success: "നിങàµà´™à´³àµâ€ ഇപàµà´ªàµ‹à´³àµâ€ à´¸àµà´¹àµƒà´¤àµà´¤àµà´•àµà´•à´³à´¾à´£àµ." - helper: - new_requests: - one: "ഒരൠപàµà´¤à´¿à´¯ അപേകàµà´·!" - other: "%{count} à´ªàµà´¤à´¿à´¯ അപേകàµà´·à´•à´³àµâ€!" - zero: "à´ªàµà´¤à´¿à´¯ അപേകàµà´·à´¯àµŠà´¨àµà´¨àµà´®à´¿à´²àµà´²" - manage_aspect_contacts: - existing: "നിലവിലàµà´³àµà´³ സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµâ€" - manage_within: "ഉളàµà´³à´¿à´²àµà´³àµà´³ സമàµà´ªà´°àµâ€à´•àµà´•à´™àµà´™à´³àµ† നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•" - new_request_to_person: - sent: "അയചàµà´šàµ!" reshares: comment_email_subject: "%{resharer}'s reshare of %{author}'s post" - create: - failure: "There was an error resharing this post." reshare: deleted: "Original post deleted by author." - reshare: - few: "%{count} reshares" - many: "%{count} reshares" - one: "1 reshare" - other: "%{count} reshares" - two: "%{count} reshares" - zero: "Reshare" reshare_confirmation: "Reshare %{author}'s post?" - reshare_original: "Reshare original" reshared_via: "reshared via" - show_original: "Show original" search: "തിരയàµà´•" services: create: @@ -821,38 +603,15 @@ ml: success: "തിരിചàµà´šà´±à´¿à´¯à´²àµâ€ വിജയകരമായി നീകàµà´•à´‚ ചെയàµà´¤àµ." failure: error: "à´… സേവനവàµà´®à´¾à´¯à´¿ ബനàµà´§à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´²àµâ€ അവിടെ ഒരൠതെറàµà´±àµà´£àµà´Ÿàµ" - finder: - fetching_contacts: "Diaspora is populating your %{service} friends please check back in a few minutes." - no_friends: "No Facebook friends found." - service_friends: "%{service} Friends" index: disconnect: "വിചàµà´›àµ‡à´¦à´¿à´•àµà´•àµ" edit_services: "സേവനങàµà´™à´³à´¿à´²àµâ€ മാറàµà´±à´‚ വരàµà´¤àµà´¤àµà´•" logged_in_as: "ആയി à´ªàµà´°à´µàµ‡à´¶à´¿à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ" really_disconnect: "%{service} വിചàµà´›àµ‡à´¦à´¿à´•àµà´•à´£àµ‹?" services_explanation: "സേവനങàµà´™à´³àµà´®à´¾à´¯à´¿ ബനàµà´§à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´²àµ‚ടെ താങàµà´•à´³àµâ€ ഡയസàµà´ªàµ‹à´±à´¯à´¿à´²àµ†à´´àµà´¤àµà´¨àµà´¨ à´®àµà´±à´•àµà´•àµ à´•àµà´±à´¿à´ªàµà´ªàµà´•à´³àµâ€ അവയിലേകàµà´•àµ à´ªàµà´°à´¸à´¿à´¦àµà´§àµ€à´•à´°à´¿à´•àµà´•àµà´µà´¾à´¨àµà´³àµà´³ കഴിവൠതാങàµà´•à´³àµâ€à´•àµà´•àµ à´²à´à´¿à´•àµà´•àµà´¨àµà´¨àµ." - inviter: - click_link_to_accept_invitation: "à´•àµà´·à´£à´‚ à´¸àµà´µàµ€à´•à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨à´¾à´¯à´¿ à´•à´£àµà´£à´¿à´¯à´¿à´²àµâ€ അമരàµâ€à´¤àµà´¤àµà´•" - join_me_on_diaspora: "ഡയാസàµà´ªàµà´±*യിലàµâ€ à´Žà´¨àµà´¨àµ‹à´ŸàµŠà´ªàµà´ªà´‚ ചേരàµ" - remote_friend: - invite: "à´•àµà´·à´£à´¿à´•àµà´•àµ" - not_on_diaspora: "Not yet on Diaspora" - resend: "വീണàµà´Ÿàµà´‚ അയയàµà´•àµà´•àµ" settings: "à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™à´³àµâ€" - share_visibilites: - update: - post_hidden_and_muted: "%{name}'s post has been hidden, and notifications have been muted." - see_it_on_their_profile: "If you want to see updates on this post, visit %{name}'s profile page." shared: - add_contact: - add_new_contact: "Add a new contact" - create_request: "ഡയാസàµà´ªàµà´± à´à´¡à´¿ വെചàµà´šàµ à´•à´£àµà´Ÿàµ പിടികàµà´•àµà´•" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "ഒരൠഡയാസàµà´ªàµà´± ഉപയോകàµà´¤à´¨à´¾à´®à´‚ നലàµâ€à´•àµà´• :" - know_email: "ആളിനàµà´±àµ† ഇമെയിലàµâ€ വിലാസം അറിയാമോ? നിങàµà´™à´³àµâ€à´•àµà´•àµ à´† à´µàµà´¯à´•àµà´¤à´¿à´¯àµ† à´•àµà´·à´£à´¿à´•àµà´•à´¾à´‚." - your_diaspora_username_is: "താങàµà´•à´³àµà´Ÿàµ† ഡയാസàµà´ªàµà´± ഉപയോകàµà´¤àµƒ നാമം: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Add contact" toggle: few: "In %{count} aspects" many: "In %{count} aspects" @@ -860,23 +619,11 @@ ml: other: "In %{count} aspects" two: "In %{count} aspects" zero: "Add contact" - contact_list: - all_contacts: "à´Žà´²àµà´²à´¾ സമàµà´ªà´°àµâ€à´•àµà´•à´µàµà´‚" - footer: - logged_in_as: "%{name} ആയി à´ªàµà´°à´µàµ‡à´¶à´¿à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ." - your_aspects: "നിങàµà´™à´³àµà´Ÿàµ† പരിചയങàµà´™à´³àµâ€" invitations: by_email: "ഇമെയിലàµâ€ വഴി" - dont_have_now: "താങàµà´•à´³àµâ€à´•àµà´•àµ à´•àµà´·à´£à´®àµŠà´¨àµà´¨àµà´‚ ബാകàµà´•à´¿à´¯à´¿à´²àµà´², പകàµà´·àµ‡ കൂടàµà´¤à´²àµâ€ വരàµà´¨àµà´¨àµà´£àµà´Ÿàµ!" - from_facebook: "ഫേസàµâ€Œà´¬àµà´•àµà´•à´¿à´²àµâ€ നിനàµà´¨àµ" - invitations_left: "%{count}à´•àµà´·à´£à´™àµà´™à´³àµâ€ ബാകàµà´•à´¿" - invite_someone: "ആരെയെങàµà´•à´¿à´²àµà´‚ à´•àµà´·à´£à´¿à´•àµà´•àµà´•" invite_your_friends: "നിങàµà´™à´³àµà´Ÿàµ† കൂടàµà´Ÿàµà´•à´¾à´°àµ† à´•àµà´·à´£à´¿à´•àµà´•àµ." invites: "à´•àµà´·à´£à´™àµà´™à´³àµâ€" - invites_closed: "à´ˆ ഡയാസàµà´ªàµà´± പോഡിലെ à´•àµà´·à´£à´™àµà´™à´³àµâ€ നിരàµâ€à´¤àµà´¤à´¿à´µàµ†à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ" share_this: "à´ˆ ലിങàµà´•àµ ഈമെയിൽ വഴിയോ, à´¬àµà´²àµ‹à´—ൠവഴിയോ à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ ഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´Ÿ സോഷàµà´¯àµ½ നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµ വഴിയോ പങàµà´•à´¿à´Ÿàµà´•" - notification: - new: "à´ªàµà´¤à´¿à´¯ %{type} %{from} à´²àµâ€ നിനàµà´¨àµ" public_explain: atom_feed: "Atom feed" control_your_audience: "Control your Audience" @@ -888,60 +635,26 @@ ml: title: "ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´Ÿ സേവനങàµà´™à´³àµâ€ à´¸àµà´¥à´¾à´ªà´¿à´•àµà´•àµà´•" visibility_dropdown: "Use this dropdown to change visibility of your post. (We suggest you make this first one public.)" publisher: - all: "à´Žà´²àµà´²à´¾à´‚" - all_contacts: "à´Žà´²àµà´²à´¾ സമàµà´ªà´°àµâ€à´•àµà´•à´µàµà´‚" discard_post: "Discard post" get_location: "നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´¥à´¾à´¨à´‚ à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•" - make_public: "പൊതàµà´µà´¾à´•àµà´•àµà´•" new_user_prefill: hello: "Hey everyone, I'm #%{new_user_tag}. " i_like: "I'm interested in %{tags}. " invited_by: "Thanks for the invite, " newhere: "NewHere" - post_a_message_to: "%{aspect}à´²àµâ€ ഒരൠസനàµà´¦àµ‡à´¶à´‚ à´ªàµà´°à´¸à´¿à´¦àµà´§àµ€à´•à´°à´¿à´•àµà´•àµà´•" posting: "à´•àµà´±à´¿à´•àµà´•àµà´¨àµà´¨àµ..." - preview: "തിരനോടàµà´Ÿà´‚" - publishing_to: "à´ªàµà´°à´¸à´¿à´¦àµà´§àµ€à´•à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ: " share: "പങàµà´•àµà´µàµ†à´¯àµà´•àµà´•àµà´•" - share_with: "പങàµà´•àµà´µàµ†à´¯àµà´•àµà´•àµà´•" upload_photos: "Upload photos" whats_on_your_mind: "à´Žà´¨àµà´¤à´¾à´£àµ നിങàµà´™à´³àµà´Ÿàµ† മനസàµà´¸à´¿à´²àµâ€?" - reshare: - reshare: "വീണàµà´Ÿàµà´‚ പങàµà´•à´¿à´Ÿàµà´•" stream_element: - connect_to_comment: "Connect to this user to comment on their post" - currently_unavailable: "commenting currently unavailable" - dislike: "ഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨à´¿à´²àµà´²" - hide_and_mute: "Hide and mute post" - ignore_user: "Ignore %{name}" - ignore_user_description: "Ignore and remove user from all aspects?" - like: "ഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµ" - nsfw: "This post has been flagged as NSFW by its author. %{link}" - shared_with: "Shared with: %{aspect_names}" - show: "show" - unlike: "Unlike" via: "via %{link}" via_mobile: "മൊബൈൽ ഉപയോഗിചàµà´šàµ" - viewable_to_anyone: "This post is viewable to anyone on the web" status_messages: create: success: "വിജയകരമായി സൂചിപàµà´ªà´¿à´šàµà´šàµ: %{names}" - destroy: - failure: "à´•àµà´±à´¿à´ªàµà´ªàµ നീകàµà´•à´‚ ചെയàµà´¯à´¾à´¨àµâ€ സാധികàµà´•àµà´¨àµà´¨à´¿à´²àµà´²" - helper: - no_message_to_display: "സനàµà´¦àµ‡à´¶à´®àµŠà´¨àµà´¨àµà´‚ കാണികàµà´•à´¾à´¨à´¿à´²àµà´²." new: mentioning: "സൂചിപàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨àµ: %{person}" too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - hide_comments: "Hide all comments" - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: activity: title: "My Activity" @@ -967,22 +680,11 @@ ml: title: "Public Activity" tags: title: "Posts tagged: %{tags}" - tag_followings: - create: - failure: "Failed to follow: #%{name}" - none: "You cannot follow a blank tag!" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" tags: show: follow: "Follow #%{tag}" - following: "Following #%{tag}" none: "The empty tag does not exist!" stop_following: "Stop Following #%{tag}" - terms_and_conditions: "à´µàµà´¯à´µà´¸àµà´¥à´•à´³àµà´‚ നിബനàµà´§à´¨à´•à´³àµà´‚" - undo: "പൂരàµâ€à´µà´°àµ‚പതàµà´¤à´¿à´²à´¾à´•àµà´•à´£àµ‹?" username: "ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚" users: confirm_email: @@ -1003,7 +705,6 @@ ml: character_minimum_expl: "à´•àµà´±à´žàµà´žà´¤àµ ആറൠഅകàµà´·à´°à´™àµà´™à´³àµâ€ വേണം" close_account: dont_go: "ദയവàµà´£àµà´Ÿà´¾à´¯à´¿ പോകരàµà´¤àµ!" - if_you_want_this: "If you really want this, type in your password below and click 'Close Account'" lock_username: "This will lock your username if you decided to sign back up." locked_out: "You will get signed out and locked out of your account." make_diaspora_better: "We want you to help us make Diaspora better, so you should help us out instead of leaving. If you do want to leave, we want you to know what happens next." @@ -1014,12 +715,10 @@ ml: comment_on_post: "...താങàµà´•à´³àµà´Ÿàµ† പോസàµà´±àµà´±à´¿à´²àµâ€ ആരെങàµà´•à´¿à´²àµà´‚ à´…à´à´¿à´ªàµà´°à´¾à´¯à´®à´¿à´Ÿàµà´®àµà´ªàµ‹à´³àµâ€?" current_password: "ഇപàµà´ªàµ‹à´´à´¤àµà´¤àµ† അടയാളവാകàµà´•àµ" current_password_expl: "താങàµà´•àµ¾ സൈൻ ഇൻ ചെയàµà´¯àµà´¨àµà´¨ à´† ഒരെണàµà´£à´‚." - download_photos: "à´Žà´¨àµà´±àµ† à´šà´¿à´¤àµà´°à´™àµà´™à´³àµâ€ ഇറകàµà´•àµ" edit_account: "à´…à´•àµà´•àµŒà´£àµà´Ÿàµ തിരàµà´¤àµà´¤àµ" email_awaiting_confirmation: "We have sent you an activation link to %{unconfirmed_email}. Until you follow this link and activate the new address, we will continue to use your original address %{email}." export_data: "വിവരങàµà´™à´³àµâ€ ഇറകàµà´•àµà´®à´¤à´¿ ചെയàµà´¯àµ" following: "Following Settings" - getting_started: "New User Prefrences" liked: "...someone likes your post?" mentioned: "...ഒരൠകàµà´±à´¿à´ªàµà´ªà´¿à´²àµâ€ ആരെങàµà´•à´¿à´²àµà´‚ സൂചിപàµà´ªà´¿à´•àµà´•àµà´®àµà´ªàµ‹à´³àµâ€?" new_password: "à´ªàµà´¤à´¿à´¯ അടയാളവാകàµà´•àµ" @@ -1039,7 +738,6 @@ ml: connect_to_facebook_link: "താങàµà´•à´³àµà´Ÿàµ† ഫേസàµà´¬àµà´•àµà´•àµ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ ബനàµà´§à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´•" hashtag_explanation: "Hashtags allow you to talk about and follow your interests. They're also a great way to find new people on Diaspora." hashtag_suggestions: "Try following tags like #art, #movies, #gif, etc." - saved: "Saved!" well_hello_there: "Well, hello there!" what_are_you_in_to: "What are you into?" who_are_you: "Who are you?" @@ -1061,13 +759,6 @@ ml: settings_updated: "Settings updated" unconfirmed_email_changed: "Email changed. Needs activation." unconfirmed_email_not_changed: "Email change failed" - webfinger: - fetch_failed: "%{profile_url} -à´¨àµà´±àµ† വെബàµà´«à´¿à´‚à´—à´°àµâ€ à´ªàµà´°àµŠà´«àµˆà´²àµâ€ à´Žà´Ÿàµà´•àµà´•àµà´¨àµà´¨à´¤à´¿à´²àµâ€ പരാജയം" - hcard_fetch_failed: "%{account} -à´¨àµà´±àµ† hcard à´Žà´Ÿàµà´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ à´ªàµà´°à´¶àµà´¨à´‚ ഉണàµà´Ÿàµ" - no_person_constructed: "ഒരൠവàµà´¯à´•àµà´¤à´¿à´¯àµà´•àµà´•àµà´‚ à´ˆ hcard à´²àµâ€ നിനàµà´¨àµ നിരàµâ€à´®àµà´®à´¿à´•àµà´•à´¾à´¨àµâ€ കഴിയിലàµà´²." - not_enabled: "%{account}-à´¨àµà´±àµ† ഹോസàµà´±àµà´±à´¿à´²àµâ€ വെബàµà´«à´¿à´‚à´—à´°àµâ€ സജàµà´œà´®à´¾à´•àµà´•à´¿à´¯à´¿à´Ÿàµà´Ÿà´¿à´²àµà´²àµ†à´¨àµà´¨àµ തോനàµà´¨àµà´¨àµà´¨àµ." - xrd_fetch_failed: "അവിടെ %{account} à´…à´•àµà´•àµŒà´£àµà´Ÿà´¿à´²àµâ€ നിനàµà´¨àµà´‚ xrd à´•à´¿à´Ÿàµà´Ÿàµà´¨àµà´¨à´¤à´¿à´¨àµ ഒരൠതെറàµà´±àµà´£àµà´Ÿàµ." - welcome: "à´¸àµà´µà´¾à´—തം!" will_paginate: next_label: "next »" previous_label: "« previous" \ No newline at end of file diff --git a/config/locales/diaspora/ms.yml b/config/locales/diaspora/ms.yml index 06c214f139ae66ea7d4d3e6136210cbbfe80ecea..275ed0a8c1761a515e8270be7c54aef4f48e9a9c 100644 --- a/config/locales/diaspora/ms.yml +++ b/config/locales/diaspora/ms.yml @@ -6,10 +6,7 @@ ms: _applications: "Aplikasi" - _comments: "komen-komen" _contacts: "Kenalan-kenalan" - _home: "Laman Utama" - _photos: "gambar" _services: "Perkhidmatan" account: "Akaun" activerecord: @@ -40,13 +37,7 @@ ms: username: invalid: "adalah tidak sah. Kami hanya membenarkan huruf, nombor, dan garis bawah." taken: "sudah diambil." - ago: "%{time} lalu" all_aspects: "Semua Aspek" - application: - helper: - unknown_person: "orang yang tidak diketahui" - video_title: - unknown: "Tajuk Wayang Tidak Diketahui" are_you_sure: "Anda yakin?" are_you_sure_delete_account: "Adakah anda pasti anda mahu menutup akaun anda? Ini tidak boleh diundur!" aspect_memberships: @@ -60,17 +51,9 @@ ms: success: "Berjaya menambah kenalan kepada aspek." aspect_listings: add_an_aspect: "+ Tambah sebuah aspek" - deselect_all: "Nyahpilih semua" - edit_aspect: "Edit %{name}" - select_all: "Pilih semua" aspect_stream: stay_updated: "Kekal Dikemaskini" stay_updated_explanation: "Aliran utama anda dipenuhi dengan semua kenalan anda, tag anda ikuti, dan catatan dari beberapa ahli kreatif komuniti." - contacts_not_visible: "Kenalan dalam aspek ini tidak akan dapat melihat satu sama lain." - contacts_visible: "Kenalan dalam aspek ini akan dapat melihat satu sama lain." - create: - failure: "Penciptaan aspek gagal." - success: "Aspek baru anda %{name} telah dibuat" destroy: failure: "%{name} tidak kosong dan tidak boleh dikeluarkan." success: "%{name} telah berjaya dikeluarkan." @@ -78,21 +61,13 @@ ms: aspect_list_is_not_visible: "Kenalan dalam aspek ini tidak dapat melihat satu sama lain." aspect_list_is_visible: "Kenalan dalam aspek ini dapat melihat satu sama lain." confirm_remove_aspect: "Adakah anda pasti anda mahu memadam aspek ini?" - make_aspect_list_visible: "Buat kenalan dalam aspek ini dapat dilihat antara satu sama lain?" - remove_aspect: "Padam aspek ini" rename: "namakan semula" update: "kemas kini" updating: "mengemas kini" index: - diaspora_id: - content_1: "ID Diaspora anda adalah:" - content_2: "Beri kepada sesiapa dan mereka akan dapat mencari anda di Diaspora." - heading: "ID Diaspora" donate: "Derma" - handle_explanation: "Ini adalah diaspora id anda. Seperti alamat e-mel, anda boleh memberikan orang-orang ini untuk mencapai anda." help: do_you: "Adakah anda:" - email_feedback: "%{link} maklumbalas anda, jika anda inginkan" feature_suggestion: "... punyai %{link} cadangan?" find_a_bug: "... mencari %{link}?" have_a_question: "... punyai %{link}?" @@ -106,25 +81,15 @@ ms: follow: "Ikuti %{link} dan selamat datang pengguna baru ke diaspora *!" learn_more: "Ketahui lebih lanjut" title: "Alukan Pengguna Baru" - no_contacts: "Tiada kenalan" - no_tags: "+ Cari tag untuk diikuti" - people_sharing_with_you: "Orang berkongsi dengan anda" - post_a_message: "hantar mesej" services: content: "Anda boleh menyambung perkhidmatan berikut kepada diaspora*:" heading: "Khidmat Perhubungan" - unfollow_tag: "berhenti mengikut #%{tag}" welcome_to_diaspora: "Selamat datang ke Diaspora, %{name}!" - new: - create: "Cipta" - name: "Nama (hanya boleh dilihat oleh anda)" no_contacts_message: community_spotlight: "komuniti sorotan" or_spotlight: "Atau anda boleh berkongsi dengan %{link}" try_adding_some_more_contacts: "Anda boleh mencari atau menjemput lebih banyak kenalan." you_should_add_some_more_contacts: "Anda perlu menambah beberapa lagi kenalan!" - no_posts_message: - start_talking: "Tiada orang berkata apa-apa lagi!" seed: acquaintances: "kenalan" family: "Famili" @@ -133,49 +98,28 @@ ms: update: failure: "Aspek anda, %{name}, mempunyai nama terlalu panjang untuk disimpan." success: "Aspek anda, %{name}, telah berjaya diedit." - back: "Undur" bookmarklet: explanation: "Pos kepada diaspora * dari mana-mana sahaja dengan bookmark link ini => %{link}." heading: "Bookmarklet" post_something: "Pos kepada diaspora*" - post_success: "Telah Di Pos! Tutup!" cancel: "Batal" comments: new_comment: comment: "Komen" commenting: "Mengulas..." - one: "1 komen" - other: "%{count} komen" - zero: "tiada komen" contacts: - create: - failure: "Gagal untuk membuat kenalan" index: add_a_new_aspect: "Tambah aspek baru" - add_to_aspect: "menambah kenalan ke %{name}" all_contacts: "Semua Kenalan" my_contacts: "Kenalan Saya" only_sharing_with_me: "Hanya berkongsi dengan saya" start_a_conversation: "Mulakan perbualan" title: "Kenalan-kenalan" - your_contacts: "Kenalan Anda" - sharing: - people_sharing: "Orang berkongsi dengan anda:" conversations: - helper: - new_messages: - few: "%{count} new messages" - many: "%{count} new messages" - one: "1 new messages" - other: "%{count} new messages" - two: "%{count} new messages" - zero: "Tiada mesej baru" index: inbox: "Peti masuk" - no_conversation_selected: "tiada perbualan dipilih" no_messages: "tiada mesej" new: - abandon_changes: "Batalkan perubahan?" send: "Hantar" sending: "Menghantar..." subject: "subjek" @@ -189,61 +133,22 @@ ms: error_messages: helper: correct_the_following_errors_and_try_again: "Betulkan kesilapan-kesilapan berikut dan cuba lagi." - invalid_fields: "bidang tidak sah" fill_me_out: "Isi" find_people: "Cari orang atau #tag" - hide: "Sembunyikan" invitations: create: - already_contacts: "Anda telah disambungkan dengan orang ini" - already_sent: "Anda telah menjemput orang ini." no_more: "Anda tidak mempunyai lebih banyak jemputan." - own_address: "Anda tidak boleh menghantar jemputan ke alamat anda sendiri." rejected: "Alamat e-mel berikut menghadapi masalah:" sent: "Jemputan telah dihantar kepada:" - edit: - accept_your_invitation: "Menerima jemputan anda" - your_account_awaits: "Akaun anda menanti!" new: - already_invited: "Orang-orang yang berikut tidak menerima jemputan anda:" - aspect: "Aspek" - if_they_accept_info: "jika mereka menerima, mereka akan dimasukkan ke dalam aspek awak telah menjemput mereka." invite_someone_to_join: "Menjemput seseorang untuk menyertai Diaspora!" language: "Bahasa" - personal_message: "Mesej peribadi" - resend: "Hantar semula" send_an_invitation: "Menghantar jemputan" - send_invitation: "Hantar jemputan" - to: "Kepada" layouts: application: powered_by: "DI KUASA OLEH DIASPORA*" - likes: - likes: - people_dislike_this: - few: "%{count} dislikes" - many: "%{count} dislikes" - one: "%{count} dislike" - other: "%{count} dislikes" - two: "%{count} dislikes" - zero: "no dislikes" - people_like_this: - few: "%{count} likes" - many: "%{count} suka" - one: "%{count} suka" - other: "%{count} suka" - two: "%{count} suka" - zero: "tiada suka" - people_like_this_comment: - few: "%{count} suka" - many: "%{count} suka" - one: "%{count} suka" - other: "%{count} suka" - two: "%{count} likes" - zero: "tiada suka" limited: "Terhad" more: "lebih banyak" - next: "seterusnya" no_results: "Tiada Hasil Dijumpai" notifications: also_commented: @@ -267,14 +172,6 @@ ms: other: "%{actors} commented on your %{post_link}." two: "%{actors} commented on your %{post_link}." zero: "%{actors} commented on your %{post_link}." - helper: - new_notifications: - few: "%{count} new notifications" - many: "%{count} new notifications" - one: "1 new notification" - other: "%{count} new notifications" - two: "%{count} new notifications" - zero: "No new notifications" index: and: "dan" and_others: @@ -348,40 +245,12 @@ ms: to_change_your_notification_settings: "untuk menukar tetapan pemberitahuan anda" nsfw: "NSFW" ok: "Baiklah" - or: "atau" - password: "kata laluan" - password_confirmation: "pengesahan kata laluan" people: - add_contact_small: - add_contact_from_tag: "menambah kenalan dari tag" - aspect_list: - edit_membership: "mengedit keahlian aspek" - helper: - results_for: "keputusan untuk %{params}" index: no_one_found: "...dan tiada orang yang dijumpai." no_results: "Hey! Anda perlu mencari sesuatu." results_for: "hasil carian untuk" - one: "1 orang" - other: "%{count} orang" - person: - add_contact: "tambah kenalan" - already_connected: "sudah disambungkan" - pending_request: "permintaan yang belum selesai" - show: - return_to_aspects: "Kembali ke halaman aspek anda" - see_all: "lihat semua" - start_sharing: "mula berkongsi" - to_accept_or_ignore: "untuk menerima atau tidak mengendahkan." - sub_header: - add_some: "menambah beberapa" - edit: "mengedit" - you_have_no_tags: "anda tiada tag!" - webfinger: - fail: "Maaf, kami tidak dapat menemui %{handle}." - zero: "tiada orang" photos: - comment_email_subject: "%{name}'s foto" create: integrity_error: "\"Upload\" foto gagal. Adakah anda pasti itu adalah imej?" runtime_error: "\"Upload\" foto gagal. Adakah anda pasti bahawa tali pinggang keledar anda telah diikat?" @@ -394,32 +263,12 @@ ms: other: "%{count} photos by %{author}" two: "Two photos by %{author}" zero: "No photos by %{author}" - previous: "Terdahulu" privacy: "Privasi" - privacy_policy: "Polisi Privasi" profile: "Profil" public: "Awam" reactions: other: "%{count} reactions" zero: "0 reaksi" - requests: - helper: - new_requests: - few: "%{count} new requests!" - many: "%{count} new requests!" - one: "new request!" - other: "%{count} new requests!" - two: "%{count} new requests!" - zero: "no new requests" - reshares: - reshare: - reshare: - few: "%{count} reshares" - many: "%{count} reshares" - one: "1 reshare" - other: "%{count} reshares" - two: "%{count} reshares" - zero: "Reshare" search: "Cari" settings: "Tetapan" shared: @@ -433,23 +282,12 @@ ms: zero: "Add contact" status_messages: too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: aspects: title: "Your Aspects" - terms_and_conditions: "Terma dan Syarat" - undo: "Batalkan?" username: "Nama Pengguna" users: edit: close_account: what_we_delete: "We delete all of your posts, profile data, as soon as humanly possible. Your comments will hang around, but be associated with your Diaspora Handle." - your_handle: "Your diaspora id" - welcome: "Selamat datang!" \ No newline at end of file + your_handle: "Your diaspora id" \ No newline at end of file diff --git a/config/locales/diaspora/nb.yml b/config/locales/diaspora/nb.yml index 25782a1ed986b4b596418a5058ffd156ca7e7ecf..9c84061f69edd574084ec881f0c751964c9b577f 100644 --- a/config/locales/diaspora/nb.yml +++ b/config/locales/diaspora/nb.yml @@ -6,11 +6,8 @@ nb: _applications: "Applikasjoner" - _comments: "Kommentarer" _contacts: "Kontakter" _help: "Hjelp" - _home: "Hjem" - _photos: "Bilder" _services: "Tjenester" _statistics: "Statistikk" _terms: "bruksvilkÃ¥r" @@ -125,13 +122,7 @@ nb: other: "Antall nye brukere denne uken: %{count}" zero: "Antall nye brukere denne uken: ingen" current_server: "Dagens server-dato er %{date}" - ago: "%{time} siden" all_aspects: "Alle aspekter" - application: - helper: - unknown_person: "ukjent person" - video_title: - unknown: "Ukjent videotittel" are_you_sure: "Er du sikker?" are_you_sure_delete_account: "Er du sikker pÃ¥ at du vil stenge kontoen din? Dette kan ikke gjøres om pÃ¥!" aspect_memberships: @@ -147,48 +138,27 @@ nb: success: "Kontakt lagt til aspekt." aspect_listings: add_an_aspect: "+ Lag et nytt aspekt" - deselect_all: "Fjern alle valg" - edit_aspect: "Rediger %{name}" - select_all: "Velg alle" aspect_stream: make_something: "Lag noe" stay_updated: "Hold deg oppdatert" stay_updated_explanation: "Din hovedstrøm viser alle kontaktene dine, tagger som du følger og innlegg fra noen kreative medlemmer i felleskapet." - contacts_not_visible: "Kontakter i dette aspektet vil ikke kunne se hverandre." - contacts_visible: "Kontakter i dette aspektet vil kunne se hverandre." - create: - failure: "Greide ikke Ã¥ opprette aspektet." - success: "Aspektet %{name} har blitt laget" destroy: failure: "%{Name} er ikke tom, og kunne ikke fjernes." success: "%{name} har blitt fjerna." success_auto_follow_back: "%{name} er fjernet. Du brukte dette aspektet for Ã¥ automatisk følge folk som begynte Ã¥ følge deg. Sjekk brukerinnstillingene dine for Ã¥ velge et nytt aspekt til Ã¥ automatisk følge folk som begynner Ã¥ følge deg." edit: - aspect_chat_is_enabled: "Kontakter i dette aspektet har mulighet til Ã¥ chatte med deg." - aspect_chat_is_not_enabled: "Kontakter i dette aspektet har ikke mulighet til Ã¥ chatte med deg." aspect_list_is_not_visible: "Kontakter i dette aspektet kan ikke se hverandre." aspect_list_is_visible: "Kontakter i dette aspektet er i stand til Ã¥ se hverandre." confirm_remove_aspect: "Er du sikker pÃ¥ at du vil slette dette aspektet?" - grant_contacts_chat_privilege: "Gi kontakter i dette aspektet chatprivilegier" - make_aspect_list_visible: "gjør aspektlisten synlig?" - remove_aspect: "Slett dette aspektet" rename: "endre navn" - set_visibility: "Sett synlighet" update: "oppdater" updating: "oppdaterer" index: - diaspora_id: - content_1: "diaspora*-ID-en din er:" - content_2: "Gi det til noen, og de vil kunne finne deg pÃ¥ diaspora*." - heading: "diaspora*-ID" donate: "Doner" - handle_explanation: "Dette er din diaspora*-ID. Som e-postadresser, kan du gi denne til folk for at de skal nÃ¥ deg." help: any_problem: "Noen problemer?" contact_podmin: "Kontakt administratoren til din \"pod\"!" do_you: "Har du:" - email_feedback: "%{link} gi tilbakemelding, om du har lyst" - email_link: "E-post" feature_suggestion: "... et %{link}-forslag?" find_a_bug: "... finn en %{link}?" have_a_question: "... et %{link}?" @@ -201,31 +171,20 @@ nb: tutorial_link_text: "Veiledninger" tutorials_and_wiki: "%{faq}, %{tutorial} og %{wiki}: Hjelp for dine første skritt" introduce_yourself: "Dette er strømmen din. Hopp inn og presenter deg selv." - keep_diaspora_running: "Bidra til kontinuerlig utvikling av diaspora* ved Ã¥ gi en mÃ¥nedlig donasjon!" keep_pod_running: "Sørg for at %{pod} gÃ¥r kjapt ved Ã¥ kjøpe kaffe-fiks til dem med en mÃ¥nedlig donasjon!" new_here: follow: "Følg %{link} og ønsk nye brukere velkommen til diaspora*!" learn_more: "Lær mer" title: "Ønsk nye brukere velkommen" - no_contacts: "Ingen kontakter" - no_tags: "No tags" - people_sharing_with_you: "Folk som deler med deg" - post_a_message: "Publiser en melding >>" services: content: "Du kan koble følgende tjenester til diaspora*:" heading: "Koble til tjenester" - unfollow_tag: "Slutt Ã¥ følge #%{tag}" welcome_to_diaspora: "Velkommen til diaspora*, %{name}!" - new: - create: "Opprett" - name: "Navn (bare synlig for deg)" no_contacts_message: community_spotlight: "kreative medlemmer" or_spotlight: "Eller du kan dele med denne %{link}" try_adding_some_more_contacts: "Du kan søke etter eller invitere flere kontakter." you_should_add_some_more_contacts: "Du bør legge til flere kontakter." - no_posts_message: - start_talking: "Ingen har sagt noe enda!" seed: acquaintances: "Bekjente" family: "Familie" @@ -234,7 +193,6 @@ nb: update: failure: "Aspektet ditt, %{name}, har for langt navn." success: "Aspektet ditt, %{name}, har blitt endra." - back: "Tilbake" blocks: create: failure: "Jeg klarte ikke Ã¥ ignorere den brukeren. #evasion" @@ -246,22 +204,15 @@ nb: explanation: "Publiser til diaspora* fra hvor som helst ved Ã¥ bokmerke denne lenken => %{link}" heading: "Diaspora Bookmarklet" post_something: "Publiser noe pÃ¥ diaspora*" - post_success: "Postet! Lukker!" cancel: "Avbryt" comments: new_comment: comment: "Kommenter" commenting: "Kommenterer ..." - one: "1 kommentar" - other: "%{count} kommentarer" - zero: "ingen kommentarer" contacts: - create: - failure: "Kunne ikke opprette kontakt" index: add_a_new_aspect: "Legg til nytt aspekt" add_contact: "Legg til kontakt" - add_to_aspect: "Legg kontakter til %{name}" all_contacts: "Alle Kontakter" community_spotlight: "Fremhevet av Fellesskapet" my_contacts: "Mine kontakter" @@ -269,19 +220,13 @@ nb: no_contacts_in_aspect: "Du har ikke noen kontakter i dette aspektet ennÃ¥. Under er en liste over eksisterende kontakter som du kan legge til i dette aspektet." no_contacts_message: "Sjekk ut %{community_spotlight}" only_sharing_with_me: "Deler bare med meg " - remove_contact: "Fjern kontakt" start_a_conversation: "Start en samtale " title: "Kontakter" user_search: "Søk etter kontakt" - your_contacts: "Dine kontakter" - sharing: - people_sharing: "Folk som deler med deg:" spotlight: community_spotlight: "Fremhevet av Fellesskapet" suggest_member: "ForslÃ¥ et nytt medlem" conversations: - conversation: - participants: "Deltakere" create: fail: "Ugyldig melding" no_contact: "Heisann, du mÃ¥ legge til kontakten først." @@ -289,23 +234,12 @@ nb: destroy: delete_success: "Samtalen ble slettet suksessfullt" hide_success: "Samtalen ble gjemt suksessfullt" - helper: - new_messages: - few: "%{count} nye meldinger" - many: "%{count} nye meldinger" - one: "1 ny melding" - other: "%{count} nye meldinger" - two: "%{count} nye beskjeder" - zero: "ingen nye meldinger" index: conversations_inbox: "Samtale - Inbox" - create_a_new_conversation: "start en ny samtale" inbox: "Innboks" new_conversation: "Ny samtale" - no_conversation_selected: "ingen samtaler valgt" no_messages: "ingen meldinger" new: - abandon_changes: "Forkaste endringene?" send: "Send" sending: "Sender ..." subject: "emne" @@ -328,10 +262,6 @@ nb: error_messages: helper: correct_the_following_errors_and_try_again: "Rett opp de følgende feilene og prøv igjen." - invalid_fields: "Ugyldige felt" - login_try_again: "Vennligst <a href=%{login_link}>logg pÃ¥</a> og forsøk igjen." - post_not_public: "Innholdet som du forsøker Ã¥ titte pÃ¥ er ikke alment tilgjengelig!" - post_not_public_or_not_exist: "Innlegget du prøver Ã¥ vise er ikke offentlig, eller eksisterer ikke!" fill_me_out: "Fortell meg" find_people: "Finn folk eller #tagger" help: @@ -551,46 +481,29 @@ nb: tutorial: "veiledning" tutorials: "veiledninger" wiki: "wiki" - hide: "Skjul" - ignore: "Ignorer" invitation_codes: - excited: "%{name} ble glad for Ã¥ se deg her." not_valid: "Den invitasjonskoden er ikke lenger gyldig" invitations: a_facebook_user: "En Facebook-bruker" check_token: not_found: "Invitasjonsnøkkelen finnes ikke" create: - already_contacts: "Du er allerede tilknyttet denne personen" - already_sent: "Du har allerede invitert denne personen." empty: "Vennligst angi i hvertfall en e-post adresse" no_more: "Du har ikke flere invitasjoner." note_already_sent: "Invitasjoner har blitt sendt til: %{emails}" - own_address: "Du kan ikke sende invitasjoner til din egen adresse." rejected: "Følgende e-postadresser hadde problemer:" sent: "Invitasjoner har blitt sendt til:" - edit: - accept_your_invitation: "Godta invitasjonen din" - your_account_awaits: "Kontoen din er klar!" new: - already_invited: "Disse personene har ikke takket ja til invitasjonen din:" - aspect: "Aspekt" - check_out_diaspora: "Sjekk ut diaspora*!" codes_left: one: "En invitasjon er igjen med denne koden" other: "%{count} invitasjoner er igjen med denne koden" zero: "Ingen flere invitasjoner kan gjøres med denne koden" comma_separated_plz: "Du kan skrive inn flere e-postadresser adskilt med komma." - if_they_accept_info: "Hvis de aksepterer, vil de bli lagt til i aspektet du valgte." invite_someone_to_join: "Inviter noen til diaspora*!" language: "SprÃ¥k" paste_link: "Del denne lenken med vennene dine for Ã¥ invitere dem til Diaspora* eller send e-post til dem med lenken direkte." - personal_message: "Personlig melding" - resend: "Send pÃ¥ nytt" send_an_invitation: "Send en invitasjon" - send_invitation: "Send invitasjon" sending_invitation: "Sender invitasjon ..." - to: "Til" layouts: application: back_to_top: "Til toppen" @@ -600,44 +513,13 @@ nb: statistics_link: "Statistikk for poden" toggle: "vis mobilsiden" whats_new: "hva er nytt?" - your_aspects: "dine aspekter" header: - admin: "administrator" - blog: "blogg" code: "kode" - help: "Hjelp" - login: "logg inn" logout: "logg ut" profile: "profil" - recent_notifications: "Nye notifications" settings: "innstillinger" - view_all: "Vis alle" - likes: - likes: - people_dislike_this: - few: "%{count} personer misliker dette" - many: "%{count} personer misliker dette" - one: "1 person misliker dette" - other: "%{count} personer misliker dette" - two: "%{count} misliker dette" - zero: "ingen misliker dette" - people_like_this: - few: "%{count} personer liker dette" - many: "%{count} personer liker dette" - one: "1 person liker dette" - other: "%{count} personer liker dette" - two: "%{count} liker dette" - zero: "ingen liker dette" - people_like_this_comment: - few: "%{count} liker" - many: "%{count} liker" - one: "%{count} liker" - other: "%{count} liker" - two: "%{count} liker dette" - zero: "ingen liker" limited: "Begrenset" more: "Mer" - next: "Neste" no_results: "Ingen resultater ble funnet" notifications: also_commented: @@ -658,14 +540,6 @@ nb: one: "%{actors} kommenterte ditt %{post_link}." other: "%{actors} kommenterte ditt %{post_link}." zero: "%{actors} kommenterte ditt %{post_link}." - helper: - new_notifications: - few: "%{count} nye varsler" - many: "%{count} nye varsler" - one: "1 nytt varsel" - other: "%{count} nye varsler" - two: "%{count} nye varsler" - zero: "ingen nye varsler" index: all_notifications: "Alle notifikasjoner" also_commented: "Kommenterte ogsÃ¥" @@ -739,7 +613,6 @@ nb: a_limited_post_comment: "Det finnes en ny kommentar pÃ¥ et begrenset innlegg i diaspora* som du kan ta en kikk pÃ¥." a_post_you_shared: "en post" a_private_message: "Det er en ny privat samtale i diaspora* du kan ta en kikk pÃ¥." - accept_invite: "Godta Diaspora*-invitasjonen din!" also_commented: limited_subject: "Det finnes en ny kommentar pÃ¥ et innlegg du kommenterte pÃ¥" click_here: "klikk her" @@ -818,7 +691,6 @@ nb: view_post: "Se innlegg >" mentioned: limited_post: "Du ble nevnt i et begrenset innlegg." - mentioned: "nevnte deg i et innlegg:" subject: "%{name} har nevnt deg pÃ¥ diaspora*" private_message: reply_to_or_view: "Svar eller se pÃ¥ denne samtalen >" @@ -872,20 +744,9 @@ nb: to_change_your_notification_settings: "for Ã¥ endre innstilliger for varsler" nsfw: "NSFW" ok: "OK" - or: "eller" - password: "Passord" - password_confirmation: "Passord bekreftelse" people: add_contact: invited_by: "du ble invitert av" - add_contact_small: - add_contact_from_tag: "legg til kontakt fra tag" - aspect_list: - edit_membership: "endre aspektmedlemskap" - helper: - is_not_sharing: "%{name} deler ikke med deg" - is_sharing: "%{name} deler med deg" - results_for: " resultater for %{params}" index: couldnt_find_them: "Kan ikke finne de?" looking_for: "Ser du etter innlegg tagget %{tag_link}?" @@ -895,100 +756,47 @@ nb: search_handle: "Benytt diaspora* ID (brukernavn@pod.tid) for Ã¥ finne dine venner." searching: "Søker. Vennligst vent ..." send_invite: "Finner fremdeles ikke de du søker? Send en invitasjon!" - one: "1 person" - other: "%{count} personer" person: - add_contact: "legg til kontakt" - already_connected: "Allerede tilkoblet" - pending_request: "Venter pÃ¥ svar" thats_you: "Det er deg!" profile_sidebar: bio: "mitt livsløp (bio)" born: "Bursdag" - edit_my_profile: "Endre profilen min" gender: "Kjønn" - in_aspects: "i aspekter" location: "Sted" - photos: "Bilder" - remove_contact: "fjern kontakt" - remove_from: "Fjern %{name} fra %{aspect}?" show: closed_account: "Denne kontoen har blitt avsluttet." does_not_exist: "Personen eksisterer ikke!" has_not_shared_with_you_yet: "%{name} har ikke delt noe med deg enda." - ignoring: "Du ignorerer innlegg fra %{name}." - incoming_request: "You have an incoming request from this person." - mention: "Omtale" - message: "Melding" - not_connected: "Du deler ikke til denne personen" - recent_posts: "Nylige Innlegg" - recent_public_posts: "Nylige Offentlige Innlegg" - return_to_aspects: "Tilbake til aspektene" - see_all: "Vis alle" - start_sharing: "begynn Ã¥ dele" - to_accept_or_ignore: "for Ã¥ akseptere eller ignorere." - sub_header: - add_some: "legg til noen" - edit: "endre" - you_have_no_tags: "du har ingen tags!" - webfinger: - fail: "Beklager, vi kunne ikke finne %{handle}." - zero: "ingen personer" photos: - comment_email_subject: "%{name} sitt foto" create: integrity_error: "Bildeopplastning mislyktes. Er du sikker pÃ¥ det var et bilde?" runtime_error: "Bildeopplastning mislyktes. Har du festet sikkerhetsbeltet?" type_error: "Bildeopplastning mislyktes. ER du sikker pÃ¥ at et bilde ble lagt til?" destroy: notice: "Bildet er sletta." - edit: - editing: "Redigerer" - new: - back_to_list: "Tilbake til lista" - new_photo: "Nytt Bilde" - post_it: "legg ut!" new_photo: empty: "{file} er tom, vennligst velg filer igjen uten den" invalid_ext: "{file} er en ugyldig filtype. Bare {extensions} er tillatt." size_error: "{file} er for stor, maks filstørrelse er {sizeLimit}." new_profile_photo: - or_select_one_existing: "eller selekter en fra dine allerede eksisterende %{photos}" upload: "Last opp et nytt profilbilde!" - photo: - view_all: "se alle bildene til %{name}" show: - collection_permalink: "kolleksjon permalink" - delete_photo: "Slett Bilde" - edit: "rediger" - edit_delete_photo: "Rediger bildebeskrivelse / slett bilde" - make_profile_photo: "gjør til profilbilde" show_original_post: "Vis originalpost" - update_photo: "Oppdater Bilde" - update: - error: "Greide ikke Ã¥ endre bildet." - notice: "Bildet er oppdatert." posts: presenter: title: "En post fra %{name}" show: - destroy: "Slett" forbidden: "Du har ikke lov til Ã¥ gjøre det" - not_found: "Beklager, vi fant ikke det inlegget. " - permalink: "permalenke" photos_by: one: "Et bilde av %{author}" other: "%{count} bilder av %{author}" zero: "Ingen bilder av %{author}" reshare_by: "Delt videre av %{author}" - previous: "forrige" privacy: "Personvern" - privacy_policy: "Personvernerklæring" profile: "Profil" profiles: edit: allow_search: "Tillat folk Ã¥ søke pÃ¥ deg i diaspora*" - edit_profile: "Endre profil" first_name: "Fornavn" last_name: "Etternavn" nsfw_check: "Marker alt jeg deler som NSFW" @@ -1001,8 +809,6 @@ nb: your_location: "Hvor bor du?" your_name: "Ditt navn" your_photo: "Ditt profilbilde" - your_private_profile: "Din private profil" - your_public_profile: "Din offentlige profil" your_tags: "Deg: i 5 #tagger" your_tags_placeholder: "f.eks. #diaspora #matlaging #skiskyting #musikk" update: @@ -1020,26 +826,16 @@ nb: closed: "Registreringer er stengt pÃ¥ denne diaspora*-serveren." create: success: "Du er nÃ¥ med i diaspora*!" - edit: - cancel_my_account: "Avbryt kontoen min" - edit: "Endre %{name}" - leave_blank: "(La stÃ¥ tom hvis du ikke ønsker Ã¥ endre det)" - password_to_confirm: "(vi trenger ditt nÃ¥værende passord for Ã¥ bekrefte endringene)" - unhappy: "Ulykkelig?" - update: "Oppdater" invalid_invite: "Invitasjonslenken som du brukte er ikke gyldig lenger!" new: - create_my_account: "Opprett min konto!" email: "E-POST" enter_email: "Skriv en e-post" enter_password: "Skriv inn et passord" enter_password_again: "Skriv inn samme passord som før" enter_username: "Velg et brukernavn (kun bokstaver, nummer og understreker)" - join_the_movement: "Bli med i nettverket!" password: "PASSORD" password_confirmation: "PASSORDBEKREFTELSE" sign_up: "REGISTRER DEG" - sign_up_message: "Sosiale nettverk med et ♥" submitting: "Sender ..." terms: "Ved Ã¥ opprette kontoen aksepterer du %{terms_link}" terms_link: "VilkÃ¥r for bruk" @@ -1054,46 +850,15 @@ nb: reported_label: "<b>Rapportert av</b> %{person}" review_link: "Markert som verifisert" status: - created: "Rapporten er opprettet" destroyed: "Innlegget ble slettet" failed: "Noe gikk galt..." - marked: "Rapporten ble markert som verifisert" title: "Oversikt over rapporter" - requests: - create: - sending: "Sender ..." - sent: "Du har bedt om Ã¥ dele med %{name}. De burde se det neste gang de logger inn pÃ¥ diaspora*" - destroy: - error: "Velg et aspekt først!" - ignore: "Ignorerte venneforespørsel" - success: "NÃ¥ deler du." - helper: - new_requests: - few: "%{count} nye forespørsler!" - many: "%{count} nye forespørsler!" - one: "nye forespørsler!" - other: "%{count} nye forespørsler!" - two: "%{count} nye forespørsler!" - zero: "ingen nye forespørsler" - manage_aspect_contacts: - existing: "Eksisterende kontakter" - manage_within: "Administrer kontakter innen" - new_request_to_person: - sent: "sendt!" reshares: comment_email_subject: "%{resharer} sin videredeling av %{author} sitt innhold" - create: - failure: "Noe gikk galt med Ã¥ videredele dette innlegget." reshare: deleted: "Opprinnelig innlegg slettet av forfatteren." - reshare: - one: "1 deling" - other: "%{count} delinger" - zero: "Del igjen" reshare_confirmation: "Reshare %{author} - %{text}?" - reshare_original: "Del originalen" reshared_via: "delt via" - show_original: "Vis originalen" search: "Søk" services: create: @@ -1105,10 +870,6 @@ nb: success: "Bekrefter slettet autentisering." failure: error: "feil under tilkobling av tjenesten" - finder: - fetching_contacts: "diaspora* finner dine %{service} venner, vær sÃ¥ snill og sjekk igjen om noen fÃ¥ minutter." - no_friends: "Ingen Facebook-venner ble funnet." - service_friends: "%{service}-venner" index: connect: "Koble til" disconnect: "koble fra" @@ -1118,56 +879,25 @@ nb: not_logged_in: "Ikke logget inn for øyeblikket." really_disconnect: "koble fra %{service}?" services_explanation: "Ved Ã¥ koble til andre sosiale tjenester, fÃ¥r du muligheten Ã¥ publisere til disse tjenestene idet du poster til diaspora*." - inviter: - click_link_to_accept_invitation: "Klikk denne linken for Ã¥ akseptere invitasjonen din" - join_me_on_diaspora: "Bli med meg pÃ¥ diaspora*" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "inviter" - not_on_diaspora: "Finnes ikke pÃ¥ diaspora* ennÃ¥." - resend: "send pÃ¥ nytt" settings: "Innstillinger" - share_visibilites: - update: - post_hidden_and_muted: "Innlegget til %{name} har blitt gjemt, og varslinger har blitt skrudd av." - see_it_on_their_profile: "Hvis du vil se oppdateringer til dette innlegget, besøk %{name} sin profilside." shared: - add_contact: - add_new_contact: "Legg til en ny kontakt" - create_request: "Finn etter diaspora*-brukernavn" - diaspora_handle: "Diaspora handle" - enter_a_diaspora_username: "Skriv inn et diaspora*-brukernavn:" - know_email: "Kan du epostadressen deres? Inviter dem!" - your_diaspora_username_is: "Ditt diaspora*-brukernavn er: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Add to aspect" mobile_row_checked: "%{name} (fjern)" mobile_row_unchecked: "%{name} (legg til)" toggle: one: "I %{count} aspekt" other: "I %{count} aspekter" zero: "Lag et aspekt" - contact_list: - all_contacts: "Alle kontakter" - footer: - logged_in_as: "innlogget som %{name}" - your_aspects: "dine aspekter" invitations: by_email: "via Epost" - dont_have_now: "Du har ingen akkurat nÃ¥, men flere invitasjoner kommer snart!" - from_facebook: "Fra Facebook" - invitations_left: "%{count} igjen" - invite_someone: "Inviter noen" invite_your_friends: "Inviter vennene dine" invites: "Invitasjoner " - invites_closed: "Invitasjoner er foreløpig stengt pÃ¥ denne diaspora*-serveren" share_this: "Del denne lenken via e-post, blogg eller ditt foretrukne sosiale nettverk!" - notification: - new: "Ny %{type} fra %{from}" public_explain: atom_feed: "Atom-strøm" control_your_audience: "Kontrollér ditt publikum" @@ -1179,12 +909,9 @@ nb: title: "Du er i ferd med Ã¥ poste et offentlig innlegg!" visibility_dropdown: "Bruk denne menyen for Ã¥ endre publikum for ditt innlegg. (Vi foreslÃ¥r at du gjør dette første innlegget offentlig.)\n" publisher: - all: "alle" - all_contacts: "alle kontakter" discard_post: "Forkast det innsendte/registrerte" formatWithMarkdown: "Du kan benytte %{markdown_link} til Ã¥ formatere din post" get_location: "Hent din posisjon" - make_public: "gjør offentlig" new_user_prefill: hello: "Hei alle sammen, jeg er #%{new_user_tag}. " i_like: "Jeg er interessert i %{tags}." @@ -1192,36 +919,14 @@ nb: newhere: "NyHer" poll: add_a_poll: "Legg til en spørreundersøkelse" - add_poll_answer: "Legg til valg" - option: "Valg 1" - question: "SpørsmÃ¥l" - remove_poll_answer: "Fjern valg" - post_a_message_to: "Post et innlegg til %{aspect}" posting: "Publiserer ..." - preview: "ForhÃ¥ndsvisning" - publishing_to: "publiserer til:" remove_location: "Fjern lokasjon" share: "Del" - share_with: "del med" upload_photos: "Last opp bilder" whats_on_your_mind: "Hva tenker du pÃ¥?" - reshare: - reshare: "Del" stream_element: - connect_to_comment: "Koble til denne brukeren for Ã¥ kommentere posten" - currently_unavailable: "kommentering er ikke tilgjengelig" - dislike: "Liker ikke" - hide_and_mute: "Gjem og demp innlegget" - ignore_user: "Ignorér %{name}" - ignore_user_description: "Ignorér og fjern bruker fra alle aspekter?" - like: "Liker" - nsfw: "Dette innholdet har blitt merket som NSFW av den som har laget det. %{link}" - shared_with: "Delt med: %{aspect_names}" - show: "vis" - unlike: "Liker ikke" via: "via %{link}" via_mobile: "via mobil" - viewable_to_anyone: "Denne posten er synlig for alle pÃ¥ Internett" simple_captcha: label: "Oppgi koden i feltet:" message: @@ -1247,21 +952,12 @@ nb: status_messages: create: success: "Nevnte :%{navn}" - destroy: - failure: "Kunne ikke slette innlegget" - helper: - no_message_to_display: "Ingen melding Ã¥ vise." new: mentioning: "Nevner: %{person}" too_long: "{\"few\"=>\"du bør begrense statusmeldingene dine til %{count} tegn\", \"many\"=>\"Du bør begrense statusmeldingene dine til %{count} characters\", \"one\"=>\"du bør begrense statusmeldingene dine til %{count} tegn\", \"other\"=>\"du mÃ¥ gjøre statusmeldingene dine kortere enn %{count} tegn\", \"two\"=>\"vær sÃ¥ snill og skriv statusoppdateringer som er under %{count} tegn\", \"zero\"=>\"Statusmeldinger mÃ¥ være lengre enn ingenting.\"}" stream_helper: - hide_comments: "Skjul kommentarer" no_more_posts: "Du er kommet til slutten av strømmen." no_posts_yet: "Det finnes ingen innlegg ennÃ¥." - show_comments: - one: "Vis en kommentar til" - other: "Vis %{count} flere kommentarer" - zero: "Ingen kommentarer" streams: activity: title: "Min aktivitet" @@ -1288,13 +984,6 @@ nb: tags: title: "Innlegg med tags: %{tags}" tag_followings: - create: - failure: "Failed to follow: #%{name}" - none: "Du kan ikke følge en blank tagg" - success: "Hurra! NÃ¥ følger du: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Du har sluttet Ã¥ følge: #%{name}" manage: no_tags: "Du følger ikke noen tagger" title: "Administrer fulgte tagger" @@ -1302,15 +991,12 @@ nb: name_too_long: "Navnet pÃ¥ taggen mÃ¥ være kortere enn %{count} tegn. Akkurat nÃ¥ er det pÃ¥ %{current_length} tegn." show: follow: "Følg #%{tag}" - following: "Følger #%{tag}" none: "Den tomme taggen eksisterer ikke." stop_following: "Slutt Ã¥ følge #%{tag}" tagged_people: one: "Én person er tagget med %{tag}" other: "%{count} personer er tagget med %{tag}" zero: "Ingen er tagget med %{tag}" - terms_and_conditions: "VilkÃ¥r og betingelser" - undo: "Angre?" username: "Brukernavn" users: confirm_email: @@ -1331,7 +1017,6 @@ nb: character_minimum_expl: "mÃ¥ være minst seks tegn" close_account: dont_go: "Vennligst ikke forsvinn nÃ¥!" - if_you_want_this: "Hvis du virkelig ønsker dette, skriver du inn passordet ditt under og klikker pÃ¥ «Avslutt konto»" lock_username: "Dette vil reservere brukernavnet ditt hvis du bestemmer deg for Ã¥ registrere deg igjen." locked_out: "Du kommer til Ã¥ bli avlogget og lÃ¥st ute fra din konto" make_diaspora_better: "Vi ønsker at du hjelper oss Ã¥ gjøre Diaspora bedre, sÃ¥ det hadde vært fint om du hjalp oss i stedet for Ã¥ forlate oss. Hvis du allikevel ønsker Ã¥ forsvinne sÃ¥ vil vi gjerne at du skal fÃ¥ vite hva som skjer videre." @@ -1344,14 +1029,12 @@ nb: current_password_expl: "det som du logger pÃ¥ med ..." download_export: "Last ned min profil" download_export_photos: "Last ned mine bilder" - download_photos: "Last ned mine bilder" edit_account: "Endre konto" email_awaiting_confirmation: "We have sent you an activation link to %{unconfirmed_email}. Till you follow this link and activate the new address, we will continue to use your original address %{email}." export_data: "Eksporter data" export_in_progress: "Vi behandler dine data nÃ¥. Vennligst prøv igjen om et lite øyeblikk." export_photos_in_progress: "Vi klargjør bildene dine. Vennligst kom tilbake om et par øyeblikk." following: "Innstillinger for deling" - getting_started: "Ny brukerinnstillinger" last_exported_at: "(Sist oppdatert %{timestamp})" liked: "noen liker innlegget ditt" mentioned: "du blir omtalt i et innlegg" @@ -1378,7 +1061,6 @@ nb: connect_to_facebook_link: "kobler opp til din Facebook konto" hashtag_explanation: "Hastags lar deg beskrive og følge dine interesser. De er ogsÃ¥ en fin mÃ¥te Ã¥ finne nye folk i diaspora*." hashtag_suggestions: "Prøv Ã¥ følge tags som #art, #movies, #gif, osv." - saved: "Lagret!" well_hello_there: "Vel, hallo der!" what_are_you_in_to: "Hva er dine interesser?" who_are_you: "Hvem er du?" @@ -1402,13 +1084,6 @@ nb: settings_updated: "Innstillinger oppdatert" unconfirmed_email_changed: "E-post endret. Behøver aktivering." unconfirmed_email_not_changed: "E-Mail Change Failed" - webfinger: - fetch_failed: "klarte ikke Ã¥ hente webfinger profil for % {profile_url}" - hcard_fetch_failed: "there was a problem fetching the hcard for #{@account}" - no_person_constructed: "Ingen personer kunne konstrueres fra dette hCard." - not_enabled: "Det virker som om webfinger ikke er aktivert for verten til %{account}" - xrd_fetch_failed: "kunne ikke fÃ¥ xrd fra kontoen %{account}" - welcome: "Velkommen!" will_paginate: next_label: "neste »" previous_label: "« forrige" \ No newline at end of file diff --git a/config/locales/diaspora/nds.yml b/config/locales/diaspora/nds.yml index 582060557919a88ccdebd6bb828b0f0dde7d1085..fdd8336c690588cb3e8e14ab0e8c3459f8ee223d 100644 --- a/config/locales/diaspora/nds.yml +++ b/config/locales/diaspora/nds.yml @@ -6,11 +6,8 @@ nds: _applications: "Programme" - _comments: "Kommentare" _contacts: "Kontakte" _help: "Hülp" - _home: "Startsiet" - _photos: "Biller" _services: "Deenste" _statistics: "Statistiken" _terms: "Bedingungen" @@ -118,13 +115,7 @@ nds: other: "Antohl von nee’e Bruker in disse Week: %{count}" zero: "Antohl von nee’e Bruker in disse Week: keene" current_server: "Dat Serverdatum is grood %{date}" - ago: "%{time} her" all_aspects: "All Aspekte" - application: - helper: - unknown_person: "Unbekannte Person" - video_title: - unknown: "Unbekannte Videotitel" are_you_sure: "Bist du sicher?" are_you_sure_delete_account: "Bist du di sicher, dat du dien Konto taumoken wist? Dat kannst du nich rückgängig moken!" aspect_memberships: @@ -138,45 +129,25 @@ nds: success: "Kontakt erfolgriek to’n Aspekt dortaudoon." aspect_listings: add_an_aspect: "+ Een Aspekt dortaudaun" - deselect_all: "Alle afwählen" - edit_aspect: "%{name} ännern" - select_all: "Alle utwählen" aspect_stream: make_something: "Mok wat" stay_updated: "Bliev op’n neesten Stand" stay_updated_explanation: "Dien Hauptstream ward mit all diene Kontakte, de Tags de du folgst und Bidräg von een poor kreative Lüüd ut de Gemeenschaft füllt." - contacts_not_visible: "Kontakte in dissen Aspekt ward sik nich gegensiedig sehn künnen." - contacts_visible: "Kontakte in dissen Aspekt ward sik gegensiedig sehn künnen." - create: - failure: "Kun Aspekt nich anleggen." - success: "Dien nee’en Aspekt %{name} is anleggt worn." destroy: failure: "%{name} kunn nich löscht warn." success: "%{name} is erfolgriek löscht worrn." edit: - aspect_chat_is_enabled: "Kontakte in dissen Aspekt künnt een Tippschnack mit di führen." - aspect_chat_is_not_enabled: "Kontakte in dissen Aspekt künnt keen Tippschnack mit di führen." aspect_list_is_not_visible: "Kontakte in dissen Aspekt künnt sik nich gegensiedig sehn." aspect_list_is_visible: "Kontakte in dissen Aspekt künnt sik gegensiedig sehn." confirm_remove_aspect: "Bist du di sicher, dat du dissen Aspekt löschen willst?" - make_aspect_list_visible: "Kontakte in dissen Aspekt to sik sülbst sichtbor moken?" - remove_aspect: "Dissen Aspekt löschen" rename: "Ãœmbenennen" - set_visibility: "Sichtborkeit setten" update: "Aktualiseern" updating: "Aktualiseer" index: - diaspora_id: - content_1: "Diene diaspora*-ID is:" - content_2: "Geev ehr to annere Lüüd, dormit se di op diaspora* finnen künnt." - heading: "diaspora*-ID" donate: "Spenden" - handle_explanation: "Dat is diene diaspora*-ID. Wie eene E-Mail-Adress kannst du ehr an annere Lüüd geben, dormit se di erreichen künnt." help: any_problem: "Hest du een Problem?" do_you: "Hest du:" - email_feedback: "Schick diene Meenung per %{link}, wenn du dat vörtüst" - email_link: "E-Mail" feature_suggestion: "... een Vörschlag för eene nee’e %{link}?" find_a_bug: "... een %{link} funnen?" have_a_question: "... eene %{link}?" @@ -193,25 +164,15 @@ nds: follow: "Folg %{link} un begrööt nee’e Bruker op diaspora*!" learn_more: "Mehr rutkriegen" title: "Begrööt nee’e Bruker" - no_contacts: "Keene Kontakte" - no_tags: "+ Een Tag ton Folgen finnen" - people_sharing_with_you: "Lüüd de mit di deelt" - post_a_message: "Schriev een Bidrag >>" services: content: "Du kannst de folgenden Deenste mit diaspora* verbinnen:" heading: "Verbinn Deenste" - unfollow_tag: "Ophören, #%{tag} to folgen" welcome_to_diaspora: "Willkomen to diaspora*, %{name}!" - new: - create: "Anleggen" - name: "Noom (nur för di sichtbor)" no_contacts_message: community_spotlight: "vörstellten Gemeenschaftsmitglieder" or_spotlight: "Oder du kannst mit de %{link} deelen" try_adding_some_more_contacts: "Du kannst mehr Kontakte seuken oder inlooden." you_should_add_some_more_contacts: "Du schullst een poor mehr Kontakte schluten!" - no_posts_message: - start_talking: "Noch keener het wat seggt!" seed: acquaintances: "Bekannte" family: "Familie" @@ -220,7 +181,6 @@ nds: update: failure: "De Noom von dien Aspekt, %{name}, wör to lang ton Speichern." success: "Dien Aspekt, %{name}, is erfolgriek ännert worn." - back: "Trüch" blocks: create: failure: "Ik kun dissen Bruker nich ignorieren. #evasion" @@ -232,22 +192,15 @@ nds: explanation: "Schriev nee’e Bidräg von öberall, indem du dissen Link to diene Leseteken dortaudeist => %{link}." heading: "Leseteken." post_something: "Schriev wat in diaspora*" - post_success: "Schreeven! Mok tau!" cancel: "Avbreken" comments: new_comment: comment: "Kommenteeren" commenting: "Kommenteer..." - one: "1 Kommentar" - other: "%{count} Kommentare" - zero: "Keene Kommentare" contacts: - create: - failure: "Kun keen Kontakt schluten" index: add_a_new_aspect: "Dau een nee’en Kontakt dortau" add_contact: "Kontakt schluten" - add_to_aspect: "Kontakte to %{name} dortaudaun" all_contacts: "Alle Kontakte" community_spotlight: "vörstellten Gemeenschaftsmitglieder" my_contacts: "Miene Kontakte" @@ -257,15 +210,10 @@ nds: start_a_conversation: "Fang een Schnack an" title: "Kontakte" user_search: "Kontaktseuk" - your_contacts: "Diene Kontakte" - sharing: - people_sharing: "Lüüd, de mit di deelt:" spotlight: community_spotlight: "Vörstellte Gemeenschaftsmitglieder" suggest_member: "schlo wen vör" conversations: - conversation: - participants: "Bedeeligte" create: fail: "Ungültige Noricht" no_contact: "He, du muss erst Kontakt schluten!" @@ -273,20 +221,12 @@ nds: destroy: delete_success: "Schnack erfolgriek löscht" hide_success: "Schnack erfolgriek versteken" - helper: - new_messages: - one: "1 nee’e Noricht" - other: "%{count} nee’e Norichten" - zero: "Keene nee’en Norichten" index: conversations_inbox: "Schnacks – Ingang" - create_a_new_conversation: "Fang een nee’en Schnack an" inbox: "Ingang" new_conversation: "Nee’en Schnack" - no_conversation_selected: "Keen Schnack utwählt" no_messages: "Keene Norichten" new: - abandon_changes: "Ännerungen opgeben?" send: "Schicken" sending: "Schick..." subject: "Sook" @@ -309,10 +249,6 @@ nds: error_messages: helper: correct_the_following_errors_and_try_again: "Kiek mol de folgenden Fehler dörch und verseuk dat nochmol." - invalid_fields: "Ungültige Felder" - login_try_again: "Bidde <a href='%{login_link}'>meld di an</a> und verseuk dat nochmol." - post_not_public: "De Bidrag, den du verseukst, di antokieken, is nich öffentlich!" - post_not_public_or_not_exist: "Den Bidrag, den du verseukst di antokieken, gift dat nich oder he is nich öffentlich!" fill_me_out: "Füll mi ut" find_people: "Lüüd or #Tags finnen" help: @@ -452,45 +388,27 @@ nds: tutorial: "Anleidung" tutorials: "Anleidungen" wiki: "Wiki" - hide: "Versteken" - ignore: "Ignorieren" - invitation_codes: - excited: "%{name} is hen und weg, di hier to sehn." invitations: a_facebook_user: "Een Facebook-Bruker" check_token: not_found: "Inlodungstoken nich funnen" create: - already_contacts: "Du bist schon mit disse Person verbunnen" - already_sent: "Du hest disse Person schon inlod." empty: "Bidde geev minstens eene E-Mail-Adress in." no_more: "Du kannst keene Inlodungen mehr schicken." note_already_sent: "Inlodungen sind schon schickt worn an: %{emails}" - own_address: "Du kannst keene Inlodung an diene eegene Adress schicken." rejected: "Bi disse E-Mail-Adressen geev dat Probleme: " sent: "Inlodungen sind schickt worn an: %{emails}" - edit: - accept_your_invitation: "Nimm diene Inlodung an" - your_account_awaits: "Dien Konto töövt op di!" new: - already_invited: "Disse Lüüd hebbt diene Inlodung nich annommen:" - aspect: "Aspekt" - check_out_diaspora: "Bekiek mol diaspora*!" codes_left: one: "Eene Inlodung op dissen Code öber" other: "%{count} Inlodungen op dissen Code öber" zero: "Keene Inlodungen op dissen Code öber" comma_separated_plz: "Du kannst mehrere E-Mail-Adressen dörch Kommas trennt ingeben." - if_they_accept_info: "wenn se annehmt, ward se von sülbst to den Aspekt dortaudoon, in den du jüm inlod hest." invite_someone_to_join: "Lod eenen to diaspora* in!" language: "Sprook" paste_link: "Deel dissen Link mit diene Frünnen oder schick jüm direkt een Nettbreef dormit, üm jüm to diaspora* intoloden." - personal_message: "Persönliche Noricht" - resend: "Nochmol schicken" send_an_invitation: "Eene Inlodung schicken" - send_invitation: "Inladung afschicken" sending_invitation: "Schick Inlodung..." - to: "An" layouts: application: back_to_top: "Trüch no boben" @@ -500,35 +418,13 @@ nds: statistics_link: "Podstatistiken" toggle: "Mobile Ansicht ümschalten" whats_new: "Wat gift dat Nee’es?" - your_aspects: "Diene Aspekte" header: - admin: "Admin" - blog: "Blog" code: "Code" - help: "Hülp" - login: "Anmelden" logout: "Afmelden" profile: "Profil" - recent_notifications: "Letzte Benorichtigungen" settings: "Instellungen" - view_all: "Alle ankieken" - likes: - likes: - people_dislike_this: - one: "%{count} Person mag dat nich" - other: "%{count} Lüüd mögt dat nich" - zero: "Keener mag dat nich" - people_like_this: - one: "%{count} Person mag dat" - other: "%{count} Lüüd mögt dat" - zero: "Keener mag dat" - people_like_this_comment: - one: "Eener mag dissen Kommentar" - other: "%{count} Lüüd mögt dissen Kommentar" - zero: "Keener mag dissen Kommentar" limited: "Inschränkt" more: "Mehr" - next: "Neegste" no_results: "Keene Resultate funnen" notifications: also_commented: @@ -543,11 +439,6 @@ nds: one: "%{actors} het dien Bidrag %{post_link} kommentiert." other: "%{actors} hebbt dien Bidrag %{post_link} kommentiert." zero: "Keener het dien Bidrag %{post_link} kommentiert." - helper: - new_notifications: - one: "Eene nee’e Benorichtigung" - other: "%{count} nee’e Benorichtigungen" - zero: "Keene nee’en Benorichtigungen" index: all_notifications: "Alle Benorichtigungen" and: "und" @@ -600,7 +491,6 @@ nds: a_limited_post_comment: "Dat gift een nee’en Kommentar op een inschränkten Bidrag för di to’n Ankieken op diaspora*." a_post_you_shared: "een Bidrag." a_private_message: "Dat gift eene nee’e private Noricht för di to’n Ankieken op diaspora*." - accept_invite: "Nehm diene diaspora*-Inlodung an!" click_here: "Klick hier" comment_on_post: reply: "Op den Bidrag von %{name} antwoorten oder em ankieken >" @@ -639,7 +529,6 @@ nds: liked: "%{name} mag dien Bidrag" view_post: "Bidrag ankieken >" mentioned: - mentioned: "het di in een Bidrag erwähnt:" subject: "%{name} het di op diaspora* erwähnt" private_message: reply_to_or_view: "Op dissen Schnack antwoorten or em ankieken >" @@ -662,20 +551,9 @@ nds: to_change_your_notification_settings: "üm diene Benorichtigungsinstellungen to ännern" nsfw: "NSFW (unpassend för den Arbeitsplatz)" ok: "OK" - or: "or" - password: "Passwoord" - password_confirmation: "Passwoordbestätigung" people: add_contact: invited_by: "Du bist inlod worn von" - add_contact_small: - add_contact_from_tag: "Kontakt öber een Hashtag schluten" - aspect_list: - edit_membership: "Aspekttaugehörigkeit ännern" - helper: - is_not_sharing: "%{name} deelt nich mit di" - is_sharing: "%{name} deelt mit di" - results_for: " Resultate för %{params}" index: couldnt_find_them: "Kunnst du jüm nich finnen?" looking_for: "Seukst du no Bidräg, de mit %{tag_link} taggt sind?" @@ -684,99 +562,46 @@ nds: results_for: "%{search_term} entsprekende Bruker" searching: "Seuk, bidde weest geduldig..." send_invite: "Immer noch nix? Schick ne Inlodung!" - one: "1 Person" - other: "%{count} Lüüd" person: - add_contact: "Kontakt schluten" - already_connected: "Schon verbunnen" - pending_request: "Utstohnde Anfroog" thats_you: "Dat bist du!" profile_sidebar: bio: "Beschriebung" born: "Geburtsdag" - edit_my_profile: "Mien Profil ännern" gender: "Geschlecht" - in_aspects: "In Aspekte" location: "Ort" - photos: "Bilder" - remove_contact: "Kontakt löschen" - remove_from: "%{name} ut %{aspect} rutdaun?" show: closed_account: "Dit Konto is taumokt worn." does_not_exist: "De Person gift dat nich!" has_not_shared_with_you_yet: "%{name} het noch keene Bidräg mit di deelt!" - ignoring: "Du ignorierst alle Bidräg von %{name}." - incoming_request: "%{name} will mit di deelen" - mention: "Erwähnung" - message: "Noricht" - not_connected: "Du deels nich mit disse Person" - recent_posts: "Letzte Bidräg" - recent_public_posts: "Letzte öffentliche Bidräg" - return_to_aspects: "Trüch to diene Aspekte-Siet" - see_all: "Alle ankieken" - start_sharing: "Mit Deelen anfangen" - to_accept_or_ignore: "üm dat antonehmen oder to ignorieren." - sub_header: - add_some: "Dau een poor dortau" - edit: "Ännern" - you_have_no_tags: "Du hest keene Tags!" - webfinger: - fail: "Deit mi leed, wi kunnen %{handle} nich finnen." - zero: "Keene Lüüd" photos: - comment_email_subject: "Bild von %{name}" create: integrity_error: "Hoochloden von dat Bild fehlschloon. Bist du di sicher, dat dat een Bild wör?" runtime_error: "Hoochloden von dat Bild fehlschloon. Bist du di sicher, dat du di anschnallt hest?" type_error: "Hoochloden von dat Bild fehlschloon. Bist du di sicher, dat du een Bild dortaudoon hest?" destroy: notice: "Bild löscht." - edit: - editing: "Änner" - new: - back_to_list: "Trüch to de List" - new_photo: "Nee’es Bild" - post_it: "Schriev dat!" new_photo: empty: "{file} is leer, bidde wähl de Dateien noch mol ohne er ut." invalid_ext: "{file} het een ungültiges Enn. Nur {extensions} sind erlaubt." size_error: "{file} is to groot, Dateien dröfft höchstens {sizeLimit} groot ween." new_profile_photo: - or_select_one_existing: "oder een von de %{photos} utwählen, de du schon hoochlod hest." upload: "Nee’es Profilbild hoochloden!" - photo: - view_all: "Alle Bilder von %{name} ankieken" show: - collection_permalink: "Permalink to disse Sammlung" - delete_photo: "Bild löschen" - edit: "Ännern" - edit_delete_photo: "Bildbeschriebung ännern / Bild löschen" - make_profile_photo: "As Profilbild nehmen" show_original_post: "Originalbidrag anzeigen" - update_photo: "Bild aktualisieren" - update: - error: "Kun Bild nich ännern." - notice: "Bild is erfolgriek aktualisiert worn." posts: presenter: title: "Een Bidrag von %{name}" show: - destroy: "Löschen" - not_found: "Deit mi leed, wi kunnen den Bidrag nich finnen." - permalink: "Permalink" photos_by: one: "Een Bild von %{author}" other: "%{count} Biller von %{author}" zero: "Keene Biller von %{author}" reshare_by: "Wiederseggt von %{author}" - previous: "Vörherige" privacy: "Privatsphäre" - privacy_policy: "Datenschutz" profile: "Profil" profiles: edit: allow_search: "Lüüd erlauben, op diaspora* no di to seuken" - edit_profile: "Profil ännern" first_name: "Vörnoom" last_name: "Nonoom" nsfw_check: "Markier alles, wat ik deel, as NSFW" @@ -788,8 +613,6 @@ nds: your_location: "Dien Ort" your_name: "Dien Noom" your_photo: "Dien Bild" - your_private_profile: "Dien privates Profil" - your_public_profile: "Dien öffentliches Profil" your_tags: "Beschriev di sülbst in fiev Wüür" your_tags_placeholder: "To’n Bispeel #Filme #Katten #Reisen #Lehrer #NewYork" update: @@ -804,26 +627,16 @@ nds: closed: "Registrerungen sind op dissen diaspora*-Pod schloten." create: success: "Du bist nu bi diaspora*!" - edit: - cancel_my_account: "Schlut mien Konto" - edit: "%{name} ännern" - leave_blank: "(lot dat leer, wenn du dat nich ännern willst)" - password_to_confirm: "(wi brukt dien jetziges Passwoort, üm diene Ännerungen to bestätigen)" - unhappy: "Unglücklich?" - update: "Ännern" invalid_invite: "Dien Inlodungslink is nich mehr gültig!" new: - create_my_account: "Legg mien Konto an!" email: "E-Mail-Adress" enter_email: "Geev dien E-Mail-Adress in" enter_password: "Geev een Passwoort in (minnens söss Teken)" enter_password_again: "Geev dat glieke Passwoort wie vörher in" enter_username: "Seuk di een Brukernoom ut (nur Bookstoven, Nummern und Ãœnnerstriche)" - join_the_movement: "Mok bi de Bewegung mit!" password: "Passwoort" password_confirmation: "Passwoortbestätigung" sign_up: "Registrieren" - sign_up_message: "Soziales Nettwarken mit een ♥" terms_link: "Nutzungsbedingungen" username: "Brukernoom" report: @@ -837,38 +650,12 @@ nds: destroyed: "De Bidrag is löscht worn" failed: "Irgendwat in scheevgoon" title: "Meldungsöbersicht" - requests: - create: - sending: "Schick" - sent: "Du hest beden, mit %{name} to deelen. He schull dat sehn, wenn he sik dat neegste Mol bi diaspora* anmeld." - destroy: - error: "Bidde wähl een Aspekt ut!" - ignore: "Ignorierte Kontaktanfroogen." - success: "Du deelst nu." - helper: - new_requests: - one: "Eene nee’e Anfroog!" - other: "%{count} nee’e Anfroogen!" - zero: "Keene nee’en Anfroogen" - manage_aspect_contacts: - existing: "Bestohnde Kontakte" - manage_within: "Verwalt Kontakte in" - new_request_to_person: - sent: "Schickt!" reshares: comment_email_subject: "%{resharer} sien Version von %{author} sien Bidrag" - create: - failure: "Dat geev een Fehler bi’n Wiederseggen von den Bidrag." reshare: deleted: "Originalbidrag von’n Autor löscht." - reshare: - one: "Een mol wiederseggt" - other: "%{count} mol wiederseggt" - zero: "Keen mol wiederseggt" reshare_confirmation: "Bidrag von %{author} wiederseggen?" - reshare_original: "Original wiederseggen" reshared_via: "Wiederseggt öber" - show_original: "Original anzeigen" search: "Seuken" services: create: @@ -880,10 +667,6 @@ nds: success: "Autorisierung erfolgriek rückgängig mokt." failure: error: "Dat geev een Fehler bin Verbinnen mit den Deenst" - finder: - fetching_contacts: "diaspora* lod diene Frünnen von %{service} grood in, bidde kiek in een poor Minuten noch mol trüch." - no_friends: "Keene Facebook-Frünnen funnen." - service_friends: "%{service}-Frünnen" index: connect: "Verbinnen" disconnect: "Verbinnung trennen" @@ -891,54 +674,23 @@ nds: logged_in_as: "Anmeld as %{nickname}." not_logged_in: "Grood nich anmeld." really_disconnect: "Verbinnung to %{service} trennen?" - inviter: - click_link_to_accept_invitation: "Folg dissen Link, üm diene Inlodung antonehmen" - join_me_on_diaspora: "Komm to mi op diaspora*" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "Inloden" - not_on_diaspora: "Noch nich op diaspora*" - resend: "Nochmol schicken" settings: "Instellungen" - share_visibilites: - update: - post_hidden_and_muted: "De Bidrag von %{name} is verstekt worn und Benorichtigungen sind stummschalt worn." - see_it_on_their_profile: "Wenn du nee’es von dissen Bidrag sehn willst, bekiek de Profilsiet von %{name}." shared: - add_contact: - add_new_contact: "Een nee’en Kontakt schluten" - create_request: "Anhand von de diaspora*-ID finnen" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Geev een diaspora*-Brukernoom in:" - know_email: "Du kennst jümmer E-Mail-Adress? Du schust jüm inloden" - your_diaspora_username_is: "Dien diaspora*-Brukernoom is: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Kontakt schluten" toggle: one: "In een Aspekt" other: "In %{count} Aspekte" zero: "Kontakt sluten" - contact_list: - all_contacts: "Alle Kontakte" - footer: - logged_in_as: "Anmeld as %{name}" - your_aspects: "Diene Aspekte" invitations: by_email: "Per E-Mail" - dont_have_now: "Du hest grood keene, aber mehr Inlodungen kommt bald!" - from_facebook: "Von Facebook" - invitations_left: "%{count} öber" - invite_someone: "Lod wen in" invite_your_friends: "Lod dien Frünnen in" invites: "Inlodungen" - invites_closed: "Inlodungen sind op dissen diaspora*-Pod grood schloten" share_this: "Deel dissen Link öber E-Mail, dien Blog oder soziale Nettwaark!" - notification: - new: "Nee’e %{type} von %{from}" public_explain: atom_feed: "Atom-Feed" control_your_audience: "Legg diene anpielte Grupp fast" @@ -948,44 +700,20 @@ nds: share: "Deelen" title: "Verbunnene Deenste inrichten" publisher: - all: "Alle" - all_contacts: "Alle Kontakte" discard_post: "Bidrag opgeben" formatWithMarkdown: "Du kannst %{markdown_link} nehmen, üm dien Bidrag to formatieren" - make_public: "Öffentlich moken" new_user_prefill: hello: "Moin alle, Ik bin #%{new_user_tag}. " i_like: "Ik interessier mi för %{tags}. " invited_by: "Danke för de Inlodung, " newhere: "neehier" - poll: - option: "Mööglichkeit 1" - question: "Froog" - post_a_message_to: "Schriev eene Noricht an %{aspect}" posting: "Schriev..." - preview: "Vörschau" - publishing_to: "veröffentlichen an: " share: "Deelen" - share_with: "Deelen mit" upload_photos: "Biller hoochloden" whats_on_your_mind: "Wat geiht di dörch den Kopp?" - reshare: - reshare: "Wiederseggen" stream_element: - connect_to_comment: "Verbinn di mit dissen Bruker, üm sien Bidrag to kommenteren" - currently_unavailable: "Kommentieren is grood nich parat" - dislike: "Mag ik nich" - hide_and_mute: "Bidrag versteken und stummschalten" - ignore_user: "%{name} ignorieren" - ignore_user_description: "Bruker ignorieren und ut alle Aspekte rutdaun?" - like: "Mag ik" - nsfw: "Disse Bidrag is von sien Autor as NSFW markiert worn. %{link}" - shared_with: "Deelt mit: %{aspect_names}" - show: "Anzeigen" - unlike: "Mag ik nich mehr" via: "Öber %{link}" via_mobile: "Öber mobil" - viewable_to_anyone: "Disse Bidrag is för alle in’t Internet sichtbor." simple_captcha: label: "Geev den Code in dat Feld in:" message: @@ -1008,21 +736,12 @@ nds: status_messages: create: success: "Erfolgriek erwähnt: %{names}" - destroy: - failure: "Kunn Bidrag nich löschen" - helper: - no_message_to_display: "Keene Norichten ton Anzeigen." new: mentioning: "Erwähn: %{person}" too_long: "Bidde mok dien Bidrag kötter as %{count} Teken. In Moment is he %{current_length} Teken lang" stream_helper: - hide_comments: "Verstek alle Kommentare" no_more_posts: "Du bist an't Enn von'n Stream ankommen." no_posts_yet: "Dat gift noch keene Bidräg." - show_comments: - one: "Zeig een annern Kommentar" - other: "Zeig %{count} annere Kommentare" - zero: "Keene annern Kommentore" streams: activity: title: "Mien Rümröören" @@ -1048,26 +767,15 @@ nds: title: "Öffentliches Rümröören" tags: title: "Bidräg tagged mit: %{tags}" - tag_followings: - create: - failure: "Kun #%{name} nich folgen. Folgst du dat schon?" - none: "Du kanns keen leeres Tag folgen!" - success: "Hurra! Du folgst nu #%{name}." - destroy: - failure: "Kun nich ophören, #%{name} to folgen. Möglicherwies folgst du dat schon gor nich mehr?" - success: "Alas! Du folgst #%{name} nich mehr." tags: show: follow: "Folg #%{tag}" - following: "Du folgst #%{tag}" none: "Den leeren Tag gift dat nich!" stop_following: "#%{tag} nich mehr folgen" tagged_people: one: "1 Person taggt mit %{tag}" other: "%{count} Lüüd taggt mit %{tag}" zero: "Keener taggt mit %{tag}" - terms_and_conditions: "Nutzungsbedingungen" - undo: "Rückgängig moken?" username: "Brukernaam" users: confirm_email: @@ -1088,7 +796,6 @@ nds: character_minimum_expl: "mut minstens söss Teken lang ween" close_account: dont_go: "He, bidde goh nich!" - if_you_want_this: "Wenn du wirklich willst, dat dat passiert, geev dien Passwoort ünnen in und klick op „Konto schluten“" lock_username: "Dien Brukernoom ward spart. Du warst op dissen Pod keen nee'es Konto mit de sülbe ID anleggen künnen." locked_out: "Du warst afmeld und ut dien Konto utspart warn, bit dat löscht worn is." make_diaspora_better: "Wi deen dat good finnen, wenn du bliffst un uns hülpst, diaspora* beter to moken, statt wegtogohn. Wenn du aber wirklich weggohn willst, ward dat hier as neegstes passiern:" @@ -1101,13 +808,11 @@ nds: current_password_expl: "dat, mit dat du di anmeldst..." download_export: "Mien Profil rünnerloden" download_export_photos: "Miene Bilder rünnerloden" - download_photos: "Miene Bilder rünnerloden" edit_account: "Konto ännern" email_awaiting_confirmation: "Wie hebbt di een Link ton In-Gang-Setten an %{unconfirmed_email} schickt. Bit du dissen Link folgst und diene nee’e E-Mail-Adress in gang sets, ward wi wieder diene ole Adress %{email} nehmen." export_data: "Daten exportieren" export_photos_in_progress: "Wi verarbeit grood diene Bilder. Bidde kiek gliek noch mol trüch." following: "Instellungen för’t Deelen" - getting_started: "Instellungen för nee’e Bruker" liked: "wen dien Bidrag mag" mentioned: "du in een Bidrag erwähnt warst" new_password: "Nee’es Passwoort" @@ -1131,7 +836,6 @@ nds: connect_to_facebook_link: "Mit dien Facebook-Konto verbinnen" hashtag_explanation: "Mit Hashtags kannst du öber diene Interessen schnacken und jüm folgen. Se sind ok eene tolle Mööglichkeit, üm nee'e Lüüd op diaspora* kennen to lernen." hashtag_suggestions: "Verseuk mol, Tags wie #Kunst, #Filme, #gif oder so to folgen" - saved: "Speichert!" well_hello_there: "Naja, hallo erstmol!" what_are_you_in_to: "Wat magst du?" who_are_you: "Wer bist du?" @@ -1154,12 +858,6 @@ nds: settings_updated: "Instellungen aktualisiert" unconfirmed_email_changed: "E-Mail-Adress ännert. Mutt in gang set warn." unconfirmed_email_not_changed: "Ännern von de E-Mail-Adress fehlschloon" - webfinger: - fetch_failed: "Kunn Webfinger-Profil för %{profile_url} nich afropen" - hcard_fetch_failed: "Dat geev een Problem bien afropen von de hcard för %{account}" - not_enabled: "Dat süt so ut, as op Webfinger för %{account} sien Host nich aktiviert is" - xrd_fetch_failed: "Dat geev een Problem bien afropen von de xrd von dat Konto %{account}" - welcome: "Willkomen!" will_paginate: next_label: "neegste »" previous_label: "« vörherige" \ No newline at end of file diff --git a/config/locales/diaspora/ne.yml b/config/locales/diaspora/ne.yml index 0220eff542507e097a1d6e8216a8c268f6e5d6df..93d9f1203c10f8f5b0400ea07e234e26cc4bfce0 100644 --- a/config/locales/diaspora/ne.yml +++ b/config/locales/diaspora/ne.yml @@ -5,13 +5,7 @@ ne: - _home: "गृहपृषà¥à¤ " - _photos: "तसà¥à¤µà¥€à¤°à¤¹à¤°à¥" _services: "सेवाहरà¥" - ago: "%{time} अघि" - application: - helper: - unknown_person: "अपरिचित वà¥à¤¯à¤•à¥à¤¤à¤¿" aspects: index: help: @@ -28,13 +22,10 @@ ne: send: "पठाउनà¥à¤¹à¥‹à¤¸à¥" delete: "मेटà¥à¤¨à¥à¤¹à¥‹à¤¸à¥" email: "ईमेल" - hide: "लà¥à¤•à¤¾à¤‰à¤¨à¥à¤¹à¥‹à¤¸à¥" invitations: a_facebook_user: "फेसबà¥à¤• पà¥à¤°à¤¯à¥‹à¤—करà¥à¤¤à¤¾" new: language: "à¤à¤¾à¤·à¤¾" - personal_message: "वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त सनà¥à¤¦à¥‡à¤¶" - resend: "पà¥à¤¨à¤ƒ पठाउनà¥à¤¹à¥‹à¤¸à¥" notifications: index: and: "र" @@ -42,12 +33,7 @@ ne: hello: "नमसà¥à¤•à¤¾à¤° %{name} !" thanks: "धनà¥à¤¯à¤µà¤¾à¤¦," ok: "ठीक छ" - or: "वा" - password: "गोपà¥à¤¯ शबà¥à¤¦" - photos: - comment_email_subject: "%{name}को तसà¥à¤µà¥€à¤°" privacy: "गोपनीयता" - privacy_policy: "गोपनीयता नीति" profiles: edit: first_name: "थर" @@ -58,12 +44,6 @@ ne: your_photo: "तपाईको तसà¥à¤µà¥€à¤°" public: "सारà¥à¤µà¤œà¤¨à¤¿à¤•" search: "खोज" - services: - finder: - service_friends: "%{service}का साथीहरà¥" - remote_friend: - invite: "निमà¥à¤¤à¥‹ पठाउनà¥à¤¹à¥‹à¤¸à¥" - resend: "पà¥à¤¨à¤ƒ पठाउनà¥à¤¹à¥‹à¤¸à¥" username: "पà¥à¤°à¤¯à¥‹à¤—करà¥à¤¤à¤¾ नाम" users: edit: @@ -71,7 +51,5 @@ ne: change_language: "à¤à¤¾à¤·à¤¾ परिवरà¥à¤¤à¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥" change_password: "गोपà¥à¤¯ शबà¥à¤¦ परिवरà¥à¤¤à¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥" current_password: "हालको गोपà¥à¤¯ शबà¥à¤¦" - download_photos: "आफà¥à¤¨à¥‹ तसà¥à¤µà¤¿à¤°à¤¹à¤°à¥ डाउनलोड गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥" new_password: "नयाठगोपà¥à¤¯ शबà¥à¤¦" - your_email: "तपाईको ईमेल" - welcome: "सà¥à¤µà¤¾à¤—तम !" \ No newline at end of file + your_email: "तपाईको ईमेल" \ No newline at end of file diff --git a/config/locales/diaspora/nl.yml b/config/locales/diaspora/nl.yml index 93222e252a708c125f4fbab2b704bdce1c134028..af552a81dd3775fcc0b47aeed3b6db5fc7914a9c 100644 --- a/config/locales/diaspora/nl.yml +++ b/config/locales/diaspora/nl.yml @@ -6,11 +6,8 @@ nl: _applications: "Applicaties" - _comments: "Reacties" _contacts: "Contacten" _help: "Help" - _home: "Home" - _photos: "Foto's" _services: "Diensten" _statistics: "Statistieken" _terms: "Voorwaarden" @@ -53,12 +50,19 @@ nl: taken: "is al in gebruik." admins: admin_bar: + dashboard: "Dashboard" pages: "Pagina's" + pod_network: "Pod netwerk" pod_stats: "Pod Statistieken" report: "Meldingen" sidekiq_monitor: "Sidekiq monitor" user_search: "Gebruiker Zoeken" weekly_user_stats: "Wekelijkse Gebruikersstatistieken" + dashboard: + fetching_diaspora_version: "Bepalen laatste versie van diaspora*..." + pod_status: "Pod status" + pods: + pod_network: "Pod netwerk" stats: 2weeks: "2 weken" 50_most: "50 meest populaire tags" @@ -92,6 +96,7 @@ nl: email: "E-mailadres" guid: "GUID" id: "ID" + invite_token: "Uitnodig token" last_seen: "Laatst gezien" ? "no" : Nee @@ -109,7 +114,10 @@ nl: are_you_sure_unlock_account: "Weet je zeker dat je dit account wilt deblokkeren?" close_account: "Afsluiten account" email_to: "E-mail om uit te nodigen" + invite: "Nodig uit" + lock_account: "Blokkeer account" under_13: "Toon gebruikers onder de 13 (COPPA)" + unlock_account: "Deblokkeer account" users: one: "%{count} gebruiker gevonden" other: "%{count} gebruikers gevonden" @@ -125,13 +133,63 @@ nl: other: "Aantal nieuwe gebruikers deze week: %{count}" zero: "Aantal nieuwe gebruikers deze week: geen" current_server: "Huidige server datum is %{date}" - ago: "%{time} geleden" all_aspects: "Alle aspecten" - application: - helper: - unknown_person: "Onbekende persoon" - video_title: - unknown: "Onbekende Videotitel" + api: + openid_connect: + authorizations: + destroy: + fail: "De poging om de autorisatie met ID %{id} in te trekken is mislukt" + new: + access: "%{name} wil toegang tot" + approve: "Toestaan" + bad_request: "Ontbrekende client id of redirect URI" + client_id_not_found: "Geen client met client_id %{client_id} met doorverwijzing URI %{redirect_uri} gevonden" + deny: "Weigeren" + no_requirement: "%{name} vereist geen permissies" + redirection_message: "Weet je zeker dat je toegang wilt verlenen tot %{redirect_uri}" + error_page: + contact_developer: "Neem contact op met de ontwikkelaar van de applicatie en voeg de gedetailleerde foutboodschap bij:" + could_not_authorize: "De applicatie kon niet worden geautoriseerd" + login_required: "Je moet eerst inloggen voordat je deze applicatie kunt autoriseren" + title: "Ohhh! Er ging iets verkeerd :(" + scopes: + aud: + description: "Dit verleent aud toegang tot de applicatie" + name: "aud" + name: + description: "Dit verleent naam toegang tot de applicatie" + name: "naam" + nickname: + description: "Dit verleent bijnaam toegang tot de applicatie" + name: "bijnaam" + openid: + description: "Dit staat de applicatie toe om je basisprofiel te bekijken" + name: "basisprofiel" + picture: + description: "Dit verleent afbeelding toegang tot de applicatie" + name: "afbeelding" + profile: + description: "Dit staat de applicatie toe je uitgebreide profiel te zien" + name: "uitgebreid profiel" + read: + description: "Dit staat de applicatie toe je stream, je gesprekken en je complete profiel te zien" + name: "lees profiel, stream en gesprekken" + sub: + description: "Dit verleent sub toegang tot de applicatie" + name: "sub" + write: + description: "Dit staat de applicatie toe nieuwe berichten te plaatsen, gesprekken te schrijven en reacties in te sturen" + name: "bekijk berichten, gesprekken en reacties" + user_applications: + index: + access: "%{name} heeft toegang tot:" + edit_applications: "Applicaties" + no_requirement: "%{name} heeft geen permissies nodig" + title: "Toegestane applicaties" + no_applications: "Je hebt geen geautoriseerde applicaties" + policy: "Zie het privacystatement van de app" + revoke_autorization: "Intrekken" + tos: "Zie de gebruiksvoorwaarden van de app" are_you_sure: "Weet je het zeker?" are_you_sure_delete_account: "Weet je zeker dat je jouw account wil sluiten? Dit kan niet teruggedraaid worden!" aspect_memberships: @@ -147,48 +205,27 @@ nl: success: "Contact is met succes toegevoegd aan aspect." aspect_listings: add_an_aspect: "+ Voeg aspect toe" - deselect_all: "Deselecteer alles" - edit_aspect: "Bewerk %{name}" - select_all: "Selecteer alles" aspect_stream: make_something: "Schrijf iets" stay_updated: "Blijf op de hoogte" stay_updated_explanation: "De standaard stream is gevuld met berichten van al je contacten, met alle tags die je volgt en met berichten van een aantal creatieve leden van de community." - contacts_not_visible: "Contacten in dit aspect zullen elkaar niet kunnen zien." - contacts_visible: "Contacten in dit aspect zullen elkaar kunnen zien." - create: - failure: "Aanmaken van aspect is mislukt." - success: "Je nieuwe aspect %{name} is aangemaakt" destroy: failure: "%{name} kon niet worden verwijderd." success: "%{name} is met succes verwijderd." success_auto_follow_back: "%{name} is succesvol verwijderd. Je gebruikte dit aspect voor automatisch teruggevolgde gebruikers. Selecteer in je instellingen een nieuw aspect waarin je automatisch teruggevolgde gebruikers kunt plaatsen." edit: - aspect_chat_is_enabled: "Contacten binnen dit aspect kunnen met jou chatten." - aspect_chat_is_not_enabled: "Contacten binnen dit aspect kunnen niet met jou chatten." aspect_list_is_not_visible: "Contacten in dit aspect kunnen elkaar niet zien:" aspect_list_is_visible: "contactlijst van aspect is zichtbaar voor anderen in aspect" confirm_remove_aspect: "Weet je zeker dat je dit aspect wilt verwijderen?" - grant_contacts_chat_privilege: "Contacten in aspect chat autorisatie verlenen?" - make_aspect_list_visible: "Contacten in dit aspect voor elkaar zichtbaar maken?" - remove_aspect: "Verwijder dit aspect" rename: "Hernoemen" - set_visibility: "Instellen zichtbaarheid" update: "Bijwerken" updating: "Aan het bijwerken" index: - diaspora_id: - content_1: "Jouw diaspora* ID is:" - content_2: "Geef dit aan anderen, zodat ze je op diaspora* kunnen vinden." - heading: "diaspora* ID" donate: "Doneer" - handle_explanation: "Dit is jouw diaspora* ID. Net als een e-mailadres kun je dit aan anderen geven zodat ze je kunnen bereiken." help: any_problem: "Problemen?" contact_podmin: "Neem contact op met je podbeheerder!" do_you: "Heb je:" - email_feedback: "%{link} jouw feedback, als dat jou voorkeur heeft." - email_link: "E-mail" feature_suggestion: "... een %{link} suggestie?" find_a_bug: "... een %{link} gevonden?" have_a_question: "... een %{link}?" @@ -201,31 +238,21 @@ nl: tutorial_link_text: "Instructies" tutorials_and_wiki: "%{faq}, %{tutorial}, %{wiki}: hulp voor je eerste stappen." introduce_yourself: "Dit is jouw Stream. Spring erin en introduceer jezelf." - keep_diaspora_running: "Houdt de diaspora* ontwikkeling gaande met een maandelijkse bijdrage!" keep_pod_running: "Hou %{pod} draaiend en koop een cafeïneshot voor de servers met een maandelijkse donatie." new_here: follow: "Volg %{link} en verwelkom nieuwe diaspora* gebruikers!" learn_more: "Meer informatie" title: "Nieuwe gebruikers verwelkomen" - no_contacts: "Geen contacten" - no_tags: "+ Vind een tag" - people_sharing_with_you: "Mensen die met jou delen" - post_a_message: "Plaats een bericht >>" services: content: "Je kunt de volgende services met diaspora* verbinden:" heading: "Verbind diensten" - unfollow_tag: "Stop met volgen van #%{tag}" welcome_to_diaspora: "Welkom bij diaspora*, %{name}!" - new: - create: "Aanmaken" - name: "Naam (alleen zichtbaar voor jou)" no_contacts_message: community_spotlight: "Community aanrader" + invite_link_text: "uitnodigen" or_spotlight: "Of je kan delen met %{link}\n" - try_adding_some_more_contacts: "Je kunt zoeken en meer contacten uitnodigen." + try_adding_some_more_contacts: "Je kunt zoeken of %{invite_link} meer contacten uitnodigen." you_should_add_some_more_contacts: "Voeg wat meer contacten toe!" - no_posts_message: - start_talking: "Nog niemand heeft iets gezegd!" seed: acquaintances: "Kennissen" family: "Familie" @@ -234,34 +261,26 @@ nl: update: failure: "De naam van je aspect, %{name}, is te lang om op te slaan." success: "Je aspect, %{name}, is succesvol aangepast." - back: "Terug" blocks: create: failure: "Ik kon die gebruiker niet negeren. #vermijding" success: "Oké, deze gebruiker zul je niet meer in je stream zien. #silencio!" destroy: - failure: "Ik kon niet stoppen die gebruiker te negeren. #vermijding\n" + failure: "Ik kon niet stoppen die gebruiker te negeren. #vermijding" success: "Eens zien wat ze te zeggen hebben! #zeghallo" bookmarklet: explanation: "Publiceer van overal naar diaspora* door deze bladwijzer op te slaan => %{link}." heading: "Bookmarklet" post_something: "Publiceer op diaspora*" - post_success: "Gepost!" cancel: "Annuleren" comments: new_comment: comment: "Reactie" commenting: "Reageren..." - one: "1 reactie" - other: "%{count} reacties" - zero: "Geen reacties" contacts: - create: - failure: "Verbinding maken mislukt" index: add_a_new_aspect: "Voeg een aspect toe" add_contact: "Toevoegen contactpersoon" - add_to_aspect: "Voeg contacten toe aan %{name}" all_contacts: "Alle contacten" community_spotlight: "Community aanrader" my_contacts: "Mijn contacten" @@ -269,19 +288,13 @@ nl: no_contacts_in_aspect: "Je hebt nog geen contacten in dit aspect. Hieronder staat de lijst met je huidige contacten die je aan dit aspect kunt toevoegen." no_contacts_message: "Bekijk %{community_spotlight} eens" only_sharing_with_me: "Delen alleen met mij" - remove_contact: "Verwijderen contactpersoon" start_a_conversation: "Plaats een bericht" title: "Contacten" user_search: "Zoek gebruiker" - your_contacts: "Jouw contacten" - sharing: - people_sharing: "Mensen die met jou delen:" spotlight: community_spotlight: "Community aanrader" suggest_member: "Suggereer een lid" conversations: - conversation: - participants: "Deelnemers" create: fail: "Ongeldig bericht" no_contact: "Hallo, je moet wel eerst een contactpersoon toevoegen!" @@ -289,20 +302,13 @@ nl: destroy: delete_success: "De conversatie is verwijderd" hide_success: "De conversatie is verborgen" - helper: - new_messages: - one: "1 nieuw bericht" - other: "%{count} nieuwe berichten\n" - zero: "Geen nieuwe berichten" index: conversations_inbox: "Conversaties - inbakje" - create_a_new_conversation: "Start een nieuwe conversatie" inbox: "Postvak In" new_conversation: "Nieuwe conversatie" - no_conversation_selected: "Geen privégesprek geselecteerd" no_messages: "Geen privéberichten" new: - abandon_changes: "Wijzigingen annuleren?" + message: "Bericht" send: "Verstuur" sending: "Verzenden..." subject: "Onderwerp" @@ -313,6 +319,7 @@ nl: show: delete: "Verwijder gesprek" hide: "Verberg en onderdruk gesprekken" + last_message: "Laatste bericht ontvangen %{timeago}" reply: "Beantwoorden" replying: "Beantwoorden..." date: @@ -325,10 +332,7 @@ nl: error_messages: helper: correct_the_following_errors_and_try_again: "Corrigeer de volgende fouten en probeer opnieuw." - invalid_fields: "Ongeldige velden" - login_try_again: "<a href='%{login_link}'>Log in</a> en probeer het opnieuw." - post_not_public: "Het bericht dat je probeert de bekijken is niet openbaar!" - post_not_public_or_not_exist: "Het bericht dat je wilt bekijken is niet openbaar, of het bestaat niet!" + need_javascript: "Deze website vereist JavaScript om goed te kunnen werken. Als je JavaScript hebt uitgeschakeld, adviseren we om het te activeren en deze pagina te herladen." fill_me_out: "Vul me in!" find_people: "Zoek mensen of #tags" help: @@ -552,46 +556,59 @@ nl: tutorial: "instructie" tutorials: "instructies" wiki: "wiki" - hide: "Verbergen" - ignore: "Negeren" + home: + default: + be_who_you_want_to_be: "Wees wie je wilt zijn" + be_who_you_want_to_be_info: "Heel veel netwerken willen dat je je echte identiteit gebruikt. diaspora* niet. Hier kun je zelf bepalen wie je wilt zijn en zo veel, of zo weinig delen als je wilt. Je maakt hier helemaal zelf uit hoeveel je wilt interacteren met andere mensen." + byline: "De sociale online wereld waar jij in control bent" + choose_your_audience: "Kies je publiek" + choose_your_audience_info: "diaspora*'s aspecten maken het mogelijk om uitsluitend te delen met de mensen waarmee jij dat wilt. Je kunt zo openbaar of privé zijn als je wilt. Deel een grappige foto met de hele wereld, of een groot geheim alleen met je beste vrienden. Jij bent in control." + headline: "Welkom op %{pod_name}" + own_your_data: "Beschik over je eigen gegevens" + own_your_data_info: "Veel netwerken verdienen hun geld door jouw gedrag en interacties vanuit jouw gegevens te analyseren om 'op maat gesneden' advertenties te serveren. diaspora* gebruikt je data alleen om je in de gelegenheid te stellen te communiceren en te delen met anderen." + podmin: + admin_panel: "beheerscherm" + byline: "Je staat op het punt om het internet te veranderen. Zullen we daar maar eens mee beginnen?" + configuration_info: "Open %{database_path} en %{diaspora_path} in je voorkeurs teksteditor en bestudeer ze grondig. Ze zijn rijkelijk voorzien van commentaar." + configure_your_pod: "Configureer je pod" + contact_irc: "bereik op op IRC" + contribute: "Draag bij" + contribute_info: "Maak diaspora* nog beter! Als je bugs vind, %{report_bugs}" + create_an_account: "Creëer een account" + create_an_account_info: "%{sign_up_link} voor een nieuw account." + faq_for_podmins: "FAQ voor pod beheerders in onze wiki" + getting_help: "Hulp vragen" + getting_help_info: "We namen een paar %{faq} inclusief aanvullende tips en trucs op en oplossingen voor de meest voorkomende problemen. En kom gerust op %{irc}." + headline: "Welkom, vriend." + make_yourself_an_admin: "Maak jezelf beheerder" + make_yourself_an_admin_info: "Je kunt instructies vinden in de %{wiki}. Dit zou een \"Beheer\" link aan he gebruikersmenu in de kop moeten toevoegen als je bent ingelogd. Het geeft je dingen als Zoeken gebruiker en stats voor je pod. Voor uitgebreide details over de operationele zaken van de pod ga je naar %{admin_panel}." + report_bugs: "meld ze" + update_instructions: "update instructies in de diaspora* wiki" + update_your_pod: "Update je pod" + update_your_pod_info: "Je vind %{update_instructions}" invitation_codes: - excited: "%{name} is blij je hier te zien." not_valid: "Deze uitnodigingscode is niet langer geldig" invitations: a_facebook_user: "Een Facebook gebruiker" check_token: not_found: "Uitnodigingstoken niet gevonden" create: - already_contacts: "Je bent al verbonden met deze persoon" - already_sent: "Je hebt deze persoon al uitgenodigd." empty: "Gelieve minstens 1 e-mailadres toe te voegen." no_more: "Je hebt geen uitnodigingen meer." note_already_sent: "Er zijn al uitnodigingen verstuurd naar: %{emails}" - own_address: "Het is niet mogelijk om een uitnodiging naar je eigen adres te sturen." rejected: "De volgende e-mailadressen gaven problemen: " sent: "Uitnodigingen zijn verzonden aan:" - edit: - accept_your_invitation: "Accepteer de uitnodiging" - your_account_awaits: "Jou account wacht op je!" new: - already_invited: "De volgende mensen hebben je uitnodiging niet geaccepteerd:" - aspect: "Aspect" - check_out_diaspora: "Kijk eens naar diaspora*!" codes_left: one: "Nog één uitnodiging over op deze code" other: "Nog %{count} uitnodigingen over op deze code" zero: "Geen uitnodigingen over op deze code" comma_separated_plz: "Je kan meerdere e-mail adressen toevoegen door ze te scheiden door komma's" - if_they_accept_info: "als hij of zij accepteert zal hij of zij toegevoegd worden aan het aspect waarvoor je hem of haar uitgenodigd hebt." invite_someone_to_join: "Nodig iemand uit om lid te worden van diaspora*!" language: "Taal" paste_link: "Deel deze link met je vrienden om ze uit te nodigen voor diaspora*, of e-mail ze de link direct." - personal_message: "Persoonlijk bericht" - resend: "Stuur opnieuw" send_an_invitation: "Stuur een uitnodiging" - send_invitation: "Verstuur uitnodiging" sending_invitation: "Versturen uitnodiging..." - to: "Aan" layouts: application: back_to_top: "Terug naar top" @@ -601,35 +618,14 @@ nl: statistics_link: "Pod statistieken" toggle: "Switch mobiele versie" whats_new: "Wat is nieuw op Diaspora?" - your_aspects: "Jouw aspecten" header: - admin: "Beheer" - blog: "Blog" code: "Code" - help: "Help" - login: "Inloggen" logout: "Uitloggen" profile: "Profiel" - recent_notifications: "Recente notificaties" settings: "Instellingen" - view_all: "Bekijk alles" - likes: - likes: - people_dislike_this: - one: "%{count} persoon vindt dit niet leuk" - other: "%{count} mensen vinden dit niet leuk" - zero: "Niemand vindt dit niet leuk" - people_like_this: - one: "%{count} persoon vindt dit leuk" - other: "%{count} mensen vinden dit leuk" - zero: "Niemand vindt dit leuk" - people_like_this_comment: - one: "%{count} persoon vindt dit leuk" - other: "%{count} mensen vinden dit leuk" - zero: "Niemand vindt dit leuk" + toggle_navigation: "Switchen navigatie" limited: "Beperkt" more: "Meer" - next: "Volgende" no_results: "Geen resultaten gevonden" notifications: also_commented: @@ -647,14 +643,6 @@ nl: one: "%{actors} heeft op jouw %{post_link} gereageerd." other: "%{actors} hebben op jouw %{post_link} gereageerd." zero: "%{actors} hebben op jouw %{post_link} gereageerd." - helper: - new_notifications: - few: "%{count} nieuwe notificaties" - many: "%{count} nieuwe notificaties" - one: "1 nieuwe notificatie" - other: "%{count} nieuwe notificaties" - two: "%{count} nieuwe notificaties" - zero: "Geen nieuwe notificaties" index: all_notifications: "Alle meldingen" also_commented: "Reageerde ook" @@ -719,7 +707,6 @@ nl: a_limited_post_comment: "Er is een nieuwe reactie op een besloten bericht in diaspora* dat je even moet beoordelen." a_post_you_shared: "een bericht." a_private_message: "Er is een nieuw privébericht voor jou in diaspora*." - accept_invite: "Accepteer je diaspora* uitnodiging!" also_commented: limited_subject: "Er is een nieuwe reactie bij een bericht waar je eerder op reageerde" click_here: "Klik hier" @@ -777,12 +764,15 @@ nl: message: |- Hallo! - Je bent uitgenodigd om lid te worden van diaspora*! + Je bent door %{diaspora_id} uitgenodigd om lid te worden van diaspora*! Klik op deze link om te starten [%{invite_url}][1] + Of je kunt %{diaspora_id} aan je contactpersonen toevoegen als je al een account hebt. + + Veel plezier, De diaspora* e-mailrobot! @@ -798,10 +788,10 @@ nl: view_post: "Bekijk bericht >" mentioned: limited_post: "Je werd vermeld in een beperkt geplaatst bericht" - mentioned: "heeft jou vermeld in een bericht:" subject: "%{name} heeft jou vermeld op diaspora*" private_message: reply_to_or_view: "Reageer op of bekijk dit privégesprek >" + subject: "Er is een nieuw privébericht voor je" remove_old_user: body: |- Hallo, @@ -823,6 +813,9 @@ nl: Hallo, het %{type} met ID %{id} werd als aanstootgevend gemarkeerd. + + Reden: "%{reason}" + [%{url}][1] Beoordeel het zo snel mogelijk! @@ -851,20 +844,9 @@ nl: to_change_your_notification_settings: "om je notificatie instellingen te wijzigen" nsfw: "NSFW" ok: "OK" - or: "of" - password: "Wachtwoord" - password_confirmation: "Wachtwoordbevestiging" people: add_contact: invited_by: "Je bent uitgenodigd door" - add_contact_small: - add_contact_from_tag: "Contact toevoegen van tag" - aspect_list: - edit_membership: "Bewerken aspect lidmaatschap" - helper: - is_not_sharing: "%{name} deelt niet met jou" - is_sharing: "%{name} deelt met jou" - results_for: "resultaten voor %{params}" index: couldnt_find_them: "Kon je ze niet vinden?" looking_for: "Op zoek naar berichten getagd met %{tag_link}?\n" @@ -874,87 +856,43 @@ nl: search_handle: "Gebruik hun diaspora* ID (gebruikersnaam@pod.tld) om je vrienden te vinden." searching: "Zoeken, even geduld..." send_invite: "Nog steeds niets? Stuur een uitnodiging!" - one: "1 persoon" - other: "%{count} mensen" person: - add_contact: "Voeg contact toe" - already_connected: "Al verbonden" - pending_request: "Openstaand verzoek" thats_you: "Dat ben jij!" profile_sidebar: bio: "bio" born: "geboortedatum" - edit_my_profile: "Bewerk mijn profiel" gender: "geslacht" - in_aspects: "In de aspecten" location: "locatie" - photos: "Foto's" - remove_contact: "Verwijder contact" - remove_from: "Verwijder %{name} uit %{aspect}?" show: closed_account: "Deze account is gesloten." does_not_exist: "Die persoon bestaat niet!" has_not_shared_with_you_yet: "%{name} heeft nog geen berichten met je gedeeld!" - ignoring: "Je negeert alle berichten van %{name}." - incoming_request: "%{name} wil met je delen" - mention: "Noemen" - message: "Bericht" - not_connected: "Je deelt niet met deze persoon" - recent_posts: "Recente berichten" - recent_public_posts: "Recente openbare berichten" - return_to_aspects: "Ga terug naar je aspecten pagina" - see_all: "Zie alles" - start_sharing: "Start met delen" - to_accept_or_ignore: "om te accepteren of te negeren." - sub_header: - add_some: "Voeg wat toe" - edit: "Bewerken" - you_have_no_tags: "Je hebt geen tags!" - webfinger: - fail: "Sorry, we konden %{handle} niet vinden." - zero: "Niemand" photos: - comment_email_subject: "%{name}'s foto" create: integrity_error: "Foto uploaden mislukt. Weet je zeker dat het een afbeelding was?" runtime_error: "Foto uploaden mislukt. Weet je zeker dat je je gordel omhebt?" type_error: "Foto uploaden mislukt. Weet je zeker dat je een afbeelding toegevoegd hebt?" destroy: notice: "Foto verwijderd." - edit: - editing: "Bewerken" - new: - back_to_list: "Terug naar de lijst" - new_photo: "Nieuwe foto" - post_it: "Plaats het!" new_photo: empty: "{file} is leeg, selecteer de bestanden opnieuw zonder deze." invalid_ext: "{file} heeft een ongeldige extensie. Alleen {extensions} zijn toegestaan." size_error: "{file} is te groot, de maximale bestandsgrootte is {sizeLimit}." new_profile_photo: - or_select_one_existing: "of selecteer een van je al bestaande %{photos}\n" upload: "Upload een nieuwe profielfoto!" - photo: - view_all: "Bekijk al %{name}'s foto's" show: - collection_permalink: "Permalink collectie" - delete_photo: "Verwijderen foto" - edit: "Bewerken" - edit_delete_photo: "Bewerk foto-omschrijving / verwijder foto" - make_profile_photo: "Maak profielfoto" show_original_post: "Toon origineel bericht" - update_photo: "Bijwerken foto" - update: - error: "Foto veranderen niet gelukt." - notice: "Foto succesvol veranderd." + polls: + votes: + one: "%{count} stem tot nu" + other: "%{count} stemmen tot nu" + zero: "%{count} stemmen tot nu" posts: presenter: title: "Een bericht van %{name}" show: - destroy: "Verwijder" forbidden: "Je mag dit niet doen" - not_found: "Sorry, dat bericht konden we niet vinden." - permalink: "Permalink" + location: "Geplaats vanaf: %{location}" photos_by: few: "%{count} foto's door %{author}" many: "%{count} foto's door %{author}" @@ -963,19 +901,24 @@ nl: two: "Twee foto's door %{author}" zero: "Geen foto's van %{author}" reshare_by: "Doorgegeven door %{author}" - previous: "Vorige" privacy: "Privacy" - privacy_policy: "Privacybeleid" profile: "Profiel" profiles: edit: allow_search: "Sta mensen toe je op te zoeken binnen diaspora*" - edit_profile: "Bewerk profiel" + basic: "Mijn basisprofiel" + basic_hint: "Ieder onderwerp in je profiel is optioneel. Je basisprofiel is altijd openbaar" + extended: "Mijn uitgebreide profiel" + extended_hint: "Klik op de schakelaar om de zichtbaarheid van je uitgebreide profiel te switchen. Openbaar betekent zichtbaar voor het internet, beperkt betekent alleen zichtbaar voor de personen met wie je wilt delen." + extended_visibility_text: "Zichtbaarheid van je uitgebreide profiel:" first_name: "Voornaam" last_name: "Achternaam" + limited: "Beperkt" nsfw_check: "Markeer al mijn berichten als NSFW" nsfw_explanation: "NSFW ('not safe for work') is de standaard waarmee de diaspora* gemeenschap er zelf voor zorgt om mogelijk aanstootgevende berichten te markeren en af te schermen. Als je vaak materiaal plaatst dat anderen aanstootgevend zouden kunnen vinden, kun je het beste deze optie in je profiel aankruisen, zodat de berichten niet in de stream van anderen zichtbaar zijn, tenzij zij er zelf voor kiezen om de berichten wel te willen zien." nsfw_explanation2: "Als je deze optie niet selecteert, voeg dan de tag #nsfw toe aan ieder mogelijk aanstootgevend bericht." + public: "Openbaar" + settings: "Profielinstellingen" update_profile: "Profiel bijwerken" your_bio: "Jouw bio" your_birthday: "Je verjaardag" @@ -983,8 +926,6 @@ nl: your_location: "Jouw locatie" your_name: "Je naam" your_photo: "Je profielfoto" - your_private_profile: "Je privé-profiel" - your_public_profile: "Je openbare profiel" your_tags: "Jezelf: in 5 #tags" your_tags_placeholder: "b.v. #diaspora #strijken #kittens #muziek" update: @@ -999,26 +940,16 @@ nl: closed: "Registratie op deze diaspora* pod is niet mogelijk." create: success: "Je bent nu lid van diaspora*!" - edit: - cancel_my_account: "Annuleer mijn account" - edit: "Bewerk %{name}" - leave_blank: "(leeg laten als je niets wilt wijzigen)" - password_to_confirm: "(we hebben je huidige wachtwoord nodig om de wijzigingen te bevestigen)" - unhappy: "Ontevreden?" - update: "Bijwerken" invalid_invite: "De uitnodigingslink die je gebruikt is niet langer geldig!" new: - create_my_account: "Maak mijn account aan!" email: "E-mail" enter_email: "Vul je e-mailadres in" enter_password: "Vul een wachtwoord in (zes karakters minimaal)" enter_password_again: "Vul hetzelfde wachtwoord nogmaals in" enter_username: "Kies een gebruikersnaam (alleen letters, nummers, en underscores)" - join_the_movement: "Sluit je aan!" password: "Wachtwoord" password_confirmation: "Wachtwoordbevestiging" - sign_up: "Aanmelden" - sign_up_message: "Sociaal networken met een ♥" + sign_up: "Creëer een account" submitting: "Verwerken..." terms: "Door het aanmaken van een account accepteer je de %{terms_link}." terms_link: "gebruiksvoorwaarden" @@ -1031,45 +962,18 @@ nl: post_label: "<b>Bericht</b>: %{title}" reason_label: "Reden: %{text}" reported_label: "<b>Gemeld door</b> %{person}" + reported_user_details: "Details over gerapporteerde gebruiker" review_link: "Markeren als beoordeeld" status: - created: "Er is een melding gemaakt" destroyed: "Het bericht is vernietigd" failed: "Er ging iets verkeerd" - marked: "De melding is gemarkeerd als beoordeeld" title: "Meldingenoverzicht" - requests: - create: - sending: "Versturen..." - sent: "Je hebt gevraagd te delen met %{name}. Hij of zij zou het de eerstvolgende keer dat hij of zij inlogt op diaspora* moeten zien." - destroy: - error: "Selecteer een aspect!" - ignore: "Contactverzoek genegeerd." - success: "Jullie delen nu." - helper: - new_requests: - one: "Nieuw verzoek!" - other: "%{count} nieuwe verzoeken!" - zero: "Geen nieuwe verzoeken" - manage_aspect_contacts: - existing: "Bestaande contacten" - manage_within: "Beheer contacten in" - new_request_to_person: - sent: "Verzonden!" reshares: comment_email_subject: "%{resharer}'s doorgifte van %{author}'s post" - create: - failure: "Er is een fout opgetreden bij het herdelen van deze post." reshare: deleted: "Het originele bericht is verwijderd door de auteur." - reshare: - one: "1 keer doorgegeven" - other: "%{count} keer doorgegeven" - zero: "Doorgeven" reshare_confirmation: "%{author}'s bericht doorgeven?" - reshare_original: "Origineel doorgeven" reshared_via: "Doorgegeven via" - show_original: "Toon origineel" search: "Zoek" services: create: @@ -1081,10 +985,6 @@ nl: success: "Authenticatie succesvol vernietigd." failure: error: "Er ging iets mis bij het verbinden met die service" - finder: - fetching_contacts: "diaspora* is je %{service} vrienden aan het invullen, probeer het over een paar minuten nog een keer." - no_friends: "Geen Facebook vrienden gevonden." - service_friends: "%{service} vrienden" index: connect: "Verbinden" disconnect: "Loskoppelen" @@ -1093,34 +993,17 @@ nl: no_services_available: "Er zijn geen services beschikbaar op deze pod." not_logged_in: "Momenteel niet ingelogd." really_disconnect: "Verbreek verbinding met %{service}?" - services_explanation: "Verbinden met andere diensten biedt je de mogelijkheid om je diaspora* berichten ook daar te plaatsen" - inviter: - click_link_to_accept_invitation: "Klik op deze link om de uitnodiging te accepteren" - join_me_on_diaspora: "Volg me op diaspora*" + services_explanation: "Verbinden met diensten van derde partijen biedt je de mogelijkheid om je diaspora* berichten ook daar te plaatsen" + share_to: "Delen via %{provider}" + title: "Beheren verbonden diensten" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "Uitnodigen" - not_on_diaspora: "Nog niet op diaspora*" - resend: "Opnieuw versturen" settings: "Instellingen" - share_visibilites: - update: - post_hidden_and_muted: "%{name}'s bericht is verborgen en notificaties worden niet getoond." - see_it_on_their_profile: "Als je updates van dit bericht wilt zien, bezoek %{name}'s profiel pagina." shared: - add_contact: - add_new_contact: "Voeg een contact toe" - create_request: "Vind via diaspora* ID" - diaspora_handle: "gebruikersnaam@pod.org" - enter_a_diaspora_username: "Vul een diaspora* gebruikersnaam in:" - know_email: "Weet je hun e-mailadres? Je zou ze uit moeten nodigen" - your_diaspora_username_is: "Jouw diaspora* gebruikersnaam is: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Voeg contact toe" mobile_row_checked: "%{name} (verwijderen)" mobile_row_unchecked: "%{name} (toevoegen)" toggle: @@ -1130,23 +1013,11 @@ nl: other: "In %{count} aspecten" two: "In %{count} aspecten" zero: "Voeg contact toe" - contact_list: - all_contacts: "Alle contacten" - footer: - logged_in_as: "Ingelogd als %{name}" - your_aspects: "Jouw aspecten" invitations: by_email: "Via e-mail" - dont_have_now: "Momenteel heb je er geen, maar meer uitnodigingen volgen spoedig!" - from_facebook: "Via Facebook" - invitations_left: "%{count} over" - invite_someone: "Nodig iemand uit" invite_your_friends: "Nodig je vrienden uit" invites: "Uitnodigingen" - invites_closed: "Uitnodigingen zijn momenteel gesloten voor deze diaspora* pod" share_this: "Deel deze link via e-mail, blog, of favoriet sociaal netwerk" - notification: - new: "Nieuw %{type} van %{from}" public_explain: atom_feed: "Atom feed" control_your_audience: "Beheer je publiek" @@ -1158,12 +1029,9 @@ nl: title: "Stel verbonden services in" visibility_dropdown: "Gebruik dit dropdown menu om de zichtbaarheid van je post aan te selecteren. (We suggereren je eerste post publiek te maken.)" publisher: - all: "Alle" - all_contacts: "Alle contacten" discard_post: "Maak veld leeg" formatWithMarkdown: "Je kunt %{markdown_link} gebruiken om je bericht op te maken" get_location: "Haal je locatie op" - make_public: "Maak openbaar" new_user_prefill: hello: "Hallo iedereen, ik ben #%{new_user_tag}. " i_like: "Ik ben geïnteresseerd in %{tags}." @@ -1171,36 +1039,14 @@ nl: newhere: "NieuwHier" poll: add_a_poll: "Plaatsen peiling" - add_poll_answer: "Toevoegen keuzemogelijkheid" - option: "Keuze 1" - question: "Vraag" - remove_poll_answer: "Verwijderen keuzemogelijkheid" - post_a_message_to: "Plaats een bericht aan %{aspect}" posting: "Plaatsen..." - preview: "Voorbeeld" - publishing_to: "Publiceren naar: " remove_location: "Verwijder locatie" share: "Delen" - share_with: "Delen met" upload_photos: "Upload fotos" whats_on_your_mind: "Waar denk je aan?" - reshare: - reshare: "Doorgeven" stream_element: - connect_to_comment: "Verbind met deze gebruiker om op zijn of haar berichten te reageren" - currently_unavailable: "Reageren nu niet beschikbaar" - dislike: "Vind ik niet meer leuk" - hide_and_mute: "Verberg en blokkeer bericht" - ignore_user: "Negeer %{name}" - ignore_user_description: "Gebruiker negeren en hem uit alle aspecten verwijderen?" - like: "Vind ik leuk" - nsfw: "Dit bericht is aangemerkt als NSFW door de auteur. %{link}" - shared_with: "Gedeeld met: %{aspect_names}" - show: "Laat zien" - unlike: "vind ik niet meer leuk" via: "Via %{link}" via_mobile: "Via mobiel" - viewable_to_anyone: "Deze post is zichtbaar voor iedereen op het internet" simple_captcha: label: "Voer de code in dit veld in:" message: @@ -1226,24 +1072,12 @@ nl: status_messages: create: success: "Succesvol vermeld: %{names}" - destroy: - failure: "Verwijderen van post mislukt" - helper: - no_message_to_display: "Geen bericht om te weergeven." new: mentioning: "Noem: %{person}" too_long: "Zorg ervoor dat je statusbericht korter is dan %{count} tekens. Nu is het %{current_length} tekens lang" stream_helper: - hide_comments: "Verberg alle reacties" no_more_posts: "Je bent aan het eind van je stream beland." no_posts_yet: "Er zijn nog geen berichten." - show_comments: - few: "Toon nog %{count} andere reacties." - many: "Toon nog %{count} andere reacties." - one: "Toon nog één andere reactie." - other: "Toon nog %{count} andere reacties" - two: "Toon nog twee andere reacties." - zero: "Geen andere reacties meer" streams: activity: title: "Mijn activiteit" @@ -1270,13 +1104,6 @@ nl: tags: title: "Posts getagged: %{tags}" tag_followings: - create: - failure: "Volgen van #%{name} mislukt. Misschien volg je het al?" - none: "Je kan geen blanco tag volgen!" - success: "Hoera! Vanaf nu volg je #%{name}." - destroy: - failure: "Het is niet gelukt om te stoppen met het volgen van #%{name}. Misschien ben je al succesvol gestopt met volgen?" - success: "Jammer! Je bent gestopt met het volgen van #%{name}." manage: no_tags: "Je volgt geen tags." title: "Beheren van gevolgde tags" @@ -1284,15 +1111,12 @@ nl: name_too_long: "Zorg ervoor dat je tagnaam korter is dan %{count} tekens. Nu is dat %{current_length} tekens." show: follow: "Volg #%{tag}" - following: "Volgt #%{tag}" none: "Deze lege tag bestaat niet!" stop_following: "Stop met volgen van #%{tag}" tagged_people: one: "1 persoon heeft getagged met %{tag}" other: "%{count} personen hebben getagged met %{tag}" zero: "Niemand heeft getagged met %{tag}" - terms_and_conditions: "Algemene voorwaarden" - undo: "Ongedaan maken?" username: "Gebruikersnaam" users: confirm_email: @@ -1307,13 +1131,13 @@ nl: auto_follow_aspect: "Aspect voor automatisch gevolgde gebruikers:" auto_follow_back: "Automatisch terugvolgen wanneer iemand jou volgt" change: "Verander" + change_color_theme: "Wijzigen kleurenschema" change_email: "Verander e-mailadres" change_language: "Taal wijzigen" change_password: "Verander wachtwoord" character_minimum_expl: "moet ten minste zes karakters bevatten" close_account: dont_go: "He daar, ga alsjeblieft niet weg!" - if_you_want_this: "Als je dit echt wilt, typ je wachtwoord hieronder in en klik op 'Sluit Account'" lock_username: "Dit vergrendelt je gebruikersnaam. Je kunt op deze pod later niet een nieuw account met dezelfde ID maken." locked_out: "Je wordt afgemeld en afgesloten van je account totdat het is verwijderd." make_diaspora_better: "We zouden liever willen dat je ons helpt om diaspora* te verbeteren dan dat je weggaat. Als je echt weg wilt gaan, dan vertellen we je wat er dan gebeurt:" @@ -1326,14 +1150,12 @@ nl: current_password_expl: "het wachtwoord waar je mee inlogt..." download_export: "Download mijn profiel" download_export_photos: "Download mijn foto's" - download_photos: "Download mijn foto's" edit_account: "Bewerk account" email_awaiting_confirmation: "We hebben een activatielink verzonden naar %{unconfirmed_email}. Totdat je het adres geactiveerd hebt zullen we je originele adress blijven gebruiken %{email}." export_data: "Exporteer data" export_in_progress: "We zijn bezig je aanvraag te verwerken. Controleer het opnieuw over een paar ogenblikken." export_photos_in_progress: "We verwerken nu je foto's. Kom zometeen terug." following: "Volgvoorkeuren" - getting_started: "Nieuwe gebruikersvoorkeuren" last_exported_at: "(Laatst bijgewerkt op %{timestamp})" liked: "iemand je bericht leuk vindt" mentioned: "je vermeld wordt in een bericht" @@ -1360,7 +1182,6 @@ nl: connect_to_facebook_link: "Verbinden met je Facebook account" hashtag_explanation: "Hashtags maken het je makkelijk je interesses volgen. Bovendien kunnen ze je helpen bij het vinden van nieuwe contacten op diaspora*." hashtag_suggestions: "Probeer het volgen van tags zoals #art, #movies, #gif, etc. eens uit." - saved: "Opgeslagen!" well_hello_there: "O, hallo daar!" what_are_you_in_to: "Wat interesseert je?" who_are_you: "Wie ben je?" @@ -1373,6 +1194,8 @@ nl: public: does_not_exist: "Gebruiker %{username} bestaat niet!" update: + color_theme_changed: "Kleurenschema succesvol gewijzigd." + color_theme_not_changed: "Er trad een fout op bij het wijzigen van het kleurenschema." email_notifications_changed: "E-mailnotificaties gewijzigd" follow_settings_changed: "Volgvoorkeuren aangepast" follow_settings_not_changed: "Aanpassing aan de volgvoorkeuren is mislukt." @@ -1384,13 +1207,6 @@ nl: settings_updated: "Instellingen aangepast" unconfirmed_email_changed: "E-mail gewijzigd. Nog te activeren." unconfirmed_email_not_changed: "E-mail wijzigen mislukt" - webfinger: - fetch_failed: "Ophalen van webfinger profiel voor %{profile_url} is mislukt." - hcard_fetch_failed: "Er was een probleem bij het ophalen van de hcard voor %{account}" - no_person_constructed: "Er kon geen persoon worden gemaakt van deze hcard." - not_enabled: "Webfinger lijkt niet aan te staan voor %{account}'s provider" - xrd_fetch_failed: "Er was een probleem bij het verkrijgen van de xrd van het account %{account}" - welcome: "Welkom!" will_paginate: next_label: "volgende »" previous_label: "« vorige" \ No newline at end of file diff --git a/config/locales/diaspora/nn.yml b/config/locales/diaspora/nn.yml index d0cd7f40bdd9385eee285283170aef023d7fd9fc..2a6b074df2e7cdf696f00c054aa766e3260692db 100644 --- a/config/locales/diaspora/nn.yml +++ b/config/locales/diaspora/nn.yml @@ -6,11 +6,8 @@ nn: _applications: "Program" - _comments: "Merknader" _contacts: "Kontaktar" _help: "Hjelp" - _home: "Heim" - _photos: "Bilete" _services: "Tenester" account: "Konto" activerecord: @@ -91,13 +88,7 @@ nn: other: "Mengd nye brukarar denne veka: %{count}" zero: "Mengd nye brukarar denne veka: ingen" current_server: "Noverande dato pÃ¥ serveren er %{date}" - ago: "for %{time} sida" all_aspects: "Alle aspekta" - application: - helper: - unknown_person: "ukjend person" - video_title: - unknown: "Ukjend filmtittel" are_you_sure: "Er du sikker?" are_you_sure_delete_account: "Er du heilt sikker pÃ¥ at du vil stenge kontoen din? Dette kan ikkje gjerast om!" aspect_memberships: @@ -111,18 +102,10 @@ nn: success: "La kontakten til aspektet." aspect_listings: add_an_aspect: "+ Legg til eit aspekt" - deselect_all: "Vel vekk alle" - edit_aspect: "Endra %{name}" - select_all: "Vel alle" aspect_stream: make_something: "Lag noko" stay_updated: "Hald deg oppdatert" stay_updated_explanation: "Hovudstraumen din er sett saman av kontaktane dine, tags du følgjer og innlegg frÃ¥ nokre kreative medlemmar pÃ¥ D*" - contacts_not_visible: "Kontaktar i dette aspektet vil ikkje kunna sjÃ¥ kvarandre." - contacts_visible: "Kontaktar i dette aspektet vil kunna sjÃ¥ kvarandre." - create: - failure: "Klarte ikkje Ã¥ laga aspektet." - success: "Det nye aspektet %{name} vart laga" destroy: failure: "%{name} mÃ¥ vere tom for Ã¥ kunne slettast." success: "%{name} vart fjerna." @@ -130,24 +113,15 @@ nn: aspect_list_is_not_visible: "Aspektet er gøymt frÃ¥ andre i aspektet" aspect_list_is_visible: "Aspektlista er synleg for andre i aspektet" confirm_remove_aspect: "Er du sikker pÃ¥ at du vil sletta aspektet?" - make_aspect_list_visible: "Skal kontaktane i dette aspektet kunna sjÃ¥ kvarandre?" - remove_aspect: "Slett dette aspektet" rename: "Gje nytt namn" update: "Oppdatering" updating: "oppdaterer" index: - diaspora_id: - content_1: "Diaspora-ID-en din er:" - content_2: "Gje han til kven som helst sÃ¥ kan dei finna deg pÃ¥ Diaspora." - heading: "Diaspora-ID" donate: "Doner" - handle_explanation: "Dette er Diaspora-ID-en din. Nett som ei e-postadresse kan du gje han til folk slik at dei kan nÃ¥ deg." help: any_problem: "Har du eit problem?" contact_podmin: "Ta kontakt med administratoren (podminen) pÃ¥ poden din." do_you: "Har du:" - email_feedback: "%{link} gi meldingar attende, om du vil" - email_link: "E-post" feature_suggestion: "eit %{link}forslag?" find_a_bug: "funne ein %{link}?" have_a_question: "eit %{link}?" @@ -160,31 +134,20 @@ nn: tutorial_link_text: "Innføringar" tutorials_and_wiki: "%{faq}, %{tutorial} og %{wiki} er her for Ã¥ hjelpe deg med dei første skritta." introduce_yourself: "Dette er straumen din.   Hiv deg med og introduser deg sjølv." - keep_diaspora_running: "Held utviklinga av Diaspora* rask med ei mÃ¥nadleg donasjon!" keep_pod_running: "Held %{pod} pÃ¥ beina og spander kaffi pÃ¥ serverane med ein mÃ¥nadleg donasjon!" new_here: follow: "Følg %{link} og sei velkomen til nye brukarar pÃ¥ Diaspora*!" learn_more: "Lær meir" title: "Sei velkomen til nye brukarar" - no_contacts: "Ingen kontaktar" - no_tags: "+ Finn ein etikett du vil følgja" - people_sharing_with_you: "Folk som deler med deg" - post_a_message: "Skriv eit innlegg >>" services: content: "Du kan kopla desse tenestene til Diaspora:" heading: "Kopla tenester" - unfollow_tag: "Slutt Ã¥ følgja #%{tag}" welcome_to_diaspora: "Velkomen til Diaspora, %{name}!" - new: - create: "Lag" - name: "Namn (berre du kan sjÃ¥ det)" no_contacts_message: community_spotlight: "Kreative medlemmar" or_spotlight: "Eller du kan dele med %{link}" try_adding_some_more_contacts: "Du kan søkja etter eller invitera fleire kontaktar." you_should_add_some_more_contacts: "Du bør leggja til nokre fleire kontaktar." - no_posts_message: - start_talking: "Ingen har sagt noko enno." seed: acquaintances: "Kjende" family: "Familie" @@ -193,7 +156,6 @@ nn: update: failure: "Aspektet ditt, %{name}, hadde eit for langt namn til Ã¥ bli lagra." success: "Aspektet ditt, %{name}, er vorte endra." - back: "Attende" blocks: create: failure: "Brukaren kunne diverre ikkje blokkerast. #evasion" @@ -205,21 +167,14 @@ nn: explanation: "Legg ut pÃ¥ Diaspora frÃ¥ kor som helst ved Ã¥ lagra %{link} som bokmerke." heading: "Bookmarklet" post_something: "denne lenkja" - post_success: "Sendt. Lukkar." cancel: "Avbryt" comments: new_comment: comment: "Kommenter" commenting: "Kommenterer …" - one: "1 kommentar" - other: "%{count} kommentarar" - zero: "ingen kommentarar" contacts: - create: - failure: "Klarte ikkje Ã¥ laga kontakten" index: add_a_new_aspect: "Legg til eit nytt aspekt" - add_to_aspect: "legg kontaktar til %{name}" all_contacts: "Alle kontaktane" community_spotlight: "Kreative medlemer" my_contacts: "Kontaktane mine" @@ -228,33 +183,18 @@ nn: only_sharing_with_me: "Deler berre med meg" start_a_conversation: "Start ein samtale" title: "Kontaktar" - your_contacts: "Kontaktane dine" - sharing: - people_sharing: "Personar som deler med deg:" spotlight: community_spotlight: "Kreative medlemer" suggest_member: "ForeslÃ¥ eit medlem" conversations: - conversation: - participants: "Deltakarar" create: fail: "Ugyldig melding" no_contact: "Hei, du mÃ¥ leggje til kontakten først!" sent: "Meldinga er sendt" - helper: - new_messages: - few: "%{count} nye meldingar" - many: "%{count} nye meldingar" - one: "1 ny melding" - other: "%{count} nye meldingar" - two: "%{count} nye meldingar" - zero: "Ingen nye meldingar" index: inbox: "Innkorg" - no_conversation_selected: "ingen samtale er vald" no_messages: "ingen meldingar" new: - abandon_changes: "SjÃ¥ vekk frÃ¥ endringane?" send: "" sending: "Sender …" subject: "emne" @@ -273,9 +213,6 @@ nn: error_messages: helper: correct_the_following_errors_and_try_again: "Rett opp desse feila og prøv pÃ¥ nytt." - invalid_fields: "Ugyldige felt" - login_try_again: "Ver ven og <a href='%{login_link}'>logg pÃ¥</a> og prøv att." - post_not_public: "Innlegget du prøvar Ã¥ sjÃ¥ er ikkje offentleg!" fill_me_out: "Fyll meg ut" find_people: "Finn personar eller #grindmerke" help: @@ -290,44 +227,27 @@ nn: tutorial: "innføring" tutorials: "innføringar" wiki: "wiki" - hide: "Gøym" - invitation_codes: - excited: "%{name} er glad for Ã¥ sjÃ¥ deg her!" invitations: a_facebook_user: "Ein Facebook-brukar" check_token: not_found: "Fann ikkje invitasjonskoda" create: - already_contacts: "Du er allereie knytt til denne personen" - already_sent: "Du har allereie invitert denne personen." empty: "Skriv inn minst ei e-post-adresse." no_more: "Du har ingen fleire invitasjonar." note_already_sent: "Invitasjonar er allereie sende til: %{emails}" - own_address: "Du kan ikkje senda invitasjon til di eiga adresse." rejected: "Det oppstod problem med desse e-postadressene:" sent: "Invitasjonar er sende til:" - edit: - accept_your_invitation: "Godta invitasjonen din" - your_account_awaits: "Kontoen din ventar pÃ¥ deg." new: - already_invited: "Desse personane har ikkje godteke invitasjonen din:" - aspect: "Aspekt" - check_out_diaspora: "Ta ein kikk pÃ¥ Diaspora!" codes_left: one: "%{count} invitasjon igjen pÃ¥ denne koden" other: "%{count} invitasjonar igjen pÃ¥ denne koden" zero: "Ingen invitasjonar igjen pÃ¥ denne koden" comma_separated_plz: "Du kan skriva fleire e-postadresser om du skil dei med komma." - if_they_accept_info: "om dei godtek, vil dei verta lagde til aspektet du inviterte dei til." invite_someone_to_join: "Inviter nokon til Ã¥ bli med Diaspora!" language: "SprÃ¥k" paste_link: "Del denne lenkja med venene dine for Ã¥ invitere dei til Diaspora* eller send dei lenkja direkte pÃ¥ epost." - personal_message: "Personleg melding" - resend: "Send pÃ¥ nytt" send_an_invitation: "Send ein invitasjon" - send_invitation: "Send invitasjonen" sending_invitation: "Sendar invitasjon..." - to: "Til" layouts: application: back_to_top: "Attende til toppen" @@ -336,37 +256,13 @@ nn: source_package: "last ned kjeldekodepakka" toggle: "slÃ¥ pÃ¥ mobilnettstad" whats_new: "kva er nytt?" - your_aspects: "aspekta dine" header: - admin: "Admin" - blog: "blogg" code: "kode" - login: "Logg pÃ¥" logout: "Logg ut" profile: "Profil" - recent_notifications: "Nylege varsel" settings: "Innstillingar" - view_all: "Syn alt" - likes: - likes: - people_dislike_this: - few: "%{count} dislikes" - many: "%{count} dislikes" - one: "%{count} dislike" - other: "%{count} dislikes" - two: "%{count} dislikes" - zero: "no dislikes" - people_like_this: - one: "%{count} likar dette" - other: "%{count} likar dette" - zero: "ingen likar dette" - people_like_this_comment: - one: "%{count} likar dette" - other: "%{count} likar dette" - zero: "ingen likar dette" limited: "Avgrensa" more: "Meir" - next: "neste" no_results: "Fann ingen resultat" notifications: also_commented: @@ -384,14 +280,6 @@ nn: one: "%{actors} kommenterte %{post_link}et ditt." other: "%{actors} kommenterte %{post_link}et ditt." zero: "%{actors} kommenterte %{post_link}et ditt." - helper: - new_notifications: - few: "%{count} nye varsel" - many: "%{count} nye varsel" - one: "1 nytt varsel" - other: "%{count} nye varsel" - two: "%{count} nye varsel" - zero: "Ingen nye varsel" index: and: "og" and_others: @@ -459,7 +347,6 @@ nn: zero: "%{actors} byrja Ã¥ dela med deg." notifier: a_post_you_shared: "eit innlegg." - accept_invite: "Godta Diaspora*-invitasjonen din!" click_here: "klikk her" comment_on_post: reply: "Svar pÃ¥ eller syn %{name} sitt innlegg >" @@ -489,7 +376,6 @@ nn: liked: "%{name} likte innlegget ditt" view_post: "Syn innlegget >" mentioned: - mentioned: "nemnde deg i eit innlegg:" subject: "%{name} har nemnt deg pÃ¥ Diaspora*" private_message: reply_to_or_view: "Svar pÃ¥ eller syn denne samtalen >" @@ -507,119 +393,55 @@ nn: to_change_your_notification_settings: "for Ã¥ endra varslingsinnstillingane dine" nsfw: "NSFW" ok: "OK" - or: "eller" - password: "Passord" - password_confirmation: "Passordstadfesting" people: add_contact: invited_by: "du vart invitert av" - add_contact_small: - add_contact_from_tag: "legg til kontakt frÃ¥ etiketten" - aspect_list: - edit_membership: "endra aspektmedlemskap" - helper: - is_not_sharing: "%{name} delar ikkje med deg" - is_sharing: "%{name} delar med deg" - results_for: " resultat for %{params}" index: looking_for: "Ser du etter innlegg merka med %{tag_link}?" no_one_found: "… og ingen vart funnen." no_results: "Du mÃ¥ søkja etter noko." results_for: "søkjeresultat for" searching: "me leiter, ver ven og vent litt..." - one: "1 person" - other: "%{count} personar" person: - add_contact: "legg til kontakt" - already_connected: "Allereie tilkopla" - pending_request: "Ventande førespurnad" thats_you: "Deg!" profile_sidebar: bio: "Livshistorie" born: "Fødselsdag" - edit_my_profile: "Endra profilen min" gender: "Kjønn" - in_aspects: "i aspekta" location: "Stad" - photos: "Bilete" - remove_contact: "Fjern kontakten" - remove_from: "Fjerna %{name} frÃ¥ %{aspect}?" show: closed_account: "Denne kontoen er lÃ¥st." does_not_exist: "Personen finst ikkje." has_not_shared_with_you_yet: "%{name} har enno ikkje delt noko innlegg med deg." - ignoring: "Du ser ikkje innlegg frÃ¥ %{name} lengjer." - incoming_request: "%{name} ønskjer Ã¥ dela med deg" - mention: "Nemn" - message: "Melding" - not_connected: "Du deler ikkje med denne personen" - recent_posts: "Nylege innlegg" - recent_public_posts: "Nylege offentlege innlegg" - return_to_aspects: "GÃ¥ attende til aspektsida di." - see_all: "SjÃ¥ alle" - start_sharing: "byrja delinga" - to_accept_or_ignore: "Ã¥ godta eller forkasta det." - sub_header: - add_some: "legg til noko" - edit: "endra" - you_have_no_tags: "du har ingen etikettar." - webfinger: - fail: "Vi fann dessverre ikkje %{handle}." - zero: "ingen personar" photos: - comment_email_subject: "%{name} sitt bilete" create: integrity_error: "Klarte ikkje Ã¥ lasta opp biletet. Er du sikker pÃ¥ at det verkeleg var eit bilete?" runtime_error: "Klarte ikkje Ã¥ lasta opp biletet. Er du sikker pÃ¥ at du har festa setebeltet?" type_error: "Klarte ikkje Ã¥ lasta opp biletet. Er du sikker pÃ¥ at du la til eit bilete?" destroy: notice: "Biletet er sletta." - edit: - editing: "Endrar" - new: - back_to_list: "Tilbake til lista" - new_photo: "Nytt bilete" - post_it: "send det." new_photo: empty: "{file} er tom, vel filer utan Ã¥ ta ho med." invalid_ext: "{file} har ein ugyldig filtype. Berre {extensions} er tillatne." size_error: "{file} er for stor, kan ikkje vera større enn {sizeLimit}." new_profile_photo: - or_select_one_existing: "" upload: "Last opp eit nytt profilbilete." - photo: - view_all: "syn alle bileta til %{name} " show: - collection_permalink: "permanent lenkje til samlinga" - delete_photo: "Slett biletet" - edit: "endra" - edit_delete_photo: "Endra biletskildringa / slett biletet" - make_profile_photo: "gjer til profilbilete" show_original_post: "Syn den opphavlege meldinga" - update_photo: "Oppdater biletet" - update: - error: "Klarte ikkje Ã¥ endra biletet." - notice: "Biletet vart oppdatert." posts: presenter: title: "Eit innlegg av %{name}" show: - destroy: "Sletta" - not_found: "Vi klarte dessverre ikkje Ã¥ finna innlegget." - permalink: "permlenkje" photos_by: one: "Eitt bilete av %{author}" other: "%{count} bilete av %{author}" zero: "Inga bilete av %{author}" reshare_by: "Deling av %{author}" - previous: "førre" privacy: "Personvern" - privacy_policy: "Retningslinje for personvern" profile: "Profil" profiles: edit: allow_search: "Tillat at folk kan søkja etter deg i Diaspora" - edit_profile: "Endra profilen" first_name: "Fornamn" last_name: "Etternamn" update_profile: "Oppdater profilen" @@ -629,8 +451,6 @@ nn: your_location: "Staden du er" your_name: "Namnet ditt" your_photo: "Foto av deg" - your_private_profile: "Den private profilen din" - your_public_profile: "Den offentlege profilen din" your_tags: "5 ord om deg sjølv" your_tags_placeholder: "liker #movies #kittens #travel #teacher #newyork" update: @@ -645,62 +465,23 @@ nn: closed: "Kan ikkje oppretta brukarar pÃ¥ denne Diaspora-poden." create: success: "Du er vorten med i Diaspora." - edit: - cancel_my_account: "Avslutt kontoen min" - edit: "Endra %{name}" - leave_blank: "(lat vera tomt om du ikkje vil endra)" - password_to_confirm: "(vi treng det gjeldande passordet ditt for Ã¥ kunna stadfesta endringane)" - unhappy: "Ulukkeleg?" - update: "Oppdater" invalid_invite: "Invitasjonslenkja du nytta er ikkje lengjer gyldig!" new: - create_my_account: "Lag kontoen min." email: "E-POST" enter_email: "Skriv ei e-postadresse" enter_password: "Skriv eit passord (minst seks teikn)" enter_password_again: "Skriv passordet éin gong til" enter_username: "Vel eit brukarnamn (berre bokstavar, tal og understrekingsteikn)" - join_the_movement: "Vert med i rørsla!" password: "PASSORD" password_confirmation: "Passordstadfesting" sign_up: "PÃ…MELDING" - sign_up_message: "Sosialt nettverk med eit ♥" username: "BRUKARNAMN" - requests: - create: - sending: "Sender" - sent: "Du bad om Ã¥ dela med %{name}. Dei ser det neste gong dei loggar seg pÃ¥ Diaspora." - destroy: - error: "Vel eit aspekt." - ignore: "Ignorerte kontaktførespurnaden." - success: "No deler du." - helper: - new_requests: - few: "%{count} nye førespurnader." - many: "%{count} nye førespurnader." - one: "ny førespurnad." - other: "%{count} nye førespurnader." - two: "%{count} nye førespurnader." - zero: "ingen nye førespurnader" - manage_aspect_contacts: - existing: "Eksisterande kontaktar" - manage_within: "Handsam kontaktane i" - new_request_to_person: - sent: "sendt!" reshares: comment_email_subject: "%{resharer} si deling av %{author} sitt innlegg" - create: - failure: "Klarte ikkje Ã¥ dela dette innlegget pÃ¥ nytt." reshare: deleted: "Forfattaren har sletta originalinnlegget." - reshare: - one: "1 deling" - other: "%{count} delingar" - zero: "Del vidare" reshare_confirmation: "Vil du dele %{author} sitt innlegg?" - reshare_original: "Del originalen vidare" reshared_via: "delt via" - show_original: "Syn original" search: "Søk" services: create: @@ -712,37 +493,14 @@ nn: success: "Sletta autentiseringa." failure: error: "klarte ikkje Ã¥ kopla til tenesta" - finder: - fetching_contacts: "Diaspora* hentar %{service}venene dine, kom attende om eit par minutt." - no_friends: "Fann ingen Facebook-vener." - service_friends: "%{service}-vener" index: disconnect: "kopla frÃ¥" edit_services: "Endra tenester" logged_in_as: "pÃ¥logga som" really_disconnect: "kopla frÃ¥ %{service}?" - inviter: - click_link_to_accept_invitation: "Godta invitasjonen ved Ã¥ klikka pÃ¥ denne lenkja" - join_me_on_diaspora: "Ver med meg pÃ¥ DIASPORA*" - remote_friend: - invite: "inviter" - not_on_diaspora: "Enno ikkje pÃ¥ Diaspora" - resend: "send pÃ¥ nytt" settings: "Innstillingar" - share_visibilites: - update: - post_hidden_and_muted: "%{name} sine innlegg er gøymd og varsel er skrudd av." - see_it_on_their_profile: "Om du vil sjÃ¥ oppdateringar pÃ¥ dette innlegget, gÃ¥ til %{name} sin profil." shared: - add_contact: - add_new_contact: "Legg til ein ny kontakt" - create_request: "Finn ved hjelp av Diaspora-id-en" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Skriv inn eit Diaspora-brukarnamn:" - know_email: "Kjenner du epostadressene deira? Du burde invitera dei" - your_diaspora_username_is: "Diaspora-brukarnamnet ditt er: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Legg til kontakt" toggle: few: "I %{count} aspekt" many: "I %{count} aspekt" @@ -750,23 +508,11 @@ nn: other: "I %{count} aspekt" two: "I %{count} aspekt" zero: "Legg til kontakt" - contact_list: - all_contacts: "Alle kontaktane" - footer: - logged_in_as: "pÃ¥logga som %{name}" - your_aspects: "aspekta dine" invitations: by_email: "Per e-post" - dont_have_now: "Du har ingen akkurat no, men fleire invitasjonar kjem snart." - from_facebook: "FrÃ¥ Facebook" - invitations_left: "%{count} igjen" - invite_someone: "Inviter nokon" invite_your_friends: "Inviter venene dine" invites: "Invitasjonar" - invites_closed: "Denne Diaspora-noden gjev for tida ikkje ut invitasjonar" share_this: "Del denne lenkja via e-post, bloggen din eller eit sosialt nettverk." - notification: - new: "Ny %{type} frÃ¥ %{from}" public_explain: atom_feed: "Atom feed" control_your_audience: "Bestem publikumet ditt sjølve" @@ -778,56 +524,25 @@ nn: title: "Setja opp tilkopla tenester" visibility_dropdown: "Nytt denne rullegardinmenyen for Ã¥ endra synlegheita til innlegga dine. (Me foreslÃ¥r at du gjer det første innlegget offentleg.)" publisher: - all: "alle" - all_contacts: "alle kontaktane" discard_post: "Forkast innlegget" - make_public: "gjer offentlig" new_user_prefill: hello: "Hei alle saman! Eg er #%{new_user_tag}. " i_like: "Eg interesserer meg for %{tags}. " invited_by: "Takk for innbydinga, " newhere: "NyHer" - post_a_message_to: "Send ei melding til %{aspect}" posting: "Sender …" - preview: "Førehandsvising" - publishing_to: "publiserer til:" share: "Del" - share_with: "del med" upload_photos: "Last opp bilete" whats_on_your_mind: "Kva tenkjer du pÃ¥?" - reshare: - reshare: "Del pÃ¥ nytt" stream_element: - connect_to_comment: "For Ã¥ kommentera denne brukaren sitt innlegg mÃ¥ du byrja Ã¥ dela med vedkommande." - currently_unavailable: "for tida gÃ¥r det ikkje an Ã¥ kommentera" - dislike: "Mislik" - hide_and_mute: "Gøym og demp" - ignore_user: "OversjÃ¥ %{name}" - ignore_user_description: "Vil du oversjÃ¥ og fjerne brukaren frÃ¥ alle aspekta dine?" - like: "Lik" - nsfw: "Dette innlegget er merka som NSFW av den som har lagt det ut. %{link}" - shared_with: "Delt med: %{aspect_names}" - show: "syn" - unlike: "Lik ikkje lenger" via: "via %{link}" via_mobile: "via mobiltelefon" - viewable_to_anyone: "Alle kan sjÃ¥ dette innlegget" status_messages: create: success: "Nemnde: %{names}" - destroy: - failure: "Klarte ikkje Ã¥ sletta innlegget" - helper: - no_message_to_display: "Ingen innlegg kan synast." new: mentioning: "Nemner: %{person}" too_long: "{\"few\"=>\"sjÃ¥ til at statusmeldingane dine har færre enn %{count} teikn\", \"many\"=>\"sjÃ¥ til at statusmeldingane dine har færre enn %{count} teikn\", \"one\"=>\"sjÃ¥ til at statusmeldingane dine har færre enn %{count} teikn\", \"other\"=>\"sjÃ¥ til at statusmeldingane dine har færre enn %{count} teikn\", \"two\"=>\"sjÃ¥ til at statusmeldingane dine har færre enn %{count} teikn\", \"zero\"=>\"sjÃ¥ til at statusmeldingane dine har færre enn %{count} teikn\"}" - stream_helper: - hide_comments: "Gøym alle kommentarane" - show_comments: - one: "Syn ein kommentar til" - other: "Syn %{count} kommentarar til" - zero: "Ikkje fleire kommentarar" streams: activity: title: "Min aktivitet" @@ -854,13 +569,6 @@ nn: tags: title: "Innlegg merka med: %{tags}" tag_followings: - create: - failure: "Klarte ikkje Ã¥ følgja: #%{name}. Følgjer du allereie?" - none: "Du kan ikkje følgje ein tom tag!" - success: "Bra! No følgjer du: #%{name}." - destroy: - failure: "Failed to stop following: #%{name}" - success: "Du har slutta Ã¥ følgje #%{name}" manage: no_tags: "Du følgjer ikkje nokon taggar" title: "Administrer taggane du følgjer" @@ -868,15 +576,12 @@ nn: name_too_long: "Namnet pÃ¥ taggen mÃ¥ vere færre enn %{count} teikn. Nett no er det %{current_length} teikn." show: follow: "Følg #%{tag}" - following: "Følgjer #%{tag}" none: "Det finnast ikkje tomme tags!" stop_following: "Ikkje følg #%{tag} lenger" tagged_people: one: "Det er ein person som er merka med %{tag}" other: "Det er %{count} personar som er merka med %{tag}" zero: "Det er ingen som er merka med %{tag}" - terms_and_conditions: "VilkÃ¥r og retningslinjer" - undo: "Gjera om?" username: "Brukarnamn" users: confirm_email: @@ -897,7 +602,6 @@ nn: character_minimum_expl: "mÃ¥ vere minst seks teikn" close_account: dont_go: "Ikkje forlat oss!" - if_you_want_this: "Om du verkeleg vil dette, skriv inn passordet ditt og klikk pÃ¥ 'Lukk konto'" lock_username: "Dette vil fryse brukarnamnet ditt om du vel Ã¥ registrera deg igjen." locked_out: "Du vert logga ut og stengd ute frÃ¥ kontoen din." make_diaspora_better: "Me treng deg for Ã¥ gjera Diaspora* betre, sÃ¥ om du kan hjelpe oss i staden for Ã¥ forlate oss vert me veldig takksame. Om du faktisk vil forlate oss, sÃ¥ skal du vite kva som skjer." @@ -908,12 +612,10 @@ nn: comment_on_post: "… nokon kommenterer innlegget ditt?" current_password: "Gjeldande passord" current_password_expl: "det du loggar pÃ¥ med..." - download_photos: "Last ned bileta mine" edit_account: "Endra kontoen" email_awaiting_confirmation: "Vi har sendt ei aktiveringslenkje til %{unconfirmed_email}. Vi vil halda fram med Ã¥ senda til originaladressa di, %{email}, fram til du følgjer lenkja og tek i bruk den nye." export_data: "Eksporter data" following: "Følgje-innstillingar" - getting_started: "Innstillingar for nye brukarar" liked: "… nokon likar innlegget ditt?" mentioned: "… du er nemnt i eit innlegg?" new_password: "Nytt passord" @@ -933,7 +635,6 @@ nn: connect_to_facebook_link: "kopla til Facebook-kontoen din" hashtag_explanation: "Grindmerke (#) gjer at du kan tala om og følgja interessene dine. Dei er òg ein fin mÃ¥te Ã¥ finna nye Diaspora-brukarar pÃ¥." hashtag_suggestions: "Prøv Ã¥ følgje tags som #kunst, #film, #Ã¥tgaum, #katt, etc." - saved: "Lagra!" well_hello_there: "Neimen, hei der!" what_are_you_in_to: "Kva likar du?" who_are_you: "Kven er du?" @@ -955,13 +656,6 @@ nn: settings_updated: "Innstillingar oppdaterte" unconfirmed_email_changed: "E-postadresse er endra. Treng Ã¥ verta teken i bruk." unconfirmed_email_not_changed: "Klarte ikkje Ã¥ endra e-postkontoen" - webfinger: - fetch_failed: "fekk ikkje til Ã¥ hente webfingerprofilen for %{profile_url}" - hcard_fetch_failed: "det var eit problem med Ã¥ hente hcard for %{account}" - no_person_constructed: "Klarte ikkje Ã¥ laga nokon person frÃ¥ hcard-fila." - not_enabled: "webfinger latar ikkje til Ã¥ vere slÃ¥tt pÃ¥ for %{account} sin konto" - xrd_fetch_failed: "det var eit problem med Ã¥ fÃ¥ tak i xrd'en til kontoen %{account}" - welcome: "Velkomen!" will_paginate: next_label: "neste »" previous_label: "« førre" \ No newline at end of file diff --git a/config/locales/diaspora/pa.yml b/config/locales/diaspora/pa.yml index a395e8dce1c9e79dfe70d89188a119148ae5cc31..6e5957e5035025d3b22bb95d8ee0a0f7ee5916e3 100644 --- a/config/locales/diaspora/pa.yml +++ b/config/locales/diaspora/pa.yml @@ -5,10 +5,7 @@ pa: - _comments: "ਟਿੱਪਣੀਆਂ" _contacts: "ਸੰਪਰਕ" - _home: "ਘਰ" - _photos: "ਫੋਟੋ" _services: "ਸਰਵਿਸਾਂ" account: "ਅਕਾਊਂਟ" activerecord: @@ -22,32 +19,22 @@ pa: attributes: username: invalid: "is invalid. We only allow letters, numbers, and underscores" - ago: "%{time} ਪਹਿਲਾਂ" all_aspects: "All aspects" are_you_sure: "ਕੀ ਤà©à¨¸à©€à¨‚ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?" aspects: edit: - make_aspect_list_visible: "make aspect list visible to others in aspect" rename: "ਨਾਂ-ਬਦਲੋ" index: - handle_explanation: "This is your diaspora handle. Like an email address, you can give this to people to reach you." help: here_to_help: "Diaspora community is here to help!" tag_bug: "#bug" tag_feature: "#feature" tag_question: "#question" - no_contacts: "ਕੋਈ ਸੰਪਰਕ ਨਹੀਂ" - no_tags: "No tags" - new: - name: "Name" no_contacts_message: try_adding_some_more_contacts: "You can search (top) or invite (right) more contacts." - no_posts_message: - start_talking: "Nobody has said anything yet. Get the conversation started!" seed: family: "ਪਰਿਵਾਰ" work: "ਕੰਮ" - back: "ਪਿੱਛੇ" bookmarklet: explanation: "%{link} from anywhere by bookmarking this link." heading: "Diaspora Bookmarklet" @@ -58,59 +45,20 @@ pa: commenting: "ਟਿੱਪਣੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ..." contacts: index: - add_to_aspect: "Add contacts to %{name}" no_contacts: "No contacts." - conversations: - helper: - new_messages: - few: "%{count} new messages" - many: "%{count} new messages" - one: "1 new messages" - other: "%{count} new messages" - two: "%{count} new messages" - zero: "no new messages" delete: "ਹਟਾਓ" email: "ਈਮੇਲ" find_people: "Find people" - invitations: - new: - already_invited: "Already invited" layouts: application: toggle: "toggle mobile site" whats_new: "ਨਵਾਂ ਕੀ ਹੈ?" header: - blog: "ਬਲੌਗ" code: "ਕੋਡ" - login: "ਲਾਗਇਨ" logout: "ਲਾਗਆਉਟ" profile: "profile" settings: "settings" - likes: - likes: - people_dislike_this: - few: "%{count} people disliked this" - many: "%{count} people disliked this" - one: "1 person disliked this" - other: "%{count} people disliked this" - two: "%{count} dislikes" - zero: "no people disliked this" - people_like_this: - few: "%{count} people liked this" - many: "%{count} people liked this" - one: "1 person liked this" - other: "%{count} people liked this" - two: "%{count} likes" - zero: "no people liked this" - people_like_this_comment: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" more: "ਹੋਰ" - next: "ਅੱਗੇ" notifications: also_commented: few: "%{actors} also commented on %{post_author}'s %{post_link}." @@ -133,14 +81,6 @@ pa: other: "%{actors} commented on your %{post_link}." two: "%{actors} commented on your %{post_link}." zero: "%{actors} commented on your %{post_link}." - helper: - new_notifications: - few: "%{count} new notifications" - many: "%{count} new notifications" - one: "1 new notifications" - other: "%{count} new notifications" - two: "%{count} new notifications" - zero: "no new notifications" index: and_others: few: "and %{count} others" @@ -218,21 +158,9 @@ pa: started_sharing: subject: "%{name} has started sharing with you on Diaspora*" ok: "ਠੀਕ ਹੈ" - or: "ਜਾਂ" - password: "ਪਾਸਵਰਡ" - password_confirmation: "ਪਾਸਵਰਡ ਪà©à¨¸à¨¼à¨Ÿà©€" people: - helper: - results_for: "%{params} ਲਈ ਨਤੀਜੇ" - one: "1 person" - other: "%{count} people" person: - add_contact: "ਸੰਪਰਕ ਸ਼ਾਮਲ" - already_connected: "ਪਹਿਲਾਂ ਹੀ ਕà©à¨¨à©ˆà¨•à¨Ÿ ਹੈ" - pending_request: "pending request" thats_you: "thats you!" - show: - not_connected: "You are not sharing with %{name}" posts: show: photos_by: @@ -242,7 +170,6 @@ pa: other: "%{count} photos by %{author}" two: "Two photos by %{author}" zero: "No photos by %{author}" - previous: "ਪਿੱਛੇ" profiles: edit: your_tags: "You: in 5 #tags" @@ -255,60 +182,22 @@ pa: two: "%{count} reactions" zero: "0 reactions" registrations: - edit: - cancel_my_account: "ਮੇਰਾ ਅਕਾਊਂਟ ਰੱਦ ਕਰੋ" - edit: "%{name} ਸੋਧ" - unhappy: "ਖà©à¨¸à¨¼ ਨਹੀਂ?" - update: "ਅੱਪਡੇਟ" new: - create_my_account: "Create my account" enter_email: "ਈਮੇਲ ਦਿਓ" enter_password: "ਪਾਸਵਰਡ ਦਿਓ" enter_password_again: "ਪਹਿਲਾਂ ਵਾਲਾ ਪਾਸਵਰਡ ਦਿਓ" enter_username: "ਯੂਜ਼ਰ ਨਾਂ ਚà©à¨£à©‹ (ਕੇਵਲ ਅੱਖਰ, ਅੰਕ ਅਤੇ ਹੇਠਾਂ ਲਾਈਨ)" - sign_up_message: "Social Networking with a <3" - requests: - destroy: - success: "ਹà©à¨£ ਤà©à¨¸à©€à¨‚ ਦੋਸਤ ਹੋ।" - helper: - new_requests: - few: "%{count} new requests!" - many: "%{count} new requests!" - one: "new request!" - other: "%{count} new requests!" - two: "%{count} new requests!" - zero: "no new requests" - new_request_to_person: - sent: "à¨à©‡à¨œà¨¿à¨†!" reshares: reshare: - reshare: - few: "%{count} Reshares" - many: "%{count} Reshares" - one: "1 Reshare" - other: "%{count} Reshares" - two: "%{count} reshares" - zero: "Reshare" reshare_confirmation: "Reshare %{author} - %{text}?" - reshare_original: "Reshare orignial" - show_original: "Show Original" search: "ਖੋਜ" services: index: disconnect: "ਕà©à¨¨à©ˆà¨•à¨¸à¨¼à¨¨ ਖਤਮ ਕਰੋ" edit_services: "ਸਰਵਿਸ ਸੋਧ" logged_in_as: "ਇੰਠਲਾਗ ਕਰੋ" - inviter: - click_link_to_accept_invitation: "Click this link to accept your invitation" - remote_friend: - invite: "ਸੱਦਾ" - resend: "ਮà©à©œ-à¨à©‡à¨œà©‹" shared: - add_contact: - create_request: "Find by Diaspora handle" - diaspora_handle: "diaspora@handle.org" aspect_dropdown: - add_to_aspect: "Add to aspect" toggle: few: "In %{count} aspects" many: "In %{count} aspects" @@ -316,50 +205,22 @@ pa: other: "In %{count} aspects" two: "In %{count} aspects" zero: "Add to aspect" - contact_list: - all_contacts: "ਸਠਸੰਪਰਕ" invitations: by_email: "by Email" - invitations_left: "(%{count} left)" public_explain: title: "You are about to post a public message!" publisher: - all: "ਸà¨" - all_contacts: "ਸਠਸੰਪਰਕਾਂ ਨਾਲ" - make_public: "ਪਬਲਿਕ ਬਣਾਓ" new_user_prefill: i_like: "I'm interested in %{tags}." posting: "ਪੋਸਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..." whats_on_your_mind: "ਤà©à¨¹à¨¾à¨¡à©‡ ਦਿਮਾਗ 'ਚ ਕੀ ਹੈ?" - stream_element: - dislike: "I dislike this" - hide_and_mute: "Hide and Mute" - like: "I like this" status_messages: - helper: - no_message_to_display: "ਵੇਖਾਉਣ ਲਈ ਕੋਈ ਸà©à¨¨à©‡à¨¹à¨¾ ਨਹੀਂ ਹੈ।" too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - hide_comments: "ਟਿੱਪਣੀਆਂ ਓਹਲੇ ਕਰੋ" - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: aspects: title: "Your Aspects" mentions: title: "Your Mentions" - tag_followings: - create: - failure: "Failed to follow: #%{name}" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" username: "ਯੂਜ਼ਰ ਨਾਂ" users: confirm_email: diff --git a/config/locales/diaspora/pl.yml b/config/locales/diaspora/pl.yml index cc07ec317448d73f7b11c48d057a9acda83beba4..c664c3714efb9b4c61a29135e01f58aeb47238d7 100644 --- a/config/locales/diaspora/pl.yml +++ b/config/locales/diaspora/pl.yml @@ -6,11 +6,8 @@ pl: _applications: "Aplikacje" - _comments: "Komentarze" _contacts: "Kontakty" _help: "Pomoc" - _home: "Główna" - _photos: "ZdjÄ™cia" _services: "UsÅ‚ugi" _statistics: "Statystyki" _terms: "warunki" @@ -53,12 +50,19 @@ pl: taken: "jest już zajÄ™ta." admins: admin_bar: + dashboard: "Deska rozdzielcza" pages: "Strony" + pod_network: "Sieć poda" pod_stats: "Statystyki Poda" report: "ZgÅ‚oszenia" sidekiq_monitor: "Monitor Sidekiq" user_search: "Wyszukiwanie użytkowników" weekly_user_stats: "Tygodniowe statystyki użytkowników" + dashboard: + fetching_diaspora_version: "Ustalanie najnowszej wersji diaspory*" + pod_status: "Stan poda" + pods: + pod_network: "Sieć poda" stats: 2weeks: "2 tygodnie" 50_most: "50 najpopularniejszych znaczników" @@ -117,7 +121,9 @@ pl: are_you_sure_unlock_account: "Na pewno odblokować to konto?" close_account: "zamknij konto" email_to: "ZaproÅ› przez e-mail" + lock_account: "Zablokuj konto" under_13: "WyÅ›wietl użytkowników mÅ‚odszych niż 13 lat." + unlock_account: "Odblokuj konto" users: few: "%{count} znalezionych użytkowników" many: "%{count} znalezionych użytkowników" @@ -139,18 +145,37 @@ pl: other: "liczba nowych użytkowników w tym tygodniu: %{count}" zero: "liczba nowych użytkowników w tym tygodniu: żadnego" current_server: "Aktualna data na serwerze to %{date}" - ago: "%{time} temu" all_aspects: "Wszystkie aspekty" - application: - helper: - unknown_person: "Nieznana osoba" - video_title: - unknown: "Film bez tytuÅ‚u" + api: + openid_connect: + authorizations: + new: + access: "%{name} wymaga dostÄ™p do:" + approve: "Zatwierdź" + deny: "Odmów" + no_requirement: "%{name} nie wymaga żadnego pozwolenia" + scopes: + openid: + description: "Pozwala aplikacji na czytanie profilu podstawowego" + name: "Profil podstawowy" + read: + name: "Czytaj profil, strumieÅ„ i rozmowy" + user_applications: + index: + access: "%{name} ma dostÄ™p do:" + edit_applications: "Aplikacje" + no_requirement: "%{name} nie wymaga pozwolenia" + title: "Autoryzowane aplikacje" + no_applications: "Nie masz pozwolonych aplikacji" + policy: "Sprawdź warunki prywatnoÅ›ci aplikacji" + revoke_autorization: "OdwoÅ‚uj" + tos: "Sprawdź warunki obsÅ‚ugi aplikacji" are_you_sure: "Czy na pewno?" are_you_sure_delete_account: "Czy na pewno chcesz zamknąć swoje konto? Tego nie można cofnąć!" aspect_memberships: destroy: failure: "Nie udaÅ‚o siÄ™ usunąć osoby z aspektu" + forbidden: "Nie masz pozwolenia by to zrobić." no_membership: "Nie udaÅ‚o siÄ™ odnaleźć wskazanej osoby w tym aspekcie" success: "PomyÅ›lnie usuniÄ™to osobÄ™ z aspektu" aspects: @@ -159,48 +184,27 @@ pl: success: "Dodano kontakt to aspektu." aspect_listings: add_an_aspect: "+ Dodaj aspekt" - deselect_all: "Odznacz wszystkie" - edit_aspect: "Edycja %{name}" - select_all: "Zaznacz wszystkie" aspect_stream: make_something: "Zrób coÅ›" stay_updated: "BÄ…dź na bieżąco" stay_updated_explanation: "Główny strumieÅ„ jest wypeÅ‚niony przez wszystkie Twoje kontakty, znaczniki które obserwujesz i wpisy niektórych bardziej kreatywnych czÅ‚onków spoÅ‚ecznoÅ›ci." - contacts_not_visible: "Kontakty z tego aspektu nie bÄ™dÄ… dla siebie widoczne." - contacts_visible: "Kontakty z tego aspektu bÄ™dÄ… widziaÅ‚y się nawzajem." - create: - failure: "Nie udaÅ‚o siÄ™ utworzyć aspektu." - success: "Nowy aspekt, o nazwie %{name}, zostaÅ‚ utworzony" destroy: failure: "%{name} nie mógÅ‚ być usuniÄ™ty." success: "%{name} zostaÅ‚ usuniÄ™ty." success_auto_follow_back: "%{name} zostaÅ‚ poprawnie usuniÄ™ty. Ten aspekt byÅ‚ używany aby automatycznie obserwować wzajemnie użytkowników. Przejdź do ustawieÅ„ aby wybrać nowy aspekt do automatycznego obserwowania użytkowników." edit: - aspect_chat_is_enabled: "Kontakty w tym aspekcie mogÄ… z tobÄ… czatować." - aspect_chat_is_not_enabled: "Kontakty w tym aspekcie nie mogÄ… z tobÄ… czatować." aspect_list_is_not_visible: "Kontakty z tego aspektu nie widzÄ… siÄ™ nawzajem." aspect_list_is_visible: "Kontakty z tego aspektu mogÄ… zobaczyć siÄ™ nawzajem." confirm_remove_aspect: "@{m,f:JesteÅ›|n:Czy na}{ pew}{m:ien|f:na|n:no}{m,f:, że } chcesz usunąć ten aspekt?" - grant_contacts_chat_privilege: "przyznać kontaktom z aspektu prawa do czatu?" - make_aspect_list_visible: "Sprawić aby kontakty w tym aspekcie widziaÅ‚y się wzajemnie?" - remove_aspect: "UsuÅ„ ten aspekt" rename: "ZmieÅ„ nazwÄ™" - set_visibility: "Ustaw widoczność" update: "Aktualizuj" updating: "Aktualizowanie" index: - diaspora_id: - content_1: "Twój identyfikator w sieci Diaspora* to:" - content_2: "Osoby którym go przekażesz bÄ™dÄ… mogÅ‚y odnaleźć ciÄ™ na diasporze*." - heading: "Identyfikator Diaspory*" donate: "Wspomóż" - handle_explanation: "Oto Twój identyfikator diaspory*. Możesz podawać go osobom z którymi chcesz być w kontakcie, podobnie jak adres e-mail." help: any_problem: "JakiÅ› problem?" contact_podmin: "Skontaktuj siÄ™ z administratorem swojego poda!" do_you: "Czy:" - email_feedback: "WyÅ›lij %{link}, jeÅ›li wolisz" - email_link: "E-mail" feature_suggestion: "... masz propozycjÄ™ (%{link})?" find_a_bug: "... znal@{m:azÅ‚eÅ›|f:azÅ‚aÅ›|n:eziono} %{link}?" have_a_question: "... masz %{link}?" @@ -213,31 +217,21 @@ pl: tutorial_link_text: "Samouczki" tutorials_and_wiki: "%{faq}, %{tutorial} i %{wiki}: Pomoc w Twoich pierwszych krokach." introduce_yourself: "Oto Twoj strumieÅ„. Wskocz do niego i przedstaw siÄ™." - keep_diaspora_running: "UÅ‚atw sprawny rozwój Diaspory dziÄ™ki miesiÄ™cznej darowiźnie!" keep_pod_running: "Aby %{pod} dziaÅ‚aÅ‚ szybko podaruj serwerom dawkÄ™ kofeiny w postaci miesiÄ™cznej darowizny!" new_here: follow: "Obserwuj %{link} i powitaj nowych użytkowników diaspory*!" learn_more: "Dowiedz siÄ™ wiÄ™cej" title: "Powitaj nowych użytkowników" - no_contacts: "Brak kontaktów" - no_tags: "+ Znajdź znacznik do obserwowania" - people_sharing_with_you: "Osoby udostÄ™pniajÄ…ce Tobie" - post_a_message: "napisz wiadomość >>" services: content: "Z sieciÄ… Diaspora* można poÅ‚Ä…czyć nastÄ™pujÄ…ce usÅ‚ugi:" heading: "PodÅ‚Ä…cz usÅ‚ugi" - unfollow_tag: "PrzestaÅ„ obserwować #%{tag}" welcome_to_diaspora: "Witaj w Diasporze, %{name}!" - new: - create: "Stwórz" - name: "Nazwa (widoczna tylko dla Ciebie)" no_contacts_message: community_spotlight: "w centrum uwagi" + invite_link_text: "ZaproÅ›" or_spotlight: "Lub możesz udostÄ™pnić z %{link}" try_adding_some_more_contacts: "Możesz wyszukać lub zaprosić wiÄ™cej osób." you_should_add_some_more_contacts: "Dodaj wiÄ™cej kontaktów!" - no_posts_message: - start_talking: "Nikt jeszcze nic nie powiedziaÅ‚!" seed: acquaintances: "Dalsi znajomi" family: "Rodzina" @@ -246,7 +240,6 @@ pl: update: failure: "Aspekt %{name} nie mógÅ‚ zostać zapisany z powodu zbyt dÅ‚ugiej nazwy." success: "Edycja aspektu %{name} powiodÅ‚a siÄ™." - back: "Powrót" blocks: create: failure: "Nie mogÄ™ zignorować tego użytkownika. #unikanie" @@ -258,22 +251,15 @@ pl: explanation: "Publikuj w diasporze* z dowolnego miejsca poprzez dodanie tego linku do zakÅ‚adek => %{link}" heading: "Bookmarklet" post_something: "Opublikuj w Diasporze" - post_success: "Wpis zostaÅ‚ opublikowany! Okno zostanie zamkniÄ™te!" cancel: "Anuluj" comments: new_comment: comment: "Skomentuj" commenting: "Dodawanie komentarza..." - one: "1 komentarz" - other: "Komentarze: %{count}" - zero: "Brak komentarzy" contacts: - create: - failure: "Nie udaÅ‚o siÄ™ utworzyć kontaktu" index: add_a_new_aspect: "Dodaj aspekt" add_contact: "Dodaj kontakt" - add_to_aspect: "Dodaj kontakty do %{name}" all_contacts: "Wszystkie kontakty" community_spotlight: "W centrum uwagi" my_contacts: "Moje kontakty" @@ -281,19 +267,13 @@ pl: no_contacts_in_aspect: "Nie masz jeszcze żadnych kontaktów w tym aspekcie. Poniżej widnieje lista kontaktów które możesz do niego dodać." no_contacts_message: "Sprawdź kto jest %{community_spotlight}" only_sharing_with_me: "Jedynie mi udostÄ™pniajÄ…" - remove_contact: "UsuÅ„ kontakt" start_a_conversation: "Rozpocznij rozmowÄ™" title: "Kontakty" user_search: "Wyszukiwanie użytkowników" - your_contacts: "Twoje kontakty" - sharing: - people_sharing: "Osoby które Ci udostÄ™pniajÄ…:" spotlight: community_spotlight: "W centrum uwagi spoÅ‚ecznoÅ›ci" suggest_member: "Zasugeruj czÅ‚onka" conversations: - conversation: - participants: "Uczestnicy" create: fail: "NieprawidÅ‚owa wiadomość" no_contact: "Hej! Najpierw należy dodać kontakt!" @@ -301,22 +281,13 @@ pl: destroy: delete_success: "Rozmowa usuniÄ™ta" hide_success: "Rozmowa ukryta" - helper: - new_messages: - few: "%{count} nowe wiadomoÅ›ci" - many: "%{count} nowych wiadomoÅ›ci" - one: "1 nowa wiadomość" - other: "%{count} nowych wiadomoÅ›ci" - zero: "Brak nowych wiadomoÅ›ci" index: conversations_inbox: "Rozmowy - Skrzynka Odbiorcza" - create_a_new_conversation: "rozpocznij nowÄ… rozmowÄ™" inbox: "Skrzynka odbiorcza" new_conversation: "Nowa rozmowa" - no_conversation_selected: "Nie wybrano wÄ…tku" no_messages: "Brak wiadomoÅ›ci" new: - abandon_changes: "Porzucić zmiany?" + message: "Wiadomość" send: "WyÅ›lij" sending: "WysyÅ‚anie..." subject: "Temat" @@ -327,6 +298,7 @@ pl: show: delete: "UsuÅ„ rozmowÄ™" hide: "ukryj i wycisz rozmowÄ™" + last_message: "Ostatni komunikat odebrano %{timeago}" reply: "Odpowiedz" replying: "Odpowiadanie..." date: @@ -339,10 +311,6 @@ pl: error_messages: helper: correct_the_following_errors_and_try_again: "Popraw poniższe bÅ‚Ä™dy i spróbuj ponownie." - invalid_fields: "Pola z bÅ‚Ä™dami" - login_try_again: "<a href='%{login_link}'>Zaloguj siÄ™</a> i spróbuj ponownie." - post_not_public: "Wpis, który chcesz wyÅ›wietlić nie jest dostÄ™pny publicznie!" - post_not_public_or_not_exist: "Wpis, który chcesz zobaczyć nie jest publiczny lub nie istnieje!" fill_me_out: "WypeÅ‚nij mnie" find_people: "Znajdź osoby lub #znaczniki" help: @@ -562,30 +530,17 @@ pl: tutorial: "samouczek" tutorials: "samouczki" wiki: "wiki" - hide: "Ukryj" - ignore: "Ignoruj" - invitation_codes: - excited: "%{name} cieszy siÄ™, że CiÄ™ tutaj widzi." invitations: a_facebook_user: "Użytkownik Facebooka" check_token: not_found: "Nie odnaleziono identyfikatora zaproszenia" create: - already_contacts: "{m,f:JesteÅ› już|n:PoÅ‚Ä…czono już}{ }{m,f:poÅ‚Ä…czon}{m:y|f:a} z tÄ… osobÄ…." - already_sent: "Już zapros@{m:iÅ‚eÅ›|f:iÅ‚aÅ›|n:zono} tÄ™ osobÄ™." empty: "Podaj przynajmniej jeden adres e-mail." no_more: "Nie masz wiÄ™cej zaproszeÅ„." note_already_sent: "Zaproszenia zostaÅ‚y już wysÅ‚ane do: %{emails}" - own_address: "Nie możesz wysÅ‚ać zaproszenia na swój wÅ‚asny adres." rejected: "NastÄ™pujÄ…ce adresy e-mail okazaÅ‚y siÄ™ problematyczne:" sent: "Zaproszenia zostaÅ‚y wysÅ‚ane do: %{emails}" - edit: - accept_your_invitation: "Zaakceptuj zaproszenie" - your_account_awaits: "Twoje konto czeka!" new: - already_invited: "Te osoby nie zaakceptowaÅ‚y jeszcze Twojego zaproszenia:" - aspect: "Aspekt" - check_out_diaspora: "Wypróbuj DiasporÄ™!" codes_left: few: "%{count} zaproszenia na ten kod" many: "%{count} zaproszeÅ„ na ten kod" @@ -593,16 +548,11 @@ pl: other: "%{count} zaproszeÅ„ na ten kod" zero: "Brak zaproszeÅ„ na ten kod" comma_separated_plz: "Można wprowadzić wiele adresów e-mail oddzielonych przecinkami." - if_they_accept_info: "JeÅ›li wybrana osoba przyjmie zaproszenie, zostanie dodana do aspektów, do których jÄ… zapros@{m:iÅ‚eÅ›|f:iÅ‚aÅ›|n:zono}." invite_someone_to_join: "ZaproÅ› kogoÅ› do Diaspory!" language: "JÄ™zyk" paste_link: "UdostÄ™pnij to Å‚Ä…cze znajomym, aby zaprosić ich do Diaspory* lub wyÅ›lij je do nich przez e-mail." - personal_message: "Dodatkowa wiadomość" - resend: "WyÅ›lij ponownie" send_an_invitation: "WyÅ›lij zaproszenie" - send_invitation: "WyÅ›lij zaproszenie" sending_invitation: "WysyÅ‚a zaproszenie..." - to: "Do" layouts: application: back_to_top: "Powrót na górÄ™" @@ -612,41 +562,14 @@ pl: statistics_link: "Statystyki poda" toggle: "PrzeÅ‚Ä…cz widok mobilny" whats_new: "Co nowego?" - your_aspects: "Twoje aspekty" header: - admin: "Administrator" - blog: "Blog" code: "Kod" - help: "Pomoc" - login: "Zaloguj siÄ™" logout: "Wyloguj" profile: "Profil" - recent_notifications: "Najnowsze powiadomienia" settings: "Ustawienia" - view_all: "WyÅ›wietl wszystkie" - likes: - likes: - people_dislike_this: - few: "%{count} os. tego nie lubi" - many: "%{count} os. tego nie lubi" - one: "1 osoba tego nie lubi" - other: "%{count} os. tego nie lubi" - zero: "nikt tego nie nielubi" - people_like_this: - few: "%{count} os. to lubi" - many: "%{count} os. to lubi" - one: "%{count} os. to lubi" - other: "%{count} os. to lubi" - zero: "nikt nie lubi" - people_like_this_comment: - few: "%{count} os. to lubi" - many: "%{count} os. to lubi" - one: "%{count} osoba to lubi" - other: "%{count} os. to lubi" - zero: "nikt nie lubi" + toggle_navigation: "PrzeÅ‚Ä…cz nawigacjÄ™" limited: "Ograniczone" more: "WiÄ™cej" - next: "NastÄ™pny" no_results: "Niczego nie znaleziono" notifications: also_commented: @@ -667,13 +590,6 @@ pl: one: "Twój wpis %{post_link} ma komentarz od %{actors}." other: "Twój wpis %{post_link} ma komentarze od %{actors}." zero: "nikt nie skomentowaÅ‚ Twojego wpisu %{post_link}." - helper: - new_notifications: - few: "%{count} nowe powiadomienia" - many: "%{count} nowych powiadomieÅ„" - one: "1 nowe powiadomienie" - other: "%{count} nowych powiadomieÅ„" - zero: "Brak nowych powiadomieÅ„" index: all_notifications: "Wszystkie Powiadomienia" also_commented: "Także skometowali" @@ -750,7 +666,6 @@ pl: a_limited_post_comment: "PojawiÅ‚ siÄ™ nowy komentarz w ograniczonym wpisie na diasporze*. Zapoznaj siÄ™ z nim." a_post_you_shared: "wpis." a_private_message: "Masz nowÄ… wiadomość w diaspora*" - accept_invite: "Zaakceptuj zaproszenie do diaspory*!" also_commented: limited_subject: "PojawiÅ‚ siÄ™ nowy komentarz do wpisu, który komentowaÅ‚eÅ›" click_here: "Kliknij tutaj" @@ -830,7 +745,6 @@ pl: view_post: "WyÅ›wietl wpis >" mentioned: limited_post: "ZostaÅ‚eÅ› wspomniany w poÅ›cie o ograniczonej widocznoÅ›ci." - mentioned: "wspomniaÅ‚(a) o Tobie we wpisie:" subject: "%{name} wspomniaÅ‚ o Tobie na diasporze*" private_message: reply_to_or_view: "Odpowiedz lub wyÅ›wietl wÄ…tek >" @@ -882,20 +796,9 @@ pl: to_change_your_notification_settings: "aby zmienić ustawienia powiadomieÅ„" nsfw: "NSFW" ok: "OK" - or: "lub" - password: "HasÅ‚o" - password_confirmation: "Potwierdzenie hasÅ‚a" people: add_contact: invited_by: "Zaproszenie wysÅ‚ane przez" - add_contact_small: - add_contact_from_tag: "Dodaj znajomego ze znacznika" - aspect_list: - edit_membership: "Edycja przynależnoÅ›ci do aspektów" - helper: - is_not_sharing: "%{name} Ci nie udostÄ™pnia." - is_sharing: "%{name} udostÄ™pnia Ci." - results_for: "wyniki dla %{params}" index: couldnt_find_them: "Nie możesz ich znaleźć?" looking_for: "Szukasz wpisów oznaczonych %{tag_link}?" @@ -905,86 +808,37 @@ pl: search_handle: "Użyj identyfikatora diaspory* (użytkownik@pod.example.com) aby mieć pewność, że znajdziesz swoich znajomych." searching: "wyszukiwanie, proszÄ™ czekać..." send_invite: "Wciąż nic nowego? WyÅ›lij zaproszenie!" - one: "1 osoba" - other: "Osoby: %{count}" person: - add_contact: "Dodaj kontakt" - already_connected: "Już podÅ‚Ä…czono" - pending_request: "OczekujÄ…ce zaproszenia" thats_you: "To Ty!" profile_sidebar: bio: "Notka biograficzna" born: "Urodziny" - edit_my_profile: "Edycja mojego profilu" gender: "PÅ‚eć" - in_aspects: "W aspektach" location: "Lokalizacja" - photos: "ZdjÄ™cia" - remove_contact: "UsuÅ„ kontakt" - remove_from: "Usunąć %{name} z aspektu %{aspect}?" show: closed_account: "Te konto zostaÅ‚o zamkniÄ™te." does_not_exist: "Osoba nie istnieje!" has_not_shared_with_you_yet: "%{name} nie udostÄ™pnia Ci jeszcze żadnych wpisów!" - ignoring: "Ignorujesz wszystkie wpisy od %{name}." - incoming_request: "%{name} chce Ci udostÄ™pniać" - mention: "Wspomnij" - message: "Wiadomość" - not_connected: "Nie udostÄ™pniasz tej osobie" - recent_posts: "Ostatnie wpisy" - recent_public_posts: "Ostatnie wpisy publiczne" - return_to_aspects: "Wróć do strony aspektów" - see_all: "Zobacz wszystkich" - start_sharing: "Rozpocznij udostÄ™pnianiać" - to_accept_or_ignore: "by je przyjąć lub zignorować." - sub_header: - add_some: "Dodaj" - edit: "Edycja" - you_have_no_tags: "Nie masz tagów!" - webfinger: - fail: "Nie odnaleziono %{handle}." - zero: "Brak osób" photos: - comment_email_subject: "ZdjÄ™cie użytkownika %{name}" create: integrity_error: "Nie udaÅ‚o siÄ™ przesÅ‚ać zdjÄ™cia? Czy to na pewno byÅ‚ plik obrazu?" runtime_error: "Nie udaÅ‚o siÄ™ przesÅ‚ać zdjÄ™cia. Czy @{m:zapiÄ…Å‚eÅ› |f:zapięłaÅ› }pasy bezpieczeÅ„stwa@{n: sÄ… zapiÄ™te}?" type_error: "Nie udaÅ‚o siÄ™ przesÅ‚ać zdjÄ™cia. Czy na pewno doda@{m:Å‚eÅ›|f:Å‚aÅ›|n:no} obraz?" destroy: notice: "UsuniÄ™to zdjÄ™cie." - edit: - editing: "Edycja" - new: - back_to_list: "Powrót do listy" - new_photo: "Nowe zdjÄ™cie" - post_it: "Opublikuj!" new_photo: empty: "Plik {file} jest pusty. Wybierz proszÄ™ jeszcze raz odpowiednie pliki, pomijajÄ…c ten." invalid_ext: "Plik {file} ma niewÅ‚aÅ›ciwe rozszerzenie. Akceptowane rozszerzenia: {extensions}" size_error: "Plik {file} jest zbyt duży, maksymalny rozmiar to {sizeLimit}." new_profile_photo: - or_select_one_existing: "lub wybierz któreÅ› z istniejÄ…cych %{photos}" upload: "PrzeÅ›lij nowe zdjÄ™cie profilowe!" - photo: - view_all: "WyÅ›wietl wszystkie zdjÄ™cia należące do: %{name}" show: - collection_permalink: "ÅÄ…cze bezpoÅ›rednie do kolekcji" - delete_photo: "UsuÅ„ zdjÄ™cie" - edit: "Edycja" - edit_delete_photo: "Edycja opisu zdjÄ™cia / usuwanie zdjÄ™cia" - make_profile_photo: "Ustaw jako zdjÄ™cie profilowe" show_original_post: "WyÅ›wietl oryginalny wpis" - update_photo: "Aktualizacja zdjÄ™cia" - update: - error: "BÅ‚Ä…d podczas edycji zdjÄ™cia." - notice: "PomyÅ›lnie zaktualizowano zdjÄ™cie." posts: presenter: title: "Wpis od %{name}" show: - destroy: "UsuÅ„" - not_found: "Nie można odnaleźć wskazanego wpisu." - permalink: "ÅÄ…cze bezpoÅ›rednie" + forbidden: "Nie masz pozwolenia by to zrobić." photos_by: few: "%{count} zdjÄ™cia od %{author}" many: "%{count} zdjęć od %{author}" @@ -992,14 +846,11 @@ pl: other: "%{count} zdjÄ™cia od %{author}" zero: "Brak zdjęć od %{author}" reshare_by: "Przekazane dalej przez %{author}" - previous: "Poprzedni" privacy: "Prywatność" - privacy_policy: "Polityka prywatnoÅ›ci" profile: "Profil" profiles: edit: allow_search: "Pozwól innym użytkownikom diaspory* na wyszukanie ciebie" - edit_profile: "Edycja profilu" first_name: "ImiÄ™" last_name: "Nazwisko" nsfw_check: "Oznacz wszystko co udostÄ™pniam jako NSFW" @@ -1012,8 +863,6 @@ pl: your_location: "Lokalizacja" your_name: "ImiÄ™" your_photo: "Twoje zdjÄ™cie" - your_private_profile: "Twój profil prywatny" - your_public_profile: "Twój profil publiczny" your_tags: "Opisz siebie w piÄ™ciu sÅ‚owach" your_tags_placeholder: "np. #filmy #kotki #podróże #nauczyciel #warszawa" update: @@ -1030,26 +879,16 @@ pl: closed: "Ten pod diaspory* nie zezwala na rejestracjÄ™ nowych użytkowników." create: success: "DoÅ‚Ä…czyÅ‚@{f:aÅ›|m:eÅ›|n:aÅ›/eÅ›} do diaspory*!" - edit: - cancel_my_account: "Anuluj moje konto" - edit: "Edycja: %{name}" - leave_blank: "(pozostaw puste, jeÅ›li nie chcesz zmieniać)" - password_to_confirm: "(potrzebujemy obecnego hasÅ‚a, żeby zatwierdzić zmiany)" - unhappy: "CoÅ› Ci siÄ™ nie podoba?" - update: "Aktualizacja" invalid_invite: "Podane Å‚Ä…cze do zaproszenia jest nieważne!" new: - create_my_account: "Utwórz konto!" email: "E-mail" enter_email: "Wpisz adres e-mail" enter_password: "Podaj hasÅ‚o (maks. 6 znaków)" enter_password_again: "Wprowadź ponownie to samo hasÅ‚o" enter_username: "Wybierz nazwÄ™ użytkownika (możliwe litery, cyfry i podkreÅ›lniki)" - join_the_movement: "DoÅ‚Ä…cz do ruchu!" password: "HasÅ‚o" password_confirmation: "Potwierdzenie hasÅ‚a" sign_up: "Rejestracja" - sign_up_message: "Sieć spoÅ‚ecznoÅ›ciowa z ♥" submitting: "WysyÅ‚anie..." terms: "ZakÅ‚adajÄ…c konto akceptujesz %{terms_link}." terms_link: "warunki korzystania z serwisu" @@ -1064,47 +903,15 @@ pl: reported_label: "<b>ZgÅ‚oszony przez</b> %{person}" review_link: "Oznacz jako sprawdzony" status: - created: "ZgÅ‚oszenie zostaÅ‚o utworzone" destroyed: "Wpis zostaÅ‚Â zniszczony" failed: "CoÅ› poszÅ‚o nie tak" - marked: "ZgÅ‚oszenie zostaÅ‚o oznaczone jako sprawdzone" title: "PrzeglÄ…d zgÅ‚oszeÅ„" - requests: - create: - sending: "WysyÅ‚anie" - sent: "Współdzielenie aktywne. %{name} otrzyma o tym komunikat, gdy tylko zaloguje się w diasporze*." - destroy: - error: "Wybierz aspekt!" - ignore: "Zignorowano proÅ›bÄ™ o dodanie do znajomych." - success: "JesteÅ›cie teraz znajomymi." - helper: - new_requests: - few: "%{count} nowe zaproszenia" - many: "%{count} nowych zaproszeÅ„" - one: "nowe zaproszenie!" - other: "%{count} nowych zaproszeÅ„" - zero: "brak nowych zaproszeÅ„" - manage_aspect_contacts: - existing: "IstniejÄ…ce kontakty" - manage_within: "ZarzÄ…dzanie kontaktami w" - new_request_to_person: - sent: "WysÅ‚ano!" reshares: comment_email_subject: "%{resharer} przekazaÅ‚/a dalej wpis %{author}" - create: - failure: "Przekazywanie dalej nie powiodÅ‚o siÄ™." reshare: deleted: "OryginaÅ‚ zostaÅ‚ usuniÄ™ty przez autora." - reshare: - few: "Przekazano dalej: %{count}" - many: "Przekazano dalej: %{count}" - one: "Przekazano dalej: 1" - other: "Przekazano dalej: %{count}" - zero: "Przekaż dalej" reshare_confirmation: "Przekazać dalej wpis użytkownika %{author}?" - reshare_original: "Przekaż dalej oryginaÅ‚" reshared_via: "Przekazano dalej przez " - show_original: "WyÅ›wietl oryginaÅ‚" search: "Znajdź" services: create: @@ -1116,10 +923,6 @@ pl: success: "PomyÅ›lnie usuniÄ™to dane uwierzytelniajÄ…ce." failure: error: "WystÄ…piÅ‚ bÅ‚Ä…d podczas Å‚Ä…czenia z tÄ… usÅ‚ugÄ…" - finder: - fetching_contacts: "diaspora* importuje Twoich znajomych z %{service}, sprawdź postÄ™p ponownie za kilka minut." - no_friends: "Nie znaleziono znajomych z Facebooka." - service_friends: "Znajomi z %{service} " index: connect: "Connect" disconnect: "RozÅ‚Ä…cz" @@ -1129,33 +932,14 @@ pl: not_logged_in: "Nie zalogowany." really_disconnect: "OdÅ‚Ä…czyć %{service}?" services_explanation: "PodÅ‚Ä…czenie usÅ‚ug umożliwia jednoczesne publikowanie w nich wpisów, które udostÄ™pniasz w sieci Diaspora*." - inviter: - click_link_to_accept_invitation: "Kliknij to Å‚Ä…cze, aby przyjąć zaproszenie" - join_me_on_diaspora: "DoÅ‚Ä…cz do mnie na diasporze*" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "ZaproÅ›" - not_on_diaspora: "Nie ma jeszcze konta na diasporze*" - resend: "WyÅ›lij ponownie" settings: "Ustawienia" - share_visibilites: - update: - post_hidden_and_muted: "Wpisy użytkownika %{name} zostaÅ‚y ukryte, a powiadomienia wyciszone." - see_it_on_their_profile: "JeÅ›li chcesz zobaczyć aktualizacje tego wpisu, odwiedź profil użytkownika %{name}." shared: - add_contact: - add_new_contact: "Dodaj nowy kontakt" - create_request: "Szukaj wg Identyfikatora Diaspory" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Wpisz nazwÄ™ użytkownika diaspory*:" - know_email: "Znasz ich adresy e-mail? Powi@{m:nieneÅ›|f:nnaÅ›|n:nni}{ }{m,f:ich zaprosić|n:zostać zaproszeni}!" - your_diaspora_username_is: "Twój nazwa użytkownika na diasporze* to: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Dodaj kontakt" mobile_row_checked: "%{name} (usuÅ„)" mobile_row_unchecked: "%{name} (dodaj)" toggle: @@ -1164,23 +948,11 @@ pl: one: "W %{count} aspekcie" other: "W %{count} aspektach" zero: "Dodaj kontakt" - contact_list: - all_contacts: "Wszystkie kontakty" - footer: - logged_in_as: "Zalogowano jako %{name}" - your_aspects: "Twoje aspekty" invitations: by_email: "Przez e-mail" - dont_have_now: "Nie masz wolnych zaproszeÅ„, ale niebawem się pojawiÄ…!" - from_facebook: "Z Facebooka" - invitations_left: "PozostaÅ‚o: %{count}" - invite_someone: "ZaproÅ› kogoÅ›" invite_your_friends: "ZaproÅ› swoich znajomych" invites: "Zaproszenia" - invites_closed: "WysyÅ‚anie zaproszeÅ„ jest obecnie wyÅ‚Ä…czone na tym podzie Diaspory" share_this: "UdostÄ™pnij to Å‚Ä…cze przez e-mail, na blogu lub w sieci spoÅ‚ecznoÅ›ciowej!" - notification: - new: "Nowy(-a,-e) %{type} od %{from}" public_explain: atom_feed: "KanaÅ‚ Atom" control_your_audience: "Dostosuj swojÄ… publiczność" @@ -1192,12 +964,9 @@ pl: title: "Konfiguracja poÅ‚Ä…czonych usÅ‚ug" visibility_dropdown: "Użyj tej listy rozwijalnej, aby zmienić widoczność swojego wpisu. (Proponujemy, aby ten pierwszy byÅ‚ publiczny.)" publisher: - all: "Wszyscy" - all_contacts: "Wszystkim kontaktom" discard_post: "Porzuć wpis" formatWithMarkdown: "Możesz użyć %{markdown_link} aby sformatować swój wpis" get_location: "Ustal twojÄ… lokalizacjÄ™" - make_public: "Upublicznij" new_user_prefill: hello: "Witajcie wszyscy, jestem #%{new_user_tag}. " i_like: "InteresujÄ… mnie %{tags}." @@ -1205,36 +974,14 @@ pl: newhere: "TutajOdNiedawna" poll: add_a_poll: "Dodaj ankietÄ™" - add_poll_answer: "Dodaj opcjÄ™" - option: "Opcja 1" - question: "Pytanie" - remove_poll_answer: "UsuÅ„ opcjÄ™" - post_a_message_to: "WyÅ›lij wiadomość do %{aspect}" posting: "Publikowanie..." - preview: "PodglÄ…d" - publishing_to: "Publikuj na: " remove_location: "UsuÅ„ lokalizacjÄ™" share: "UdostÄ™pnij" - share_with: "UdostÄ™pnij" upload_photos: "PrzeÅ›lij zdjÄ™cia" whats_on_your_mind: "O czym myÅ›lisz?" - reshare: - reshare: "Przekaż dalej" stream_element: - connect_to_comment: "PoÅ‚Ä…cz siÄ™ z tym użytkownikiem, aby komentować jego wpisy" - currently_unavailable: "Dodawanie komentarzy jest aktualnie niemożliwe" - dislike: "Nie lubiÄ™" - hide_and_mute: "Ukryj i wycisz wpis" - ignore_user: "Ignoruj - %{name}" - ignore_user_description: "Dodać użytkownika do listy ignorowanych i usunąć ze wszystkich aspektów?" - like: "LubiÄ™ to!" - nsfw: "Ten wpis zostaÅ‚ oznaczony przez jego autora jako NSFW (Not suitable/safe for work). %{link}" - shared_with: "Opublikowano w: %{aspect_names}" - show: "WyÅ›wietl" - unlike: "Nie lubiÄ™" via: "Przez %{link}" via_mobile: "Przez urzÄ…dzenie przenoÅ›ne" - viewable_to_anyone: "Ten wpis jest widoczny dla każdego" simple_captcha: label: "Wpisz kod z obrazka" message: @@ -1260,23 +1007,12 @@ pl: status_messages: create: success: "PomyÅ›lnie wspomniano o: %{names}" - destroy: - failure: "BÅ‚Ä…d podczas usuwania wpisu" - helper: - no_message_to_display: "Brak wiadomoÅ›ci do wyÅ›wietlenia." new: mentioning: "Wspominasz o: %{person}" too_long: "Skróć swój status do mniej niż %{count} znaków. Obecnie jej dÅ‚ugość to %{current_length} znaków." stream_helper: - hide_comments: "Ukryj wszystkie komentarze" no_more_posts: "DotarÅ‚eÅ› do koÅ„ca strumienia." no_posts_yet: "Nie ma jeszcze żadnych wpisów." - show_comments: - few: "WyÅ›wietl %{count} komentarze wiÄ™cej" - many: "WyÅ›wietl %{count} komentarzy wiÄ™cej" - one: "WyÅ›wietl jeden komentarz wiÄ™cej" - other: "WyÅ›wietl %{count} komentarzy wiÄ™cej" - zero: "Nie ma wiÄ™cej komentarzy" streams: activity: title: "Moja aktywność" @@ -1303,13 +1039,6 @@ pl: tags: title: "Oznaczone wpisy: %{tags}" tag_followings: - create: - failure: "Nie udaÅ‚o siÄ™ dodać do obserwowanych #%{name}. Może już to obserwujesz?" - none: "Nie możesz obserwować pustego znacznika!" - success: "Brawo! Od teraz obserwujesz #%{name}." - destroy: - failure: "Nie udaÅ‚o siÄ™ zatrzymać obserwowania: #% {name}. Może już tego nie obserwujesz?" - success: "Nie obserwujesz już: #%{name}" manage: no_tags: "Nie obserwujesz żadnych tagów" title: "ZarzÄ…dzaj obserwowanymi tagami" @@ -1317,7 +1046,6 @@ pl: name_too_long: "ProszÄ™ skróć nazwÄ™ taga do mniej niż %{count} znaków. Obecnie zawiera %{current_length} znaków." show: follow: "Obserwuj #%{tag}" - following: "Obserwowanie #%{tag}" none: "Pusty znacznik nie istnieje!" stop_following: "PrzestaÅ„ obserwować #%{tag}" tagged_people: @@ -1326,8 +1054,6 @@ pl: one: "1 osoba otagowana %{tag}" other: "%{count} osób otagowanych %{tag}" zero: "Nikogo otagowanego %{tag}" - terms_and_conditions: "Regulamin" - undo: "Cofnąć?" username: "Nazwa użytkownika" users: confirm_email: @@ -1348,7 +1074,6 @@ pl: character_minimum_expl: "minimum 6 znaków" close_account: dont_go: "Prosimy, nie odchodź!" - if_you_want_this: "JeÅ›li naprawdÄ™ tego chcesz, wpisz swoje hasÅ‚o poniżej i kliknij \"Zamknij konto\"." lock_username: "Nazwa Twojego konta zostanie zablokowana. Na tym podzie nie bÄ™dziesz już mógÅ‚ stworzyć nowego, o tym samym identyfikatorze." locked_out: "Zostaniesz wylogowa@{m:ny|f:na|n:ny/na} i zablokowany, dopóki Twoje konto nie zostanie usuniÄ™te." make_diaspora_better: "WolelibyÅ›my, żebyÅ› zostaÅ‚ tu i pomógÅ‚ nam ulepszyć diasporÄ™*, zamiast opuszczać sieć. Jednak jeÅ›li naprawdÄ™ odchodzisz, oto co siÄ™ potem stanie:" @@ -1361,14 +1086,12 @@ pl: current_password_expl: "to, którego używasz do logowania" download_export: "Pobierz mój profil" download_export_photos: "Pobierz moje zdjÄ™cia" - download_photos: "Pobierz moje zdjÄ™cia" edit_account: "Edycja konta" email_awaiting_confirmation: "ÅÄ…cze aktywacyjne zostaÅ‚o wysÅ‚ane na adres \"%{unconfirmed_email}\". Do momentu klikniÄ™cia Å‚Ä…cza i aktywacji nowego adresu, nadal bÄ™dziemy korzystać z obecnego \"%{email}\"." export_data: "Eksport danych" export_in_progress: "Przetwarzamy twoje dane. Sprawdź ponownie za kilka minut." export_photos_in_progress: "Aktualnie przetwarzamy twoje zdjÄ™cia. Sprawdź ponownie za kilka chwil." following: "Ustawienia udostÄ™pniania" - getting_started: "Ustawienia nowego użytkownika" last_exported_at: "(ostatnio aktualizowano o %{timestamp})" liked: "...ktoÅ› polubiÅ‚ mój wpis" mentioned: "...ktoÅ› wspomniaÅ‚ mnie we wpisie" @@ -1395,7 +1118,6 @@ pl: connect_to_facebook_link: "PodpiÄ™cie konta na Facebooku" hashtag_explanation: "Znaczniki pozwalajÄ… Å‚atwo odnaleźć interesujÄ…ce CiÄ™ tematy. SÄ… także Å›wietnym sposobem na nawiÄ…zywanie znajomoÅ›ci na diasporze*." hashtag_suggestions: "Spróbuj obserwować znaczniki takie jak #sztuka, #filmy, #gif, itd." - saved: "Zapisano!" well_hello_there: "No, witam!" what_are_you_in_to: "Czym siÄ™ interesujesz?" who_are_you: "Kim jesteÅ›?" @@ -1419,13 +1141,6 @@ pl: settings_updated: "Zaktualizowano ustawienia" unconfirmed_email_changed: "Adres e-mail zostaÅ‚ zmieniony. Wymagana jest weryfikacja." unconfirmed_email_not_changed: "Zmiana adresu e-mail nie powiodÅ‚a siÄ™" - webfinger: - fetch_failed: "Nie udaÅ‚o siÄ™ pobrać profilu Webfinger dla %{profile_url}" - hcard_fetch_failed: "WystÄ…piÅ‚ problem podczas pobierania wizytówki hcard użytkownika %{account}" - no_person_constructed: "Nie udaÅ‚o siÄ™ utworzyć osoby używajÄ…c tego zbioru hcard." - not_enabled: "UsÅ‚uga Webfinger nie dziaÅ‚a w systemie utrzymujÄ…cym konto użytkownika %{account}" - xrd_fetch_failed: "wystÄ…piÅ‚ bÅ‚Ä…d podczas pobierania xrd z konta %{account}" - welcome: "Witamy!" will_paginate: next_label: "dalej »" previous_label: "« wstecz" \ No newline at end of file diff --git a/config/locales/diaspora/pt-BR.yml b/config/locales/diaspora/pt-BR.yml index 2940b6729235d7a193fc766645db1659bb61a2d2..6aa04fa4b8f88a6b1ac99b755ade0c6d9e7e3569 100644 --- a/config/locales/diaspora/pt-BR.yml +++ b/config/locales/diaspora/pt-BR.yml @@ -6,11 +6,8 @@ pt-BR: _applications: "Aplicativos" - _comments: "Comentários" _contacts: "Contatos" _help: "Ajuda" - _home: "InÃcio" - _photos: "Fotos" _services: "Serviços" _statistics: "EstatÃsticas" _terms: "Termos" @@ -53,12 +50,19 @@ pt-BR: taken: "já foi escolhido." admins: admin_bar: + dashboard: "Painel" pages: "Páginas" - pod_stats: "Status do Servidor" + pod_network: "Rede" + pod_stats: "EstatÃsticas do servidor" report: "Relatos" sidekiq_monitor: "Monitor Sidekiq" user_search: "Busca de usuários" weekly_user_stats: "EstatÃsticas semanais" + dashboard: + fetching_diaspora_version: "Buscando versão mais recente de diaspora*..." + pod_status: "Estado do servidor" + pods: + pod_network: "Rede" stats: 2weeks: "2 semanas" 50_most: "50 tags mais populares" @@ -88,15 +92,16 @@ pt-BR: week: "Semana" user_entry: account_closed: "Conta encerrada" - diaspora_handle: "Diaspora ID" + diaspora_handle: "diaspora* ID" email: "Email" guid: "GUID" id: "ID" + invite_token: "Convite" last_seen: "Última visita" ? "no" : Não nsfw: "#nsfw" - unknown: "desconhecido" + unknown: "Desconhecido" ? "yes" : Sim user_search: @@ -109,7 +114,10 @@ pt-BR: are_you_sure_unlock_account: "Tem certeza de que deseja desbloquear esta conta?" close_account: "Encerrar conta" email_to: "E-mail para convidar" + invite: "Convidar" + lock_account: "Bloquear conta" under_13: "Mostrar usuários menores de 13 anos" + unlock_account: "Desbloquear conta" users: one: "%{count} usuário encontrado" other: "%{count} usuários encontrados" @@ -125,13 +133,57 @@ pt-BR: other: "Quantidade de novos usuários esta semana: %{count}" zero: "Quantidade de novos usuários esta semana: Nenhum" current_server: "Data atual do servidor é %{date}" - ago: "%{time} atrás" all_aspects: "Todos os aspectos" - application: - helper: - unknown_person: "Pessoa desconhecida" - video_title: - unknown: "VÃdeo sem tÃtulo" + api: + openid_connect: + authorizations: + destroy: + fail: "Falha ao anular autorização de ID %{id}" + new: + access: "%{name} requer acesso para:" + approve: "Aprovar" + bad_request: "ID do cliente ou URI de redirecionamento está ausente" + client_id_not_found: "Não foi encontrado cliente com \"client_id\" %{client_id} e URI de redirecionamento %{redirect_uri}" + deny: "Negar" + no_requirement: "%{name} não requer permissões" + redirection_message: "Tem certeza de que quer dar acesso a %{redirect_uri}?" + error_page: + contact_developer: "Você deve entrar em contato com a pessoa responsável pela programação do aplicativo e incluir esta mensagem de erro:" + could_not_authorize: "Não foi possÃvel autorizar o aplicativo" + login_required: "Você deve entrar no sistema para autorizar esse aplicativo" + title: "Opa! Alguma coisa deu errado :(" + scopes: + name: + description: "O aplicativo teria acesso ao seu nome" + name: "nome" + nickname: + description: "O aplicativo teria acesso ao seu apelido" + name: "apelido" + openid: + description: "O aplicativo teria permissão para ler seu perfil básico" + name: "perfil básico" + picture: + description: "O aplicativo teria acesso à s suas imagens" + name: "imagem" + profile: + description: "O aplicativo teria permissão para ler seu perfil ampliado" + name: "perfil ampliado" + read: + description: "O aplicativo teria permissão para ler seu fluxo, conversas e perfil completo" + name: "ler perfil, fluxo e conversas" + write: + description: "O aplicativo teria permissão para publicar, conversar e enviar reações" + name: "enviar publicações, conversas e reações" + user_applications: + index: + access: "%{name} tem acesso a:" + edit_applications: "Aplicativos" + no_requirement: "%{name} não requer permissões" + title: "Aplicativos autorizados" + no_applications: "Você não tem aplicativos autorizados" + policy: "Ver polÃtica de privacidade do aplicativo" + revoke_autorization: "Anular" + tos: "Ver termos de serviço do aplicativo" are_you_sure: "Tem certeza?" are_you_sure_delete_account: "Tem certeza de que deseja cancelar sua conta? Isso não poderá ser desfeito!" aspect_memberships: @@ -147,48 +199,27 @@ pt-BR: success: "Contato adicionado ao aspecto com sucesso." aspect_listings: add_an_aspect: "+ Adicione um Aspecto" - deselect_all: "Desmarcar tudo" - edit_aspect: "Editar %{name}" - select_all: "Selecionar tudo" aspect_stream: make_something: "Faça algo" stay_updated: "Fique por dentro" stay_updated_explanation: "Seu fluxo é preenchido com todos os seus contatos, tags que você segue e as mensagens de alguns membros criativos da comunidade." - contacts_not_visible: "Contatos neste aspecto não poderão ver uns aos outros." - contacts_visible: "Contatos neste aspecto poderão ver uns aos outros." - create: - failure: "Não foi possÃvel criar o aspecto." - success: "Seu novo aspecto %{name} foi criado" destroy: failure: "%{name} não pôde ser removido." success: "%{name} foi removido com sucesso." success_auto_follow_back: "%{name} foi removido(a) com sucesso. Este aspecto está configurado para seguir de volta automaticamente todos os usuários que seguem você. Verifique suas configurações." edit: - aspect_chat_is_enabled: "Contatos neste aspecto podem bater papo com você." - aspect_chat_is_not_enabled: "Contatos neste aspecto não podem bater papo com você." aspect_list_is_not_visible: "Contatos neste aspecto não podem ver uns aos outros." aspect_list_is_visible: "Contatos neste aspecto podem ver uns aos outros." confirm_remove_aspect: "Tem certeza que deseja apagar este aspecto?" - grant_contacts_chat_privilege: "Conceder aos contatos neste aspecto privilégios de bate-papo?" - make_aspect_list_visible: "Tornar contatos deste aspecto visÃveis entre si?" - remove_aspect: "Apagar este aspecto" rename: "Renomear" - set_visibility: "Configurar visibilidade" update: "Atualizar" updating: "Atualizando" index: - diaspora_id: - content_1: "Sua diaspora* ID é:" - content_2: "Com ele, as pessoas podem te encontrar na diaspora*." - heading: "diaspora* ID" donate: "Faça uma Doação" - handle_explanation: "Essa é sua diaspora* ID. Como um endereço de e-mail, você pode fornecê-la para que outras pessoas contatem com você." help: any_problem: "Algum problema?" contact_podmin: "Entre em contato com a administração do seu servidor!" do_you: "Você:" - email_feedback: "%{link} seu feedback, se você preferir" - email_link: "Email" feature_suggestion: "... tem uma sugestão de %{link}?" find_a_bug: "... encontrou um %{link}?" have_a_question: "... Tem uma %{link}?" @@ -199,33 +230,23 @@ pt-BR: tag_feature: "recurso" tag_question: "pergunta" tutorial_link_text: "Tutoriais" - tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: ajudas para seus primeiros passos." + tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: ajuda para os seus primeiros passos." introduce_yourself: "Este é seu fluxo. Se apresente!" - keep_diaspora_running: "Mantenha o desenvolvimento de diaspora* acelerado com uma doação mensal!" keep_pod_running: "Mantenha %{pod} funcionando bem e pague um café para nossos voluntários com uma doação fixa mensal!" new_here: follow: "Siga %{link} e dê boas vindas aos novos usuários de Diaspora*!" learn_more: "Saiba mais" title: "Dê boas-vindas aos novatos" - no_contacts: "Nenhum contato" - no_tags: "+ Procurar uma tag para seguir" - people_sharing_with_you: "Pessoas compartilhando com você" - post_a_message: "Publicar uma mensagem >>" services: content: "Você pode conectar os seguintes serviços em diaspora*:" heading: "Conecte-se" - unfollow_tag: "Parar de seguir #%{tag}" welcome_to_diaspora: "Bem-vindo(a) a diaspora*, %{name}!" - new: - create: "Criar" - name: "Nome (só é visÃvel para você)" no_contacts_message: community_spotlight: "Destaques da Comunidade" + invite_link_text: "convidar" or_spotlight: "Ou você pode compartilhar com %{link}" try_adding_some_more_contacts: "Você pode buscar ou %{invite_link} mais pessoas." you_should_add_some_more_contacts: "Adicione mais alguns contatos!" - no_posts_message: - start_talking: "Ninguém disse nada ainda!" seed: acquaintances: "Conhecidos" family: "FamÃlia" @@ -234,34 +255,26 @@ pt-BR: update: failure: "Seu aspecto %{name} tem um nome muito longo para ser salvo." success: "Seu aspecto %{name} foi editado com sucesso." - back: "Voltar" blocks: create: - failure: "Não foi possÃvel ignorar esse usuário." + failure: "Não foi possÃvel ignorar esse usuário. #evasiva" success: "Tudo bem, você não verá esse usuário em seu fluxo novamente. #silencio!" destroy: - failure: "Não foi possÃvel deixar de ignorar esse usuário." + failure: "Não foi possÃvel deixar de ignorar esse usuário. #evasiva" success: "Vamos ver o que eles têm a dizer! #digaoi" bookmarklet: explanation: "Publique em diaspora* de qualquer lugar favoritando este link: %{link}" heading: "Favoritos" post_something: "Publicar em diaspora*" - post_success: "Publicado! Fechando!" cancel: "Cancelar" comments: new_comment: comment: "Comentar" commenting: "Comentando..." - one: "1 comentário" - other: "%{count} comentários" - zero: "Sem comentários" contacts: - create: - failure: "Falha em criar contato" index: add_a_new_aspect: "Adicione um novo aspecto" add_contact: "Adicionar contato" - add_to_aspect: "Adicionar contatos a %{name}" all_contacts: "Todos os Contatos" community_spotlight: "Destaque da Comunidade" my_contacts: "Meus Contatos" @@ -269,19 +282,14 @@ pt-BR: no_contacts_in_aspect: "Você ainda não tem contatos neste aspecto. Abaixo, veja uma lista dos contatos que podem ser adicionados." no_contacts_message: "Veja %{community_spotlight}" only_sharing_with_me: "Só compartilhando comigo" - remove_contact: "Remover contato" start_a_conversation: "Iniciar uma conversa" title: "Contatos" - user_search: "Busca de Usuário" - your_contacts: "Seus contatos" - sharing: - people_sharing: "Pessoas compartilhando com você:" + user_search: "Busca de contatos" spotlight: community_spotlight: "Destaque da Comunidade" + no_members: "Não há membros ainda." suggest_member: "Sugerir um membro" conversations: - conversation: - participants: "Participantes" create: fail: "Mensagem inválida" no_contact: "Cuidado, você precisa adicionar o contato primeiro!" @@ -289,23 +297,13 @@ pt-BR: destroy: delete_success: "Conversa excluÃda com sucesso" hide_success: "Conversa escondida com sucesso" - helper: - new_messages: - few: "%{count} novas mensagens" - many: "%{count} novas mensagens" - one: "1 nova mensagem" - other: "%{count} novas mensagens" - two: "%{count} novas mensagens" - zero: "Nenhuma mensagem nova" index: conversations_inbox: "Conversas – Caixa de Entrada" - create_a_new_conversation: "iniciar uma nova conversa" inbox: "Entrada" new_conversation: "Nova conversa" - no_conversation_selected: "Nenhuma conversa selecionada" no_messages: "Não há mensagens" new: - abandon_changes: "Abandonar modificações?" + message: "Mensagem" send: "Enviar" sending: "Enviando..." subject: "Assunto" @@ -316,6 +314,7 @@ pt-BR: show: delete: "Apagar conversa" hide: "Esconder e silenciar conversa" + last_message: "Última mensagem recebida %{timeago}" reply: "Responder" replying: "Respondendo..." date: @@ -328,17 +327,14 @@ pt-BR: error_messages: helper: correct_the_following_errors_and_try_again: "Corrija os erros a seguir e tente novamente." - invalid_fields: "Campos inválidos" - login_try_again: "Por favor faça<a href='%{login_link}'>login</a> e tente novamente." - post_not_public: "A publicação que está tentando visualizar não é pública!" - post_not_public_or_not_exist: "A publicação que você está tentando ver não é pública, ou não existe!" + need_javascript: "Este site precisa de JavaScript para funcionar corretamente. Se você desabilitou o Javascript, habilite-o e atualize esta página." fill_me_out: "Preencha" find_people: "Encontrar pessoas ou #tags" help: account_and_data_management: close_account_a: "Vá até o final da página de configurações e clique em \"Encerrar conta\". Será preciso informar sua senha para completar o processo. Lembre-se: se você encerrar sua conta, <strong>nunca mais</strong> poderá registrar seu nome de usuário no mesmo servidor." close_account_q: "Como eu apago minha semente (conta)?" - data_other_podmins_a: "Uma vez que você está compartilhando com alguém de outro servidor, quaisquer publicações que você compartilha com eles, e uma cópia dos dados do seu perfil (em cache), estão acessÃveis ao administrador da base de dados desse servidor. Quando você apaga uma publicação ou dados do perfil, estes são eliminados do seu servidor e de quaisquer outros servidores onde estavam armazenados previamente." + data_other_podmins_a: "Quando você compartilha com alguém de outro servidor, todas as publicações que você compartilhar com essa pessoa e uma cópia dos seus dados de perfil (em cache) vão poder ser acessados pelos administradores da base de dados desse outro servidor. Quando você apaga uma publicação ou um dado do seu perfil, eles são eliminados do seu servidor e um pedido de exclusão é enviado para todos os outros servidores onde estavam armazenados. As suas imagens só são armazenadas no seu próprio servidor; os outros recebem apenas links para elas." data_other_podmins_q: "Quem administra outros servidores pode ver minhas informações?" data_visible_to_podmin_a: "Tudo. A comunicação entre servidores é sempre criptografada (com SSL e o método próprio de diaspora*), mas o armazenamento de dados nos servidores não. A administração da base de dados de seu servidor – normalmente quem o opera – pode acessar todos os seus dados do perfil e publicações, assim como a maioria dos sites da Web que armazenam dados de usuários). Por isso, você pode escolher um servidor em cuja administração confie para se registrar. Operar seu próprio servidor proporciona mais privacidade, pois é você quem controla o acesso à base de dados." data_visible_to_podmin_q: "Quanta informação minha quem administra meu servidor pode ver?" @@ -352,19 +348,19 @@ pt-BR: change_aspect_of_post_q: "Uma vez que eu publiquei alguma coisa, posso mudar o(s) aspecto(s) que pode(m) ver isto?" contacts_know_aspect_a: "Não. Eles não podem ver o nome do aspecto em nenhuma circunstância." contacts_know_aspect_q: "Meus contactos sabem em que aspectos eu os coloquei?" - contacts_visible_a: "Se você selecionar esta opção, então os contatos daquele aspecto serão capazes de ver quem mais está lá dentro, na sua página de perfil, sob a sua imagem pessoal. É melhor selecionar esta opção somente se todos os contatos naquele aspecto se conhecerem. Eles ainda não serão capazes de poder ver o nome do aspecto." + contacts_visible_a: "Se você marcar esta opção, então os contatos incluÃdos no aspecto vão poder ver uns aos outros na sua página de perfil, na aba \"Contatos\". É melhor marcar esta opção somente se todos os contatos no aspecto se conhecerem – por exemplo, se o aspecto reunir as pessoas de um clube ou sociedade à qual você pertence. O nome do aspecto vai continuar invisÃvel para eles." contacts_visible_q: "O que significa \"tornar contatos desse aspecto visÃveis entre si\"?" - delete_aspect_a: "Na sua lista de aspectos do lado esquerdo na página principal, aponte o mouse para o aspecto que você quer apagar. Clique no pequeno lápis de edição que aparece à direita. Clique no botão Apagar na caixa que aparece." + delete_aspect_a: "Na página inicial, clique em \"Meus aspectos\", na barra lateral, e clique no Ãcone de lápis ao lado do aspecto indesejado, ou abra a página dos seus contatos e selecione o aspecto. AÃ, clique no Ãcone de lixeira no canto superior direito da página." delete_aspect_q: "Como eu apago um aspecto?" - person_multiple_aspects_a: "Sim. Vá até sua página de contatos e clique em meus contatos. Para cada contato você pode usar o menu à direita para adicioná-los para (ou removê-los de) tantos aspectos quanto você quiser. Ou você pode adicioná-los a um novo aspecto (ou removê-los de um aspecto) clicando no botão seletor de aspectos na sua página de perfil. Ou você pode ainda apenas mover o cursor sobre o nome que você vê no fluxo, e um 'cartão flutuante' aparecerá. Você pode mudar os aspectos que estão à direita." + person_multiple_aspects_a: "Sim. Vá até sua página de contatos e clique em \"Meus contatos\". Cada contato pode ser adicionado (ou removido) dos aspectos usando o menu à direita. Você também pode adicionar e remover contatos de aspectos na sua página de perfil, com o botão seletor de aspectos. Você pode ainda passar o cursor sobre o nome da pessoa no fluxo: os aspectos podem ser alterados no cartão de visita que aparecer." person_multiple_aspects_q: "Posso adicionar uma pessoa a múltiplos aspectos?" - post_multiple_aspects_a: "Sim. Quando você está fazendo uma publicação, use o botão seletor de aspectos para selecionar ou desselecionar aspectos. Sua publicação será visÃvel a todos os aspectos que você selecionou. Você pode também selecionar na barra lateral os aspectos para os quais você quer publicar. Quando você publica, o(s) aspecto(s) que você selecionou da lista à esquerda será(ão) automaticamente selecionado(s) no seletor de aspectos." + post_multiple_aspects_a: "Sim. Quando você estiver escrevendo um post, use o botão seletor de aspectos para selecionar aspectos ou desfazer a seleção. \"Todos os aspectos\" é a configuração padrão. O seu post será visÃvel a todos os aspectos que você assinalar. Você pode também marcar os aspectos desejados na barra lateral. Quando começar um novo post, os que tiverem sido destacados na lista à esquerda serão automaticamente selecionados como público." post_multiple_aspects_q: "Posso publicar conteúdo em múltiplos aspectos de uma vez?" remove_notification_a: "Não. Ela também não será notificada se você adicioná-la a outros aspectos, uma vez que você já está compartilhando com ela." remove_notification_q: "Se eu remover uma pessoa de um ou mais aspectos, ela será notificada?" rename_aspect_a: "Do lado esquerdo da página principal, na sua lista de aspectos, coloque o cursor do mouse sobre o aspecto que você quer renomear. Clique no pequeno lápis de edição que aparece à direita. Depois renomeie na caixa que aparece." rename_aspect_q: "Como renomear um aspecto?" - restrict_posts_i_see_a: "Sim. Clique em Meus Aspectos na barra lateral e em seguida clique em aspectos individuais na lista para selecioná-los ou desselecioná-los. Apenas as publicações de pessoas dos aspectos selecionados aparecerão no seu Fluxo." + restrict_posts_i_see_a: "Sim. Clique em \"Meus aspectos\", na barra lateral, e, em seguida, clique nos aspectos individuais, na lista, para selecioná-los ou desfazer a seleção. Apenas as publicações de membros dos aspectos selecionados vão aparecer no seu fluxo." restrict_posts_i_see_q: "Posso restringir as publicações que eu vejo apenas a certos aspectos?" title: "Aspectos" what_is_an_aspect_a: "Aspectos são a maneira que você agupa seus contactos em diaspora*. Um aspecto é uma das faces que você se mostra ao mundo. Poderá ser quem você é no emprego, ou quem você é para a sua famÃlia, ou quem você é para os seus amigos em um clube ao qual você pertence." @@ -406,38 +402,36 @@ pt-BR: title: "Teclas de atalho" markdown: "Markdown" mentions: - how_to_mention_a: "Digite o sÃmbolo \"@\" e comece a digitar o nome da pessoa. Um menu de lista deve aparecer para que você escolha mais facilmente. Note que somente é possÃvel mencionar pessoas que você adicionou a algum aspecto." + how_to_mention_a: "Digite o sÃmbolo \"@\" e comece a escrever o nome da pessoa. Um menu suspenso deve aparecer para facilitar a seleção. Repare que só é possÃvel mencionar pessoas adicionadas a algum aspecto seu." how_to_mention_q: "Como eu menciono alguém quando estou fazendo uma pubicação?" mention_in_comment_a: "Não, atualmente não." mention_in_comment_q: "Posso mencionar alguém em um comentário?" - see_mentions_a: "Sim, clique em \"Menções\" na coluna do lado esquerdo na sua página inicial." + see_mentions_a: "Sim. Clique em \"@Menções\" na sua página inicial, na coluna à esquerda." see_mentions_q: "Existe uma maneira de ver as publicações nas quais eu tenha sido mencionado?" title: "Menções" - what_is_a_mention_a: "Uma menção é uma ligação para a página do perfil de uma pessoa que aparece na publicação. Quando alguém é mencionado, essa pessoa recebe uma notificação que chama a atenção dela para a publicação." + what_is_a_mention_a: "Uma menção é um link para o perfil de uma pessoa que aparece em um post. Quando é mencionada, ela recebe uma notificação chamando a atenção dela para o post." what_is_a_mention_q: "O que é uma menção?" miscellaneous: - back_to_top_a: "Sim. Depois de rolar até o final da página, clique na seta cinza que aparece no canto direito no final da janela do navegador." + back_to_top_a: "Sim. Depois de rolar até o final da página, clique na seta cinza que aparece no canto inferior direito da janela do navegador." back_to_top_q: "Existe uma maneira rápida de voltar ao topo da página depois que eu tenha rolado até o final?" - diaspora_app_a: |- - Existem vários aplicativos Android em estágio inicial de desenvolvimento. Vários deles são projetos abandonados há muito tempo, então não funcionam bem com a versão atual de diaspora*. Não espere muito destes aplicativos no momento. Atualmente a melhor maneira de acessar diaspora* a partir de seu dispositivo móvel é através de um navegador, porque nós projetamos uma versão do site para celular que deve funcionar bem em todos os dispositivos. - Atualmente não existe nenhum aplicativo para iOS. Novamente, diaspora* deve funcionar bem através de seu navegador. + diaspora_app_a: "Vários aplicativos para Android tem sido desenvolvidos por membros da comunidade. Alguns estão abandonados há muito tempo, por isso não funcionam bem com a versão atual da diaspora*. Não espere muito desses aplicativos no momento. Atualmente, não existe nenhum aplicativo para iOS. A melhor maneira de acessar a diaspora* a partir do seu dispositivo móvel é usando um navegador, porque nós projetamos uma versão móvel do site que deve funcionar bem em todos os dispositivos, embora ainda não disponha de todas as funções." diaspora_app_q: "Existe um aplicativo diaspora* para Android ou iOS?" - photo_albums_a: "Não, no momento não. No entanto, você pode ver um fluxo com as fotos que foram subidas, na seção Fotos na barra lateral da página do perfil visitado." + photo_albums_a: "Não, no momento não. Porém você pode ver as fotos subidas por uma pessoa na seção Fotos do perfil dela." photo_albums_q: "Existem álbuns de fotos e de vÃdeos?" subscribe_feed_a: "Sim, mas esse recurso ainda não está funcionando perfeitamente, e a formatação dos resultados ainda é bem grosseira. Se você quiser tentar mesmo assim, vá para a página do perfil e clique no botão de feed do seu navegador ou copie a URL da página (por exemplo, https://podname.org/people/123abc) e cole em um leitor de feed. O endereço de feed é mais ou menos assim: https://podname.org/public/username.atom – diaspora* usa o formato Atom em vez de RSS." subscribe_feed_q: "Posso usar um leitor de feed para acompanhar uma publicação pública?" title: "Miscelânea" pods: - find_people_a: "Convide seus amigos utilizando o link \"Por email\" na barra lateral. Siga #tags para descobrir outros que compartilhem de seus interesses, e adicione a algum aspecto aqueles que publicam coisas que interessam a você. Grite que você é #novato em uma publicação." + find_people_a: "Se quiser convidar seus amigos para a diaspora*, use o link de convite ou o link de e-mail na barra lateral. Siga #tags para descobrir pessoas que compartilhem de seus interesses e adicione a algum aspecto aquelas que chamarem a sua atenção. Conte para todo mundo que você é #novata ou #novato em um post público." find_people_q: "Eu acabei de me associar ao pod, como eu posso encontrar pessoas com quem eu possa compartilhar?" title: "Pods" - use_search_box_a: "Se você conhece a diaspora* ID completa dessas pessoas (ex.: nomedousuario@nomedopod.org), você pode encontrá-las buscando diretamente pelas IDs. Se você está no mesmo pod, você pode buscar apenas pelo nomedousuario. Uma alternativa é buscar por elas através do nome de perfil (o nome que você vê na tela). Se uma busca não funciona na primeira vez, tente novamente." + use_search_box_a: "Se você sabe a diaspora* ID completa dessas pessoas (nomedeusuario@nomedopod.org, p. ex.), você pode encontrá-las buscando diretamente pelas IDs. Se vocês estão no mesmo servidor, basta buscar pelo nome de usuário. Uma alternativa é buscar pelo nome de perfil (o que aparece na tela). Se uma busca não funcionar da primeira vez, tente novamente." use_search_box_q: "Como eu utilizo a caixa de busca para encontrar pessoas em particular?" - what_is_a_pod_a: "Um pod é um servidor executando o software diaspora* e conectado à rede diaspora*. \"Pod\" é uma metáfora referindo-se à s vagens nas plantas que contém sementes, da mesma maneira que um servidor contém um número de contas de usuários. Existem muitos pods diferentes. Você pode adicionar amigos de outros pods e se comunicar com eles. (Você pode pensar de um pod diaspora* como sendo similar a um provedor de email: existem pods públicos, pods privados, e com algum esforço você pode até mesmo rodar o seu próprio)." + what_is_a_pod_a: "Um pod é um servidor executando o software diaspora* e conectado à rede diaspora*. \"Pod\", inglês para \"vagem\", é uma metáfora das vagens que contêm as sementes das plantas, da mesma maneira que um servidor contém contas de usuários. Existem diversos pods. Você pode adicionar amigos de outros servidores e se comunicar com eles. Não é preciso abrir conta em mais de um – nesse sentido, um pod se parece com um provedor de e-mails. Há servidores públicos, privados e, com um pouco de esforço, você pode até abrir o seu próprio pod." what_is_a_pod_q: "O que é um pod?" posts_and_posting: - char_limit_services_a: "Neste caso sua publicação é limitada pela menor contagem de caracteres (140 no caso do Twitter; 1000 no caso do Tumblr), e o número de caracteres que você deixar de usar é mostrado quando o Ãcone daquele serviço é destacado. Você ainda pode publicar nestes serviços se sua publicação está acima destes limites, no entanto o texto ficará truncado nestes serviços." - char_limit_services_q: "Qual é o limite de caracteres para publicações compartilhadas através de um serviço conectado que possui uma menor contagem de caracteres?" + char_limit_services_a: "Nesse caso, a sua publicação será limitada pela menor contagem de caracteres (140 no Twitter, 1000 no Tumblr). O número de caracteres que faltarem para atingir o limite será mostrado para os serviços cujos Ãcones estiverem destacados. Você ainda poderá publicar nos serviços em que estourar o limite, mas o texto aparecerá truncado, e um link para o post original, na diaspora*, será fornecido." + char_limit_services_q: "E se eu compartilhar minha publicação em um serviço com uma contagem de caracteres menor?" character_limit_a: "65.535 caracteres. São 65.395 caracteres a mais do que você tem no Twitter! ;)" character_limit_q: "Qual é o limite de caracteres para publicações?" embed_multimedia_a: "Geralmente, basta colar a URL (ex. http://www.youtube.com/watch?v=nnnnnnnnn) na publicação que o vÃdeo ou áudio será incorporado automaticamente, usando oEmbed. São compatÃveis YouTube, Vimeo, SoundCloud e Flickr, entre outros; novos sites estão sempre sendo acrescentados à lista. Lembre-se de sempre publicar links simples e completos – nada de links encurtados ou caracteres depois da URL base – e esperar um pouco antes de atualizar a página depois de publicar para pré-visualizar." @@ -448,7 +442,7 @@ pt-BR: hide_posts_q: "Como faço para ocultar uma publicação?" image_text: "texto da imagem" image_url: "URL da imagem" - insert_images_a: "Clique no pequeno Ãcone de câmera para inserir uma imagem na publicação. Pressione o Ãcone de foto novamente para adicionar outra foto, ou você pode selecionar múltiplas fotos para serem carregadas de uma vez." + insert_images_a: "Clique no pequeno Ãcone de câmera para inserir uma imagem na publicação. Pressione o Ãcone novamente para adicionar outra foto. Você também pode selecionar múltiplas fotos para carregá-las de uma vez só." insert_images_comments_a1: "Não é possÃvel fazer upload de imagens para comentários, mas o seguinte código Markdown" insert_images_comments_a2: "pode ser usado para inserir imagens da web aos comentários assim como à s publicações." insert_images_comments_q: "Posso inserir imagens em comentários?" @@ -461,28 +455,28 @@ pt-BR: post_poll_q: "Como posso adicionar uma enquete à minha publicação?" post_report_a: "Clique no triângulo de aviso no canto superior direito de uma publicação para denunciá-la à administração do servidor. Justifique-se na caixa de diálogo." post_report_q: "Como denunciar uma publicação ofensiva?" - size_of_images_a: "Não. Imagens são redimensionadas automaticamente para preencherem o fluxo. Markdown não tem um código para especificar o tamanho de uma imagem." + size_of_images_a: "Não. Imagens são redimensionadas automaticamente para preencherem o fluxo. O Markdown não permite especificar o tamanho de uma imagem." size_of_images_q: "Posso personalizar o tamanho das imagens em publicações ou comentários?" stream_full_of_posts_a1: "Seu fluxo é composto de três tipos de publicações:" stream_full_of_posts_li1: "Publicações de pessoas com quem você está compartilhando, que se dividem em dois tipos: publicações públicas, e publicações limitadas compartilhadas com um aspecto do qual você faz parte. Para remover essas publicações, simplesmente pare de compartilhar com a pessoa." - stream_full_of_posts_li2: "Publicações públicas contendo uma das tags que você segue. Para remover estas, pare de seguir a tag." - stream_full_of_posts_li3: "Publicações públicas feitas por pessoas listadas no Destaque da Comunidade. Estas podem ser removidas desmarcando a opção \"Mostrar Destaque da Comunidade no seu Fluxo?\" na aba Conta de suas Configurações." - stream_full_of_posts_q: "Por que meu fluxo está cheio de publicações de pessoas as quais eu não conheço e com quem eu não compartilho?" + stream_full_of_posts_li2: "Publicações públicas contendo uma das tags que você segue. Para removê-las, pare de seguir essa tag." + stream_full_of_posts_li3: "Publicações públicas feitas por pessoas listadas no destaque da comunidade. Essas podem ser removidas desmarcando a opção \"Mostrar destaque da comunidade no fluxo?\" na aba Conta das suas Configurações." + stream_full_of_posts_q: "Por que meu fluxo está cheio de publicações de pessoas que não conheço e com quem não compartilho?" title: "Publicações e publicar" private_posts: - can_comment_a: "Somente os usuários diaspora* logados que você colocou naquele aspecto podem comentar ou curtir sua publicação privada." + can_comment_a: "Somente os usuários da diaspora* logados e colocados por você nesse aspecto antes da publicação privada ser feita podem comentá-la ou curti-la." can_comment_q: "Quem pode comentar ou curtir minha publicação privada?" can_reshare_a: "Ninguém. Publicações privadas não são recompartilháveis. Porém usuários incluÃdos no aspecto podem, se quiserem, copiar e colar a publicação." can_reshare_q: "Quem pode recompartilhar minha publicação privada?" see_comment_a: "Somente as pessoas com quem a publicação foi compartilhada (as pessoas que estão nos aspectos selecionados pelo publicador original) podem ver os comentários e as curtidas. " see_comment_q: "Quando eu comento ou curto uma publicação privada, quem pode ver?" title: "Publicações de acesso privado" - who_sees_post_a: "Somente os usuários diaspora* logados que você colocou naquele aspecto podem ver sua publicação privada." + who_sees_post_a: "Somente os usuários da diaspora* logados e colocados por você nesse aspecto antes da publicação privada ser feita podem vê-la." who_sees_post_q: "Quando eu publico uma mensagem em um aspecto (por ex., uma publicação privada), quem pode vê-la?" private_profiles: title: "Perfis privados" whats_in_profile_a: "Seu perfil privado contém informações como biografia, localização, sexo e data de nascimento. Todas são opcionais – você decide se vai fornecê-las ou não. Apenas pessoas autenticadas com quem você compartilha podem ver seu perfil privado, bem como as publicações privadas destinadas aos aspectos aos quais pertencem. As publicações privadas aparecem para elas na sua página de perfil, misturadas à s públicas." - whats_in_profile_q: "O que está no meu perfil privado?" + whats_in_profile_q: "O que faz parte do meu perfil privado?" who_sees_profile_a: "Qualquer usuário logado com quem você esteja compartilhando (significa que você os adicionou a um de seus aspectos). De qualquer modo, pessoas seguem você, mas aqueles que você não segue, somente verão sua informação pública." who_sees_profile_q: "Quem vê meu perfil privado?" who_sees_updates_a: "Qualquer pessoa nos seus aspectos vê mudanças no seu perfil privado. " @@ -490,7 +484,7 @@ pt-BR: public_posts: can_comment_reshare_like_a: "Qualquer usuário logado em diaspora* pode comentar, recompartilhar, ou curtir sua publicação pública." can_comment_reshare_like_q: "Quem pode comentar, recompartilhar, ou curtir minha publicação no modo público?" - deselect_aspect_posting_a: "Desselecionar aspectos não afeta uma publicação pública. Esta apenas irá aparecer nos fluxos de todos os seus contatos. Para tornar uma publicação visÃvel somente para aspectos especÃficos, você precisa selecionar os aspectos a partir do botão abaixo do editor." + deselect_aspect_posting_a: "Desfazer a seleção de aspectos não afeta uma publicação pública. Ela continua pública e aparece nos fluxos de todos os seus contatos. Para tornar uma publicação visÃvel somente para aspectos especÃficos, você precisa selecionar os aspectos usando o seletor de aspectos, embaixo do editor." deselect_aspect_posting_q: "O que acontece quando eu desseleciono um ou mais aspectos ao fazer uma publicação no modo público?" find_public_post_a: "Suas publicações públicas aparecem nos fluxos das pessoas que seguem você. Se contêm #tags, são mostradas nos fluxos das pessoas que seguem essas tags. Além disso, toda publicação pública tem um URL especÃfico que qualquer internauta pode ver e, portanto, divulgar via Twitter, blogs etc. Publicações públicas também podem ser indexadas por mecanismos de busca." find_public_post_q: "Como outras pessoas podem encontrar minhas publicações no modo público?" @@ -503,17 +497,17 @@ pt-BR: title: "Perfis públicos" what_do_tags_do_a: "Elas ajudam pessoas a conhecer você. Sua foto de perfil aparecerá do lado esquerdo das páginas de tags particulares, junto com alguém mais que tenha essas tags em seus perfis públicos." what_do_tags_do_q: "Para que servem as tags no meu perfil público?" - whats_in_profile_a: "Seu nome, as cinco tags que você escolheu para se descrever, e sua foto. São as opções que estão no topo da seção da página de edição do perfil. Você pode tornar esta informação de perfil identificável ou anônima, como preferir. Sua página de perfil também mostra quaisquer publicações de modo público que você tenha feito." - whats_in_profile_q: "O que está no meu perfil público?" + whats_in_profile_a: "O seu perfil público tem seu nome, as cinco tags que você escolheu para se descrever e a sua foto, se esses campos tiverem sido preenchidos. Todas essas informações são opcionais – você decide dá-las ou não. Você pode tornar suas informações de perfil identificáveis ou anônimas, como preferir. A sua página de perfil também mostra todas as publicações públicas feitas por você." + whats_in_profile_q: "O que faz parte do meu perfil público?" who_sees_profile_a: "Qualquer usuário logado em diaspora*, assim como toda a internet, podem vê-lo. Cada perfil tem um URL direto, então ele pode ter uma ligação direta a partir de sites externos. O perfil público pode ser indexado por mecanismos de busca." who_sees_profile_q: "Quem vê o meu perfil público?" who_sees_updates_a: "Quaisquer pessoas podem ver mudanças se elas visitam sua página de perfil." who_sees_updates_q: "Quem vê atualizações do meu perfil público?" resharing_posts: - reshare_private_post_aspects_a: "Não, não é possÃvel recompartilhar uma publicação privada. Isto é feito para respeitar as intenções do publicador original que compartilhou a publicação somente com um grupo particular de pessoas." + reshare_private_post_aspects_a: "Não, não é possÃvel recompartilhar uma publicação privada. A razão é o respeito pelas intenções do publicador original, que compartilhou a publicação apenas com um grupo particular de pessoas." reshare_private_post_aspects_q: "Posso recompartilhar uma publicação privada somente com certos aspectos?" - reshare_public_post_aspects_a: "Não, quando você recompartilha uma publicação pública ela automaticamente se torna uma de suas publicações públicas. Para compartilhá-la com certos aspectos, copie e cole o conteúdo da publicação dentro de uma nova publicação." - reshare_public_post_aspects_q: "Posso recompartilhar uma publicação de modo público somente com certos aspectos?" + reshare_public_post_aspects_a: "Não. Quando você recompartilha uma publicação pública, ela automaticamente se torna uma das suas publicações públicas. Para compartilhá-la com aspectos especÃficos, copie e cole o conteúdo do post dentro de uma nova publicação, privada." + reshare_public_post_aspects_q: "Posso recompartilhar uma publicação pública com aspectos selecionados?" title: "Recompartilhando publicações" sharing: add_to_aspect_a1: "Vamos supor que Ana adicione Pedro a um aspecto, mas Pedro não tenha (ainda) feito o mesmo com Ana." @@ -527,9 +521,9 @@ pt-BR: add_to_aspect_li7: "Ana aparecerá sob \"Só compartilhando comigo\" na página de contatos de Pedro." add_to_aspect_li8: "Ana também poderá @mencionar Pedro em uma publicação." add_to_aspect_q: "O que acontece quando eu adiciono alguém a um dos meus aspectos? Ou quando alguém me adiciona a um de seus aspectos?" - list_not_sharing_a: "Não, mas você pode ver se algumas pessoas estão compartilhando com você ou não, visitando o perfil deles. Se eles estão, a barra sob a foto de perfil deles estará verde; se não, estará cinza. Você deve receber uma notificação cada vez que alguém começa a compartilhar com você." + list_not_sharing_a: "Não, mas você pode checar se uma pessoa compartilha com você visitando o perfil dela. Se ela estiver, o botão que mostra os aspectos aos quais você a adicionou estará verde; senão, estará cinza." list_not_sharing_q: "Existe uma lista de pessoas as quais eu adicionei a um de meus aspectos, mas que não tenham me adicionado a um dos aspectos deles?" - only_sharing_a: "São pessoas que adicionaram você a um dos aspectos delas, mas que não estão (ainda) em um de seus aspectos. Em outras palavras, elas estão compartilhando com você, mas você ainda não está compartilhando com elas (compartilhamento assimétrico). Se você adicioná-las a um aspecto, então elas aparecerão sob o aspecto, e não mais sob \"Só compartilhando comigo\". Veja acima." + only_sharing_a: "São pessoas que adicionaram você a um dos aspectos delas, mas que não estão (ainda) em um dos seus aspectos. Em outras palavras, elas estão compartilhando com você, mas você não está compartilhando com elas: elas estão \"seguindo\" você. Se você adicioná-las a um aspecto, então elas aparecerão no aspecto, e não mais em \"Só compartilhando comigo\". Veja acima." only_sharing_q: "Quem são as pessoas listadas em \"Só compartilhando comigo\", na página de contatos?" see_old_posts_a: "Não. Eles somente serão capazes de ver novas publicações para o aspecto. Eles (e todos os demais) podem ver suas publicações públicas antigas na sua página de perfil, e eles também podem vê-las no fluxo deles." see_old_posts_q: "Quando eu adiciono alguém a um aspecto, eles podem ver publicações antigas que eu já tenha feito para aquele aspecto?" @@ -539,98 +533,91 @@ pt-BR: tags: filter_tags_a: "Ainda não é possÃvel diretamente através de diaspora*, mas algumas %{third_party_tools} tem sido escritas para poder prover isto." filter_tags_q: "Como posso filtrar/excluir algumas tags de meu fluxo?" - followed_tags_a: "Depois de buscar por uma tag você pode clicar no botão no topo da página de tag para \"seguir\" aquela tag. Então ela aparecerá na sua lista de tags seguidas, à esquerda. Clicando em uma de suas tags seguidas leva você à quela página de tag, então você pode ver publicações recentes contendo aquela tag. Clique no #Seguindo Tags para ver um fluxo de publicações que incluem qualquer uma daquelas tags seguidas por você. " + followed_tags_a: "Depois de buscar uma tag, você pode clicar no botão no topo da página dela para \"segui-la\". Ela vai então aparecer na sua lista de tags seguidas, no menu à esquerda. Clicar em uma das tags seguidas abre a página da tag, na qual você pode ver publicações recentes marcadas com ela. Clique em #Seguindo Tags para ver um fluxo das publicações que incluem qualquer uma das tags seguidas por você." followed_tags_q: "O que é \"#Seguindo Tags\" e como eu sigo uma tag?" people_tag_page_a: "São as pessoas que listaram aquela tag para descrevê-las no perfil público delas." people_tag_page_q: "Quem são as pessoas listadas no lado esquerdo da página de tag?" - tags_in_comments_a: "Uma tag adicionada a um comentário ainda aparecerá como uma ligação para aquela página de tag, mas não fará que aquela publicação (ou comentário) apareça naquela página de tag. Isto somente funciona para tags em publicações." + tags_in_comments_a: "Uma tag adicionada a um comentário ainda aparecerá como link para a página da tag, mas não fará o comentário aparecer na página da tag. Isso funciona só para tags em publicações." tags_in_comments_q: "Posso colocar tags em comentários ou apenas em publicações?" title: "Tags" - what_are_tags_for_a: "Tags são uma maneira de categorizar uma publicação, normalmente por tópico. Buscando por uma tag mostra todas as publicações com aquela tag que você pode ver (ambas publicações públicas e privadas). Isso possibilita que pessoas que estão interessadas em um determinado tópico encontrem publicações públicas sobre este tópico." + what_are_tags_for_a: "Tags são uma maneira de categorizar uma publicação, normalmente por tópico. Pesquisar uma tag mostra todas as publicações marcadas com ela, públicas e privadas, que você tem permissão para ver. Assim, os interessados em um determinado assunto podem encontrar publicações públicas sobre ele." what_are_tags_for_q: "Para que servem as tags?" third_party_tools: "Ferramentas de terceiros" title_header: "Ajuda" tutorial: "tutorial" tutorials: "tutoriais" wiki: "wiki" - hide: "Ocultar" - ignore: "Ignorar" + home: + default: + be_who_you_want_to_be: "Seja quem você quer ser" + be_who_you_want_to_be_info: "Muitas redes sociais insistem que você use a sua identidade real. Não a diaspora*. Aqui, você pode ser quem e compartilhar o quanto você quiser. Como você vai interagir com as outras pessoas depende só de você." + byline: "O mundo social on-line em que você está no controle" + choose_your_audience: "Escolha sua plateia" + choose_your_audience_info: "Os aspectos da diaspora* permitem que você decida com quem vai compartilhar. Você escolhe quanta privacidade quer ter. Compartilhe uma foto engraçada com todo mundo e guarde aquele segredo para os seus amigos mais próximos. Você está no controle." + headline: "É bom ver você em %{pod_name}" + own_your_data: "Os seus dados são seus" + own_your_data_info: "Várias redes lucram com seus dados, analisando as suas interações e usando as informações obtidas para fazer publicidade. A diaspora* não usa seus dados para nada além de possibilitar que você se conecte e compartilhe com outras pessoas." + podmin: + admin_panel: "painel de administração" + byline: "Você está prestes a revolucionar a internet. Vamos começar?" + configuration_info: "Abra %{database_path} e %{diaspora_path} no seu editor de texto favorito e revise-os cuidadosamente, estão minuciosamente comentados." + configure_your_pod: "Configure seu servidor" + contact_irc: "falar conosco no IRC" + contribute: "Contribua" + contribute_info: "Deixe a diaspora* ainda melhor! Se encontrar algum bug, por favor, %{report_bugs}." + create_an_account: "Crie uma conta" + create_an_account_info: "%{sign_up_link} para uma nova conta." + faq_for_podmins: "perguntas frequentes sobre manutenção de servidores na wiki" + getting_help: "Peça ajuda" + getting_help_info: "Nós listamos %{faq}, inclusive dicas, macetes e soluções para os problemas mais comuns. Sinta-se livre, também, para %{irc}." + headline: "Olá, colega." + make_yourself_an_admin: "Assuma a administração" + make_yourself_an_admin_info: "Você pode encontrar instruções na %{wiki}. Quando você entrar no sistema, haverá um link \"Admin\" no seu menu de usuário, no cabeçalho. Você poderá buscar usuários e ver as estatÃsticas do seu servidor. Para detalhes sobre os aspectos operacionais do seu servidor, vá para o %{admin_panel}." + report_bugs: "reporte-o" + update_instructions: "instruções para atualizar na wiki da diaspora*" + update_your_pod: "Atualize seu servidor" + update_your_pod_info: "Você pode encontrar %{update_instructions}." invitation_codes: - excited: "%{name} está contente em te ver aqui." not_valid: "Esse código de convite expirou" invitations: a_facebook_user: "Um usuário do Facebook" check_token: not_found: "Convite não encontrado." create: - already_contacts: "Você já está compartilhando com essa pessoa." - already_sent: "Você já convidou essa pessoa." empty: "Por favor, insira ao menos um endereço de email." no_more: "Você não possui mais convites." note_already_sent: "Convites já foram enviados para: %{emails}" - own_address: "Você não pode enviar um convite para seu próprio endereço." rejected: "Houve problemas com os seguintes endereços de e-mail: " sent: "Convites enviados para: %{emails}" - edit: - accept_your_invitation: "Aceitar seu convite" - your_account_awaits: "Aguarde sua conta!" new: - already_invited: "As seguintes pessoas não aceitaram seu convite:" - aspect: "Aspecto" - check_out_diaspora: "Descubra diaspora*!" codes_left: one: "%{count} convite restante neste código" other: "%{count} convites restantes neste código" zero: "Nenhum convite restante neste código" comma_separated_plz: "Você pode digitar vários endereços separados por vÃrgulas." - if_they_accept_info: "se eles aceitarem, eles serão adicionados ao aspecto para o qual você os convidou." invite_someone_to_join: "Convide os amigos para participar de diaspora*!" language: "Idioma" paste_link: "Compartilhe esse link com seus amigos para convidá-los para Diaspora*, ou envie um email com o link diretamente para eles." - personal_message: "Mensagem pessoal" - resend: "Reenviar" send_an_invitation: "Enviar um convite" - send_invitation: "Enviar convite" sending_invitation: "Enviando convite..." - to: "Para" layouts: application: back_to_top: "Voltar ao topo" + be_excellent: "Tratem-se com carinho! ♥" powered_by: "Desenvolvido por diaspora*" public_feed: "Feed público de diaspora* para %{name}" source_package: "Baixar pacote do código-fonte" statistics_link: "EstatÃsticas do servidor" toggle: "Versão para celular" whats_new: "O que há de novo?" - your_aspects: "Seus aspectos" header: - admin: "Administração" - blog: "Blog" code: "Código" - help: "Ajuda" - login: "Entrar" logout: "Sair" profile: "Perfil" - recent_notifications: "Notificações recentes" settings: "Configurações" - view_all: "Ver tudo" - likes: - likes: - people_dislike_this: - one: "1 não curtiu." - other: "%{count} não curtiram." - zero: "Ninguém não curtiu." - people_like_this: - one: "1 curtiu" - other: "%{count} curtiram" - zero: "Ninguém curtiu" - people_like_this_comment: - one: "%{count} curtiu" - other: "%{count} curtiram" - zero: "Ninguém curtiu" + toggle_navigation: "Alternar navegação" limited: "Limitado" more: "Mais" - next: "Próximo" no_results: "Nenhum resultado encontrado" notifications: also_commented: @@ -645,14 +632,6 @@ pt-BR: one: "%{actors} comentou sua %{post_link}." other: "%{actors} comentaram sua %{post_link}." zero: "%{actors} comentou sua %{post_link}." - helper: - new_notifications: - few: "%{count} novas notificações" - many: "%{count} novas notificações" - one: "1 nova notificação" - other: "%{count} novas notificações" - two: "%{count} novas notificações" - zero: "Nenhuma notificação nova" index: all_notifications: "Todas as notificações" also_commented: "Também comentou" @@ -686,9 +665,9 @@ pt-BR: other: "%{actors} curtiram sua publicação apagada." zero: "Ninguém curtiu sua publicação apagada." mentioned: - one: "%{actors} mencionou você em uma %{post_link}." - other: "%{actors} mencionaram você em uma %{post_link}." - zero: "%{actors} mencionou você em uma %{post_link}." + one: "%{actors} mencionou você na publicação %{post_link}." + other: "%{actors} mencionaram você na publicação %{post_link}." + zero: "%{actors} mencionou você na publicação %{post_link}." mentioned_deleted: one: "%{actors} mencionou você em uma publicação apagada." other: "%{actors} mencionaram você em uma publicação apagada." @@ -714,7 +693,6 @@ pt-BR: a_limited_post_comment: "Há um novo comentário em uma publicação privada na diaspora* para você ver." a_post_you_shared: "uma publicação." a_private_message: "Há uma nova mensagem privada para você na diaspora*" - accept_invite: "Aceite seu convite para diaspora*!" also_commented: limited_subject: "A publicação que você comentou tem um novo comentário" click_here: "Clique aqui" @@ -768,18 +746,21 @@ pt-BR: message: |- Oi, tudo bem? - Você recebeu um convite para se juntar à diaspora*! + %{diaspora_id} convidou você para se juntar à diaspora*! Clique neste link para começar: [%{invite_url}][1] - Caso você não saiba ainda o que é a diaspora*, encontre a resposta [aqui][2]. + Ou, se já tiver uma conta, você pode adicionar %{diaspora_id} aos seus contatos. + Um abraço, diaspora* + PS.: Ainda não conhece a diaspora*? Clique [aqui][2]! + [1]: %{invite_url} [2]: %{diasporafoundation_url} invited_you: "%{name} te convidou para Diaspora*" @@ -789,10 +770,10 @@ pt-BR: view_post: "Ver publicação >" mentioned: limited_post: "Você foi mencionado em uma publicação privada." - mentioned: "mencionou você em uma publicação:" subject: "%{name} mencionou você em Diaspora*" private_message: reply_to_or_view: "Responder ou visualizar esta conversa >" + subject: "Há uma nova mensagem privada para você" remove_old_user: body: |- Olá, @@ -813,16 +794,18 @@ pt-BR: body: |- Olá, - o %{type} com ID %{id} foi marcado como ofensivo. + O %{type} com ID %{id} foi marcado como ofensivo. + + Motivo: "%{reason}" [%{url}][1] - Por favor, revise o mais breve possÃvel! + Por favor, revise-o assim que puder! - Saudações, + Até a próxima! - O robô de email diaspora* + diaspora* [1]: %{url} subject: "Um novo %{type} foi marcado como ofensivo" @@ -843,20 +826,9 @@ pt-BR: to_change_your_notification_settings: "para alterar tuas configurações de notificações" nsfw: "Conteúdo não apropriado para todos os públicos" ok: "OK" - or: "ou" - password: "Senha" - password_confirmation: "Confirmação de senha" people: add_contact: - invited_by: "você foi convidado por" - add_contact_small: - add_contact_from_tag: "Adicionar contato de tag" - aspect_list: - edit_membership: "Editar participação no aspecto" - helper: - is_not_sharing: "%{name} não está compartilhando com você" - is_sharing: "%{name} está compartilhando com você" - results_for: " resultados para %{params}" + invited_by: "Você recebeu um convite de" index: couldnt_find_them: "Não conseguiu encontrar?" looking_for: "Buscando publicações com a tag %{tag_link}?" @@ -866,105 +838,66 @@ pt-BR: search_handle: "Para que você encontre seus amigos, use a diaspora* ID deles (nomedeusuario@nomedopod.org)." searching: "Pesquisando, seja paciente..." send_invite: "Nada ainda? Envie um convite!" - one: "1 pessoa" - other: "%{count} pessoas" person: - add_contact: "Adicionar contato" - already_connected: "Já está conectado(a)!" - pending_request: "Pedido pendente" thats_you: "É você!" profile_sidebar: bio: "Biografia" born: "Aniversário" - edit_my_profile: "Editar meu perfil" gender: "Sexo" - in_aspects: "Em aspectos" location: "Localização" - photos: "Fotos" - remove_contact: "Remover contato" - remove_from: "Remover %{name} de %{aspect}?" show: closed_account: "Essa conta foi cancelada." does_not_exist: "Esta pessoa não existe!" has_not_shared_with_you_yet: "%{name}, não possui nenhuma publicação compartilhada com você ainda!" - ignoring: "Você está ignorando todas as mensagens de %{name}." - incoming_request: "%{name}, quer compartilhar com você." - mention: "Mencionar" - message: "Mensagem" - not_connected: "Você não está compartilhando com %{name}." - recent_posts: "Publicações recentes" - recent_public_posts: "Publicações públicas recentes" - return_to_aspects: "Retornar para a página de seus aspectos" - see_all: "Ver todas" - start_sharing: "Comece a compartilhar" - to_accept_or_ignore: "Aceitar ou ignorar." - sub_header: - add_some: "Adicione algumas" - edit: "Editar" - you_have_no_tags: "Você não tem tags!" - webfinger: - fail: "Desculpe-nos, não conseguimos encontrar %{handle}." - zero: "nenhuma pessoa" photos: - comment_email_subject: "Foto de %{name}" create: integrity_error: "O envio falhou! Tem certeza que era uma imagem?" runtime_error: "O envio falhou! Você colocou seu cinto de segurança?" type_error: "O envio da foto falhou. Tem certeza que a imagem é válida?" destroy: notice: "Foto apagada." - edit: - editing: "Editando" - new: - back_to_list: "Voltar para lista" - new_photo: "Nova foto" - post_it: "Enviar!" new_photo: empty: "{file} está vazio, por favor, selecione os arquivos novamente." invalid_ext: "{file} possui uma extensão inválida. Somente {extensions} são permitidos." size_error: "{file} é muito grande, o tamanho máximo para arquivos é {sizeLimit}." new_profile_photo: - or_select_one_existing: "ou selecione uma de suas %{photos} já existentes " upload: "Envie uma foto nova para o perfil!" - photo: - view_all: "Ver todas as fotos de %{name}" show: - collection_permalink: "Link permanente da coleção" - delete_photo: "Apagar foto" - edit: "Editar" - edit_delete_photo: "Editar descrição / apagar foto" - make_profile_photo: "Marcar como foto do perfil" show_original_post: "Ver publicação original" - update_photo: "Atualizar foto" - update: - error: "Falha ao tentar enviar a foto." - notice: "A foto foi enviada com sucesso." + polls: + votes: + one: "Um voto até agora" + other: "%{count} votos até agora" + zero: "Nenhum voto até agora" posts: presenter: title: "Uma publicação de %{name}" show: - destroy: "Apagar" forbidden: "Você não tem permissão para fazer isso" - not_found: "Desculpe! Não foi possÃvel encontrar." - permalink: "Link permanente" + location: "Publicado de: %{location}" photos_by: one: "Uma foto de %{author}" other: "%{count} fotos de %{author}" zero: "Não há fotos de %{author}" reshare_by: "Recompartilhado por %{author}" - previous: "Anterior" privacy: "Privacidade" - privacy_policy: "PolÃtica de Privacidade" profile: "Perfil" profiles: edit: allow_search: "Permitir que pessoas me procurem em diaspora*" - edit_profile: "Editar perfil" + basic: "Meu perfil básico" + basic_hint: "Todos os itens do perfil são opcionais. Seu perfil básico é visÃvel publicamente, e isso não pode ser alterado." + extended: "Meu perfil ampliado" + extended_hint: "Use a chave para configurar quem pode ver as informações do seu perfil ampliado: selecione \"público\" para qualquer internauta e \"limitado\" para restringir o acesso a pessoas com quem você compartilha." + extended_visibility_text: "Visibilidade do seu perfil ampliado:" first_name: "Primeiro Nome" last_name: "Sobrenome" + limited: "Limitado" nsfw_check: "Marque tudo que eu compartilho como NSFW" - nsfw_explanation: "NSFW ('conteúdo inapropriado') é um padrão de autogovernança da comunidade diaspora* para conteúdos que podem não ser adequados para serem vistos enquanto estiver no trabalho. Se você planeja compartilhar esse tipo de material frequentemente, por favor marque esta opção, então tudo aquilo que você compartilhar ficará oculto nos fluxos das pessoas, a menos que elas escolham vê-los." + nsfw_explanation: "NSFW (\"not safe for work\", literalmente \"não é seguro ver no trabalho\") é uma norma de conduta da diaspora* a respeito de conteúdos inapropriados, que não podem ser vistos, por exemplo, no computador do escritório. Se você pretende compartilhar esse tipo de material frequentemente, por favor, marque esta opção. Assim, tudo o que você compartilhar vai ficar oculto nos fluxos dos outros até que eles cliquem para visualizar." nsfw_explanation2: "Se você escolher não selecionar esta opção, por favor adicione a tag #nsfw toda vez que você compartilhar esse tipo de material." + public: "Público" + settings: "Configurações de perfil" update_profile: "Atualizar perfil" your_bio: "Sobre você" your_birthday: "Data de nascimento" @@ -972,8 +905,6 @@ pt-BR: your_location: "Sua localização" your_name: "Seu nome" your_photo: "Sua foto" - your_private_profile: "Seu perfil privado" - your_public_profile: "Seu perfil público" your_tags: "Descreva-se em cinco palavras" your_tags_placeholder: "Ex: #diaspora #cinema #musica #cafe" update: @@ -988,26 +919,16 @@ pt-BR: closed: "Os cadastros estão temporariamente desabilitados neste servidor diaspora*." create: success: "Você se juntou à diaspora*!" - edit: - cancel_my_account: "Cancelar minha conta" - edit: "Editar %{name}" - leave_blank: "(deixe em branco se não quiser alterar)" - password_to_confirm: "(digite a senha atual para confirmar suas alterações)" - unhappy: "Infeliz?" - update: "Atualizar" invalid_invite: "O link com o convite não é mais válido." new: - create_my_account: "Criar minha conta!" email: "E-mail" enter_email: "Insira seu endereço de e-mail" enter_password: "Digite a senha (mÃnimo de seis caracteres)" enter_password_again: "Digite novamente a tua senha" enter_username: "Escolha um nome de usuário (use somente letras, números e sublinhados)" - join_the_movement: "Junte-se ao movimento!" password: "Senha" password_confirmation: "Confirmar senha" - sign_up: "Registrar-se" - sign_up_message: "Rede social com um ♥" + sign_up: "Criar conta" submitting: "Enviando..." terms: "Ao criar uma conta você aceita os %{terms_link}." terms_link: "Termos de Serviço" @@ -1020,45 +941,18 @@ pt-BR: post_label: "<b>Publicação</b>: %{title}" reason_label: "Motivo: %{text}" reported_label: "<b>Relatado por</b> %{person}" + reported_user_details: "Detalhes sobre o usuário relatado" review_link: "Marcar como revisado" status: - created: "Um relato foi criado" destroyed: "A publicação foi destruÃda" failed: "Alguma coisa deu errado" - marked: "Um relato foi marcado como revisado" title: "Visão Geral de Relatos" - requests: - create: - sending: "Enviando" - sent: "Você pediu para compartilhar com %{name}. Eles serão notificados na próxima vez que entrarem em diaspora*." - destroy: - error: "Por favor, selecione um aspecto!" - ignore: "Pedido de contato ignorado." - success: "Vocês agora estão compartilhando." - helper: - new_requests: - one: "Novo pedido!" - other: "%{count} novos pedidos!" - zero: "Nenhum pedido novo" - manage_aspect_contacts: - existing: "Contatos existentes" - manage_within: "Gerenciar contatos dentro" - new_request_to_person: - sent: "Enviado!" reshares: comment_email_subject: "publicação de %{author} recompartilhada por %{resharer}" - create: - failure: "Houve um erro ao recompartilhar esta publicação." reshare: deleted: "A publicação original foi apagada pelo autor." - reshare: - one: "1 recompartilhamento" - other: "%{count} recompartilhamentos" - zero: "Recompartilhar" reshare_confirmation: "Recompartilhar publicação de %{author}?" - reshare_original: "Recompartilhar original" reshared_via: "Recompartilhado via" - show_original: "Mostrar original" search: "Busca" services: create: @@ -1070,10 +964,6 @@ pt-BR: success: "A autenticação foi apagada com sucesso." failure: error: "Houve um erro na conexão do serviço" - finder: - fetching_contacts: "diaspora* está importando seus amigos de %{service}; por favor, volte daqui alguns minutos." - no_friends: "Nenhum amigo do Facebook foi encontrado." - service_friends: "Amigos do %{service}" index: connect: "Conectar" disconnect: "Desconectar" @@ -1082,60 +972,30 @@ pt-BR: no_services_available: "Não há serviços disponÃveis neste servidor." not_logged_in: "Você não se conectou." really_disconnect: "Desconectar %{service}?" - services_explanation: "A conexão com serviços externos permite que você faça suas publicações em serviços conectados ao mesmo tempo em que você as escreve em diaspora*." - inviter: - click_link_to_accept_invitation: "Clique neste link para aceitar o convite" - join_me_on_diaspora: "Junte-se a mim em diaspora*" + services_explanation: "Conectando-se a serviços externos, você pode publicar na diaspora* e, ao mesmo tempo, nos outros serviços que você usa." + share_to: "Compartilhar no %{provider}" + title: "Gerenciar serviços conectados" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "Convidar" - not_on_diaspora: "Ainda não está em diaspora*" - resend: "Reenviar" settings: "Configurações" - share_visibilites: - update: - post_hidden_and_muted: "A publicação de %{name} foi ocultada, e as notificações, silenciadas." - see_it_on_their_profile: "Se você quiser ver as atualizações desta publicação, visite o perfil de %{name}." shared: - add_contact: - add_new_contact: "Adicione um novo contato" - create_request: "Procurar pela diaspora* ID" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Digite um nome de usuário diaspora*:" - know_email: "Você sabe seus e-mails? Convide-os!" - your_diaspora_username_is: "Seu nome de usuário em diaspora* é: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Adicionar contato" mobile_row_checked: "%{name} (remover)" mobile_row_unchecked: "%{name} (adicionar)" toggle: one: "Em %{count} aspecto" other: "Em %{count} aspectos" - zero: "Adicionar contato" - contact_list: - all_contacts: "Todos os contatos" - footer: - logged_in_as: "Entrou como %{name}" - your_aspects: "Seus aspectos" invitations: by_email: "Por email" - dont_have_now: "Você não possui nenhum, mas novos convites chegarão em breve!" - from_facebook: "Do Facebook" - invitations_left: "%{count} restantes" - invite_someone: "Convidar alguém" invite_your_friends: "Convide seus Amigos" invites: "Convites" - invites_closed: "Convites estão temporariamente desativados neste servidor diaspora*" share_this: "Compartilhe este link via email, blog, ou redes sociais!" - notification: - new: "Novo %{type} de %{from}" public_explain: atom_feed: "Feed Atom" - control_your_audience: "Controle sua Audiência" + control_your_audience: "Controle seu público" logged_in: "Entrou no %{service}" manage: "Gerenciar serviços conectados" new_user_welcome_message: "Use #hashtags para classificar suas publicações e encontrar pessoas que compartilham de seus interesses. Chame as pessoas interessantes com @Menções" @@ -1144,49 +1004,24 @@ pt-BR: title: "Configurar serviços conectados" visibility_dropdown: "Use esta lista suspensa para alterar a visibilidade da sua publicação. (Nós sugerimos que você escolha público.)" publisher: - all: "Todos" - all_contacts: "Todos os contatos" discard_post: "Descartar publicação" formatWithMarkdown: "Você pode usar %{markdown_link} para formatar sua publicação" get_location: "Obter a sua localização" - make_public: "Tornar público" new_user_prefill: hello: "Olá a todos, sou #%{new_user_tag}. " i_like: "Tenho interesse em %{tags}. " invited_by: "Obrigado pelo convite, " - newhere: "Novato" + newhere: "novato" poll: add_a_poll: "Adicionar uma enquete" - add_poll_answer: "Adicionar opção" - option: "Opção 1" - question: "Pergunta" - remove_poll_answer: "Remover opção" - post_a_message_to: "Publicar uma mensagem para %{aspect}" posting: "Publicando..." - preview: "Visualizar" - publishing_to: "Publicando para: " remove_location: "Localização remota" share: "Compartilhar" - share_with: "Compartilhar com %{aspect}" upload_photos: "Enviar fotos" whats_on_your_mind: "O que você quer compartilhar agora?" - reshare: - reshare: "Recompartilhar" stream_element: - connect_to_comment: "Conecte-se ao usuário para comentar a publicação dele" - currently_unavailable: "comentários indisponÃveis no momento" - dislike: "Descurtir" - hide_and_mute: "Ocultar" - ignore_user: "Ignorar %{name}" - ignore_user_description: "Ignorar e remover usuário de todos os aspectos?" - like: "Curtir" - nsfw: "Essa publicação foi marcada como não apta para todos os públicos por seu autor. %{link}" - shared_with: "Compartilhado com: %{aspect_names}" - show: "Mostrar" - unlike: "Descurtir" - via: "via %{link}" - via_mobile: "pelo celular" - viewable_to_anyone: "Essa publicação é visÃvel para qualquer pessoa na internet" + via: "Via %{link}" + via_mobile: "Por dispositivo móvel" simple_captcha: label: "Digite o código na caixa de texto:" message: @@ -1212,21 +1047,12 @@ pt-BR: status_messages: create: success: "Mencionados com sucesso: %{names}" - destroy: - failure: "Falha ao apagar a publicação" - helper: - no_message_to_display: "Nenhuma mensagem para mostrar." new: mentioning: "Mencionando: %{person}" too_long: "Sua mensagem de status deve ter menos de %{count} caracteres. Agora, ela tem %{current_length} caracteres." stream_helper: - hide_comments: "Ocultar todos os comentários" no_more_posts: "Você chegou ao final do fluxo." no_posts_yet: "Não existem publicações ainda." - show_comments: - one: "Ver mais um comentário" - other: "Ver mais %{count} comentários" - zero: "Nenhum comentário" streams: activity: title: "Minha Atividade" @@ -1249,17 +1075,10 @@ pt-BR: multi: title: "Fluxo" public: - title: "Atividade Pública" + title: "Atividade pública" tags: title: "Publicações com a tag: %{tags}" tag_followings: - create: - failure: "Falha ao seguir #%{name}. Você já está seguindo esta tag?" - none: "Você não pode seguir uma tag em branco!" - success: "Sucesso! Você está seguindo #%{name}." - destroy: - failure: "Não foi possÃvel parar de seguir #%{name}. Quem sabe você já tenha feito isso?" - success: "Que pena! Você não está mais seguindo #%{name}." manage: no_tags: "Você não segue nenhuma tag." title: "Gerenciar as tags que você segue" @@ -1267,15 +1086,12 @@ pt-BR: name_too_long: "O nome da tag deve ter menos de %{count} caracteres. Agora, ela tem %{current_length} caracteres." show: follow: "Seguir #%{tag}" - following: "Seguindo #%{tag}" none: "A tag vazia não existe!" stop_following: "Parar de seguir #%{tag}" tagged_people: one: "1 pessoa marcada com %{tag}" other: "%{count} pessoas marcadas com %{tag}" zero: "Ninguém marcado com %{tag}" - terms_and_conditions: "Termos e Condições" - undo: "Desfazer?" username: "Usuário" users: confirm_email: @@ -1286,17 +1102,17 @@ pt-BR: success: "Sua conta já foi bloqueada e deve ser encerrada em até 20 minutos. Agradecemos a você por experimentar diaspora*." wrong_password: "A senha digitada não corresponde à senha atual." edit: - also_commented: "alguém comenta uma publicação que você tenha comentado" + also_commented: "alguém comentar uma publicação que você tenha comentado" auto_follow_aspect: "Aspecto para contatos adicionados automaticamente:" auto_follow_back: "Compartilhar automaticamente com usuários que começam a compartilhar com você" change: "Alterar" + change_color_theme: "Mudar paleta" change_email: "Alterar Email" change_language: "Alterar Idioma" change_password: "Alterar Senha" character_minimum_expl: "deve ter no mÃnimo seis caracteres" close_account: - dont_go: "Ei, por favor não vá!" - if_you_want_this: "Se você realmente quer isso, digite sua senha abaixo e clique em 'Cancelar conta'" + dont_go: "Ei, não vá ainda!" lock_username: "Seu nome de usuário será bloqueado. Você não poderá criar uma nova conta neste servidor com o mesmo ID." locked_out: "Você será desconectado, e sua conta, bloqueada até que seja completamente apagada." make_diaspora_better: "AdorarÃamos que você ficasse para nos ajudar a melhorar diaspora*. Se você realmente quiser ir, porém, continue a ler para saber o que virá em seguida." @@ -1304,34 +1120,32 @@ pt-BR: no_turning_back: "Isso não poderá ser desfeito! Se você tem certeza, insira sua senha abaixo." what_we_delete: "Vamos apagar todas as suas publicações e informações do perfil assim que possÃvel. Seus comentários ainda vão aparecer, mas associados à sua diaspora* ID em vez do seu nome." close_account_text: "Encerrar conta" - comment_on_post: "alguém comenta sua publicação" + comment_on_post: "alguém comentar uma publicação sua" current_password: "Senha atual" current_password_expl: "o que você usa atualmente..." download_export: "Baixar o meu perfil" download_export_photos: "Baixar minhas fotos" - download_photos: "Baixar minhas fotos" edit_account: "Editar Conta" email_awaiting_confirmation: "Temos que lhe enviar um link para a confirmação do email %{unconfirmed_email}. Enquanto você não confirmar o seu novo endereço de email, nós continuaremos utilizando o endereço antigo: %{email}." export_data: "Exportar dados" export_in_progress: "Estamos processando seus dados. Por favor, volte a verificar em alguns instantes." export_photos_in_progress: "Estamos processando suas fotos. Por favor, volte a verificar em alguns instantes." following: "Configurações de compartilhamento" - getting_started: "Preferências de novo usuário" last_exported_at: "(Atualizado pela última vez à s %{timestamp})" - liked: "alguém curte sua publicação" - mentioned: "você é mencionado(a) em uma publicação" + liked: "alguém curtir uma publicação sua" + mentioned: "mencionarem você em uma publicação" new_password: "Nova senha" - private_message: "você recebe uma mensagem privada" + private_message: "você receber uma mensagem privada" receive_email_notifications: "Receber notificações por email quando:" request_export: "Solicitar dados do meu perfil" request_export_photos: "Exportar minhas fotos" request_export_photos_update: "Atualizar minhas fotos" request_export_update: "Atualizar dados do meu perfil" - reshared: "alguém recompartilha sua publicação" + reshared: "alguém recompartilhar uma publicação sua" show_community_spotlight: "Mostrar Destaque da Comunidade no Fluxo" - show_getting_started: "Mostrar dicas de como começar" + show_getting_started: "Mostrar dicas de \"como começar\"" someone_reported: "alguém envia um relato" - started_sharing: "alguém começa a compartilhar com você" + started_sharing: "alguém começar a compartilhar com você" stream_preferences: "Preferências do Fluxo" your_email: "Seu e-mail" your_email_private: "Seu e-mail não será visto por outros usuários" @@ -1343,19 +1157,20 @@ pt-BR: connect_to_facebook_link: "Conectando seu Facebook" hashtag_explanation: "Hashtags permitem a você compartilhar e acompanhar seus interesses. Elas também são uma ótima maneira de conhecer novas pessoas." hashtag_suggestions: "Tente tags como #arte, #cinema, #gif, etc." - saved: "Salvo!" well_hello_there: "Bem, olá!" what_are_you_in_to: "Onde você está?" who_are_you: "Quem é você?" privacy_settings: ignored_users: "Usuários ignorados" no_user_ignored_message: "Você não está ignorando nenhum outro usuário" - stop_ignoring: "deixar de ignorar" + stop_ignoring: "Deixar de ignorar" strip_exif: "Remover metadados como local, autor e modelo da câmera antes de fazer upload de imagens (recomendado)" - title: "Configurações de Privacidade" + title: "Configurações de privacidade" public: does_not_exist: "O usuário %{username} não existe!" update: + color_theme_changed: "Paleta alterada com sucesso." + color_theme_not_changed: "Um erro ocorreu durante a alteração da paleta." email_notifications_changed: "Notificação de email alterado." follow_settings_changed: "Configurações de seguimento alteradas" follow_settings_not_changed: "A alteração das configurações de seguimento falhou." @@ -1367,13 +1182,6 @@ pt-BR: settings_updated: "Configurações atualizadas" unconfirmed_email_changed: "Email alterado com sucesso! É necessário realizar uma confirmação." unconfirmed_email_not_changed: "Alteração do email falhou!" - webfinger: - fetch_failed: "Falha ao obter perfil WebFinger de %{profile_url}" - hcard_fetch_failed: "Ocorreu um problema ao obter o hcard de %{account}" - no_person_constructed: "Não foi possÃvel construir uma pessoa a partir deste hcard." - not_enabled: "O webfinger parece não estar habilitado para o servidor %{account}" - xrd_fetch_failed: "Ocorreu um problema ao obter o xrd da conta %{account}" - welcome: "Bem-vindo(a)!" will_paginate: next_label: "próximo »" previous_label: "« anterior" \ No newline at end of file diff --git a/config/locales/diaspora/pt-PT.yml b/config/locales/diaspora/pt-PT.yml index c33200de0cd4145c2bcf84e0986065973d4ac84e..da2cfbc4eb2e10b916045ee2d2c514a17852e495 100644 --- a/config/locales/diaspora/pt-PT.yml +++ b/config/locales/diaspora/pt-PT.yml @@ -6,11 +6,8 @@ pt-PT: _applications: "Aplicações" - _comments: "Comentários" _contacts: "Contactos" _help: "Ajuda" - _home: "InÃcio" - _photos: "Fotografias" _services: "Serviços" account: "Conta" activerecord: @@ -93,13 +90,7 @@ pt-PT: other: "Número de novos utilizadores esta semana: %{count}" zero: "Número de novos utilizadores esta semana: nenhum" current_server: "A data do servidor atual é %{date}" - ago: "Há %{time} atrás" all_aspects: "Todos os Aspetos" - application: - helper: - unknown_person: "Pessoa desconhecida" - video_title: - unknown: "TÃtulo de vÃdeo desconhecido" are_you_sure: "Tem a certeza?" are_you_sure_delete_account: "Tem a certeza que deseja encerrar a sua conta? Isto não pode ser anulado!" aspect_memberships: @@ -113,18 +104,10 @@ pt-PT: success: "Contacto adicionado ao grupo com sucesso." aspect_listings: add_an_aspect: "+ Adicionar um grupo" - deselect_all: "Desmarcar todos" - edit_aspect: "Editar %{name}" - select_all: "Selecionar todos" aspect_stream: make_something: "Efetue algo" stay_updated: "Mantenha-se atualizado" stay_updated_explanation: "No seu fluxo geral pode encontrar todos os seus contactos, as etiquetas que segue e as publicações de alguns membros criativos da comunidade." - contacts_not_visible: "Os contactos neste aspeto não poderão ver-se uns aos outros." - contacts_visible: "Os contactos neste aspeto irão poder ver-se uns aos outros." - create: - failure: "A criação do grupo falhou." - success: "O seu novo grupo %{name} foi criado" destroy: failure: "Não foi possÃvel remover %{name}." success: "%{name} foi removido(a) com sucesso." @@ -132,24 +115,15 @@ pt-PT: aspect_list_is_not_visible: "Os contactos neste grupo não podem ver-se uns aos outros." aspect_list_is_visible: "Os contactos neste grupo podem ver-se uns aos outros." confirm_remove_aspect: "Tem a certeza que deseja apagar este grupo?" - make_aspect_list_visible: "Tornar os contactos visÃveis neste aspeto para cada um?" - remove_aspect: "Apagar este grupo" rename: "Renomear" update: "Atualizar" updating: "A atualizar" index: - diaspora_id: - content_1: "A sua identificação diaspora* é:" - content_2: "Dê-a a qualquer pessoa e elas poderão encontrá-lo no diaspora*." - heading: "Identificação do diaspora*" donate: "Doar" - handle_explanation: "Esta é a sua identificação no diaspora*. Tal como num endereço de e-mail, pode dá-la à s pessoas para o contactarem." help: any_problem: "Algum problema?" contact_podmin: "Contacte o administrador do seu servidor!" do_you: "Tem:" - email_feedback: "%{link} a sua opinião, se preferir" - email_link: "Corrreio Eletrónico" feature_suggestion: "... tem uma sugestão para %{link}?" find_a_bug: "... encontrar uma %{link}?" have_a_question: "... uma %{link}?" @@ -162,31 +136,20 @@ pt-PT: tutorial_link_text: "Tutoriais" tutorials_and_wiki: "%{faq}, %{tutorial} e %{wiki}: Ajuda para os seus primeiros passos." introduce_yourself: "Este é o seu fluxo. Venha daà e apresente-se." - keep_diaspora_running: "Mantenha o desenvolvimento constante do diaspora*, doando mensalmente!" keep_pod_running: "Mantenha %{pod} a funcionar com rapidez e compre aos servidores o \"café deles\" doando mensalmente!" new_here: follow: "Siga %{link} e dê as boas-vindas aos novos utilizadores do diaspora*!" learn_more: "Saber mais" title: "Dê as boas-vindas aos novos utilizadores" - no_contacts: "Nenhuns contactos" - no_tags: "+ Encontre uma etiqueta para seguir" - people_sharing_with_you: "Pessoas a partilhar consigo" - post_a_message: "Publicar uma mensagem >>" services: content: "Pode conetar os seguintes serviços ao diaspora*:" heading: "Ligar Serviços" - unfollow_tag: "Deixar de seguir #%{tag}" welcome_to_diaspora: "Bem-vindo ao diaspora*, %{name}!" - new: - create: "Criar" - name: "Nome (apenas visÃvel para si)" no_contacts_message: community_spotlight: "Destaque da comunidade" or_spotlight: "Ou pode partilhar com %{link}" try_adding_some_more_contacts: "Pode procurar ou convidar mais contactos." you_should_add_some_more_contacts: "Devia adicionar mais alguns contactos!" - no_posts_message: - start_talking: "Ainda ninguém disse nada!" seed: acquaintances: "Conhecidos" family: "FamÃlia" @@ -195,7 +158,6 @@ pt-PT: update: failure: "O seu grupo, %{name}, tinha um nome grande demais para ser guardado." success: "O seu grupo, %{name}, foi editado com sucesso." - back: "Voltar" blocks: create: failure: "Eu não consegui ignorar esse utilizador. #evasão" @@ -207,21 +169,14 @@ pt-PT: explanation: "Publique no diaspora* a partir de qualquer lugar, adicionando esta hiperligação aos Favoritos => %{link}" heading: "Bookmarklet" post_something: "Publique no diaspora*" - post_success: "Publicado! A fechar!" cancel: "Cancelar" comments: new_comment: comment: "Comentar" commenting: "A comentar..." - one: "1 comentário" - other: "%{count} comentários" - zero: "Sem comentários" contacts: - create: - failure: "Erro ao criar contacto" index: add_a_new_aspect: "Adicionar um novo grupo" - add_to_aspect: "Adicionar contactos a %{name}" all_contacts: "Todos os contactos" community_spotlight: "Destaques da comunidade" my_contacts: "Meus contactos" @@ -230,33 +185,18 @@ pt-PT: only_sharing_with_me: "Apenas a partilhar comigo" start_a_conversation: "Iniciar uma conversa" title: "Contactos" - your_contacts: "Seus contactos" - sharing: - people_sharing: "Pessoas a partilhar consigo:" spotlight: community_spotlight: "Destaque da comunidade" suggest_member: "Sugerir um membro" conversations: - conversation: - participants: "Participantes" create: fail: "Mensagem inválida" no_contact: "Cuidado, tem de adicionar primeiro um contacto!" sent: "A mensagem foi enviada" - helper: - new_messages: - few: "%{count} novas mensagens" - many: "%{count} novas mensagens" - one: "1 nova mensagem" - other: "%{count} novas mensagens" - two: "%{count} novas mensagens" - zero: "Não há novas mensagens" index: inbox: "Caixa de entrada" - no_conversation_selected: "Nenhuma conversa selecionada" no_messages: "Sem mensagens" new: - abandon_changes: "Abandonar as alterações?" send: "Enviar" sending: "A enviar..." subject: "Assunto" @@ -275,9 +215,6 @@ pt-PT: error_messages: helper: correct_the_following_errors_and_try_again: "Corrija os seguintes erros e volte a tentar." - invalid_fields: "Campos inválidos" - login_try_again: "Por favor, <a href='%{login_link}'>inicie a sessão</a> e tente novamente." - post_not_public: "A publicação que está a tentar visualizar não é pública!" fill_me_out: "Preencha-me" find_people: "Encontrar pessoas ou #etiquetas" help: @@ -429,44 +366,27 @@ pt-PT: tutorial: "tutorial" tutorials: "tutoriais" wiki: "wiki" - hide: "Esconder" - invitation_codes: - excited: "%{name} está contente por o ver aqui." invitations: a_facebook_user: "Um utilizador do Facebook" check_token: not_found: "Código de convite não encontrado" create: - already_contacts: "Já está ligado a esta pessoa" - already_sent: "Já convidou esta pessoa." empty: "Por favor insira pelo menos um endereço de email." no_more: "Não tem mais convites." note_already_sent: "Convites já foram enviados para: %{emails}" - own_address: "Não pode enviar um convite para o seu próprio endereço." rejected: "Os seguintes endereços de e-mail tiveram problemas: " sent: "Convites foram enviados para: %{emails}" - edit: - accept_your_invitation: "Aceite o seu convite" - your_account_awaits: "A sua conta está à espera!" new: - already_invited: "As pessoas seguintes não aceitaram o seu convite:" - aspect: "Grupo" - check_out_diaspora: "Descubra o diaspora*!" codes_left: one: "Resta um convite neste código" other: "Restam %{count} convites neste código" zero: "Não resta nenhum convite neste código" comma_separated_plz: "Pode introduzir vários endereços de email separados por vÃrgulas." - if_they_accept_info: "se aceitarem, serão adicionados ao grupo para o qual os convidou." invite_someone_to_join: "Convide alguém para aderir ao diaspora*!" language: "Linguagem" paste_link: "Compartilhe esta hiperligação com os seus amigos para os convidar para o Diaspora*, ou envie-lhes diretamente um e-mail com a hiperligação." - personal_message: "Mensagem pessoal" - resend: "Reenviar" send_an_invitation: "Envie um convite" - send_invitation: "Enviar convite" sending_invitation: "A enviar o convite ..." - to: "Para" layouts: application: back_to_top: "Voltar ao topo" @@ -475,34 +395,13 @@ pt-PT: source_package: "transfira o pacote de código fonte" toggle: "Alternar móvel" whats_new: "O que há de novo?" - your_aspects: "Seus aspetos" header: - admin: "Administrador" - blog: "Blogue" code: "Código" - login: "Iniciar sessão" logout: "Terminar sessão" profile: "Perfil" - recent_notifications: "Notificações recentes" settings: "Definições" - view_all: "Ver tudo" - likes: - likes: - people_dislike_this: - one: "%{count} pessoa não gosta" - other: "%{count} pessoas não gostam" - zero: "Nenhum 'não gostar'" - people_like_this: - one: "%{count} gosto" - other: "%{count} gostos" - zero: "Sem gostos" - people_like_this_comment: - one: "%{count} gosto" - other: "%{count} gostos" - zero: "Sem gostos" limited: "Limitado" more: "Mais" - next: "Seguinte" no_results: "Não foram encontrados resultados" notifications: also_commented: @@ -517,14 +416,6 @@ pt-PT: one: "%{actors} comentou na sua publicação %{post_link}." other: "%{actors} comentaram na sua %{post_link}." zero: "%{actors} comentaram na sua publicação %{post_link}." - helper: - new_notifications: - few: "%{count} novas notificações" - many: "%{count} novas notificações" - one: "1 nova notificação" - other: "%{count} novas notificações" - two: "%{count} novas notificações" - zero: "Não há novas notificações" index: and: "e" and_others: @@ -582,7 +473,6 @@ pt-PT: zero: "%{actors} começou a partilhar consigo." notifier: a_post_you_shared: "uma publicação." - accept_invite: "Aceite o Seu Convite do diaspora*!" click_here: "Clique aqui" comment_on_post: reply: "Responder ou ver a publicação de %{name} >" @@ -612,7 +502,6 @@ pt-PT: liked: "%{name} gostou da sua publicação" view_post: "Ver a publicação >" mentioned: - mentioned: "mencionou-o numa publicação:" subject: "O %{name} mencionou-o no Diaspora*" private_message: reply_to_or_view: "Responder ou ver esta conversa >" @@ -630,106 +519,45 @@ pt-PT: to_change_your_notification_settings: "para alterar as suas definições de notificação" nsfw: "Conteúdo impróprio" ok: "CONFIRMAR" - or: "ou" - password: "Palavra-passe" - password_confirmation: "Confirmação de palavra-passe" people: add_contact: invited_by: "foi convidado por" - add_contact_small: - add_contact_from_tag: "adicionar contacto pela etiqueta" - aspect_list: - edit_membership: "Editar afiliação do aspeto" - helper: - is_not_sharing: "%{name} não está a partilhar consigo" - is_sharing: "%{name} está a partilhar consigo" - results_for: "resultados para %{params}" index: looking_for: "À procura de publicações com a etiqueta %{tag_link}?" no_one_found: "...e ninguém foi encontrado." no_results: "Ei! Precisa pesquisar por alguma coisa." results_for: "Utilizadores que correspondem %{search_term}" searching: "a pesquisar, por favor aguarde..." - one: "1 pessoa" - other: "%{count} pessoas" person: - add_contact: "Adicionar contacto" - already_connected: "Já está ligado" - pending_request: "Solicitação pendente" thats_you: "É você!" profile_sidebar: bio: "Biografia" born: "Data de Nascimento" - edit_my_profile: "Editar o meu perfil" gender: "Sexo" - in_aspects: "Nos aspetos" location: "Localização" - photos: "Fotografias" - remove_contact: "Remover contacto" - remove_from: "Remover %{name} de %{aspect}?" show: closed_account: "Esta conta foi fechada." does_not_exist: "Essa pessoa não existe!" has_not_shared_with_you_yet: "%{name} ainda não partilhou quaisquer publicações consigo!" - ignoring: "Você está a ignorar todas as mensagens de %{name}." - incoming_request: "%{name} quer partilhar consigo" - mention: "Mencionar" - message: "Mensagem" - not_connected: "Não está ligado a esta pessoa" - recent_posts: "Publicações recentes" - recent_public_posts: "Publicações públicas recentes" - return_to_aspects: "Voltar à sua página dos grupos" - see_all: "Ver tudo" - start_sharing: "Começar a partilhar" - to_accept_or_ignore: "para o aceitar ou ignorar." - sub_header: - add_some: "adicionar alguns" - edit: "Editar" - you_have_no_tags: "não tem etiquetas!" - webfinger: - fail: "Desculpe, nós não conseguimos encontrar %{handle}." - zero: "Sem pessoas" photos: - comment_email_subject: "Fotografia de %{name}" create: integrity_error: "O envio da fotografia falhou. Tem a certeza de que o ficheiro que selecionou era uma imagem?" runtime_error: "O envio da fotografia falhou. Tem a certeza que o seu cinto de segurança está apertado?" type_error: "O envio da fotografia falhou. Tem a certeza que uma imagem foi adicionada?" destroy: notice: "Fotografia apagada." - edit: - editing: "A editar" - new: - back_to_list: "Voltar à Lista" - new_photo: "Nova fotografia" - post_it: "Publique!" new_photo: empty: "{file} está vazio, por favor seleccione de novo os ficheiros sem este último." invalid_ext: "{file} tem uma extensão inválida. Apenas são permitidas as extensões {extensions}." size_error: "{file} é demasiado grande, o tamanho máximo é {sizeLimit}." new_profile_photo: - or_select_one_existing: "ou selecione uma das suas já existentes %{photos}" upload: "Envie uma fotografia de perfil nova!" - photo: - view_all: "Ver todas as fotografias de %{name}" show: - collection_permalink: "hiperligação permanente da coleção" - delete_photo: "Eliminar fotografia" - edit: "Editar" - edit_delete_photo: "Editar descrição da fotografia / apagar fotografia" - make_profile_photo: "Tornar fotografia de perfil" show_original_post: "Mostrar publicação original" - update_photo: "Atualizar fotografia" - update: - error: "Falha ao editar a fotografia" - notice: "Fotografia atualizada com sucesso." posts: presenter: title: "Uma publicação de %{name}" show: - destroy: "Apagar" - not_found: "Desculpe, não foi possÃvel encontrar essa publicação." - permalink: "hiperligação permanente" photos_by: few: "%{count} fotografias de %{author}" many: "%{count} fotografias de %{author}" @@ -738,14 +566,11 @@ pt-PT: two: "Duas fotografias de %{author}" zero: "Nenhuma fotografia de %{author}" reshare_by: "Partilhado por %{author}" - previous: "Anterior" privacy: "Privacidade" - privacy_policy: "PolÃtica de Privacidade" profile: "Perfil" profiles: edit: allow_search: "Permitir que as outras pessoas o procurem no diaspora*" - edit_profile: "Editar perfil" first_name: "Nome próprio" last_name: "Apelido" update_profile: "Atualizar perfil" @@ -755,8 +580,6 @@ pt-PT: your_location: "A sua localização" your_name: "O seu nome" your_photo: "A sua fotografia" - your_private_profile: "O seu perfil privado" - your_public_profile: "O seu perfil público" your_tags: "Descreva-se em 5 palavras" your_tags_placeholder: "Como #filmes #gatos #viagens #professor #lisboa" update: @@ -771,59 +594,23 @@ pt-PT: closed: "Os registos estão encerrados neste pod do diaspora*." create: success: "Aderiu ao diaspora*!" - edit: - cancel_my_account: "Cancelar a minha conta" - edit: "Editar %{name}" - leave_blank: "(deixe em branco se não quiser modificar)" - password_to_confirm: "(necessitamos da sua palavra-passe atual para confirmar as modificações)" - unhappy: "Descontente?" - update: "Atualizar" invalid_invite: "A hiperligação de convite fornecida já não é válida!" new: - create_my_account: "Criar a minha conta!" email: "EMAIL" enter_email: "Insira o seu endereço de correio eletrónico" enter_password: "Insira uma senha (mÃnimo de 6 carateres)" enter_password_again: "Introduza de novo a mesma palavra-passe" enter_username: "Escolha um nome de utilizador (apenas letras, números e sublinhado (_))" - join_the_movement: "Junte-se ao movimento!" password: "PALAVRA-PASSE" password_confirmation: "CONFIRMAÇÃO DA SENHA" sign_up: "REGISTAR" - sign_up_message: "A Rede Social com ♥" username: "NOME DE UTILIZADOR" - requests: - create: - sending: "A enviar" - sent: "Pediu para compartilhar com %{name}. Eles serão avisados assim que entrarem no diaspora*." - destroy: - error: "Por favor, selecione um grupo!" - ignore: "Pedido de contacto ignorado." - success: "Já estão a partilhar." - helper: - new_requests: - one: "Novo pedido!" - other: "%{count} novos pedidos!" - zero: "Sem novos pedidos" - manage_aspect_contacts: - existing: "Contactos existentes" - manage_within: "Gerir contactos dentro de" - new_request_to_person: - sent: "Enviado!" reshares: comment_email_subject: "repartilha de %{resharer} da publicação de %{author}" - create: - failure: "Ocorreu um erro ao repartilhar esta publicação." reshare: deleted: "A publicação original foi apagada pelo autor." - reshare: - one: "1 recompartilha" - other: "%{count} recompartilhas" - zero: "Recompartilhar" reshare_confirmation: "Repartilhar a publicação de %{author}?" - reshare_original: "Repartilha o original" reshared_via: "Repartilhada via" - show_original: "Mostrar original" search: "Procurar" services: create: @@ -835,59 +622,24 @@ pt-PT: success: "A autenticação foi apagada com sucesso." failure: error: "Ocorreu um erro ao ligar a esse serviço" - finder: - fetching_contacts: "O diaspora* está a povoar %{service} dos seus amigos, por favor, verifique dentro de uns minutos." - no_friends: "Não foi encontrado nenhum amigo do Facebook." - service_friends: "Amigos do %{service}" index: disconnect: "Desligar" edit_services: "Editar serviços" logged_in_as: "Sessão iniciada como %{nickname}." really_disconnect: "Desligar de %{service}?" services_explanation: "Ao conetar aos serviços permite-lhe publicar as suas publicações nos mesmo, ao mesmo tempo que as escreve no diaspora*." - inviter: - click_link_to_accept_invitation: "Siga esta hiperligação para aceitar o seu convite" - join_me_on_diaspora: "Junte-se a mim no DIASPORA*" - remote_friend: - invite: "Convidar" - not_on_diaspora: "Ainda não está no diaspora*" - resend: "Reenviar" settings: "Configurações" - share_visibilites: - update: - post_hidden_and_muted: "A mensagem de %{name} foi ocultada e as notificações foram silenciadas." - see_it_on_their_profile: "Se desejar ver as atualizações desta publicação, visite a página do perfil de %{name}." shared: - add_contact: - add_new_contact: "Adicionar um novo contacto" - create_request: "Encontrar com a id do diaspora*" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Insira um nome de utilizador do diaspora*:" - know_email: "Sabe os seus endereços de email? Deveria convidá-los" - your_diaspora_username_is: "O seu nome de utilizador do diaspora* é: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Adicionar contacto" toggle: one: "Em %{count} aspeto" other: "Em %{count} aspetos" zero: "Adicionar contacto" - contact_list: - all_contacts: "Todos os contactos" - footer: - logged_in_as: "Sessão iniciada como %{name}" - your_aspects: "Seus aspetos" invitations: by_email: "Por email" - dont_have_now: "Não tem nenhum agora, mas brevemente terá mais convites!" - from_facebook: "do Facebook" - invitations_left: "ainda tem %{count}" - invite_someone: "Convidar alguém" invite_your_friends: "Convide os seus amigos" invites: "Convites" - invites_closed: "De momento, os convites estão encerrados neste pod do diaspora*" share_this: "Compartilhe esta hiperligação via e-mail, blogue, ou redes sociais!" - notification: - new: "Novo %{type} de %{from}" public_explain: atom_feed: "Atom feed" control_your_audience: "Controle o seu público" @@ -899,59 +651,29 @@ pt-PT: title: "Configurar serviços conectados" visibility_dropdown: "Utilize esta lista para alterar as opções de visibilidade da sua publicação. (Sugerimos que a sua primeira publicação seja pública.)" publisher: - all: "Tudo" - all_contacts: "Todos os contactos" discard_post: "Rejeitar a publicação" get_location: "Obter a minha localização" - make_public: "Tornar público" new_user_prefill: hello: "Olá a todos, eu sou #%{new_user_tag}. " i_like: "Eu estou interessado em %{tags}. " invited_by: "Obrigado(a) pelo convite," newhere: "Novo Aqui" - post_a_message_to: "Publicar uma mensagem em %{aspect}" posting: "A publicar..." - preview: "Pré-visualizar" - publishing_to: "A publicar para: " share: "Partilhar" - share_with: "Partilhar com" upload_photos: "Carregar fotos" whats_on_your_mind: "Em que está a pensar?" - reshare: - reshare: "Voltar a partilhar" stream_element: - connect_to_comment: "Ligue-se a este utilizador para comentar na sua publicação" - currently_unavailable: "Comentários atualmente indisponÃveis" - dislike: "Não Gostar" - hide_and_mute: "Ocultar e silenciar a publicação" - ignore_user: "Ignorar %{name}" - ignore_user_description: "Ignorar e remover o utilizador de todos os aspetos?" - like: "Gostar" - nsfw: "Esta publicação foi marcada pelo seu autor como tendo conteúdo impróprio. %{link}" - shared_with: "Partilhado com: %{aspect_names}" - show: "Mostrar" - unlike: "Anular Gosto" via: "Via %{link}" via_mobile: "Via telemóvel" - viewable_to_anyone: "Esta publicação é visÃvel para todos na Web" status_messages: create: success: "Mencionou com sucesso: %{names}" - destroy: - failure: "Falhou ao eliminar publicação" - helper: - no_message_to_display: "Não há mensagens para mostrar." new: mentioning: "A mencionar: %{person}" too_long: "Por favor, não utilize mais de %{count} carateres nas suas mensagens de estado\". De momento tem %{current_length} carateres" stream_helper: - hide_comments: "Ocultar todos os comentários" no_more_posts: "Chegou ao fim do fluxo." no_posts_yet: "Ainda não existem publicações." - show_comments: - one: "Mostrar mais um comentário" - other: "Mostrar mais %{count} comentários" - zero: "Sem mais comentários" streams: activity: title: "Minha atividade" @@ -977,22 +699,11 @@ pt-PT: title: "Atividade pública" tags: title: "Publicações marcadas: %{tags}" - tag_followings: - create: - failure: "Não foi possÃvel seguir: #%{name}. Já está a segui-lo?" - none: "Não pode seguir uma etiqueta em branco!" - success: "Viva! Agora, está a seguir #%{name}." - destroy: - failure: "Não foi possÃvel para de seguir: #%{name}. Talvez já tenha parado de segui-lo?" - success: "Ai! Já não está a seguir #%{name}" tags: show: follow: "Seguir #%{tag}" - following: "A Seguir #%{tag}" none: "A etiqueta vazia não existe!" stop_following: "Deixar de seguir #%{tag}" - terms_and_conditions: "Termos e Condições" - undo: "Anular?" username: "Nome de utilizador" users: confirm_email: @@ -1013,7 +724,6 @@ pt-PT: character_minimum_expl: "deve ter pelo menos seis carateres" close_account: dont_go: "Ei, por favor não vá!" - if_you_want_this: "Se realmente é o que quer, digite a seguir a sua palavra-passe e clique em 'Encerrar Conta'" lock_username: "O seu nome de utilizador será bloqueado. Não poderá criar uma conta nova neste servidor com a mesma identificação.." locked_out: "A sua sessão será terminada e a sua conta bloqueada até que esta seja apagada." make_diaspora_better: "Nós gostarÃamos que ficasse e nos ajude a tornar o diaspora* ainda melhor, em vez de nos deixar. Se realmente desejar deixar-nos, nós queremos que saiba o que irá acontecer a seguir." @@ -1024,12 +734,10 @@ pt-PT: comment_on_post: "alguém comenta na sua publicação" current_password: "Palavra-passe atual" current_password_expl: "aquela que utiliza para iniciar sessão..." - download_photos: "descarregar as minhas fotografias" edit_account: "Editar conta" email_awaiting_confirmation: "Enviámos-lhe uma hiperligação de ativação para %{unconfirmed_email}. Até que siga esta hiperligação e ative o novo endereço, continuaremos a utilizar o seu endereço original %{email}." export_data: "Exportar dados" following: "Definições do Compartilhar" - getting_started: "Novas preferências de utilizador" liked: "alguém gosta da sua publicação" mentioned: "está mencionado numa publicação" new_password: "Nova palavra-passe" @@ -1049,7 +757,6 @@ pt-PT: connect_to_facebook_link: "a interligar à sua conta do Facebook" hashtag_explanation: "Os cardinais (#) permitem-lhe falar sobre e seguir os seus interesses. Eles também são uma boa forma para encontrar novas pessoas no diaspora*." hashtag_suggestions: "Tente seguir as etiquetas, tais como #arte, #cinema, #gif, etc." - saved: "Guardado!" well_hello_there: "Oh! Olá a todos!" what_are_you_in_to: "O que gosta mais?" who_are_you: "Quem é você?" @@ -1071,13 +778,6 @@ pt-PT: settings_updated: "Configurações atualizadas" unconfirmed_email_changed: "O endereço de email foi alterado. É necessária ativação." unconfirmed_email_not_changed: "A mudança de email falhou" - webfinger: - fetch_failed: "não foi possÃvel obter o perfil 'webfinger' para %{profile_url}" - hcard_fetch_failed: "ocorreu um problema ao obter o 'hcard' para %{account}" - no_person_constructed: "Nenhuma pessoa pôde ser construÃda através deste hcard." - not_enabled: "o 'webfinger' parece não estar ativado para o anfitrião de %{account}" - xrd_fetch_failed: "ocorreu um erro ao obter o xrd da conta %{account}" - welcome: "Bem-vindo!" will_paginate: next_label: "seguinte »" previous_label: "« anterior" \ No newline at end of file diff --git a/config/locales/diaspora/ro.yml b/config/locales/diaspora/ro.yml index f2c892e5e598d6c95200046bfce3a2249382735e..06eedbab07bafe7f4e3b919da96ce8957cf9cfc8 100644 --- a/config/locales/diaspora/ro.yml +++ b/config/locales/diaspora/ro.yml @@ -6,11 +6,8 @@ ro: _applications: "AplicaÅ£ii" - _comments: "Comentarii" _contacts: "contacte" _help: "Ajutor" - _home: "Acasă" - _photos: "Fotografii" _services: "Servicii" account: "Cont" activerecord: @@ -40,13 +37,16 @@ ro: admins: admin_bar: pages: "Pagini" - ago: "%{time} în urmă" + user_search: + invite: "Invită" all_aspects: "All aspects" - application: - helper: - unknown_person: "persoană necunoscută" - video_title: - unknown: "Titlu necunoscut" + api: + openid_connect: + scopes: + name: + name: "nume" + picture: + name: "imagine" are_you_sure: "EÅŸti sigur?" are_you_sure_delete_account: "EÈ™ti sigur(ă) că vrei sa închizi contul? Acest lucru nu poate fi refăcut!" aspect_memberships: @@ -60,17 +60,9 @@ ro: success: "Contactul a fost adăugat cu succes la aspect." aspect_listings: add_an_aspect: "+ Adaugă un aspect" - deselect_all: "Deselectează tot" - edit_aspect: "Modifică %{name}" - select_all: "Selectare tot" aspect_stream: stay_updated: "Rămâi la curent" stay_updated_explanation: "Fluxul tău de date este populat cu toate contactele tale, toate etichetele pe care le urmăreÈ™ti È™i articolele publicate de unii membri creativi ai comunității." - contacts_not_visible: "Contactele din acest aspect nu vor putea sa se vada intre ele." - contacts_visible: "Contactele din acest aspect se vor putea vedea intre ele." - create: - failure: "Crearea aspectului a eÅŸuat." - success: "S-a creat noul aspect %{name}" destroy: failure: "%{name} nu este gol ÅŸi nu poate fi ÅŸters." success: "%{name} a fost eliminat cu succes." @@ -78,20 +70,13 @@ ro: aspect_list_is_not_visible: "lista de aspecte nu este vizibila persoanelor adaugate" aspect_list_is_visible: "lista de aspecte este vizibila persoanelor adaugate" confirm_remove_aspect: "EÅŸti sigur că doreÅŸti să ÅŸtergi acest aspect?" - remove_aspect: "Åžterge acest aspect" rename: "redenumeÅŸte" update: "actualizare" updating: "actualizare" index: - diaspora_id: - content_1: "ID-ul tău pe diaspora* este:" - content_2: "Transmite-l tuturor È™i ei vor putea să te găsească pe diaspora*." - heading: "ID-ul tău pe diaspora*" donate: "Donează" - handle_explanation: "This is your diaspora handle. Like an email address, you can give this to people to reach you." help: do_you: "Tu:" - email_feedback: "%{link} feedback-ul tău, dacă preferi." feature_suggestion: "ai o sugestie de %{link}?" find_a_bug: "... cauÅ£i un %{link}?" have_a_question: "... ai un %{link}?" @@ -104,25 +89,15 @@ ro: follow: "Urmează legătura %{link} si urează-le bun venit noilor utilizatori in comunitatea Diaspora" learn_more: "Află mai multe" title: "Bun venit noilor utilizatori" - no_contacts: "Niciun contact" - no_tags: "+ Find a tag to follow" - people_sharing_with_you: "CunoscuÈ›i care partajează cu tine" - post_a_message: "publicaÅ£i un mesaj >>" services: content: "Te poÈ›i conecta la următoarele servicii pe Diaspora" heading: "Conectează servciii" - unfollow_tag: "Nu mai urma #%{tag}" welcome_to_diaspora: "%{name}, bine ai venit in comunitatea Diaspora!" - new: - create: "Crează" - name: "Nume (vizibil doar pentru tine)" no_contacts_message: community_spotlight: "reflectorul comunității" or_spotlight: "Sau poÈ›i partaja cu %{link}" try_adding_some_more_contacts: "You can search (top) or invite (right) more contacts." you_should_add_some_more_contacts: "Ar trebui sa mai adaugi noi persoane de contact!" - no_posts_message: - start_talking: "Nimeni nu a spus nimic deocamdată." seed: acquaintances: "CunoscuÈ›ii" family: "Familie" @@ -131,25 +106,17 @@ ro: update: failure: "Apectul tău, %{name}, are numele prea lung ca să fie salvat" success: "Aspectul, %{name}, a fost editat cu succes." - back: "ÃŽnapoi" bookmarklet: explanation: "%{link} from anywhere by bookmarking this link." post_something: "Publică ceva pe diaspora*" - post_success: "Publicat! Inchidere!" cancel: "Anulează" comments: new_comment: comment: "Comentariu" commenting: "Comentând..." - one: "1 comentariu" - other: "%{count} comentarii" - zero: "nici un comentariu" contacts: - create: - failure: "EÅŸuare la crearea contactului" index: add_a_new_aspect: "Adaugă un aspect nou" - add_to_aspect: "adaugă contacte la %{name}" all_contacts: "Toate contactele" community_spotlight: "reflectorul comunității" my_contacts: "Contactele mele" @@ -158,9 +125,6 @@ ro: only_sharing_with_me: "Partajat doar cu mine" start_a_conversation: "ÃŽncepe o conversaÈ›ie." title: "Contacte" - your_contacts: "Contactele Tale" - sharing: - people_sharing: "CunoscuÈ›i care partajează cu tine" spotlight: community_spotlight: "reflectorul comunității" suggest_member: "Propune un membru" @@ -168,18 +132,10 @@ ro: create: fail: "Mesajul nu este valid" sent: "Mesaj trimis" - helper: - new_messages: - few: "%{count} mesaje noi" - one: "1 mesaj nou" - other: "%{count} mesaje noi" - zero: "Nu ai mesaje noi" index: inbox: "Casuta postala" - no_conversation_selected: "nicio conversaÅ£ie selectată" no_messages: "niciun mesaj" new: - abandon_changes: "Abandonezi schimbările?" send: "Trimite" sending: "Trimitere..." subject: "subiect" @@ -198,7 +154,7 @@ ro: error_messages: helper: correct_the_following_errors_and_try_again: "CorectaÅ£i următoarele erori ÅŸi încercaÅ£i din nou." - invalid_fields: "Câmpuri invalide" + need_javascript: "Pentru funcÅ£ionare proprie, acest sit necesită JavaScript. Dacă ai dezactivat JavaScript, activează-l ÅŸi reîncarcă pagina." fill_me_out: "Umple-mă" find_people: "Find people" help: @@ -212,72 +168,40 @@ ro: post_report_a: "FaceÈ›i clic pe pictograma de alertă , triunghi, in dreapta sus a postului să o raporteze admin-ului. IntroduceÈ›i un motiv pentru raportarea acestui post în caseta de dialog." post_report_q: "Cum pot raporta un mesaj ofensator?" wiki: "Wiki" - hide: "Ascunde" + home: + default: + be_who_you_want_to_be: "Fii cine vrei să fii" + own_your_data: "Fii tu însăşi proprietarul datelor tale" + podmin: + admin_panel: "panoul de administrator" + contact_irc: "contactează-ne pe IRC" + contribute: "Contribuie" + create_an_account: "Crează-Å£i contul." + headline: "Bine ai venit, prietene." + make_yourself_an_admin: "Devino administrator" invitations: a_facebook_user: "Un utilizator Facebook" check_token: not_found: "InvitaÅ£ia nu a fost găsită" create: - already_contacts: "EÅŸti deja conectat cu această persoană" - already_sent: "Ai invitat deja această persoană." no_more: "Nu mai dispui de invitaÅ£ii." rejected: "Urmatoarele adrese de email au prezentat probleme:" sent: "InvitaÅ£iile a fost expediate către: %{emails}" - edit: - accept_your_invitation: "Acceptă invitaÅ£ia" - your_account_awaits: "Contul tău te aÅŸteaptă!" new: - already_invited: "Deja invitat " - aspect: "Aspect" - if_they_accept_info: "în cazul în care acceptă, vor fi adăugate la aspectul la care le-ai invitat." invite_someone_to_join: "Invită pe cineva pe Diaspora!" language: "Limbă" - personal_message: "Mesaj personal" - resend: "Mai trimite odata" send_an_invitation: "Trimite o invitaÅ£ie" - send_invitation: "Trimite invitaÅ£ie" - to: "Destinatar" layouts: application: back_to_top: "ÃŽnapoi la începutul paginii" whats_new: "ce mai e nou?" - your_aspects: "aspectele tale" header: - admin: "administrare" - blog: "Blog" code: "codul" - login: "login" logout: "IeÅŸire" profile: "Profil" - recent_notifications: "Notificări recente" settings: "Setări" - view_all: "Arata tot" - likes: - likes: - people_dislike_this: - few: "%{count} people disliked this" - many: "%{count} people disliked this" - one: "1 person disliked this" - other: "%{count} people disliked this" - two: "%{count} dislikes" - zero: "no people disliked this" - people_like_this: - few: "%{count} people liked this" - many: "%{count} people liked this" - one: "1 person liked this" - other: "%{count} people liked this" - two: "%{count} likes" - zero: "no people liked this" - people_like_this_comment: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" limited: "Limitat" more: "Mai mult" - next: "Următorul" no_results: "Niciun Rezultat Găsit" notifications: also_commented: @@ -301,14 +225,6 @@ ro: other: "%{actors} au comentat pe %{post_link} ta." two: "%{actors} commented on your %{post_link}." zero: "%{actors} commented on your %{post_link}." - helper: - new_notifications: - few: "%{count} notificări noi" - many: "%{count} notificări noi" - one: "1 new notifications" - other: "%{count} notificări noi" - two: "%{count} new notifications" - zero: "no new notifications" index: and: "ÅŸi" and_others: @@ -388,11 +304,11 @@ ro: view_post: "Vezi publicaÅ£ia >" mentioned: limited_post: "Ai fost menÈ›ionat într-o postare limitata" - mentioned: "te-a menÅ£ionat într-o publicaÅ£ie:" subject: "%{name} te-a menÅ£ionat pe diaspora*" private_message: reply_to_or_view: "Răspunde sau citeÅŸte această conversaÅ£ie >" reshared: + reshared: "%{name} a partajat postarea ta" view_post: "Vezi articolul >" single_admin: admin: "Administratorul local de Diaspora" @@ -404,96 +320,44 @@ ro: to_change_your_notification_settings: "pentru a schimba setăriile notificărilor" nsfw: "NSFW" ok: "OK" - or: "sau" - password: "Parola" - password_confirmation: "Confirmă parola" people: add_contact: invited_by: "ai fost invitat(ă) de către" - aspect_list: - edit_membership: "editaÅ£i apartenenÅ£a la aspect" - helper: - results_for: "rezultate pentru %{params}" index: looking_for: "Căutati publicaÅ£ii marcate cu %{tag_link}?" no_one_found: "... dar nimeni nu a fost găsit." no_results: "Hey! Trebuie sa cauÅ£i ceva." results_for: "caută rezultate pentru" - one: "1 persoană" - other: "%{count} persoane" person: - add_contact: "adaugă contact" - already_connected: "EÅŸti deja conectat" - pending_request: "Cerere în aÅŸteptare" thats_you: "EÅŸti tu!" profile_sidebar: bio: "Biografie" born: "Zi de naÅŸtere" - edit_my_profile: "Editează profilul meu" gender: "Gen" - in_aspects: "în aspecte" location: "LocaÅ£ie" - remove_contact: "Elimină contactul" - remove_from: "Elimini pe %{name} din %{aspect}?" show: closed_account: "Acest cont a fost închis." does_not_exist: "Persoana nu există!" has_not_shared_with_you_yet: "%{name} nu a publicat încă nimic!" - ignoring: "De acum toate publicaÅ£iile de la %{name} vor fi ignorate." - mention: "MenÅ£ionează" - message: "Mesaj" - recent_posts: "PublicaÅ£ii Recente" - recent_public_posts: "Ultimele PublicaÅ£ii Publice" - return_to_aspects: "Intoarcere către pagina de aspecte" - see_all: "Vezi tot" - start_sharing: "ÃŽncepe să comunici" - to_accept_or_ignore: "pentru a accepta sau ignora." - sub_header: - add_some: "Adaugă pe cineva" - edit: "editare" - you_have_no_tags: "nu ai nici un marcaj!" - webfinger: - fail: "Ne pare rău, nu am putut găsi %{handle}." - zero: "nimeni" photos: - comment_email_subject: "poza lui %{name}" create: integrity_error: "ÃŽncărcarea fotografiei a eÅŸuat. EÅŸti sigur că a fost o imagine?" runtime_error: "ÃŽncărcarea fotografiei a eÅŸuat. EÅŸti sigur că ai centura de siguranţă pusă?" type_error: "Imaginea nu s-a incarcat cu succes. Sunteti sigur ca era o imagine?" destroy: notice: "Fotografie eliminată." - edit: - editing: "Modificare" - new: - back_to_list: "ÃŽnapoi la Listă" - new_photo: "Nouă Fotografie" - post_it: "publică!" new_photo: empty: "{file} este gol, incearcă să selectezi fiÅŸiere din nou fără acest fiÅŸier." invalid_ext: "{file} are o extensie invalidă. Doar extensiile {extensions} sunt permise." size_error: "{file} este prea mare, mărimea maximă a unui fiÅŸier este {sizeLimit}." new_profile_photo: upload: "ÃŽncarcă o fotografie de profil nouă!" - photo: - view_all: "vizualizează toate fotografiile lui %{name}" show: - delete_photo: "Șterge Fotografie" - edit: "editează" - edit_delete_photo: "Editează descrierea imaginii / ÅŸterge imaginea" - make_profile_photo: "Setează ca fotografie de profil" show_original_post: "AfiÅŸează publicaÅ£ia originală" - update_photo: "Actualizează fotografia" - update: - error: "Nu s-a reuÅŸit editarea fotografiii." - notice: "Fotografia a fost actualizată cu succes." posts: presenter: title: "Un articol de la %{name}" show: - destroy: "Åžterge" - not_found: "Ne pare rau, dar nu am gasit publicatia." - permalink: "legătură permanentă" photos_by: few: "%{count} photos by %{author}" many: "%{count} photos by %{author}" @@ -502,14 +366,11 @@ ro: two: "Two photos by %{author}" zero: "No photos by %{author}" reshare_by: "Partajat de către %{author}" - previous: "Precedentul" privacy: "ConfidenÈ›ialitate" - privacy_policy: "Politica de confidenÅ£ialitate" profile: "Profil" profiles: edit: allow_search: "Permiteti sa fiti gasit prin cautarea pe Diaspora" - edit_profile: "Editează profil" first_name: "Prenumele" last_name: "Numele de familie" update_profile: "Actualizează Profil" @@ -519,8 +380,6 @@ ro: your_location: "LocaÅ£ia ta" your_name: "Numele tău" your_photo: "Poza ta" - your_private_profile: "Profilul tău privat" - your_public_profile: "Profilul tău public" update: failed: "EÅŸuare la actualizarea profilului" updated: "Profil actualizat" @@ -536,52 +395,15 @@ ro: closed: "ÈŠnscrierile sunt È‹nchise pe acest pod Diaspora." create: success: "Bun venit pe Diaspora!" - edit: - cancel_my_account: "Anulează contul meu" - edit: "Editează %{name}" - leave_blank: "(lăsaÅ£i necompletat dacă nu doriÅ£i să o schimbaÅ£i)" - password_to_confirm: "(avem nevoie de parola curentă pentru a confirma modificările)" - unhappy: "Nefericit?" - update: "Actualizează" new: - create_my_account: "Crează-mi un cont!" enter_email: "Introduce un e-mail" enter_password: "Introdu o parolă (de minim ÅŸase caractere)" enter_password_again: "Introduce aceeaÅŸi parolă ca ÅŸi înainte" enter_username: "Selectează un nume de utilizator (doar litere, numere si caractere underscore)" - join_the_movement: "Alătură-te miÅŸcării!" - requests: - create: - sending: "Expediez..." - destroy: - error: "Te rugăm să selectezi un aspect!" - ignore: "Ignorează cererea de contact." - success: "Acum sunteÅ£i prieteni." - helper: - new_requests: - few: "%{count} de cereri noi!" - many: "%{count} de cereri noi!" - one: "cerere nouă!" - other: "%{count} noi cereri!" - two: "%{count} cereri noi!" - zero: "nicio cerere nouă" - manage_aspect_contacts: - existing: "Contactele existente" - manage_within: "Aranjarea contactelor din acest aspect" - new_request_to_person: - sent: "trimis!" reshares: reshare: deleted: "PublicaÅ£ia originală a fost ÅŸtearsa de autorul ei." - reshare: - few: "%{count} Reshares" - many: "%{count} Reshares" - one: "1 Reshare" - other: "%{count} Reshares" - two: "%{count} reshares" - zero: "Reshare" reshared_via: "distribuit prin" - show_original: "AfiÅŸează originalul" search: "Caută" services: create: @@ -589,44 +411,17 @@ ro: success: "Autentificare cu succes." failure: error: "eroare la conectarea serviciului respectiv" - finder: - service_friends: "%{service} Prieteni" index: disconnect: "desconectează" edit_services: "Editează servicii" logged_in_as: "conectat ca" really_disconnect: "desconectează %{service}?" - inviter: - click_link_to_accept_invitation: "Click pe acest link pentru a accepta invitaÅ£ia" - join_me_on_diaspora: "Alătură-mi-te pe Diaspora*" - remote_friend: - invite: "invită" - not_on_diaspora: "Deocamdată nu este pe diaspora*" - resend: "mai trimite odata" settings: "Setări" shared: - add_contact: - add_new_contact: "Adaugă un nou contact" - create_request: "Find by Diaspora handle" - enter_a_diaspora_username: "IntroduceÅ£i numele de utilizator Diaspora :" - your_diaspora_username_is: "Numele tău de utilizator Diaspora este: %{diaspora_handle}" - aspect_dropdown: - add_to_aspect: "Adaugă la contacte" - contact_list: - all_contacts: "Toate contactele" - footer: - logged_in_as: "Autentificat ca %{name}" invitations: by_email: "prin e-mail" - dont_have_now: "Nu aveÅ£i nici una momentan, însă veÅ£i primi invitaÅ£ii noi în curând!" - from_facebook: "De pe Facebook" - invitations_left: "%{count} rămase" - invite_someone: "Invită pe cineva" invite_your_friends: "Invită-Å£i prietenii" invites: "InvitaÅ£ii " - invites_closed: "Invites are currently closed on this Diaspora seed" - notification: - new: "O noua %{type} de la %{from}" public_explain: atom_feed: "AfiÈ™are feed RSS È™i Atom" logged_in: "autentificat pe %{service}" @@ -635,44 +430,18 @@ ro: share: "Distribuie" title: "SunteÅ£i pe cale de a publica un mesaj public!" publisher: - all: "toate" - all_contacts: "toate contactele" discard_post: "Anulează publicaÅ£ia" - make_public: "Vizibil pentru toti" new_user_prefill: hello: "Salutare tuturor, sunt #%{new_user_tag}. " invited_by: "MulÅ£umesc pentru invitaÅ£ie, " newhere: "nouvenit" - post_a_message_to: "Postati un mesaj catre %{aspect}" posting: "Publicare..." share: "Distribuie" upload_photos: "ÃŽncarcă fotografii" - reshare: - reshare: "Redistribuie" stream_element: - dislike: "I dislike this" - hide_and_mute: "Hide and Mute" - ignore_user: "Ignoră utilizatorul %{name}" - like: "I like this" - show: "arată" - unlike: "Nu È‹mi place" via: "prin %{link}" - viewable_to_anyone: "Aceasta publicatie este vizibila oricui" status_messages: - destroy: - failure: "Nu sa putut ÅŸterge postul" - helper: - no_message_to_display: "Nici un mesaj nou." too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - hide_comments: "ascunde comentariile" - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: activity: title: "Activitatea proprie" @@ -689,27 +458,18 @@ ro: public: title: "Activitate publică" tag_followings: - create: - failure: "Failed to follow: #%{name}" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" manage: no_tags: "Nu urmăreÅŸti nici o etichetă" title: "Gestionează etichetele urmărite" tags: show: follow: "Urmeaza #%{tag}" - following: "Urmarind #%{tag}" stop_following: "Nu mai urmari #%{tag}" tagged_people: few: "%{count} persoane etichetate cu %{tag}" one: "O persoană etichetată cu %{tag}" other: "%{count} persoane etichetate cu %{tag}" zero: "Nimeni etichetat cu %{tag}" - terms_and_conditions: "Termeni È™i condiÈ›ii de utilizare" - undo: "refacem?" username: "Nume de utilizator" users: confirm_email: @@ -729,7 +489,6 @@ ro: close_account_text: "ÃŽnchide cont" comment_on_post: "...cineva comenteaza pe o publicatie proprie?" current_password: "Parola curentă" - download_photos: "descarcă fotografiile mele" edit_account: "Editează cont" email_awaiting_confirmation: "We have sent you an activation link to %{unconfirmed_email}. Till you follow this link and activate the new address, we will continue to use your original address %{email}." export_data: "Exportare de date" @@ -744,7 +503,6 @@ ro: your_email: "E-mailul tău" your_handle: "Identificatorul tău pe Diaspora" getting_started: - saved: "Salvat!" well_hello_there: "Bun venit" what_are_you_in_to: "Ce interese ai?" who_are_you: "Cine eÅŸti?" @@ -758,13 +516,6 @@ ro: password_not_changed: "Nu s-a putut schimba parola" unconfirmed_email_changed: "E-Mail Changed. Needs activation." unconfirmed_email_not_changed: "E-Mail Change Failed" - webfinger: - fetch_failed: "Nu s-a reusit citirea profilului webfinger din %{profile_url}" - hcard_fetch_failed: "there was a problem fetching the hcard for #{@account}" - no_person_constructed: "Nu sa putut indentifica nici o persoana prin acest hcard." - not_enabled: "webfinger nu pare sa fie activat pentru locatia %{account}" - xrd_fetch_failed: "s-a semnalat o eroare la extragerea xrd de la contul %{account}" - welcome: "Bine ai venit," will_paginate: next_label: "Pagina Următore »" previous_label: "« Pagina Precedentă" \ No newline at end of file diff --git a/config/locales/diaspora/ru.yml b/config/locales/diaspora/ru.yml index f9e298de614ead8e97a989e79282120c9a030972..f568545952266f67884a4923c976836e24bc7f0c 100644 --- a/config/locales/diaspora/ru.yml +++ b/config/locales/diaspora/ru.yml @@ -6,11 +6,8 @@ ru: _applications: "ПриложениÑ" - _comments: "Комментарии" _contacts: "Контакты" _help: "Помощь" - _home: "ГлавнаÑ" - _photos: "Фотографии" _services: "СервиÑÑ‹" _statistics: "СтатиÑтика" _terms: "уÑловиÑ" @@ -53,6 +50,7 @@ ru: taken: "уже занÑто." admins: admin_bar: + dashboard: "КонÑоль" pages: "Страницы" pod_stats: "СтатиÑтика пода" report: "ДоноÑÑ‹" @@ -117,7 +115,9 @@ ru: are_you_sure_unlock_account: "Ð’Ñ‹ уверены, что хотите разблокировать Ñтот аккаунт?" close_account: "Удалить учетную запиÑÑŒ" email_to: "E-mail Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ" + lock_account: "Заблокировать учетную запиÑÑŒ" under_13: "Показать пользователей моложе 13 (COPPA)" + unlock_account: "Разблокировать учетную запиÑÑŒ" users: few: "найдено %{count} пользователÑ" many: "найдено %{count} пользователей" @@ -139,19 +139,29 @@ ru: other: "новых пользователей на Ñтой неделе: %{count}" zero: "новых пользователей на Ñтой неделе нет" current_server: "Текущее Ð²Ñ€ÐµÐ¼Ñ Ñервера %{date}" - ago: "%{time} назад" all_aspects: "Ð’Ñе аÑпекты" - application: - helper: - unknown_person: "ÐеизвеÑтный пользователь" - video_title: - unknown: "ÐеизвеÑтное название видеозапиÑи" + api: + openid_connect: + authorizations: + new: + approve: "Одобрить" + deny: "Отказать" + error_page: + could_not_authorize: "Ðто приложение не может быть авторизовано" + login_required: "Ð’Ñ‹ должны войти, прежде чем Ñможете авторизовать данное приложение" + title: "Ой! Что-то пошло не так :(" + user_applications: + index: + edit_applications: "ПриложениÑ" + title: "Ðвторизованные приложениÑ" + revoke_autorization: "Отозвать" are_you_sure: "Ð’Ñ‹ уверены?" are_you_sure_delete_account: "Ð’Ñ‹ уверены, что хотите закрыть Ñвой аккаунт? Ðту процедуру будет невозможно отменить!" aspect_memberships: destroy: failure: "Ðе удалоÑÑŒ удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð· аÑпекта." forbidden: "Вам Ð½ÐµÐ»ÑŒÐ·Ñ Ñто делать." + invalid_statement: "Ðайдена Ð´ÑƒÐ±Ð»Ð¸Ñ€ÑƒÑŽÑ‰Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ." no_membership: "Ðе удалоÑÑŒ найти Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² аÑпекте." success: "Пользователь уÑпешно удалён из аÑпекта." aspects: @@ -160,47 +170,26 @@ ru: success: "Друг добавлен в аÑпект." aspect_listings: add_an_aspect: "+ Добавить аÑпект" - deselect_all: "Отменить выбор" - edit_aspect: "Редактировать аÑпект «%{name}»" - select_all: "Выделить вÑÑ‘" aspect_stream: make_something: "Создайте что-нибудь" stay_updated: "Будьте в курÑе" stay_updated_explanation: "Ваш оÑновной поток наполнÑетÑÑ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ контактами, метками, за которыми вы Ñледите, и некоторыми поÑтами креативных людей в ÑообщеÑтве." - contacts_not_visible: "Контакты в Ñтом аÑпекте не Ñмогут видеть друг друга." - contacts_visible: "Контакты в Ñтом аÑпекте Ñмогут видеть друг друга." - create: - failure: "Ðе удалоÑÑŒ Ñоздать аÑпект." - success: "Ваш новый аÑпект %{name} Ñоздан" destroy: failure: "%{name} не пуÑÑ‚ и не может быть удалён." success: "%{name} уÑпешно удалён." edit: - aspect_chat_is_enabled: "Контакты из Ñтого аÑпекта могут общатьÑÑ Ñ Ð²Ð°Ð¼Ð¸." - aspect_chat_is_not_enabled: "Контакты из Ñтого аÑпекта не могут общатьÑÑ Ñ Ð²Ð°Ð¼Ð¸." aspect_list_is_not_visible: "Контакты в Ñтом аÑпекте не могут видеть друг друга" aspect_list_is_visible: "Контакты в Ñтом аÑпекте могут видеть друг друга" confirm_remove_aspect: "Ð’Ñ‹ уверены, что хотите удалить Ñтот аÑпект?" - grant_contacts_chat_privilege: "предоÑтавить контактам в аÑпекте возможноÑÑ‚ÑŒ общатьÑÑ?" - make_aspect_list_visible: "Сделать контакты в Ñтом аÑпекте видимыми друг другу?" - remove_aspect: "Удалить Ñтот аÑпект" rename: "Переименовать" - set_visibility: "УÑтановить видимоÑÑ‚ÑŒ" update: "Обновить" updating: "Обновление" index: - diaspora_id: - content_1: "Ваш идентификатор в ДиаÑпоре:" - content_2: "По нему любой Ñможет найти Ð²Ð°Ñ Ð² диаÑпоре*." - heading: "Идентификатор в ДиаÑпоре" donate: "Пожертвовать" - handle_explanation: "Ðто ваш идентификатор в ДиаÑпоре. Как и Ð°Ð´Ñ€ÐµÑ Ñлектронной почты, вы можете дать его людÑм Ð´Ð»Ñ ÑвÑзи Ñ Ð²Ð°Ð¼Ð¸." help: any_problem: "Возникли проблемы?" contact_podmin: "СвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором вашего пода!" do_you: "Ð’Ñ‹:" - email_feedback: "%{link}: еще один ÑпоÑоб ÑвÑзи Ñ Ð½Ð°Ð¼Ð¸." - email_link: "E-mail" feature_suggestion: "... хотите предложить что-то новое (%{link})?" find_a_bug: "... нашли ошибку (%{link})?" have_a_question: "... хотите задать Ð²Ð¾Ð¿Ñ€Ð¾Ñ (%{link})?" @@ -213,31 +202,20 @@ ru: tutorial_link_text: "РуководÑтва" tutorials_and_wiki: "%{faq}, %{tutorial} и %{wiki}: Помощь в первых шагах." introduce_yourself: "Ðто ваш поток. ÐÑ‹Ñ€Ñйте и оÑваивайтеÑÑŒ здеÑÑŒ." - keep_diaspora_running: "Помогите развитию ДиаÑпоры ежемеÑÑчным пожертвованием!" keep_pod_running: "Помогите %{pod} работать быÑтро — купите нашим Ñерверам дозу кофе, Ñделав ежемеÑÑчное пожертвование!" new_here: follow: "ПодпишитеÑÑŒ на Ñ‚Ñг %{link} и приветÑтвуйте новых пользователей в ДиаÑпоре*!" learn_more: "Узнать больше" title: "ПриветÑтвуйте новичков" - no_contacts: "Ðет контактов" - no_tags: "+ Ðайти метку" - people_sharing_with_you: "Люди, которые добавили ваÑ" - post_a_message: "Опубликовать запиÑÑŒ >>" services: content: "Ð’Ñ‹ можете подключить к ДиаÑпоре Ñледующие ÑервиÑÑ‹:" heading: "Подключенные ÑервиÑÑ‹" - unfollow_tag: "Ðе Ñледить за меткой #%{tag}" welcome_to_diaspora: "Добро пожаловать в ДиаÑпору, %{name}!" - new: - create: "Создать" - name: "Ð˜Ð¼Ñ (видно только вам)" no_contacts_message: community_spotlight: "Рекомендуемые пользователи" or_spotlight: "Или вы можете добавить %{link}" try_adding_some_more_contacts: "Ð’Ñ‹ можете найти или приглаÑить других пользователей." you_should_add_some_more_contacts: "Добавьте больше контактов!" - no_posts_message: - start_talking: "ЗдеÑÑŒ ещё никто ничего не Ñказал." seed: acquaintances: "Знакомые" family: "СемьÑ" @@ -246,7 +224,6 @@ ru: update: failure: "Ваш аÑпект, %{name}, имеет Ñлишком длинное Ð¸Ð¼Ñ Ð´Ð»Ñ ÑохранениÑ." success: "Ваш аÑпект %{name} уÑпешно отредактирован." - back: "Ðазад" blocks: create: failure: "Я не могу заблокировать Ñтого пользователÑ. #evasion" @@ -258,22 +235,15 @@ ru: explanation: "Пишите в ДиаÑпору Ñ Ð»ÑŽÐ±Ð¾Ð¹ Ñтраницы Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñтой закладки: %{link}." heading: "Закладка ДиаÑпоры" post_something: "Отправить в ДиаÑпору" - post_success: "Опубликовано! Закрытие!" cancel: "Отменить" comments: new_comment: comment: "Комментировать" commenting: "Комментирование..." - one: "1 комментарий" - other: "%{count} комментариев" - zero: "Комментариев нет" contacts: - create: - failure: "Ðе удалоÑÑŒ Ñоздать контакт" index: add_a_new_aspect: "Ðовый аÑпект" add_contact: "Добавить контакт" - add_to_aspect: "Добавить контакты в аÑпект %{name}" all_contacts: "Ð’Ñе контакты" community_spotlight: "Рекомендованные пользователи" my_contacts: "Мои контакты" @@ -281,19 +251,13 @@ ru: no_contacts_in_aspect: "Ð’Ñ‹ еще никого не добавили в Ñтот аÑпект. Ðиже предÑтавлен ÑпиÑок ваших ÑущеÑтвующих контактов, которые вы можете добавить в Ñтот аÑпект." no_contacts_message: "ЗаглÑните на Ñтраницу %{community_spotlight}" only_sharing_with_me: "Только добавившие менÑ" - remove_contact: "Удалить контакт" start_a_conversation: "Ðачать беÑеду" title: "Контакты" user_search: "ПоиÑк пользователей" - your_contacts: "Ваши контакты" - sharing: - people_sharing: "Пользователи, которые Ð²Ð°Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ð»Ð¸:" spotlight: community_spotlight: "Рекомендованные пользователи" suggest_member: "Предложить пользователÑ" conversations: - conversation: - participants: "УчаÑтники" create: fail: "Ðеверное Ñообщение" no_contact: "Ðй, вам нужно Ñначала добавить контакт!" @@ -301,22 +265,13 @@ ru: destroy: delete_success: "Диалог уÑпешно удален" hide_success: "Диалог уÑпешно удален" - helper: - new_messages: - few: "%{count} новых ÑообщениÑ" - many: "%{count} новых Ñообщений" - one: "1 новое Ñообщение" - other: "%{count} новых Ñообщений" - zero: "Ðовых Ñообщений нет" index: conversations_inbox: "Разговоры - ВходÑщие ÑообщениÑ" - create_a_new_conversation: "Ðачать новый разговор" inbox: "ВходÑщие" new_conversation: "Ðовый разговор" - no_conversation_selected: "Разговор не выбран" no_messages: "Сообщений нет" new: - abandon_changes: "ОтказатьÑÑ Ð¾Ñ‚ изменений?" + message: "Сообщение" send: "Отправить" sending: "Отправка..." subject: "Тема разговора" @@ -327,6 +282,7 @@ ru: show: delete: "Удалить и заблокировать разговор" hide: "Удалить и заблокировать диалог" + last_message: "ПоÑледнее Ñообщение получено %{timeago}" reply: "Ответить" replying: "Ответ..." date: @@ -339,10 +295,7 @@ ru: error_messages: helper: correct_the_following_errors_and_try_again: "ИÑправьте ошибки и попробуйте Ñнова." - invalid_fields: "ÐедейÑтвительные полÑ" - login_try_again: "ПожалуйÑта, %{login_link}<a href='%{login_link}'>войдите</a> и попробуйте Ñнова." - post_not_public: "ЗапиÑÑŒ, которую вы пытаетеÑÑŒ поÑмотреть, не публична!" - post_not_public_or_not_exist: "ЗапиÑÑŒ, которую вы хотите открыть не Ð¿ÑƒÐ±Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð¸Ð»Ð¸ не ÑущеÑтвует!" + need_javascript: "Ðтот Ñайт требует JavaScript. ЕÑли у Ð²Ð°Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½ JavaScript, пожалуйÑта, включите его и обновите Ñтраницу." fill_me_out: "Заполнить" find_people: "ПоиÑк людей или #меток" help: @@ -562,31 +515,43 @@ ru: tutorial: "руководÑтво" tutorials: "руководÑтва" wiki: "wiki" - hide: "Скрыть" - ignore: "Игнорировать" + home: + default: + be_who_you_want_to_be: "Будьте тем, кем хотите быть" + be_who_you_want_to_be_info: "Многие Ñоциальные Ñети требуют от Ð²Ð°Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ñвоих наÑтоÑщих данных. Многие, но не диаÑпора*. ЗдеÑÑŒ Ð’Ñ‹ можете выбрать, кем вы хотите быть, и указать такое количеÑтво личной информации, какое Ñчитаете нужным. Только от Ð²Ð°Ñ Ð·Ð°Ð²Ð¸Ñит, как Ð’Ñ‹ будете взаимодейÑтвовать Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ людьми." + byline: "Ð¡Ð¾Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð°Ñ Ñеть, которой управлÑете вы." + choose_your_audience: "Выбирайте аудиторию" + choose_your_audience_info: "ÐÑпекты в диаÑпоре* позволÑÑŽÑ‚ вам делитьÑÑ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹ только Ñ Ñ‚ÐµÐ¼Ð¸ людьми, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ð¼Ð¸ вы хотите. Ð’Ñ‹ Ñами выбираете уровень открытоÑти или ÑекретноÑти ваших запиÑей. ДелитьÑÑ Ñмешными фотографиÑми Ñо вÑем миром - или в глубокой тайне только Ñ Ñамыми близкими друзьÑми. Ð’ÑÑ‘ под вашим контролем." + headline: "Добро пожаловать в %{pod_name}" + own_your_data: "Владелец ваших данных - вы" + own_your_data_info: "Многие Ñоциальные Ñети иÑпользуют ваши данные, чтобы делать деньги, Ð°Ð½Ð°Ð»Ð¸Ð·Ð¸Ñ€ÑƒÑ Ð²Ð°ÑˆÐ¸ интереÑÑ‹ и иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¸Ñ… Ð´Ð»Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð°Ð¼ вещей. диаÑпора* иÑпользует ваши данные только в той мере, в которой Ñто необходимо Ð´Ð»Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ð¸ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¸ Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ людьми." + podmin: + admin_panel: "админиÑтративной панелью" + byline: "Ты Ñкоро изменишь Интернет. Давай подготовим тебÑ?" + configuration_info: "Откройте %{database_path} и %{diaspora_path} в любимом текÑтовом редакторе и внимательно изучите. Они подробно прокомментированы." + configure_your_pod: "ÐаÑтроить ваш под" + contribute: "ВнеÑти Ñвой вклад" + contribute_info: "Сделайте диаÑпору* еще лучше! ЕÑли вы обнаружили ошибку, пожалуйÑта %{report_bugs}." + create_an_account: "Создать учетную запиÑÑŒ" + create_an_account_info: "Кликните %{sign_up_link} Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ аккаунта" + getting_help: "Получить помощь" + headline: "ЗдравÑтвуй, друг!" + make_yourself_an_admin: "Сделать ÑÐµÐ±Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором" + make_yourself_an_admin_info: "Ð’Ñ‹ можете найти инÑтрукции в %{wiki}. У Ð²Ð°Ñ Ð¿Ð¾ÑвитÑÑ ÑÑылка \"ÐдминиÑтратор\" в пользовательÑком меню в заголовке Ñтранице, когда вы заходите под Ñвоей учетной запиÑью. Она дает вам возможноÑти поиÑка по пользователÑм и проÑмотра ÑтатиÑтики по вашему поду. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñтей по функционированию вашего пода, воÑпользуйтеÑÑŒ %{admin_panel}." + update_your_pod: "Обновить ваш под" invitation_codes: - excited: "%{name} рад видеть Ð²Ð°Ñ Ð·Ð´ÐµÑÑŒ." not_valid: "Код Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ ÑƒÐ¶Ðµ не активен" invitations: a_facebook_user: "Пользователь Facebook" check_token: not_found: "Код Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð½Ðµ найден" create: - already_contacts: "Ð’Ñ‹ уже ÑвÑзаны Ñ Ñтим человеком" - already_sent: "Ð’Ñ‹ уже приглаÑили Ñтого человека." empty: "ПожалуйÑта введите Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один Ð°Ð´Ñ€ÐµÑ Ñлектронной почты." no_more: "У Ð²Ð°Ñ Ð·Ð°ÐºÐ¾Ð½Ñ‡Ð¸Ð»Ð¸ÑÑŒ приглашениÑ." note_already_sent: "ÐŸÑ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ ÑƒÐ¶Ðµ были выÑланы на: %{emails}" - own_address: "Ð’Ñ‹ не можете отправить приглашение на ваш ÑобÑтвенный адреÑ." rejected: "ЕÑÑ‚ÑŒ проблемы Ñо Ñледующими адреÑами Ñлектронной почты:" sent: "Ваши Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ñ‹ на: %{emails}" - edit: - accept_your_invitation: "ПринÑÑ‚ÑŒ приглашение" - your_account_awaits: "Ваш аккаунт ждёт ваÑ!" new: - already_invited: "Следующие люди не принÑли ваше приглашение:" - aspect: "ÐÑпект" - check_out_diaspora: "Попробуйте ДиаÑпору!" codes_left: few: "По Ñтому коду оÑталоÑÑŒ %{count} приглашениÑ" many: "По Ñтому коду оÑталоÑÑŒ %{count} приглашений" @@ -594,60 +559,28 @@ ru: other: "По Ñтому коду оÑталоÑÑŒ %{count} приглашений" zero: "По Ñтому коду не оÑталоÑÑŒ приглашений." comma_separated_plz: "Ð’Ñ‹ можете ввеÑти неÑколько адреÑов Ñлектронной почты через запÑтую." - if_they_accept_info: "поÑле ÑоглаÑÐ¸Ñ Ñ Ð¸Ñ… Ñтороны, они будут добавлены в предложенный вами аÑпект." invite_someone_to_join: "ПриглаÑить кого-нибудь в ДиаÑпору!" language: "Язык" paste_link: "ПоделитеÑÑŒ Ñтой ÑÑылкой Ñ Ð´Ñ€ÑƒÐ·ÑŒÑми, чтобы приглаÑить их в ДиаÑпору*." - personal_message: "Личное Ñообщение" - resend: "Ещё раз поÑлать" send_an_invitation: "Отправить приглашение" - send_invitation: "Отправить приглашение" sending_invitation: "Отправка приглашениÑ..." - to: "ДлÑ" layouts: application: back_to_top: "ВернутьÑÑ Ð½Ð°Ð²ÐµÑ€Ñ…" + be_excellent: "Будьте прекраÑны друг к другу! ♥" powered_by: "ОÑновано на диаÑпоре*" public_feed: "Публичный поток %{name} в ДиаÑпоре" source_package: "Ñкачать иÑходный код" statistics_link: "СтатиÑтика пода" toggle: "Обычный/мобильный" whats_new: "Что нового?" - your_aspects: "Ваши аÑпекты" header: - admin: "ÐдминиÑтратор" - blog: "Блог" code: "Код" - help: "Помощь" - login: "Войти" logout: "Выйти" profile: "Профиль" - recent_notifications: "ПоÑледние извещениÑ" settings: "ÐаÑтройки" - view_all: "ПоÑмотреть вÑÑ‘" - likes: - likes: - people_dislike_this: - few: "Ðе нравитÑÑ: %{count} " - many: "Ðе нравитÑÑ: %{count} " - one: "Ðе нравитÑÑ: %{count} " - other: "Ðе нравитÑÑ: %{count} " - zero: "Ðе нравитÑÑ: 0" - people_like_this: - few: "ПонравилоÑÑŒ: %{count}" - many: "ПонравилоÑÑŒ: %{count}" - one: "ПонравилоÑÑŒ: %{count}" - other: "ПонравилоÑÑŒ: %{count}" - zero: "ПонравилоÑÑŒ:" - people_like_this_comment: - few: "ПонравилоÑÑŒ: %{count}" - many: "ПонравилоÑÑŒ: %{count}" - one: "ПонравилоÑÑŒ: %{count}" - other: "ПонравилоÑÑŒ: %{count}" - zero: "ПонравилоÑÑŒ:0" limited: "ОграниченнаÑ" more: "Ещё" - next: "Далее" no_results: "Результатов не найдено" notifications: also_commented: @@ -670,13 +603,6 @@ ru: other: "%{actors} прокомментировали вашу %{post_link}." two: "%{actors} прокомментировали вашу %{post_link}." zero: "%{actors} прокомментировали вашу %{post_link}." - helper: - new_notifications: - few: "%{count} новых уведомлениÑ" - many: "%{count} новых уведомлений" - one: "1 новое уведомление" - other: "%{count} новых уведомлений" - zero: "Ðовых уведомлений нет" index: all_notifications: "Ð’Ñе оповещениÑ" also_commented: "Также прокомментировали" @@ -757,7 +683,6 @@ ru: a_limited_post_comment: "Добавлен новый комментарий на ограниченной запиÑи в диаÑпоре*." a_post_you_shared: "запиÑÑŒ." a_private_message: "Вам поÑтупило новое личное Ñообщение в диаÑпоре*." - accept_invite: "Примите ваше приглашение в ДиаÑпору*!" also_commented: limited_subject: "Прокомментированный вами поÑÑ‚ прокомментировали" click_here: "нажмите здеÑÑŒ" @@ -829,7 +754,6 @@ ru: view_post: "ПоÑмотреть запиÑÑŒ >" mentioned: limited_post: "Ð’Ð°Ñ ÑƒÐ¿Ð¾Ð¼Ñнули в приватной запиÑи." - mentioned: "упомÑнул Ð²Ð°Ñ Ð² запиÑи:" subject: "%{name} упомÑнул Ð²Ð°Ñ Ð² ДиаÑпоре*" private_message: reply_to_or_view: "Ответить или поÑмотреть Ñту беÑеду >" @@ -881,20 +805,9 @@ ru: to_change_your_notification_settings: "чтобы изменить ваши наÑтройки уведомлений" nsfw: "18+" ok: "Ок" - or: "или" - password: "Пароль" - password_confirmation: "Подтверждение паролÑ" people: add_contact: invited_by: "Ð²Ð°Ñ Ð¿Ñ€Ð¸Ð³Ð»Ð°Ñил пользователь" - add_contact_small: - add_contact_from_tag: "добавить контакт из метки" - aspect_list: - edit_membership: "Редактировать пользователей в аÑпекте" - helper: - is_not_sharing: "%{name} не добавил ваÑ" - is_sharing: "%{name} делитÑÑ Ñ Ð²Ð°Ð¼Ð¸" - results_for: "результаты Ð´Ð»Ñ %{params}" index: couldnt_find_them: "Ðе Ñмогли найти?" looking_for: "Ищете ÑообщениÑ, отмеченные %{tag_link}?" @@ -904,87 +817,37 @@ ru: search_handle: "ИÑпользуйте идентификаторы ДиаÑпоры (имÑ@домен.зона) чтобы найти ваших друзей." searching: "идёт поиÑк: пожалуйÑта, подождите..." send_invite: "Ð’ÑÑ‘ ещё пуÑто? ПриглаÑите кого-нибудь!" - one: "1 пользователь" - other: "%{count} пользователей" person: - add_contact: "Добавить контакт" - already_connected: "Уже подключён" - pending_request: "Ð’ ожидании запроÑа" thats_you: "Ðто вы!" profile_sidebar: bio: "О Ñебе" born: "День рождениÑ" - edit_my_profile: "Редактировать профиль" gender: "Пол" - in_aspects: "Ð’ аÑпектах" location: "МеÑтоположение" - photos: "Фотографии" - remove_contact: "Удалить контакт" - remove_from: "Удалить %{name} из %{aspect}?" show: closed_account: "Ðта ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ была закрыта." does_not_exist: "Ðет такого пользователÑ!" has_not_shared_with_you_yet: "%{name} ещё не делилÑÑ Ñ Ð²Ð°Ð¼Ð¸ запиÑÑми!" - ignoring: "Ð’Ñ‹ блокируете вÑе запиÑи Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{name}." - incoming_request: "%{name} хочет добавить ваÑ" - mention: "Упоминание" - message: "Сообщение" - not_connected: "Ð’Ñ‹ ещё не добавили Ñтого пользователÑ" - recent_posts: "ПоÑледние запиÑи" - recent_public_posts: "ПоÑледние публичные запиÑи" - return_to_aspects: "ВернутьÑÑ Ð½Ð° Ñтраницу аÑпектов" - see_all: "Показать вÑÑ‘" - start_sharing: "Ðачать делитьÑÑ" - to_accept_or_ignore: "принÑÑ‚ÑŒ или игнорировать." - sub_header: - add_some: "Добавить" - edit: "Редактировать" - you_have_no_tags: "У Ð²Ð°Ñ Ð½ÐµÑ‚ меток!" - webfinger: - fail: "К Ñожалению, мы не Ñмогли найти %{handle}." - zero: "0 пользователей" photos: - comment_email_subject: "Ð¤Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ñ %{name}" create: integrity_error: "Сбой при загрузке фотографии. Ð’Ñ‹ уверены, что Ñто правильный файл?" runtime_error: "Сбой при загрузке фотографии." type_error: "Сбой при загрузке фототрафии. Ð’Ñ‹ уверены, что добавили фотографию?" destroy: notice: "Ð¤Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð°." - edit: - editing: "Изменить" - new: - back_to_list: "ВернутьÑÑ Ðº ÑпиÑку" - new_photo: "ÐÐ¾Ð²Ð°Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ñ" - post_it: "Опубликовать!" new_photo: empty: "{file} пуÑÑ‚, выберите пожалуйÑта файлы без него." invalid_ext: "{file} имеет недопуÑтимое раÑширение. Разрешены только {extensions}." size_error: "{file} Ñлишком большой, макÑимальный размер файла {sizeLimit}." new_profile_photo: - or_select_one_existing: "или выберите одну из уже загруженных %{photos}" upload: "Загрузить новое фото Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ!" - photo: - view_all: "ПоÑмотреть вÑе фотографии %{name}" show: - collection_permalink: "СÑылка на коллекцию" - delete_photo: "Удалить фотографию" - edit: "Редактировать" - edit_delete_photo: "Изменить опиÑание фотографии / удалить фотографию" - make_profile_photo: "Сделать аватаром" show_original_post: "Показать иÑходную запиÑÑŒ" - update_photo: "Обновить фотографию" - update: - error: "Ðе удалоÑÑŒ изменить фотографию." - notice: "Ð¤Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ñ ÑƒÑпешно загружена." posts: presenter: title: "ЗапиÑÑŒ %{name}" show: - destroy: "Удалить" forbidden: "Вам Ð½ÐµÐ»ÑŒÐ·Ñ Ñто делать." - not_found: "Извините, мы не Ñмогли найти Ñту запиÑÑŒ." - permalink: "поÑтоÑÐ½Ð½Ð°Ñ ÑÑылка" photos_by: few: "%{count} фото Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{author}" many: "%{count} фото Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{author}" @@ -992,14 +855,12 @@ ru: other: "%{count} фото Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{author}" zero: "Ðет фото Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{author}" reshare_by: "ПоделилÑÑ (-лаÑÑŒ) %{author}" - previous: "Ðазад" privacy: "КонфиденциальноÑÑ‚ÑŒ" - privacy_policy: "Политика конфиденциальноÑти" profile: "Профиль" profiles: edit: allow_search: "Разрешить иÑкать Ð²Ð°Ñ Ð² ДиаÑпоре" - edit_profile: "Редактировать профиль" + basic: "Мой базовый профиль" first_name: "ИмÑ" last_name: "ФамилиÑ" nsfw_check: "Пометить вÑе мои запиÑи как NSFW" @@ -1012,8 +873,6 @@ ru: your_location: "Ваше меÑтоположение" your_name: "Ваше имÑ" your_photo: "Ваша фотографиÑ" - your_private_profile: "Ваш личный профиль" - your_public_profile: "Ваш публичный профиль" your_tags: "Опишите ÑÐµÐ±Ñ Ð² пÑти Ñловах" your_tags_placeholder: "например, #кино #котÑта #путешеÑÑ‚Ð²Ð¸Ñ #учитель #моÑква" update: @@ -1030,26 +889,16 @@ ru: closed: "Ðа Ñтом Ñервере ДиаÑпоры региÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð°." create: success: "Ð’Ñ‹ вÑтупили в диаÑпору*!" - edit: - cancel_my_account: "Отменить региÑтрацию" - edit: "Редактировать %{name}" - leave_blank: "(ОÑтавьте пуÑтым, еÑли не хотите менÑÑ‚ÑŒ)" - password_to_confirm: "(введите ваш текущий пароль Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹)" - unhappy: "Ðедовольны?" - update: "Обновить" invalid_invite: "Ðто приглашение уже недейÑтвительно!" new: - create_my_account: "Создать аккаунт" email: "ПОЧТÐ" enter_email: "Введите E-mail" enter_password: "Введите пароль (не меньше шеÑти Ñимволов)" enter_password_again: "Повторите пароль" enter_username: "Выберите Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ (только латинÑкие буквы, цифры и подчеркивание)" - join_the_movement: "ПриÑоединÑйтеÑÑŒ к движению!" password: "ПÐРОЛЬ" password_confirmation: "ПОДТВЕРЖДЕÐИЕ ПÐРОЛЯ" sign_up: "РЕГИСТРÐЦИЯ" - sign_up_message: "Ð¡Ð¾Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð°Ñ Ñеть Ñ â™¥" submitting: "Отправка..." terms: "Ð¡Ð¾Ð·Ð´Ð°Ð²Ð°Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚ вы ÑоглашаетеÑÑŒ Ñ %{terms_link}." terms_link: "уÑÐ»Ð¾Ð²Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑлуг" @@ -1064,47 +913,15 @@ ru: reported_label: "<b>Ð”Ð¾Ð½Ð¾Ñ Ð¾Ñ‚</b> %{person}" review_link: "Отметить как проÑмотренный" status: - created: "Ð”Ð¾Ð½Ð¾Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½" destroyed: "ЗапиÑÑŒ была уничтожена" failed: "Произошла ошибка" - marked: "Ð”Ð¾Ð½Ð¾Ñ Ð±Ñ‹Ð» помечен как проÑмотренный" title: "ПроÑмотр доноÑов" - requests: - create: - sending: "Отправка" - sent: "Ð’Ñ‹ проÑили добавить %{name}. Они должны увидеть Ñто при Ñледующем входе в диаÑпору*." - destroy: - error: "ПожалуйÑта, выберите аÑпект!" - ignore: "Проигнорированные запроÑÑ‹ на дружбу." - success: "Теперь вы друзьÑ." - helper: - new_requests: - few: "%{count} новых запроÑа!" - many: "%{count} новых запроÑов!" - one: "новый запроÑ!" - other: "%{count} новых запроÑов!" - zero: "новых запроÑов нет" - manage_aspect_contacts: - existing: "СущеÑтвующие контакты" - manage_within: "Управление контактами в" - new_request_to_person: - sent: "Отправлено!" reshares: comment_email_subject: "запиÑÑŒ %{author}, раÑпроÑÑ‚Ñ€Ð°Ð½Ñ‘Ð½Ð½Ð°Ñ %{resharer}" - create: - failure: "Ошибка при попытке поделитьÑÑ Ñтой запиÑью." reshare: deleted: "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ удалена автором." - reshare: - few: "ПоделилиÑÑŒ: %{count}" - many: "ПоделилиÑÑŒ: %{count}" - one: "ПоделилÑÑ: %{count}" - other: "ПоделилиÑÑŒ: %{count}" - zero: "ПоделитьÑÑ" reshare_confirmation: "ПоделитьÑÑ Ð·Ð°Ð¿Ð¸Ñью %{author}?" - reshare_original: "ПоделитьÑÑ Ð¸Ñходной запиÑью" reshared_via: "раÑпроÑтранено пользователем" - show_original: "Показать иÑходную запиÑÑŒ" search: "ПоиÑк" services: create: @@ -1116,45 +933,24 @@ ru: success: "Ð˜Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ ÑƒÑпешно удалена." failure: error: "Произошла ошибка при подключении Ñтого ÑервиÑа" - finder: - fetching_contacts: "ДиаÑпора добавлÑет ваших друзей из %{service}. ПожалуйÑта, подождите пару минут." - no_friends: "Ðе найдено друзей из Facebook." - service_friends: "Ð”Ñ€ÑƒÐ·ÑŒÑ Ð¸Ð· %{service}" index: connect: "Подключить" disconnect: "отключить" edit_services: "Редактировать ÑервиÑÑ‹" logged_in_as: "Ð’Ñ‹ вошли как %{nickname}" no_services_available: "Ðа Ñтом поде недоÑтупны ÑервиÑÑ‹." + not_logged_in: "Ðа данный момент вы не вошли в ÑиÑтему." really_disconnect: "отключить %{service}?" services_explanation: "Подключение ÑервиÑов позволÑет публиковать на них запиÑи напиÑанные в ДиаÑпоре." - inviter: - click_link_to_accept_invitation: "Чтобы принÑÑ‚ÑŒ приглашение перейдите по Ñтой ÑÑылке" - join_me_on_diaspora: "ПриÑоединÑйтеÑÑŒ ко мне в DIASPORA*" + share_to: "ПоделитьÑÑ Ð² %{provider}" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "приглашение" - not_on_diaspora: "Ещё не в ДиаÑпоре" - resend: "отправить повторно" settings: "ÐаÑтройки" - share_visibilites: - update: - post_hidden_and_muted: "ЗапиÑÑŒ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{name} была Ñкрыта, а ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ñ‹." - see_it_on_their_profile: "ЕÑли вы хотите видеть Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ñтой запиÑи, поÑетите профиль Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{name}." shared: - add_contact: - add_new_contact: "Добавить контакт" - create_request: "ПоиÑк по идентификатору в ДиаÑпоре" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Введите Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð”Ð¸Ð°Ñпоры:" - know_email: "Знаете их email адреÑа? Ð’Ñ‹ можете предложить им вÑтупить в ДиаÑпору" - your_diaspora_username_is: "Ваше Ð¸Ð¼Ñ Ð² ДиаÑпоре: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Добавить контакт" mobile_row_checked: "%{name} (перемеÑтить)" mobile_row_unchecked: "%{name} (добавить)" toggle: @@ -1163,23 +959,11 @@ ru: one: "Ð’ %{count} аÑпекте" other: "Ð’ %{count} аÑпектах" zero: "Добавить контакт" - contact_list: - all_contacts: "Ð’Ñе контакты" - footer: - logged_in_as: "вошли как %{name}" - your_aspects: "Ваши аÑпекты" invitations: by_email: "По Ñлектронной почте" - dont_have_now: "У Ð²Ð°Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ нет приглашений, но новые будут уже Ñкоро!" - from_facebook: "Из Facebook" - invitations_left: "оÑталоÑÑŒ %{count}" - invite_someone: "ПриглаÑить кого-нибудь" invite_your_friends: "ПриглаÑить друзей" invites: "ПриглашениÑ" - invites_closed: "Ð’ данный момент на Ñтом Ñервере ДиаÑпоры возможноÑÑ‚ÑŒ приглашений закрыта" share_this: "ПоделитеÑÑŒ Ñтой ÑÑылкой по почте, через блог или Ñоциальную Ñеть!" - notification: - new: "Ðовый %{type} из %{from}" public_explain: atom_feed: "RSS (Atom) лента" control_your_audience: "Выбирайте Ñвою аудиторию" @@ -1191,12 +975,9 @@ ru: title: "ÐаÑтройка подключенных ÑервиÑов" visibility_dropdown: "ИÑпользуйте Ñто выпадающее меню Ð´Ð»Ñ Ñмены видимоÑти вашей запиÑи (мы предлагаем вам Ñделать Ñту первую запиÑÑŒ публичной)." publisher: - all: "вÑе" - all_contacts: "вÑе контакты" discard_post: "Отменить запиÑÑŒ" formatWithMarkdown: "ИÑпользуйте %{markdown_link} Ð´Ð»Ñ Ð¾Ñ„Ð¾Ñ€Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ‚ÐµÐºÑта" get_location: "Добавить меÑтонахождение" - make_public: "Сделать публичным" new_user_prefill: hello: "Ð’Ñем привет, Ñ #%{new_user_tag}." i_like: "Мне интереÑны %{tags}. " @@ -1204,36 +985,14 @@ ru: newhere: "новичок" poll: add_a_poll: "Добавить опроÑ" - add_poll_answer: "Добавить вариант" - option: "Вариант 1" - question: "ВопроÑ" - remove_poll_answer: "Убрать вариант" - post_a_message_to: "Опубликовать Ñообщение Ð´Ð»Ñ %{aspect}" posting: "Отправка..." - preview: "ПредпроÑмотр" - publishing_to: "ÐŸÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð²: " remove_location: "Удалить меÑтонахождение" share: "ПоделитьÑÑ" - share_with: "ПоделитьÑÑ Ñ" upload_photos: "Загрузить фотографии" whats_on_your_mind: "О чём вы думаете?" - reshare: - reshare: "ПоделитьÑÑ" stream_element: - connect_to_comment: "ПодключитеÑÑŒ к Ñтому пользователю, чтобы комментировать его запиÑи" - currently_unavailable: "Ð’ данный момент комментарии недоÑтупны" - dislike: "Ðе нравитÑÑ" - hide_and_mute: "Скрыть и отключить уведомлениÑ" - ignore_user: "Блокировать Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{name}" - ignore_user_description: "Блокировать и удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð· вÑех аÑпектов?" - like: "ÐравитÑÑ" - nsfw: "Ðвтор пометил Ñту запиÑÑŒ как \"только Ð´Ð»Ñ Ð²Ð·Ñ€Ð¾Ñлых\". %{link}" - shared_with: "Ð”Ð»Ñ Ð°Ñпектов: %{aspect_names}" - show: "показать" - unlike: "Ðе нравитÑÑ" via: "через %{link}" via_mobile: "Ñ Ð¼Ð¾Ð±Ð¸Ð»ÑŒÐ½Ð¾Ð³Ð¾ уÑтройÑтва" - viewable_to_anyone: "Ðту запиÑÑŒ может видеть любой в интернете" simple_captcha: label: "Введите код в поле:" message: @@ -1259,23 +1018,12 @@ ru: status_messages: create: success: "УÑпешно упомÑнут: %{names}" - destroy: - failure: "Ðе удалоÑÑŒ удалить запиÑÑŒ" - helper: - no_message_to_display: "Ðовых Ñообщений нет." new: mentioning: "Упоминание: %{person}" too_long: "Будьте добры, Ñократите ваше Ñообщение до %{count} Ñимволов. Ðа данный момент Ñообщение ÑоÑтавлÑет %{current_length} Ñимволов" stream_helper: - hide_comments: "Скрыть вÑе комментарии" no_more_posts: "Ð’Ñ‹ доÑтигли конца потока." no_posts_yet: "Ещё нет ни одной запиÑи." - show_comments: - few: "Показать еще %{count} комментариÑ" - many: "Показать еще %{count} комментариев" - one: "Показать еще 1 комментарий" - other: "Показать еще %{count} комментариев" - zero: "Больше нет комментариев" streams: activity: title: "ÐœÐ¾Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚ÑŒ" @@ -1302,13 +1050,6 @@ ru: tags: title: "ЗапиÑи, отмеченные: %{tags}" tag_followings: - create: - failure: "Ошибка отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¼ÐµÑ‚ÐºÐ¸ #%{name}. Возможно, вы уже Ñледите за ней?" - none: "ÐÐµÐ»ÑŒÐ·Ñ Ñледить за пуÑтой меткой!" - success: "Ура! Теперь вы Ñледите за меткой #%{name}." - destroy: - failure: "Ðе вышло переÑтать Ñледить за меткой #%{name}. Возможно, вы уже отпиÑалиÑÑŒ от нее?" - success: "Увы! Ð’Ñ‹ больше не Ñледите за меткой #%{name}." manage: no_tags: "Ð’Ñ‹ не отÑлеживаете ни одной метки." title: "Управление отÑлеживаемыми метками" @@ -1316,7 +1057,6 @@ ru: name_too_long: "Будьте добры, уменьшите размер метки до %{count} Ñимволов. Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€ ÑоÑтавлÑет %{current_length} Ñимволов." show: follow: "Следить за #%{tag}" - following: "Ð’Ñ‹ Ñледите за меткой #%{tag}" none: "ПуÑÑ‚Ð°Ñ Ð¼ÐµÑ‚ÐºÐ° не ÑущеÑтвует!" stop_following: "Ðе Ñледить за #%{tag}" tagged_people: @@ -1325,8 +1065,6 @@ ru: one: "%{count} человек Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹ %{tag}" other: "%{count} человек Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹ %{tag}" zero: "Ðет ни одного человека Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹ %{tag}" - terms_and_conditions: "УÑÐ»Ð¾Ð²Ð¸Ñ Ð¾ÐºÐ°Ð·Ð°Ð½Ð¸Ñ ÑƒÑлуг" - undo: "Отменить?" username: "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ" users: confirm_email: @@ -1347,7 +1085,6 @@ ru: character_minimum_expl: "не менее шеÑти Ñимволов" close_account: dont_go: "ПожалуйÑта, не уходите!" - if_you_want_this: "ЕÑли вы дейÑтвительно хотите Ñто Ñделать, введите ваш пароль и нажмите 'Закрыть аккаунт'." lock_username: "Ðто зарезервирует ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ð° Ñлучай, еÑли вы захотите Ñнова зарегиÑтрироватьÑÑ." locked_out: "Будет произведён выход, и вы будете отключены от вашей учетной запиÑи." make_diaspora_better: "Мы хотели бы, чтобы вы помогли нам Ñделать диаÑпору* лучше вмеÑто того, чтобы проÑто уйти отÑюда. ЕÑли вы дейÑтвительно решили уйти, мы хотим, чтобы вы знали, что ÑлучитÑÑ Ð´Ð°Ð»ÑŒÑˆÐµ." @@ -1360,14 +1097,12 @@ ru: current_password_expl: "иÑпользуемый Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð°..." download_export: "Скачать данные из моего профилÑ" download_export_photos: "Загрузить мои фотографии" - download_photos: "Скачать мои фотографии" edit_account: "Изменить аккаунт" email_awaiting_confirmation: "Мы поÑлали ÑÑылку Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ð¸ на %{unconfirmed_email}. Пока вы не пройдете по ней и не активируете новый адреÑ, мы будем иÑпользовать ваш прежний Ñщик %{email}." export_data: "ÐкÑпорт информации" export_in_progress: "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð¼Ñ‹ обрабатываем ваши данные. Повторите попытку через неÑколько минут." export_photos_in_progress: "Ð’ данный момент мы обрабатываем ваши фотографии. Будьте добры, проверьте Ñнова через неÑколько минут." following: "ÐаÑтройки подпиÑок" - getting_started: "Ðовые пользовательÑкие наÑтройки" last_exported_at: "(ПоÑледнее обновление было %{timestamp})" liked: "кому-то понравилаÑÑŒ ваша запиÑÑŒ" mentioned: "вы были упомÑнуты в запиÑи" @@ -1394,7 +1129,6 @@ ru: connect_to_facebook_link: "Подключаем ваш Facebook аккаунт" hashtag_explanation: "Метки позволÑÑŽÑ‚ вам обÑуждать и Ñледить за интереÑующими Ð²Ð°Ñ Ñ‚ÐµÐ¼Ð°Ð¼Ð¸. Ðто также отличный ÑпоÑоб поиÑка единомышленников в диаÑпоре*." hashtag_suggestions: "Попробуйте Ñледующие метки, например #иÑкуÑÑтво, #art, #кино, #movies, #gif и Ñ‚. п." - saved: "Сохранено!" well_hello_there: "ПриветÑтвуем ваÑ!" what_are_you_in_to: "Чем вы интереÑуетеÑÑŒ?" who_are_you: "Кто вы?" @@ -1418,13 +1152,6 @@ ru: settings_updated: "ÐаÑтройки Ñохранены" unconfirmed_email_changed: "E-mail изменилÑÑ. Ðужна активациÑ." unconfirmed_email_not_changed: "Ошибка при изменении E-mail" - webfinger: - fetch_failed: "Ðе удалоÑÑŒ получить профиль Ð´Ð»Ñ %{profile_url}" - hcard_fetch_failed: "Возникла проблема при получении hcard Ð´Ð»Ñ %{account}" - no_person_constructed: "Ðи одна пользователь не может быть Ñобран из Ñтой hcard." - not_enabled: "webfinger не включен Ð´Ð»Ñ Ñ…Ð¾Ñта аккаунта %{account}" - xrd_fetch_failed: "Произошла ошибка при получении xrd Ñ %{account}" - welcome: "Добро пожаловать!" will_paginate: next_label: "вперед »" previous_label: "« назад" \ No newline at end of file diff --git a/config/locales/diaspora/sc.yml b/config/locales/diaspora/sc.yml index 615a991796a0352c89ce769a201a20e7cd2ec62a..52b2b399593c94aa20586ac36de965f70806c5ee 100644 --- a/config/locales/diaspora/sc.yml +++ b/config/locales/diaspora/sc.yml @@ -5,11 +5,8 @@ sc: - _applications: "Aplicos" - _comments: "Cummentos" + _applications: "Aplicatziones" _contacts: "Cuntatos" - _home: "Printzipale" - _photos: "Fotos" _services: "Servìtzios" account: "Contu" activerecord: @@ -40,29 +37,23 @@ sc: username: invalid: "no est bà lidu. Est possìbile impreare petzi lìteras, nùmeros, e underscores." taken: "est giai istadu pigadu." - ago: "%{time} fà ghet" all_aspects: "Totu sas caras" - application: - helper: - unknown_person: "Pessone disconnota" - video_title: - unknown: "Tìtulu vìdeo disconnotu" are_you_sure: "Seguru ses?" are_you_sure_delete_account: "Seguru ses de bòlere serrare su contu tuo? Custu non podet èssere annuddadu!" + aspect_memberships: + destroy: + failure: "No est istadu possìbile bogare sa pessone dae s'aspetu." + no_membership: "Sa pessone ischertada no est istada agatada in cussu aspetu." + success: "Sa pessone est istada bogada dae s'aspetu." aspects: add_to_aspect: failure: "Annanghidura de su cuntatu a sa cara faddida." success: "Annanghidura de su cuntatu a sa cara resissida." aspect_listings: add_an_aspect: "+ Annanghe una cara" - deselect_all: "Disischerta totu" - edit_aspect: "Modìfica %{name}" - select_all: "Ischerta totu" - contacts_not_visible: "Sos cuntatos de custa cara non s'ant a pòdere bìdere intre issos." - contacts_visible: "Sos cuntatos de custa cara s'ant a pòdere bìdere intre issos." - create: - failure: "Creatzione de sa cara non resissida." - success: "Sa cara tua noa %{name} est istada creada" + aspect_stream: + stay_updated: "Abarra agiornadu" + stay_updated_explanation: "In su flussu tuo bi sunt totu sos cuntatos tuos, sas etichetas chi sighis e sos messà gios pùblicos de sos membros prus creativos de sa comunidade." destroy: failure: "No est istadu possìbile bogare %{name}." success: "%{name} est istada bogada." @@ -70,26 +61,35 @@ sc: aspect_list_is_not_visible: "Sos cuntatos de custa cara non si podent bìdere intre issos." aspect_list_is_visible: "Sos cuntatos de custa cara si podent bìdere intre issos." confirm_remove_aspect: "Seguru ses de bòlere burrare custa cara?" - make_aspect_list_visible: "Boles chi sos cuntatos de custa cara s'ant a pòdere bìdere intre issos?" - remove_aspect: "Burra custa cara" rename: "Cà mbia nùmene" update: "Agiorna" updating: "Agiornande" index: donate: "Dona" - handle_explanation: "Custu est s'ID diaspora* tuo. Comente un'indiritzu de posta eletrònica, lu podes dare a sa gente pro ti fà ghere agatare." - no_tags: "+ Agata un'eticheta de sighire" - unfollow_tag: "Non sighire prus %{tag}" - new: - create: "Crea" - name: "Nùmene (lu podes bìere petzi tue)" + help: + do_you: "Boles..." + feature_suggestion: "propònnere una %{link}?" + find_a_bug: "sinnalare un'%{link}?" + have_a_question: "fà ghere una %{link}?" + here_to_help: "Sa comunidade de diaspora* est inoghe!" + need_help: "Tenes bisòngiu de agiudu?" + tag_bug: "errore" + tag_feature: "funtzionalidade" + tag_question: "pregunta" + introduce_yourself: "Custu est su flussu tuo. Brinca in intro e presenta·ti." + new_here: + follow: "Sighi %{link} e saluda sos impitadores noos de diaspora*!" + learn_more: "Àteras informatziones" + title: "Saluda sos impitadores noos" + services: + content: "Podes connètere custos servìtzios a diaspora*:" + heading: "Connessione a sos servìtzios" + welcome_to_diaspora: "Bene bènnidu in diaspora*, %{name}!" no_contacts_message: community_spotlight: "Prus de importu in sa comunidade" or_spotlight: "O podes cumpartzire cun %{link}" try_adding_some_more_contacts: "Podes chircare o invitare à teros cuntatos." you_should_add_some_more_contacts: "Dias dèpere annà nghere carchi cuntatu in prus!" - no_posts_message: - start_talking: "Perunu at galu naradu nudda!" seed: acquaintances: "Connoschentes" family: "Famìlia" @@ -98,20 +98,26 @@ sc: update: failure: "Sa cara tua, %{name}, tenet unu nùmene tropu longu pro èssere sarbada." success: "Sa cara tua, %{name}, est istada modificada." - back: "In dae segus" + bookmarklet: + explanation: "Pùblica in diaspora* dae totue annanghende %{link} a sos preferidos tuos." + post_something: "Pùblica in diaspora*" cancel: "Annudda" + comments: + new_comment: + comment: "Cummenta" + commenting: "Cummentende..." + contacts: + index: + start_a_conversation: "Incumintza un'arresonu" delete: "Burra" email: "P. eletr. (e-mail)" error_messages: helper: correct_the_following_errors_and_try_again: "Currege custos errore e torra a proare." - invalid_fields: "Campos non bà lidos" fill_me_out: "Iscrie inoghe" find_people: "Agata pessonas o #etichetas" - hide: "Cua" limited: "Limitadu" more: "Àteru" - next: "Imbeniente" no_results: "Perunu resurtadu agatadu" notifier: export_photos_email: @@ -122,23 +128,21 @@ sc: Saludos, Su robot de sa posta eletrònica de diaspora*! + private_message: + subject: "B'est unu messà giu privadu nou pro tie" nsfw: "NSFW (no est adatu pro unu logu de traballu)" ok: "AB" - or: "o" - password: "Crae (password)" - password_confirmation: "Cunfirma sa crae (password)" - previous: "Antepostu" privacy: "Privadesa" - privacy_policy: "Normativa pro sa privadesa" profile: "Profilu" public: "Pùblicu" + reactions: + one: "1 reatzione" + other: "%{count} reatziones" + zero: "Peruna reatzione" search: "Chirca" settings: "Impostatziones" - terms_and_conditions: "Tèrmines e cunditziones" - undo: "Annuddare?" username: "Nùmene impitadore" users: edit: download_export_photos: "Iscà rriga sas fotos meas" - export_photos_in_progress: "Semus elaborande sas fotos tuas. Pro piaghere torra a compidare intre pagu." - welcome: "Benènnidu!" \ No newline at end of file + export_photos_in_progress: "Semus elaborande sas fotos tuas. Pro piaghere torra a compidare intre pagu." \ No newline at end of file diff --git a/config/locales/diaspora/si.yml b/config/locales/diaspora/si.yml index ce96dd44c7f3d49cf5cf9a83ebe51a5e181b3217..398ff4552392201d18731151cc85153473faf8ad 100644 --- a/config/locales/diaspora/si.yml +++ b/config/locales/diaspora/si.yml @@ -5,9 +5,6 @@ si: - _comments: "ප්â€à¶»à¶à·’චà·à¶»" - _home: "නිවස" - _photos: "පින්à¶à·–ර" _services: "සේවà·à·€à¶±à·Š" account: "ගිණුම" activerecord: @@ -31,33 +28,18 @@ si: go: "යන්න" month: "මà·à·ƒà¶º" week: "à·ƒà¶à·’ය" - application: - helper: - unknown_person: "නà·à¶³à·”නන කෙනෙක්" - video_title: - unknown: "නà·à¶³à·”නන වීඩිය෠මà·à¶à·˜à¶šà·à·€à¶šà·’" are_you_sure: "ඔබට විà·à·Šà·€à·à·ƒà¶¯ ?" aspects: aspect_listings: add_an_aspect: "+ අංගයන් එක් කරන්න" - deselect_all: "සියල්ල නොසලක෠හරින්න" - edit_aspect: "%{name} සංස්කරණය කරන්න" - select_all: "සියල්ල à¶à·à¶»à¶±à·Šà¶±" - create: - failure: "අංගය à·ƒà·à¶¯à·“ම අසà·à¶»à·Šà¶®à¶šà¶ºà·’" - success: "ඔබගේ නව අංගයන් %{name} à·ƒà·à¶¯à¶± ලදී" destroy: failure: "%{name} හිස්ව නොපවà¶à·“ සහ ඉවà¶à·Š කිරීමට නොහà·à¶š." success: "%{name} à·ƒà·à¶»à·Šà¶®à¶šà·€ ඉවà¶à·Š කරන ලදී." edit: - remove_aspect: "මෙම අංගය මකà·à¶¯à¶¸à¶±à·Šà¶±" rename: "නà·à·€à¶ නම් කරන්න" update: "යà·à·€à¶à·Šà¶šà·à¶½ කරන්න" updating: "යà·à·€à¶à·Šà¶šà·à¶½ වෙමින් පවà¶à·“" index: - diaspora_id: - content_1: "මෙය ඔබගේ ඩයස්පà·à¶»à· ID එකයි:" - heading: "ඩයස්පà·à¶»à· ID එක" donate: "පරිà¶à·Šâ€à¶ºà·à¶œ කරන්න" help: here_to_help: "ඩයස්පà·à¶»à· ප්â€à¶»à¶¢à·à·€ මෙà¶à·à¶±à¶ºà·’ !" @@ -72,9 +54,6 @@ si: content: "ඔබට පහචසේවà·à·€à¶±à·Š Diaspora සමග සම්බන්ධ කරන්න පුළුවන්:" heading: "සේවà·à·€à¶±à·Š සම්බන්ධ කරන්න" welcome_to_diaspora: "ඩයස්පොර෠වෙà¶à·’න් ආයුබොවන්, %{name}!" - new: - create: "à·ƒà·à¶¯à¶±à·Šà¶±" - name: "නම (ඔබට පමණක් පෙනෙන)" seed: acquaintances: " ඇඳුනුම්කම්" family: "පවුල" @@ -83,15 +62,12 @@ si: update: failure: "ඔබගේ අංගය, %{name}, à·„à·’ නම save කිරීමට දිග à·€à·à¶©à·’යි." success: "ඔබගේ අංගය, %{name}, à·ƒà·à¶»à·Šà¶®à¶šà·€ නà·à·€à¶ සකසන ලදී." - back: "පිටුපසට" bookmarklet: heading: "පොà¶à·Š සලකුණ" comments: new_comment: comment: "ප්â€à¶»à¶à·’චà·à¶»à¶ºà¶šà·Š" commenting: "ප්â€à¶»à¶à·’චà·à¶» දක්වමින්..." - one: "එක් ප්â€à¶»à¶à·’චà·à¶»à¶ºà¶šà·Š" - zero: "ප්â€à¶»à¶à·’චà·à¶» නොමà·à¶" contacts: index: only_sharing_with_me: "ම෠සමග පමණක් share කර ඇà¶" @@ -101,7 +77,6 @@ si: fail: "පණිවිඩයක් වලංගු නà·à¶" sent: "පණිවිඩය යà·à·€à·Šà·€à·" index: - no_conversation_selected: "කිසිම සංවà·à¶¯à¶ºà¶šà·Š à¶à·à¶»à·à¶œà·™à¶± නà·à·„à·" no_messages: "පණිවිඩ නà·à¶" new: send: "යවන්න" @@ -115,90 +90,44 @@ si: delete: "මකන්න" email: "විද්â€à¶ºà·”à¶à·Š à¶à·à¶´à·‘ල" find_people: "පුද්ගයින් සෙවීම à·„à· #tags" - hide: "සගවන්න" invitations: a_facebook_user: "Facebook පරිà·à·“ලකයෙක්" create: - already_contacts: "ඔබ දà·à¶±à¶§à¶¸à¶à·Š මෙම පුද්ගලය෠සමග සම්බන්ධ වී සිටි." - already_sent: "ඔබ දà·à¶±à¶§à¶¸à¶à·Š මෙම පුද්ගලයà·à¶§ ආරà·à¶°à¶±à· කොට ඇà¶." no_more: "ඔබ à·ƒà¶à·”à·€ à¶à·€à¶à·Š අරà·à¶°à¶±à·à·€à¶±à·Š නà·à¶." - own_address: "ඔබට ඔබගේම ලිපිනයට අරà·à¶°à¶±à· යà·à·€à·’ය නොහà·à¶š." new: - aspect: "අංගය" invite_someone_to_join: "කà·à¶§ හරි ආරà·à¶°à¶±à· කරන්න ඩයසපà·à¶»à· සමග සම්බන්ධවන්න!" language: "භà·à·‚à·à·€" - personal_message: "පුද්ගලික පණිවිඩය" - resend: "නà·à·€à¶ යවන්න" send_an_invitation: "ආරà·à¶°à¶±à·à·€à¶šà·Š යවන්න" - send_invitation: "ආරà·à¶°à¶±à·à·€à¶šà·Š යවන්න" - to: "වෙà¶" layouts: application: back_to_top: "නà·à·€à¶ ඉහලට යන්න" whats_new: "අලුà¶à·’න් මොනවද?" header: - admin: "පරිපà·à¶½à¶š" - blog: "බ්ලොගය" code: "කේà¶à¶º" settings: "à·ƒà·à¶šà·ƒà·”ම්" - view_all: "සියල්ල පෙන්වන්න" - likes: - likes: - people_dislike_this: - one: "%{count} අකමà·à¶à·Šà¶à¶šà·Š" - other: "අකමà·à¶à·’ %{count} " - zero: "අකමà·à¶à·’ නà·à¶" - people_like_this: - one: "%{count} කà·à¶¸à·à¶à·Šà¶à¶šà·Š " - other: "කà·à¶¸à·à¶à·’ %{count}" - zero: "කà·à¶¸à·à¶à·’ නà·à¶" - people_like_this_comment: - one: "%{count} කà·à¶¸à·à¶à·Šà¶à¶šà·Š " - other: "කà·à¶¸à·à¶à·’ %{count}" - zero: "කà·à¶¸à·à¶à·’ නà·à¶" limited: "සීමිà¶à¶ºà·’" more: "à¶à·€à¶à·Š..." - next: "ඊළගට" no_results: "කිසිදු ප්â€à¶»à¶à·’ඵලයක් හමු නොවුණි." notifier: - accept_invite: "ඔබගේ ඩයස්පà·à¶»à·* ආරà·à¶°à·à¶±à·€ අනුමචකරන්න!" click_here: "මෙà¶à¶± click කරන්න" hello: "හෙල෠%{name}!" thanks: "ස්à¶à·”à¶à·’යි," nsfw: "NSFW" ok: "හරි" - or: "à·„à·" - password: "මුර පදය" people: index: no_results: "හලà·! ඔයà·à¶§ මොකක් හරි සෙවීමට අවà·à·Šâ€à¶ºà¶¯ ?" results_for: "සෙවුම් ප්â€à¶»à¶à·’ඵල සඳහà·" - one: "එක පුද්ගලයෙක්" - other: "පුද්ගලයින් %{count}" person: thats_you: "ඒ ඔබයි!" profile_sidebar: born: "උපන්දිනය" gender: "ලිංගභේදය" location: "ස්ථà·à¶±à¶º" - zero: "පුද්ගලයින් නà·à¶" photos: destroy: notice: "පින්à¶à·–රය ඉවà¶à·Š කරන ලදී." - new: - back_to_list: "නà·à·€à¶ ලà·à¶ºà·’ස්à¶à·”à·€ වෙà¶" - new_photo: "අලුà¶à·Š පින්à¶à·”රයක්" - show: - delete_photo: "පින්à¶à·”රය ඉවà¶à·Šà¶šà¶»à¶±à·Šà¶±" - update_photo: "පින්à¶à·”රය යà·à·€à¶à·Šà¶šà·à¶½à·“න කරන්න" - update: - notice: "පින්à¶à·–රය à·ƒà·à¶»à·Šà¶®à¶šà·€ යà·à·€à¶à·Šà¶šà·à¶½à·“න වන ලදී." - posts: - show: - destroy: "ඉවà¶à·Š කරන්න" - previous: "පෙර පිටුවට" privacy: "පෞද්ගලිකà¶à·Šà·€à¶º" - privacy_policy: "පෞද්ගලික ප්â€à¶»à¶à·’පà¶à·Šà¶à·’ය" profiles: edit: first_name: "මුල් නම" @@ -214,10 +143,6 @@ si: other: "ප්â€à¶»à¶à·’චà·à¶» %{count} " zero: "ප්â€à¶»à¶à·’චà·à¶» නà·à¶" registrations: - edit: - edit: "%{name} සංස්කරණය කරන්න" - unhappy: "අසà¶à·”ටෙන්ද ?" - update: "යà·à·€à¶à·Šà¶šà·à¶½à·“න කරන්න" new: enter_email: "email එක ඇà¶à·”ලà¶à·Š කරන්න" enter_password: "මුර පදයක් ඇà¶à·”ලà¶à·Š කරන්න ( අවම à·€à·à¶ºà·™à¶±à·Šà·€à¶à·Š අකුරු 6 ක් )" @@ -225,50 +150,28 @@ si: username: "පරිà·à·“ලක නà·à¶¸à¶º" search: "සෙවීම" services: - finder: - no_friends: "Facebook යහළුවන් සොය෠ගචනොහà·à¶š." - service_friends: "%{service} යහළුවන්" index: disconnect: "විසන්ධි කරන්න" edit_services: "සේවà·à·€à¶±à·Š නà·à·€à¶ සකසන්න" really_disconnect: "%{service} විසන්ධි කරන්නද?" - remote_friend: - invite: "ආරà·à¶°à¶±à· කරන්න" - not_on_diaspora: "à¶à·€à¶¸ Diaspora à¶à·”ල නà·à¶" - resend: "නà·à·€à¶ යවන්න" settings: "à·ƒà·à¶šà·ƒà·”ම්" shared: - add_contact: - create_request: "ඩයස්පà·à¶»à· ID එකෙන් සොයà·à¶œà¶±à·Šà¶±" - enter_a_diaspora_username: "ඩයස්පà·à¶»à· පරිà·à·“ලක නà·à¶¸à¶º ඇà¶à·”ලà¶à·Š කරන්න:" - your_diaspora_username_is: "මෙය ඔබගේ ඩයස්පà·à¶»à· පරිà·à·“ලක නà·à¶¸à¶ºà¶ºà·’ : %{diaspora_handle}" invitations: by_email: "email එකකින්" - from_facebook: "Facebook එකෙන්" - invitations_left: "%{count} ඉà¶à·”රුයි" - invite_someone: "කà·à¶§à·„රි ආරà·à¶°à¶±à· කරන්න" invite_your_friends: "ඔබේ මිà¶à·”රන්ට ආරà·à¶°à¶±à· කරන්න" invites: "ආරà·à¶°à¶±à· කළà·" public_explain: manage: "සම්බන්ධ සේවà·à·€à¶±à·Š කළමනà·à¶šà¶»à¶«à¶º කරන්න" publisher: - all: "සියල්ල" new_user_prefill: invited_by: "ආරà·à¶°à¶±à· කලà·à¶§ ස්à¶à·”à¶à·’යි, " stream_element: - dislike: "කමà¶à·’ නà·à¶" - like: "කà·à¶¸à¶à·’යි" - show: "පෙන්වන්න" - unlike: "අකà·à¶¸à¶à·’යි" via_mobile: "ජංගම දුරකථනය හරහà·" status_messages: create: success: "à·ƒà·à¶»à·Šà¶®à¶š ලෙස සදහන්කරà·: %{names}" - helper: - no_message_to_display: "පෙන්වීමට කිසිදු පනිවිඩයක් නà·à¶." new: mentioning: "සදහන්කරන්න: %{person}" - terms_and_conditions: "කොන්දේසි සහ à¶à¶à·Šà¶à·Šà·€à¶ºà¶±à·Š" username: "පරිà·à·Šâ€à¶»à·“ලක නම" users: edit: @@ -279,8 +182,6 @@ si: close_account: dont_go: "හලà·, කරුණà·à¶šà¶» යන්න එපà·!" current_password: "දà·à¶±à¶§ පවà¶à·’න මුරපදය" - download_photos: "මගේ පින්à¶à·–ර භà·à¶œà¶ කරන්න" - getting_started: "නව පරිà·à·“ලකගේ අභිරුචියන්" new_password: "නව මුරපදය" your_email: "ඔබගේ email" your_handle: "ඔබගේ ඩයස්පà·à¶»à· ID" @@ -289,5 +190,4 @@ si: privacy_settings: ignored_users: "ප්â€à¶»à¶à·’ක්ෂේපිචපරිà·à·“ලකයන්" stop_ignoring: "ප්â€à¶»à¶à·’ක්ෂේප කිරීම නවà¶à·Šà·€à¶±à·Šà¶±" - title: "පෞද්ගලිකà¶à·Šà·€ à·ƒà·à¶šà·ƒà·”ම්" - welcome: "ආයුබà·à·€à¶±à·Š!" \ No newline at end of file + title: "පෞද්ගලිකà¶à·Šà·€ à·ƒà·à¶šà·ƒà·”ම්" \ No newline at end of file diff --git a/config/locales/diaspora/sk.yml b/config/locales/diaspora/sk.yml index b94e4c2face97f2d915d57b13c1981f05c4c540a..9394322d158001ab05824ba125581dbd83617268 100644 --- a/config/locales/diaspora/sk.yml +++ b/config/locales/diaspora/sk.yml @@ -6,11 +6,8 @@ sk: _applications: "Aplikácie" - _comments: "Komentáre" _contacts: "Kontakty" _help: "Pomoc" - _home: "Domov" - _photos: "Fotky" _services: "Služby" account: "ÚÄet" activerecord: @@ -100,13 +97,7 @@ sk: other: "PoÄet nových použÃvateľov tento týždeň: %{count}" zero: "PoÄet nových použÃvateľov tento týždeň: žiaden" current_server: "Aktuálny dátum na serveri je %{date}" - ago: "pred %{time}" all_aspects: "VÅ¡etky kategórie" - application: - helper: - unknown_person: "Neznámy Älovek" - video_title: - unknown: "Neznámy názov videa" are_you_sure: "Si si istý(á)?" are_you_sure_delete_account: "UrÄite chceÅ¡ zruÅ¡iÅ¥ svoj úÄet? Potom sa to už nedá vrátiÅ¥ späť!" aspect_memberships: @@ -120,18 +111,10 @@ sk: success: "Kontakt bol úspeÅ¡ne pridaný do kategórie." aspect_listings: add_an_aspect: "+ PridaÅ¥ kategóriu" - deselect_all: "OdznaÄiÅ¥ vÅ¡etky" - edit_aspect: "UpraviÅ¥ %{name}" - select_all: "OznaÄiÅ¥ vÅ¡etky" aspect_stream: make_something: "Urob nieÄo" stay_updated: "Zostaň v obraze" stay_updated_explanation: "Na svojej hlavnej nástenke nájdeÅ¡ vÅ¡etky svoje kontakty, znaÄky, ktoré sledujeÅ¡, a prÃspevky od niektorých tvorivých Älenov komunity." - contacts_not_visible: "Kontakty v tejto kategórii sa nebudú môcÅ¥ navzájom vidieÅ¥." - contacts_visible: "Kontakty v tejto kategórii sa budú môcÅ¥ navzájom vidieÅ¥." - create: - failure: "Kategóriu sa nepodarilo vytvoriÅ¥." - success: "Nová kategória %{name} bola vytvorená" destroy: failure: "Kategória %{name} sa nedá odstrániÅ¥." success: "Použ. %{name} bol úspeÅ¡ne odstránený." @@ -139,25 +122,15 @@ sk: aspect_list_is_not_visible: "Ľudia v tejto kategórii sa nevida" aspect_list_is_visible: "Kontakty v tejto kategórii sú navzájom viditeľné" confirm_remove_aspect: "Si si istý(á), že chceÅ¡ zmazaÅ¥ túto kategóriu?" - make_aspect_list_visible: "PovoliÅ¥, aby sa kontakty v tejto kategórii navzájom videli?" - remove_aspect: "ZmazaÅ¥ túto kategóriu" rename: "PremenovaÅ¥" - set_visibility: "NastaviÅ¥ viditeľnosÅ¥" update: "AktualizovaÅ¥" updating: "Aktualizuje sa" index: - diaspora_id: - content_1: "Tvoje ID na diasporu* je:" - content_2: "Daj ho hocikomu a bude Å¥a môcÅ¥ nájsÅ¥ na diaspore*." - heading: "ID na diasporu*" donate: "PrispieÅ¥" - handle_explanation: "Toto je tvoje ID na diasporu*. MôžeÅ¡ ho daÅ¥ ostatným ľuÄom ako e-mailovú adresu, aby sa s tebou mohli spojiÅ¥." help: any_problem: "Nejaký problém?" contact_podmin: "Kontaktuj administrátora svojho podu." do_you: "Povedz:" - email_feedback: "Ak ti to vyhovuje viac, svoje podnety nám môžeÅ¡ poslaÅ¥ na %{link}" - email_link: "E-mail" feature_suggestion: "... máš nápad na novú %{link}?" find_a_bug: "... naÅ¡iel (-Å¡la) si %{link}?" have_a_question: "... máš %{link}?" @@ -170,31 +143,20 @@ sk: tutorial_link_text: "Návody" tutorials_and_wiki: "%{faq}, %{tutorial} a %{wiki}: pomoc pri prvých krokoch." introduce_yourself: "Toto je tvoja nástenka. Predstav sa." - keep_diaspora_running: "Udrž vývoj Diaspory mesaÄným prÃspevkom v rýchlom tempe!" keep_pod_running: "Udrž %{pod} v rýchlom tempe a kúp serverom mesaÄným prÃspevkom kávu vo forme opráv!" new_here: follow: "Sleduj %{link} a privÃtaj nových použÃvateľov na Diaspore*!" learn_more: "ZistiÅ¥ viac" title: "PrivÃtaj nových použÃvateľov" - no_contacts: "Žiadne kontakty" - no_tags: "+ Nájdi znaÄku, ktorú chceÅ¡ sledovaÅ¥" - people_sharing_with_you: "Ľudia, s ktorými si v kontakte" - post_a_message: "PoslaÅ¥ správu >>" services: content: "S diasporou* môžeÅ¡ prepojiÅ¥ tieto služby:" heading: "PripojiÅ¥ sa k službám" - unfollow_tag: "PrestaÅ¥ sledovaÅ¥ #%{tag}" welcome_to_diaspora: "Vitaj na diaspore*, %{name}!" - new: - create: "VytvoriÅ¥" - name: "Meno (uvidÃÅ¡ ho iba ty)" no_contacts_message: community_spotlight: "Aktuality z komunity" or_spotlight: "Alebo si do kontaktov môžeÅ¡ pridaÅ¥ použÃvateľov %{link}" try_adding_some_more_contacts: "MôžeÅ¡ nájsÅ¥ alebo pozvaÅ¥ viac ľudÃ." you_should_add_some_more_contacts: "Mal(a) by si eÅ¡te pridaÅ¥ pár kontaktov!" - no_posts_message: - start_talking: "Nikto eÅ¡te niÄ nepovedal!" seed: acquaintances: "Známi" family: "Rodina" @@ -203,7 +165,6 @@ sk: update: failure: "Tvoja kategória %{name} má prÃliÅ¡ dlhý názov." success: "ÚspeÅ¡ne si upravil(a) kategóriu %{name}." - back: "Späť" blocks: create: failure: "Tohto použÃvateľa nemôžem ignorovaÅ¥. #evasion" @@ -215,21 +176,14 @@ sk: explanation: "PrÃspevky na diasporu* môžeÅ¡ pÃsaÅ¥ z hocikiaľ cez záložku s týmto odkazom => %{link}." heading: "Bookmarklet" post_something: "PoslaÅ¥ na diasporu*" - post_success: "Odoslané! Zatvára sa!" cancel: "ZruÅ¡iÅ¥" comments: new_comment: comment: "OkomentovaÅ¥" commenting: "Posiela sa komentár..." - one: "1 komentár" - other: "%{count} komentárov" - zero: "Žiadne komentáre" contacts: - create: - failure: "Nepodarilo sa vytvoriÅ¥ kontakt" index: add_a_new_aspect: "PridaÅ¥ novú kategóriu" - add_to_aspect: "PridaÅ¥ kontakty do kategórie %{name}" all_contacts: "VÅ¡etky kontakty" community_spotlight: "Aktuality z komunity" my_contacts: "Moje kontakty" @@ -238,36 +192,20 @@ sk: only_sharing_with_me: "Ľudia, ktorà majú v kontaktoch iba mňa" start_a_conversation: "ZaÄaÅ¥ rozhovor" title: "Kontakty" - your_contacts: "Tvoje kontakty" - sharing: - people_sharing: "Ľudia, ktorà vás majú v kontaktoch:" spotlight: community_spotlight: "Aktuality z komunity" suggest_member: "Navrhnúť Älena" conversations: - conversation: - participants: "ÚÄastnÃci" create: fail: "Neplatná správa" no_contact: "Pozor, najprv treba pridaÅ¥ kontakt!" sent: "Správa odoslaná" - helper: - new_messages: - few: "%{count} nové správy" - many: "%{count} nových správ" - one: "1 nová správa" - other: "%{count} nových správ" - two: "%{count} nové správy" - zero: "Žiadne nové správy" index: conversations_inbox: "Rozhovory – PoÅ¡tová schránka" - create_a_new_conversation: "zaÄaÅ¥ nový rohovor" inbox: "PoÅ¡tová schránka" new_conversation: "Nový rozhovor" - no_conversation_selected: "Nevybral(a) si žiaden rozhovor" no_messages: "Žiadne správy" new: - abandon_changes: "ZruÅ¡iÅ¥ zmeny?" send: "PoslaÅ¥" sending: "Posiela sa..." subject: "Vec" @@ -288,10 +226,6 @@ sk: error_messages: helper: correct_the_following_errors_and_try_again: "Oprav nasledujúce chyby a skús to znova." - invalid_fields: "Neplatné polia" - login_try_again: "ProsÃm, <a href='%{login_link}'>prihlás sa</a> a skús to znova." - post_not_public: "PrÃspevok, ktorý sa snažÃÅ¡ zobraziÅ¥, nie je verejný!" - post_not_public_or_not_exist: "PrÃspevok, ktorý chcete zobraziÅ¥, nie je verejný alebo neexistuje." fill_me_out: "Vyplň formulár, prosÃm" find_people: "NájsÅ¥ ľudà alebo #znaÄky" help: @@ -383,46 +317,28 @@ sk: tutorial: "návod" tutorials: "návody" wiki: "wiki" - hide: "SchovaÅ¥" - ignore: "IgnorovaÅ¥" - invitation_codes: - excited: "%{name} Å¥a tu rád/rada vidÃ" invitations: a_facebook_user: "PoužÃvateľ(ka) Facebooku" check_token: not_found: "ÄŒÃslo pozvánky sa nenaÅ¡lo" create: - already_contacts: "Tohto Äloveka si už kontaktoval(a)." - already_sent: "Tohto Äloveka si už pozval(a)." empty: "Zadajte, prosÃm, aspoň jednu e-mailovú adresu." no_more: "Nemáš žiadne nové pozvánky." note_already_sent: "Pozvánky už boli odoslané na adresy: %{emails}" - own_address: "NemôžeÅ¡ poslaÅ¥ pozvánku na svoju vlastnú adresu." rejected: "S týmito adresami sa vyskytli problémy: " sent: "Pozvánky boli odoslané na adresy: %{emails}" - edit: - accept_your_invitation: "PrijaÅ¥ pozvanie" - your_account_awaits: "Tvoj úÄet Äaká!" new: - already_invited: "TÃto ľudia neprijali tvoje pozvanie:" - aspect: "Kategória" - check_out_diaspora: "Vyskúšaj diasporu*!" codes_left: few: "Pre tento kód zostali %{count} pozvánky" one: "Pre tento kód zostala %{count} pozvánka" other: "Pre tento kód zostalo %{count} pozvánok" zero: "Pre tento kód zostalo %{count} pozvánok" comma_separated_plz: "MôžeÅ¡ zadaÅ¥ viac e-mailových adries oddelených Äiarkami." - if_they_accept_info: "Po prijatà pozvánky budú pozvanà použÃvatelia pridanà do prÃsluÅ¡nej kategórie." invite_someone_to_join: "Pozvi niekoho na diasporu*!" language: "Jazyk" paste_link: "Podeľ sa o tento odkaz s priateľmi a pozvi ich na Diasporu* alebo im ho poÅ¡li rovno na e-mail." - personal_message: "Súkromná správa" - resend: "PreposlaÅ¥" send_an_invitation: "PoslaÅ¥ pozvánku" - send_invitation: "PoslaÅ¥ pozvánku" sending_invitation: "Posiela sa pozvánka..." - to: "PrÃjemcovia" layouts: application: back_to_top: "Späť nahor" @@ -431,38 +347,13 @@ sk: source_package: "stiahnuÅ¥ balÃk so zdrojovým kódom" toggle: "Prepnúť (na) mobilnú verziu" whats_new: "ÄŒo je nové?" - your_aspects: "Tvoje kategórie" header: - admin: "Správca" - blog: "Blog" code: "Kód" - help: "Pomoc" - login: "PrihlásiÅ¥ sa" logout: "OdhlásiÅ¥ sa" profile: "Profil" - recent_notifications: "NajnovÅ¡ie oznamy" settings: "Nastavenia" - view_all: "ZobraziÅ¥ vÅ¡etko" - likes: - likes: - people_dislike_this: - few: "%{count} ľuÄom sa to nepáÄi" - one: "%{count} Äloveku sa to nepáÄi" - other: "%{count} ľuÄom sa to nepáÄi" - zero: "nikto neoznaÄil, že sa mu to nepáÄi" - people_like_this: - few: "%{count} ľuÄom sa páÄi" - one: "%{count} Äloveku sa páÄi" - other: "%{count} ľuÄom sa páÄi" - zero: "Nikomu sa nepáÄi" - people_like_this_comment: - few: "%{count} ľuÄom sa páÄi" - one: "%{count} Äloveku sa páÄi" - other: "%{count} ľuÄom sa páÄi" - zero: "nikomu sa nepáÄi" limited: "Vyhradený" more: "Viac" - next: "ÄŽalej" no_results: "Žiadne výsledky sa nenaÅ¡li" notifications: also_commented: @@ -480,14 +371,6 @@ sk: one: "%{actors} okomentoval(a) tvoj prÃspevok %{post_link}." other: "%{actors} okomentovali tvoj prÃspevok %{post_link}." zero: "%{actors} ľudà okomentovalo tvoj prÃspevok %{post_link}." - helper: - new_notifications: - few: "%{count} nové oznamy" - many: "%{count} nových oznamov" - one: "1 nový oznam" - other: "%{count} nových oznamov" - two: "%{count} nové oznamy" - zero: "Žiadne nové oznamy" index: all_notifications: "VÅ¡etky oznamy" and: "a" @@ -546,7 +429,6 @@ sk: zero: "%{actors} si Å¥a pridalo do kontaktov." notifier: a_post_you_shared: "prÃspevok." - accept_invite: "Odsúhlas svoju pozvánku na Diasporu*!" click_here: "Klikni sem" comment_on_post: reply: "ZobraziÅ¥ prÃspevok použ. %{name} alebo naň odpovedaÅ¥ >" @@ -576,7 +458,6 @@ sk: liked: "%{name} oznaÄil(a), že sa mu (jej) páÄi tvoj prÃspevok" view_post: "ZobraziÅ¥ prÃspevok >" mentioned: - mentioned: "vás spomenul(a) v prÃspevku:" subject: "%{name} Å¥a spomenul(a) na Diaspore*" private_message: reply_to_or_view: "ZobraziÅ¥ tento rozhovor alebo sa doň zapojiÅ¥ >" @@ -594,19 +475,9 @@ sk: to_change_your_notification_settings: "a budeÅ¡ môcÅ¥ zmeniÅ¥ nastavenia oznamov" nsfw: "Nevhodné v práci" ok: "OK" - or: "alebo" - password: "Heslo" - password_confirmation: "Potvrdenie hesla" people: add_contact: invited_by: "Pozval(a) vás" - add_contact_small: - add_contact_from_tag: "PridaÅ¥ kontakt zo znaÄky" - aspect_list: - edit_membership: "ZmeniÅ¥ kategóriu" - helper: - is_sharing: "%{name} sa s Tebou o nieÄo delÃ" - results_for: "výsledky pre %{params}" index: couldnt_find_them: "Nevedeli ste ich nájsÅ¥?" looking_for: "Hľadáš prÃspevky oznaÄené znaÄkou %{tag_link}?" @@ -616,86 +487,36 @@ sk: search_handle: "Na to, aby ste sa uistili, že nájdete svojich kamarátov, použite ich ID na diasporu*" searching: "hľadá sa, prosÃm buÄ trpezlivý (-á)." send_invite: "Stále niÄ? PoÅ¡lite pozvánku." - one: "1 Älovek" - other: "%{count} ľudÃ" person: - add_contact: "PridaÅ¥ kontakt" - already_connected: "Už pripojené" - pending_request: "ÄŒakajúca žiadosÅ¥" thats_you: "To si ty!" profile_sidebar: bio: "NieÄo o tebe" born: "Narodeniny" - edit_my_profile: "UpraviÅ¥ si profil" gender: "Pohlavie" - in_aspects: "V kategóriách" location: "Bydlisko" - photos: "Fotky" - remove_contact: "OdstrániÅ¥ kontakt" - remove_from: "OdstrániÅ¥ použÃvateľa %{name} z kategórie %{aspect}?" show: closed_account: "Tento úÄet bol zruÅ¡ený." does_not_exist: "Tento Älovek neexistuje!" has_not_shared_with_you_yet: "%{name} sa s tebou eÅ¡te nepodelil(a) o žiadne prÃspevky!" - ignoring: "IgnorujeÅ¡ vÅ¡etky prÃspevky, ktoré vytvoril(a) %{name}." - incoming_request: "%{name} si Å¥a chce pridaÅ¥ do kontaktov" - mention: "Zmienka" - message: "Správa" - not_connected: "S týmto Älovekom sa o niÄ nedelÃÅ¡" - recent_posts: "NajnovÅ¡ie prÃspevky" - recent_public_posts: "NajnovÅ¡ie verejné prÃspevky" - return_to_aspects: "VrátiÅ¥ sa na stránku s kategóriami" - see_all: "ZobraziÅ¥ vÅ¡etko" - start_sharing: "PridaÅ¥ do kontaktov" - to_accept_or_ignore: "prijaÅ¥ alebo ignorovaÅ¥." - sub_header: - add_some: "Pridaj si nejaké" - edit: "UpraviÅ¥" - you_have_no_tags: "Nemáš žiadne znaÄky!" - webfinger: - fail: "PrepáÄ, %{handle} sa nedá nájsÅ¥." - zero: "Žiadni ľudia" photos: - comment_email_subject: "fotka použ. %{name}" create: integrity_error: "Nepodarilo sa nahraÅ¥ fotku. Si si istý (-á), že ten súbor bol obrázok?" runtime_error: "Nepodarilo sa nahraÅ¥ fotku. UrÄite máš zapnutý bezpeÄnostný pás? :)" type_error: "Nepodarilo sa nahraÅ¥ fotku. UrÄite si pridal(a) obrázok?" destroy: notice: "Fotka zmazaná." - edit: - editing: "Upravuje sa" - new: - back_to_list: "Späť na zoznam" - new_photo: "Nová fotka" - post_it: "PoÅ¡li to!" new_photo: empty: "Súbor {file} je prázdny; vyber, prosÃm, znova vÅ¡etky súbory okrem tohto." invalid_ext: "Súbor {file} má neplatnú prÃponu. Povolené sú len prÃpony {extensions}." size_error: "Súbor {file} je prÃliÅ¡ veľký, maximálna povolená veľkosÅ¥ je {sizeLimit}." new_profile_photo: - or_select_one_existing: "alebo si vyber jednu z fotiek, ktoré už existujú %{photos}" upload: "NahraÅ¥ novú profilovú fotku!" - photo: - view_all: "zobraziÅ¥ vÅ¡etky fotky použ. %{name}" show: - collection_permalink: "trvalý odkaz na kolekciu" - delete_photo: "ZmazaÅ¥ fotku" - edit: "UpraviÅ¥" - edit_delete_photo: "UpraviÅ¥ popis fotky/zmazaÅ¥ fotku" - make_profile_photo: "VytvoriÅ¥ profilovú fotku" show_original_post: "ZobraziÅ¥ pôvodný prÃspevok" - update_photo: "AktualizovaÅ¥ fotku" - update: - error: "Nepodarilo sa upraviÅ¥ fotku." - notice: "Fotka bola úspeÅ¡ne aktualizovaná." posts: presenter: title: "PrÃspevok, ktorý napÃsal(a) %{name}" show: - destroy: "OdstrániÅ¥" - not_found: "PrepáÄ, ten prÃspevok sme nenaÅ¡li." - permalink: "Trvalý odkaz" photos_by: few: "%{count} fotiek, ktoré nahral(a) %{author}" many: "%{count} fotiek, ktoré nahral(a) %{author}" @@ -704,14 +525,11 @@ sk: two: "Dve fotky, ktoré nahral(a) %{author}" zero: "Žiadne fotky, ktoré nahral(a) %{author}" reshare_by: "Znova ukázal(a) prÃspevok %{author}" - previous: "Dozadu" privacy: "Ochrana súkromia" - privacy_policy: "Ochrana súkromia" profile: "Profil" profiles: edit: allow_search: "UmožniÅ¥ ostatným ľuÄom, aby Å¥a naÅ¡li na diaspore*" - edit_profile: "UpraviÅ¥ profil" first_name: "Krstné meno" last_name: "Priezvisko" nsfw_check: "OznaÄiÅ¥ vÅ¡etko, Äo ukazujem ako NSFW" @@ -723,8 +541,6 @@ sk: your_location: "Tvoje bydlisko" your_name: "Tvoje meno" your_photo: "Tvoja fotka" - your_private_profile: "Tvoj verejný profil" - your_public_profile: "Tvoj verejný profil" your_tags: "NapÃÅ¡ o sebe 5 slov" your_tags_placeholder: "Ako #filmy #maÄiatka #cestovanie #uÄiteľ #newyork" update: @@ -740,26 +556,16 @@ sk: closed: "Registrácie sú na tomto serveri diaspory* pozastavené." create: success: "Pridal(a) si sa k diaspore*!" - edit: - cancel_my_account: "ZruÅ¡iÅ¥ úÄet" - edit: "UpraviÅ¥ %{name}" - leave_blank: "(ak to nechceÅ¡ zmeniÅ¥, nevypĺňaj toto pole)" - password_to_confirm: "(na potvrdenie zmien budeme potrebovaÅ¥ tvoje heslo)" - unhappy: "Si neÅ¡Å¥astný (-á)?" - update: "AktualizovaÅ¥" invalid_invite: "Odkaz na pozvánku, ktorý si zadal(a), už nie je platný!" new: - create_my_account: "Založ si úÄet!" email: "E-MAIL" enter_email: "Zadaj svoju e-mailovú adresu" enter_password: "Zadaj heslo (minimálne Å¡esÅ¥ znakov)" enter_password_again: "Zadaj rovnaké heslo ako predtým" enter_username: "Zadaj použÃvateľské meno (iba pÃsmená, ÄÃslice a podÄiarkovnÃky)" - join_the_movement: "Pripoj sa k hnutiu!" password: "HESLO" password_confirmation: "POTVRDENIE HESLA" sign_up: "ZAREGISTROVAŤ SA" - sign_up_message: "Prepojenie ostatných sociálnych sietà s ♥" submitting: "Posiela sa..." username: "POUŽÃVATEĽ" report: @@ -771,40 +577,12 @@ sk: reported_label: "<b>Nahlásil(a)</b> %{person}" review_link: "OznaÄiÅ¥ ako skontrolované" title: "Prehľad správ" - requests: - create: - sending: "Posiela sa" - sent: "Niekto Å¥a poprosil, aby si nieÄo ukázal(a) použ. %{name}. Mal by to uvidieÅ¥, keÄ sa nabudúce prihlási na diasporu*." - destroy: - error: "Vyberte, prosÃm, kategóriu!" - ignore: "Ignorované žiadosti o priateľstvo." - success: "Teraz máte na seba kontakt." - helper: - new_requests: - few: "%{count} nové žiadosti!" - one: "Nová žiadosÅ¥!" - other: "%{count} nových žiadostÃ!" - zero: "Žiadne nové žiadosti" - manage_aspect_contacts: - existing: "Existujúce kontakty" - manage_within: "RiadiÅ¥ kontakty v" - new_request_to_person: - sent: "Odoslané!" reshares: comment_email_subject: "%{resharer} znova ukázal(a) prÃspevok použ. %{author} priateľom" - create: - failure: "Pri pokuse znova sa podeliÅ¥ o tento prÃspevok nastala chyba." reshare: deleted: "Pôvodný prÃspevok vymazal(a) jeho autor(ka)." - reshare: - few: "%{count} ľudia znova ukázali prÃspevok priateľom" - one: "1 Älovek znova ukázal prÃspevok svojim priateľom" - other: "%{count} ľudà znova ukázalo prÃspevok priateľom" - zero: "Znova ukázaÅ¥ prÃspevok" reshare_confirmation: "ChceÅ¡ sa znova podeliÅ¥ o prÃspevok, ktorý napÃsal(a) %{author}?" - reshare_original: "Originál znova ukázaÅ¥ priateľom" reshared_via: "Znova zverejnené cez" - show_original: "ZobraziÅ¥ originál" search: "Vyhľadávanie" services: create: @@ -815,60 +593,25 @@ sk: success: "Overenie totožnosti úspeÅ¡ne vymazané." failure: error: "Pri pripájanà k službe nastala chyba" - finder: - fetching_contacts: "diaspora* pridáva údaje o tvojich priateľoch zo siete %{service}, prosÃm, vráť sa sem o niekoľko minút." - no_friends: "Žiadni priatelia z Facebooku sa nenaÅ¡li." - service_friends: "Priatelia zo siete %{service}" index: disconnect: "OdpojiÅ¥ sa" edit_services: "UpraviÅ¥ pripojenie na služby" logged_in_as: "Prihlásil(a) si sa ako %{nickname}" really_disconnect: "ChceÅ¡ sa odpojiÅ¥ zo služby %{service}?" services_explanation: "Pripojenie k službám Ti umožňuje publikovaÅ¥ na nich prÃspevky, len Äo ich napÃÅ¡eÅ¡ na Diasporu*." - inviter: - click_link_to_accept_invitation: "Ak chcete prijaÅ¥ pozvanie, kliknite na tento odkaz" - join_me_on_diaspora: "PridaÅ¥ sa k Diaspore*" - remote_friend: - invite: "PozvaÅ¥" - not_on_diaspora: "EÅ¡te nie je na diaspore*" - resend: "PreposlaÅ¥" settings: "Nastavenia" - share_visibilites: - update: - post_hidden_and_muted: "PrÃspevok, ktorý vytvoril(a) %{name}, je schovaný a neposielajú sa ani oznamy" - see_it_on_their_profile: "Ak si chceÅ¡ preÄÃtaÅ¥ novÅ¡ie verzie tohto prÃspevku, navÅ¡tÃv stránku s profilom použ. %{name}." shared: - add_contact: - add_new_contact: "PridaÅ¥ nový kontakt" - create_request: "NájsÅ¥ podľa ID na diasporu*" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Zadaj použÃvateľské meno na diasporu*:" - know_email: "Poznáš túto adresu? MôžeÅ¡ na ňu poslaÅ¥ pozvánku." - your_diaspora_username_is: "Tvoje použÃvateľské meno na diasporu* je %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "PridaÅ¥ kontakt" toggle: few: "V(o) %{count} kategóriách" one: "V %{count} kategórii" other: "V(o) %{count} kategóriách" zero: "PridaÅ¥ kontakt" - contact_list: - all_contacts: "VÅ¡etky kontakty" - footer: - logged_in_as: "Prihlásil(a) si sa ako %{name}" - your_aspects: "Tvoje kategórie" invitations: by_email: "e-mailom" - dont_have_now: "Momentálne už nemáš žiadnu pozvánku, ale ÄalÅ¡ie Äoskoro prÃdu!" - from_facebook: "z Facebooku" - invitations_left: "ostáva(jú) %{count}" - invite_someone: "PozvaÅ¥ niekoho" invite_your_friends: "Pozvi svojich priateľov" invites: "Pozvánky" - invites_closed: "Pozývanie je na tomto serveri diaspory* momentálne pozastavené" share_this: "Podeľ sa o tento odkaz cez e-mail, blog alebo obľúbenú sociálnu sieÅ¥!" - notification: - new: "Nový %{type} od použ. %{from}" public_explain: atom_feed: "Zdroj RSS Atom" control_your_audience: "KontrolovaÅ¥ publikum" @@ -880,45 +623,22 @@ sk: title: "NastaviÅ¥ pripojené služby" visibility_dropdown: "Na zmenu viditeľnosti svojho prÃspevku použi toto rozbaľovacie menu. (Navrhujeme, aby bol tento prvý prÃspevok verejný.)" publisher: - all: "VÅ¡etko" - all_contacts: "VÅ¡etky kontakty" discard_post: "VymazaÅ¥ prÃspevok" formatWithMarkdown: "Na formátovanie svojho prÃspevku môžeÅ¡ použiÅ¥ %{markdown_link}" get_location: "VypÃsaÅ¥ tvoju polohu" - make_public: "ZverejniÅ¥" new_user_prefill: hello: "Hej, vÅ¡etci, som #%{new_user_tag}. " i_like: "ZaujÃma ma %{tags}." invited_by: "VÄaka za pozvanie, " newhere: "NováÄik" - poll: - question: "Otázka" - post_a_message_to: "PoslaÅ¥ správu na %{aspect}" posting: "Posiela sa..." - preview: "Ukážka" - publishing_to: "Publikuje sa na: " remove_location: "OdstrániÅ¥ umiestnenie" share: "UverejniÅ¥" - share_with: "podeliÅ¥ sa s" upload_photos: "NahraÅ¥ fotky" whats_on_your_mind: "Na Äo myslÃÅ¡?" - reshare: - reshare: "Znovu zdieľaÅ¥" stream_element: - connect_to_comment: "Pripoj sa k tomuto použÃvateľovi a okomentuj jeho prÃspevok" - currently_unavailable: "Momentálne sa nedajú pÃsaÅ¥ komentáre" - dislike: "NepáÄi sa mi to" - hide_and_mute: "SchovaÅ¥ prÃspevok a vypnúť oznamy" - ignore_user: "IgnorovaÅ¥ použ. %{name}" - ignore_user_description: "IgnorovaÅ¥ použ. a odstrániÅ¥ ho (ju) zo vÅ¡etkých kategóriÃ?" - like: "PáÄi sa mi to" - nsfw: "Autor(ka) oznaÄil(a) tento prÃspevok za nevhodný v práci. %{link}" - shared_with: "Na vedomie: %{aspect_names}" - show: "ZobraziÅ¥" - unlike: "Už sa mi to nepáÄi" via: "na %{link}" via_mobile: "mobilom" - viewable_to_anyone: "Tento prÃspevok si môže pozrieÅ¥ každý na webe" simple_captcha: label: "Do poľa zadajte kód:" message: @@ -927,20 +647,9 @@ sk: status_messages: create: success: "ÚspeÅ¡ne sa spomÃna: %{names}" - destroy: - failure: "Nepodarilo sa zmazaÅ¥ prÃspevok" - helper: - no_message_to_display: "Žiadna správa na zobrazenie." new: mentioning: "SpomÃna sa: %{person}" too_long: "ProsÃm, skráť svoju správu v statuse na menej ako %{count} znakov. Momentálne má %{current_length} znakov." - stream_helper: - hide_comments: "schovaÅ¥ komentáre" - show_comments: - few: "ZobraziÅ¥ ÄalÅ¡ie %{count} komentáre" - one: "ZobraziÅ¥ eÅ¡te %{count} komentár" - other: "ZobraziÅ¥ ÄalÅ¡Ãch %{count} komentárov" - zero: "Žiadne ÄalÅ¡ie komentáre nie sú" streams: activity: title: "Moja aktivita" @@ -966,22 +675,11 @@ sk: title: "Verejná aktivita" tags: title: "PrÃspevky so znaÄkami: %{tags}" - tag_followings: - create: - failure: "Nedá sa sledovaÅ¥ #%{name}. NesledujeÅ¡ to už?" - none: "NemôžeÅ¡ sledovaÅ¥ prázdnu znaÄku!" - success: "Hurá! Teraz sledujeÅ¡ #%{name}." - destroy: - failure: "Nepodarilo sa zruÅ¡iÅ¥ sledovanie #%{name}. Možno si to už prestal(a) sledovaÅ¥." - success: "No! Už viac nesledujeÅ¡ #%{name}." tags: show: follow: "SledovaÅ¥ #%{tag}" - following: "SledujeÅ¡ #%{tag}" none: "Prázdna znaÄka neexistuje!" stop_following: "PrestaÅ¥ sledovaÅ¥ #%{tag}" - terms_and_conditions: "Podmienky" - undo: "VrátiÅ¥ zmeny?" username: "PoužÃvateľské meno" users: confirm_email: @@ -1002,7 +700,6 @@ sk: character_minimum_expl: "musà maÅ¥ aspoň 6 znakov" close_account: dont_go: "ProsÃm, neodchádzaj!" - if_you_want_this: "Ak to naozaj chceÅ¡, dole napÃÅ¡te svoje heslo a klikni na tlaÄidlo „ZruÅ¡iÅ¥ úÄet“" lock_username: "Takto si rezervujeÅ¡ svoje použÃvateľské meno pre prÃpad, že by si sa rozhodol (-la) znova sa zaregistrovaÅ¥." locked_out: "OdhlásiÅ¡ a zamkneÅ¡ svoj úÄet." make_diaspora_better: "Chceme, aby si nám pomohol (-la) vylepÅ¡iÅ¥ Diasporu, a tak by si nám mal(a) pomôcÅ¥ namiesto odchodu. Ak chceÅ¡ odÃsÅ¥, chceme, aby si vedel(a), Äo sa bude diaÅ¥ Äalej." @@ -1013,12 +710,10 @@ sk: comment_on_post: "...niekto okomentuje tvoj prÃspevok?" current_password: "SúÄasné heslo" current_password_expl: "s ktorým sa prihlasujeÅ¡." - download_photos: "StiahnuÅ¥ si fotky" edit_account: "UpraviÅ¥ úÄet" email_awaiting_confirmation: "Poslali sme ti odkaz na aktiváciu %{unconfirmed_email}. Kým neklikneÅ¡ na tento odkaz a neaktivujeÅ¡ si novú adresu, budeme stále použÃvaÅ¥ tvoju pôvodnú adresu %{email}." export_data: "ExportovaÅ¥ dáta" following: "Nastavenia sledovania" - getting_started: "Nové predvoľby týkajúce sa použÃvateľa" liked: "...sa niekomu zapáÄi tvoj prÃspevok?" mentioned: "...Å¥a niekto spomenie v prÃspevku?" new_password: "Nové heslo" @@ -1038,7 +733,6 @@ sk: connect_to_facebook_link: "pripojenÃm tvojho úÄtu na Facebooku" hashtag_explanation: "ZnaÄky ti umožňujú hovoriÅ¥ o tom, Äo Å¥a zaujÃma a sledovaÅ¥ diskusie o tom, Äo Å¥a zaujÃma. Je to aj skvelý spôsob na spoznanie nových ľudà na Diaspore." hashtag_suggestions: "Skús sledovaÅ¥ znaÄky, ako napr. #umenie, #filmy, #gif, atÄ." - saved: "Uložené!" well_hello_there: "Vitaj!" what_are_you_in_to: "ÄŒo Å¥a bavÃ?" who_are_you: "Kto si?" @@ -1060,13 +754,6 @@ sk: settings_updated: "Nastavenia aktualizované" unconfirmed_email_changed: "E-mailová adresa sa zmenila. Treba ju aktivovaÅ¥." unconfirmed_email_not_changed: "Nepodarilo sa zmeniÅ¥ e-mailovú adresu" - webfinger: - fetch_failed: "Nepodarilo sa zÃskaÅ¥ profil webfinger pre %{profile_url}" - hcard_fetch_failed: "Nepodarilo sa zÃskaÅ¥ hkartu pre %{@account}" - no_person_constructed: "Z tejto hkarty sa nedá vytvoriÅ¥ žiaden kontakt." - not_enabled: "Zdá sa, že webfinger nie je povolený pre hostiteľa úÄtu %{account}" - xrd_fetch_failed: "Pri zÃskavanà xrd z úÄtu %{account} nastala chyba" - welcome: "Vitajte!" will_paginate: next_label: "ÄŽalej »" previous_label: "« Predchádzajúca" \ No newline at end of file diff --git a/config/locales/diaspora/sl.yml b/config/locales/diaspora/sl.yml index e8c8b4798da9ae4fb3761e2113ef2eec2244eb83..9f3de5e90e143597e71fd60f1ff76e34888ed438 100644 --- a/config/locales/diaspora/sl.yml +++ b/config/locales/diaspora/sl.yml @@ -6,11 +6,8 @@ sl: _applications: "Aplikacije" - _comments: "Komentarji" _contacts: "Stiki" _help: "PomoÄ" - _home: "Domov" - _photos: "slike" _services: "Storitve" account: "UporabniÅ¡ki raÄun" activerecord: @@ -103,13 +100,7 @@ sl: two: "Å tevilo novih uporabnikov ta teden: %{count}" zero: "Nobenega novega uporabnika ta teden" current_server: "Trenutni Äas strežnika je %{date}" - ago: "%{time} nazaj" all_aspects: "Vsi pogledi" - application: - helper: - unknown_person: "neznana oseba" - video_title: - unknown: "Neznani naslov videa" are_you_sure: "Ste prepriÄani?" are_you_sure_delete_account: "Ali ste prepriÄani, da želite zapreti vaÅ¡ raÄun? Tega koraka se ne da razveljaviti!" aspect_memberships: @@ -123,18 +114,10 @@ sl: success: "Dodajanje stika v vidik je uspelo." aspect_listings: add_an_aspect: "+ Dodaj vidik" - deselect_all: "Odstrani izbiro" - edit_aspect: "Uredi %{name}" - select_all: "OznaÄi vse" aspect_stream: make_something: "Naredi nekaj" stay_updated: "Ostanite na tekoÄem" stay_updated_explanation: "VaÅ¡ glavni tok vsebuje vsebine vseh vaÅ¡ih kontaktov, oznak, ki jih sledite, in prispevkov od nekaterih ustvarjalnih Älanov skupnosti." - contacts_not_visible: "Stiki v tem vidiku drug drugega ne bodo videli." - contacts_visible: "Stiki v tem vidiku lahko vidijo drug drugega." - create: - failure: "Ustvarjanje vidika ni uspelo." - success: "Novi vidik %{name} je ustvarjen." destroy: failure: "%{name} ni prazen in ga ni mogoÄe odstraniti." success: "%{name} je uspeÅ¡no odstranjen." @@ -142,24 +125,15 @@ sl: aspect_list_is_not_visible: "seznam vidikov ni viden ostalim stikom v tem vidiku" aspect_list_is_visible: "seznam vidikov je viden ostalim stikom v tem vidiku" confirm_remove_aspect: "Ali ste prepriÄani, da bi radi izbrisali ta vidik?" - make_aspect_list_visible: "naj bodo stiki v tem vidiku vidni med sabo?" - remove_aspect: "IzbriÅ¡i ta vidik" rename: "preimenuj" update: "posodobi" updating: "posodabljanje" index: - diaspora_id: - content_1: "VaÅ¡ Diaspora ID je:" - content_2: "Svoj Diaspora ID delite z drugimi, da vas bodo lahko naÅ¡li." - heading: "Diaspora ID" donate: "Prispevajte" - handle_explanation: "To je vaÅ¡ Diaspora ID. Uporabite ga lahko, da drugi stopijo v stik z vami, podobno kot vaÅ¡ e-naslov." help: any_problem: "Imate problem?" contact_podmin: "Kontaktirajte administratorja vaÅ¡ega pod-a!" do_you: "Ali:" - email_feedback: "Äe želite, %{link} povratno informacijo" - email_link: "poÅ¡ljite" feature_suggestion: "... imate predlog(%{link})?" find_a_bug: "... ste naÅ¡li hroÅ¡Äa(%{link})?" have_a_question: "... imate vpraÅ¡anje(%{link})?" @@ -171,31 +145,20 @@ sl: tag_question: "question" tutorials_and_wiki: "%{faq}, %{tutorial} in %{wiki}: pomoÄ pri zaÄetnih težavah." introduce_yourself: "To je vaÅ¡ tok. VskoÄite in predstavite se." - keep_diaspora_running: "Z meseÄnim prispevkom pohitrite razvoj Diaspore!" keep_pod_running: "Pomagajte, da bo %{pod} deloval hitro in plaÄajte strežnikom kavico z meseÄnim prispevkom!" new_here: follow: "Sledite %{link} in pozdravite nove uporabnike *Diaspore!" learn_more: "VeÄ o tem" title: "DobrodoÅ¡li novi uporabniki" - no_contacts: "Ni stikov" - no_tags: "+ Za sledenje poiÅ¡Äi oznako" - people_sharing_with_you: "Ljudje, ki delijo z vami" - post_a_message: "objavi sporoÄilo >>" services: content: "Naslednje storitve lahko povežete z Diasporo:" heading: "Povežite storitve" - unfollow_tag: "Nehaj slediti #%{tag}" welcome_to_diaspora: "DobrodoÅ¡li v Diaspori, %{name}!" - new: - create: "Ustvari" - name: "Ime (vidno samo vam)" no_contacts_message: community_spotlight: "srediÅ¡Äe pozornosti skupnosti" or_spotlight: "Lahko pa delite tudi z %{link}" try_adding_some_more_contacts: "PoiÅ¡Äete ali povabite lahko veÄ stikov." you_should_add_some_more_contacts: "Lahko bi dodali Å¡e kakÅ¡no osebo!" - no_posts_message: - start_talking: "Trenutno ni Å¡e nihÄe niÄesar objavil!" seed: acquaintances: "Poznanstva" family: "Družina" @@ -204,7 +167,6 @@ sl: update: failure: "Vidik %{name} ima predolgo ime, zato ga ni mogoÄe shraniti." success: "VaÅ¡ vidik %{name} je bil uspeÅ¡no posodobljen." - back: "Nazaj" blocks: create: failure: "Nisem mogel zavrniti tega uporabnika. #evasion" @@ -216,21 +178,14 @@ sl: explanation: "Objavite na Diasporo od koderkoli s pomoÄjo te povezave => %{link}." heading: "Zaznamek" post_something: "Objavite na Diaspori" - post_success: "Objavljeno! Zapiram!" cancel: "PrekliÄi" comments: new_comment: comment: "NapiÅ¡i mnenje" commenting: "Pisanje mnenja ..." - one: "1 mnenje" - other: "%{count} mnenj" - zero: "nobenega mnenja" contacts: - create: - failure: "Ustvarjanje stika ni bilo mogoÄe" index: add_a_new_aspect: "Dodaj nov vidik" - add_to_aspect: "Dodaj stik k %{name}" all_contacts: "Vsi stiki" community_spotlight: "SrediÅ¡Äe pozornosti skupnosti" my_contacts: "Moji stiki" @@ -239,32 +194,18 @@ sl: only_sharing_with_me: "Delijo samo z mano" start_a_conversation: "ZaÄni pogovor" title: "Stiki" - your_contacts: "VaÅ¡i stiki" - sharing: - people_sharing: "Ljudje, ki delijo z vami:" spotlight: community_spotlight: "SrediÅ¡Äe pozornosti skupnosti" suggest_member: "Predlagaj Älana" conversations: - conversation: - participants: "Udeleženci" create: fail: "Neveljavno sporoÄilo" no_contact: "Hej, najprej moraÅ¡ dodati stike!" sent: "SporoÄilo poslano" - helper: - new_messages: - few: "%{count} nova sporoÄila" - one: "1 novo sporoÄilo" - other: "%{count} novih sporoÄil" - two: "%{count} novi sporoÄili" - zero: "Nobenih novih sporoÄil" index: inbox: "Prejeto" - no_conversation_selected: "oznaÄen ni bil noben pogovor" no_messages: "ni sporoÄil" new: - abandon_changes: "Opusti spremembe?" send: "PoÅ¡lji" sending: "PoÅ¡iljanje ..." subject: "zadeva" @@ -283,34 +224,19 @@ sl: error_messages: helper: correct_the_following_errors_and_try_again: "Popravite naslednje napake in poskusite znova." - invalid_fields: "Neveljavna polja" - login_try_again: "<a href='%{login_link}'>Prijavite</a> se prosim in poskusite znova." - post_not_public: "Objava, ki jo želite pogledati ni javna!" fill_me_out: "Izpolni me" find_people: "PoiÅ¡Äi ljudi ali #zaznamke" - hide: "Skrij" - invitation_codes: - excited: "Oseba %{name} je navduÅ¡ena, da vas vidi tukaj." invitations: a_facebook_user: "Facebook uporabnik" check_token: not_found: "Povabilo ni bilo najdeno" create: - already_contacts: "S to osebo ste že povezani" - already_sent: "To osebo ste že povabili." empty: "Prosim vnesite vsaj en elektronski poÅ¡tni naslov." no_more: "Nimate veÄ povabil." note_already_sent: "Povabila so bila že poslana na: %{emails}" - own_address: "Povabila ne morete poslati na lasten e-naslov." rejected: "SledeÄi e-naslovi imajo težave: " sent: "Povabila so bila poslana naslednjim: " - edit: - accept_your_invitation: "Sprejmite povabilo" - your_account_awaits: "VaÅ¡ raÄun vas že Äaka!" new: - already_invited: "Naslednje osebe Å¡e niso potrdile vaÅ¡ega povabila:" - aspect: "Vidik" - check_out_diaspora: "Preverite Diasporo!" codes_left: few: "S to kodo so na razpolago Å¡e %{count} vabila" one: "S to kodo je na razpolago Å¡e eno vabilo" @@ -318,16 +244,11 @@ sl: two: "S to kodo sta na razpolago Å¡e %{count} vabili" zero: "S to kodo ni veÄ vabil na razpolago" comma_separated_plz: "Vnesete lahko veÄ e-naslovov loÄenih z vejico." - if_they_accept_info: "v kolikor sprejmejo vaÅ¡e povabilo, bodo samodejno dodani vidikom v katere ste jih povabili." invite_someone_to_join: "Povabite nekoga v omrežje Diaspora!" language: "Jezik" paste_link: "Delite to povezavo s svojimi prijatelji in jih povabite v Diasporo*. Lahko jim pa tudi direktno poÅ¡ljete povezavo po e-poÅ¡ti." - personal_message: "Osebno sporoÄilo" - resend: "Ponovno poÅ¡lji" send_an_invitation: "PoÅ¡lji eno povabilo" - send_invitation: "PoÅ¡lji povabilo" sending_invitation: "PoÅ¡iljanje povabila..." - to: "Za" layouts: application: back_to_top: "Na vrh" @@ -336,40 +257,13 @@ sl: source_package: "prenesi paket izvorne kode" toggle: "preklop mobilne strani" whats_new: "kaj je novega?" - your_aspects: "vaÅ¡i vidiki" header: - admin: "administrator" - blog: "blog" code: "izvorna koda" - login: "prijava" logout: "Odjava" profile: "Profil" - recent_notifications: "Nedavna obvestila" settings: "Nastavitve" - view_all: "Prikaži vse" - likes: - likes: - people_dislike_this: - few: "%{count} osebam ni vÅ¡eÄ" - one: "1 osebi ni vÅ¡eÄ" - other: "%{count} osebam ni vÅ¡eÄ" - two: "%{count} osebama ni vÅ¡eÄ" - zero: "ni osebe, ki ji ni vÅ¡eÄ" - people_like_this: - few: "%{count} osebam je vÅ¡eÄ" - one: "1 osebi je vÅ¡eÄ" - other: "%{count} osebam je vÅ¡eÄ" - two: "%{count} osebama je vÅ¡eÄ" - zero: "nikomur ni vÅ¡eÄ" - people_like_this_comment: - few: "%{count} osebam je vÅ¡eÄ" - one: "%{count} osebi je vÅ¡eÄ" - other: "%{count} osebam je vÅ¡eÄ." - two: "%{count} osebama je vÅ¡eÄ" - zero: "nikomur ni vÅ¡eÄ" limited: "Omejeno" more: "VeÄ" - next: "naslednja" no_results: "Ni zadetkov" notifications: also_commented: @@ -390,13 +284,6 @@ sl: other: "%{actors} jih je napisalo mnenje o vaÅ¡em %{post_link}." two: "%{actors} sta napisala mnenje o vaÅ¡em %{post_link}." zero: "NihÄe ni napisal mnenja o vaÅ¡em %{post_link}." - helper: - new_notifications: - few: "%{count} nova obvestila" - one: "1 novo obvestilo" - other: "%{count} novih obvestil" - two: "%{count} novi obvestili" - zero: "Ni novih obvestil" index: and: "in" and_others: @@ -460,7 +347,6 @@ sl: zero: "%{actors} jih ni zaÄelo deliti z vami." notifier: a_post_you_shared: "objava." - accept_invite: "Sprejmite povabilo v Diasporo*!" click_here: "kliknite sem" comment_on_post: reply: "Odgovorite ali poglejte objavo osebe %{name} >" @@ -490,7 +376,6 @@ sl: liked: "Osebi %{name} je vÅ¡eÄ vaÅ¡a objava: " view_post: "Poglej objavo >" mentioned: - mentioned: "v objavi so vas omenili:" subject: "%{name} vas je omenil v Diaspori*" private_message: reply_to_or_view: "Odgovorite ali poglejte ta pogovor>" @@ -508,106 +393,45 @@ sl: to_change_your_notification_settings: "da spremenite nastavitve obvestil" nsfw: "NSFW (Ni varno za službo)" ok: "V redu" - or: "ali" - password: "Geslo" - password_confirmation: "Potrditev gesla" people: add_contact: invited_by: "povabil vas je" - add_contact_small: - add_contact_from_tag: "dodaj osebo iz oznake" - aspect_list: - edit_membership: "urejanje Älanstva vidikov" - helper: - is_not_sharing: "%{name} ne deli s teboj" - is_sharing: "%{name} deli s teboj" - results_for: "zadetkov za %{params}" index: looking_for: "IÅ¡Äete morda objave z oznako %{tag_link}?" no_one_found: "...nikogar ni bilo mogoÄe najti." no_results: "Hej! Za iskanje je potrebno vpisati nekaj." results_for: "rezultati iskanja za" searching: "iskanje poteka, bodite potrpežljivi ..." - one: "1 oseba" - other: "%{count} oseb" person: - add_contact: "dodaj stik" - already_connected: "Ste že povezani" - pending_request: "ÄŒakajoÄe zahteve" thats_you: "To ste vi!" profile_sidebar: bio: "življenjepis" born: "datum rojstva" - edit_my_profile: "Uredi moj profil" gender: "spol" - in_aspects: "v vidikih" location: "kraj" - photos: "Fotografije" - remove_contact: "odstrani stik" - remove_from: "Naj odstranim %{name} iz %{aspect}?" show: closed_account: "Ta raÄun je bil zaprt." does_not_exist: "Oseba ne obstaja!" has_not_shared_with_you_yet: "Oseba %{name} Å¡e ni izmenjala objave z vami!" - ignoring: "Vi ignorirate vse prispevke osebe %{name}." - incoming_request: "%{name} želi deliti z vami." - mention: "Omemba" - message: "SporoÄilo" - not_connected: "S to osebo ne delite" - recent_posts: "Zadnje objave" - recent_public_posts: "Zadnje javne objave" - return_to_aspects: "Vrnite se na vaÅ¡o stran z vidiki" - see_all: "Oglejte si vse" - start_sharing: "zaÄni deliti" - to_accept_or_ignore: "sprejmite ali zavrnite." - sub_header: - add_some: "dodaj nekaj" - edit: "uredi" - you_have_no_tags: "nimate nobene oznake!" - webfinger: - fail: "Žal ni bilo mogoÄe najti %{handle}." - zero: "ni oseb" photos: - comment_email_subject: "Slika osebe %{name}" create: integrity_error: "Nalaganje slike ni uspelo. Ste prepriÄani, da ste izbrali sliko?" runtime_error: "Nalaganje slike ni uspelo. Imate pripet varnostni pas?" type_error: "Nalaganje slike ni uspelo. Ste prepriÄani, da je bila dodana slika?" destroy: notice: "Slika izbrisana." - edit: - editing: "Urejanje" - new: - back_to_list: "Nazaj na seznam" - new_photo: "Nova slika" - post_it: "objavi!" new_photo: empty: "Datoteka {file} je prazna, prosimo ponovno izberite datoteke brez nje." invalid_ext: "Datoteka {file} ni veljavna. Dovoljene so samo naslednje vrste datotek {extensions}." size_error: "Datoteka {file} je prevelika, najveÄja dovoljena velikost je {sizeLimit}." new_profile_photo: - or_select_one_existing: "ali pa izberite eno od vaÅ¡ih že obstojeÄih slik: %{photos}" upload: "Naloži novo sliko profila!" - photo: - view_all: "ogled vseh slik osebe %{name}" show: - collection_permalink: "trajna povezava do zbirke" - delete_photo: "IzbriÅ¡i sliko" - edit: "uredi" - edit_delete_photo: "Dodaj opis slike ali izbriÅ¡i sliko" - make_profile_photo: "uporabi sliko za moj profil" show_original_post: "Prikaži originalno objavo" - update_photo: "Posodobi sliko" - update: - error: "Urejanje slike ni uspelo." - notice: "Slika uspeÅ¡no posodobljena." posts: presenter: title: "Objava osebe %{name}" show: - destroy: "IzbriÅ¡i" - not_found: "Oprostite, te objave ni mogoÄe najti." - permalink: "trajna povezava" photos_by: few: "%{count} slike o %{author}" one: "Ena slika o %{author}" @@ -615,14 +439,11 @@ sl: two: "%{count} sliki o %{author}" zero: "Ni slik o %{author}" reshare_by: "Ponovna deljenja po %{author}" - previous: "prejÅ¡nja" privacy: "Zasebnost" - privacy_policy: "Pravila o zasebnosti" profile: "Profil" profiles: edit: allow_search: "Dovolite, da vas drugi lahko iÅ¡Äejo v Diaspori" - edit_profile: "Uredi profil" first_name: "Ime" last_name: "Priimek" update_profile: "Posodobi profil" @@ -632,8 +453,6 @@ sl: your_location: "VaÅ¡ kraj" your_name: "VaÅ¡e ime" your_photo: "VaÅ¡a slika" - your_private_profile: "VaÅ¡ zasebni profil" - your_public_profile: "VaÅ¡ javni profil" your_tags: "OpiÅ¡ite se v petih besedah" your_tags_placeholder: "npr. #movies #kittens #travel #teacher #newyork" update: @@ -650,65 +469,23 @@ sl: closed: "Za ta Pod Diaspore registracije trenutno niso mogoÄe." create: success: "Pridružili ste se v omrežje Diaspora!" - edit: - cancel_my_account: "PrekliÄi moj uporabniÅ¡ki raÄun" - edit: "Uredi %{name}" - leave_blank: "(v kolikor ne želite spremeniti pustite prazno)" - password_to_confirm: "(spremembo je potrebno potrditi z vaÅ¡im geslom)" - unhappy: "Niste zadovoljni?" - update: "Posodobi" invalid_invite: "Povezava na povabilo, ki ste jo uporabili ni veÄ veljavna!" new: - create_my_account: "Ustvari moj raÄun!" email: "E-POÅ TA" enter_email: "VpiÅ¡ite e-naslov" enter_password: "VpiÅ¡ite geslo (najmanj Å¡est znakov)" enter_password_again: "Ponovno vpiÅ¡ite isto geslo" enter_username: "Izberite uporabniÅ¡ko ime (samo Ärke, Å¡tevilke in podÄrtaji)" - join_the_movement: "Pridružite se gibanju!" password: "GESLO" password_confirmation: "POTRDITEV GESLA" sign_up: "VPIS" - sign_up_message: "Socialno omrežje s ♥" username: "UPORABNIK" - requests: - create: - sending: "PoÅ¡iljanje" - sent: "Osebo %{name} ste vpraÅ¡ali, Äe bi delila z vami. VaÅ¡e vpraÅ¡anje bo videla, ko se bo prijavila v Diasporo." - destroy: - error: "Prosim izberite vidik!" - ignore: "ProÅ¡nja za stik je zavrnjena." - success: "Sedaj delite." - helper: - new_requests: - few: "%{count} nove proÅ¡nje!" - many: "%{count} novih proÅ¡nj!" - one: "nova proÅ¡nja!" - other: "%{count} novih proÅ¡enj!" - two: "%{count} novi proÅ¡nji!" - zero: "ni novih proÅ¡enj" - manage_aspect_contacts: - existing: "ObstojeÄi stiki" - manage_within: "Uredi stike znotraj" - new_request_to_person: - sent: "poslano!" reshares: comment_email_subject: "%{resharer} je delil objavo osebe %{author}" - create: - failure: "PriÅ¡lo je do napake pri ponovni delitvi objave." reshare: deleted: "Avtor je izbrisal izvirno objavo." - reshare: - few: "%{count} delitve" - many: "%{count} delitev" - one: "1 delitev" - other: "%{count} delitev" - two: "%{count} delitvi" - zero: "Ponovno deli" reshare_confirmation: "Deli objavo osebe %{author}?" - reshare_original: "Deli izvirnik" reshared_via: "ponovno deljeno preko" - show_original: "Prikaži izvirnik" search: "Najdi" services: create: @@ -719,60 +496,25 @@ sl: success: "Preverjanje istovetnosti je uspeÅ¡no izbrisano." failure: error: "pri povezovanju s storitvijo je priÅ¡lo do napake" - finder: - fetching_contacts: "Diaspora pridobiva vaÅ¡e prijatelje iz storitve %{service}. Prosimo poÄakajte nekaj minut." - no_friends: "Noben prijatelj s Facebook-a ni bil najden." - service_friends: "%{service} Prijatelji" index: disconnect: "prekini povezavo" edit_services: "Uredi storitve" logged_in_as: "prijavljeni ste kot" really_disconnect: "prekinitev povezavo s storitvijo %{service}?" - inviter: - click_link_to_accept_invitation: "Kliknite na povezavo za potrditev vaÅ¡ega povabila" - join_me_on_diaspora: "Pridruži se mi na DIASPORI*" - remote_friend: - invite: "povabi" - not_on_diaspora: "Å e niso na Diaspori" - resend: "poÅ¡lji ponovno" settings: "Nastavitve" - share_visibilites: - update: - post_hidden_and_muted: "Objava osebe %{name} je bila skrita in vsa obvestila za to objavo so bila onemogoÄena." - see_it_on_their_profile: "ÄŒe želite videti posodobitve te objave, obiÅ¡Äite profil osebe %{name}." shared: - add_contact: - add_new_contact: "Dodaj nov stik" - create_request: "PoiÅ¡Äi po Diaspora ID" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "VpiÅ¡ite uporabniÅ¡ko ime Diaspora:" - know_email: "Ali poznate njihove naslove e-naslove? Povabite jih" - your_diaspora_username_is: "VaÅ¡e uporabniÅ¡ko ime Diaspora je: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Dodaj stik" toggle: few: "V %{count} vidikih" one: "V %{count} vidiku" other: "V %{count} vidikih" two: "V %{count} vidikih" zero: "Dodaj stik" - contact_list: - all_contacts: "Vsi stiki" - footer: - logged_in_as: "prijavljen kot %{name}" - your_aspects: "vaÅ¡i vidiki" invitations: by_email: "Po e-poÅ¡ti" - dont_have_now: "Trenutno nimate povabil, vendar jih lahko v kratkem priÄakujete!" - from_facebook: "Iz Facebook-a" - invitations_left: "Å¡e %{count}" - invite_someone: "Povabi nekoga" invite_your_friends: "Povabi prijatelje" invites: "Povabila" - invites_closed: "Za ta Pod Diaspore povabila trenutno niso mogoÄa." share_this: "Delite to povezavo preko e-poÅ¡te, bloga ali priljubljenega socialnega omrežja!" - notification: - new: "Novo %{type} od %{from}" public_explain: atom_feed: "vir Atom" control_your_audience: "Nadzor ciljne skupine" @@ -784,59 +526,26 @@ sl: title: "Nastavitev povezanih storitev" visibility_dropdown: "Uporabite ta spustni seznam za spremembo vidnosti vaÅ¡e objave. (PriporoÄamo vam, da naj bo prva objava javna.)" publisher: - all: "vsi" - all_contacts: "vsi stiki" discard_post: "Zavrzi objavo" get_location: "Pridobi svojo lokacijo" - make_public: "objavi kot javno" new_user_prefill: hello: "Zdravo vsem. Jaz sem #%{new_user_tag}. " i_like: "Zanimajo me naslednje oznake %{tags}." invited_by: "Hvala za povabilo, " newhere: "NovTukaj" - post_a_message_to: "Objavi sporoÄilo v %{aspect}" posting: "Objavljanje ..." - preview: "Predogled" - publishing_to: "objavljanje na: " share: "Objavi" - share_with: "deli z" upload_photos: "Naložite slike" whats_on_your_mind: "Kaj tuhtate?" - reshare: - reshare: "Ponovno deli" stream_element: - connect_to_comment: "Povežite se s tem uporabnikom, Äe želite napisati mnenje o njegovi objavi" - currently_unavailable: "pisanje mnenj trenutno ni na voljo" - dislike: "Ni mi vÅ¡eÄ" - hide_and_mute: "Skrij in utiÅ¡aj objavo" - ignore_user: "Ne meni se za osebo %{name}" - ignore_user_description: "Zavrni in odstrani osebo iz vseh pogledov?" - like: "VÅ¡eÄ mi je" - nsfw: "To objavo je avtor oznaÄil kot neprimerno za delo. %{link}" - shared_with: "Deljeno z: %{aspect_names}" - show: "prikaži" - unlike: "Ni mi vÅ¡eÄ" via: "preko %{link}" via_mobile: "preko mobilnika" - viewable_to_anyone: "Ta objava je vidna vsakomur na spletu" status_messages: create: success: "UspeÅ¡no omenjeni: %{names}" - destroy: - failure: "Ni bilo mogoÄe izbrisati objave" - helper: - no_message_to_display: "Ni sporoÄil." new: mentioning: "Omembe: %{person}" too_long: "{\"few\"=>\"vaÅ¡e sproÄilo o stanju morajo vsebovati manj kot %{count} znake\", \"one\"=>\"vaÅ¡e sproÄilo o stanju morajo vsebovati manj kot %{count} znak\", \"other\"=>\"vaÅ¡e sproÄilo o stanju morajo vsebovati manj kot %{count} znakov\", \"two\"=>\"vaÅ¡e sproÄilo o stanju morajo vsebovati manj kot %{count} znaka\", \"zero\"=>\"vaÅ¡e sproÄilo o stanju morajo vsebovati manj kot %{count} znakov\"}" - stream_helper: - hide_comments: "Skrij vsa mnenja" - show_comments: - few: "Prikaži Å¡e %{count} mnenja" - one: "Prikaži Å¡e eno mnenje" - other: "Prikaži Å¡e %{count} mnenj" - two: "Prikaži Å¡e %{count} mnenji" - zero: "Ni veÄ mnenj" streams: activity: title: "Moje dejavnosti" @@ -862,22 +571,11 @@ sl: title: "Javna aktivnost" tags: title: "Objave oznaÄene z: %{tags}" - tag_followings: - create: - failure: "Sledenje #%{name} ni uspelo. Ali že sledite?" - none: "Ne morete slediti prazni objavi!" - success: "Hura! Sedaj sledite #%{name}." - destroy: - failure: "Ni mogoÄe prekiniti sledenja #%{name}. MogoÄe ste že prekinili sledenje?" - success: "Žal veÄ ne sledite #%{name}." tags: show: follow: "Sledite #%{tag}" - following: "Sledenje #%{tag}" none: "Prazna oznaka ne obstaja!" stop_following: "Prenehaj slediti #%{tag}" - terms_and_conditions: "Pravila in pogoji" - undo: "Razveljavi?" username: "UporabniÅ¡ko ime" users: confirm_email: @@ -898,7 +596,6 @@ sl: character_minimum_expl: "dolgo mora biti vsaj Å¡est znakov" close_account: dont_go: "Prosim, ne odidite!" - if_you_want_this: "ÄŒe zares hoÄete to, vnesite spodaj geslo in kliknite 'Zapri raÄun'" lock_username: "To bo zaklenilo vaÅ¡e uporabniÅ¡ko ime, Äe se boste odloÄili ponovno vpisati." locked_out: "Odjavljeni boste in izkljuÄeni iz vaÅ¡ega raÄuna." make_diaspora_better: "Želimo, da nam pomagate narediti Diasporo boljÅ¡o, zato nam raje pomagajte, kot pa da odidete. ÄŒe želite oditi, želimo vedeti kaj se bo zgodilo za tem." @@ -909,12 +606,10 @@ sl: comment_on_post: "... nekdo napiÅ¡e mnenje o vaÅ¡i objavi?" current_password: "Trenutno geslo" current_password_expl: "tisto s katerim ste se prijavili ..." - download_photos: "prenesi moje slike" edit_account: "Uredi uporabniÅ¡ki raÄun" email_awaiting_confirmation: "Poslali smo vam povezavo za aktiviranje na %{unconfirmed_email}. Dokler ne sledite tej povezavi in ​​aktivirate nov naslov, bomo Å¡e naprej uporabljati vaÅ¡ stari naslov %{email}." export_data: "Izvozi podatke" following: "Nastavitve za sledenje" - getting_started: "Nastavitve novega uporabnika" liked: "... je nekomu vÅ¡eÄ vaÅ¡a objava?" mentioned: "... ste omenjeni v objavi?" new_password: "Novo geslo" @@ -934,7 +629,6 @@ sl: connect_to_facebook_link: "povezavo vaÅ¡ega raÄuna Facebook" hashtag_explanation: "Oznake vam omogoÄajo, da govorite in sledite vaÅ¡im interesom. So tudi dober naÄin za iskanje novih ljudi na Diaspori." hashtag_suggestions: "Poskusite lahko oznake, kot so #art, #movies, #gif in podobno." - saved: "Shranjeno!" well_hello_there: "No, pozdravljeni!" what_are_you_in_to: "Kaj vas zanima?" who_are_you: "Kdo ste?" @@ -956,13 +650,6 @@ sl: settings_updated: "Nastavitve posodobljene" unconfirmed_email_changed: "E-poÅ¡ta spremenjena. Potrebna je aktivacija." unconfirmed_email_not_changed: "Sprememba e-naslova ni uspela" - webfinger: - fetch_failed: "'webfinger' profil ni bilo mogoÄe prenesti za %{profile_url}" - hcard_fetch_failed: "priÅ¡lo je do težave pri prenosu 'hcard' za %{account}" - no_person_constructed: "Iz te 'hcard' kartice ni bilo mogoÄe razpoznati nobene osebe." - not_enabled: "izgleda, da webfinger ni dejaven za %{account} na gostitelju" - xrd_fetch_failed: "pri pridobivanju xrd iz uporabniÅ¡kega raÄuna %{account} je priÅ¡lo do napake" - welcome: "DobrodoÅ¡li!" will_paginate: next_label: "naslednja »" previous_label: "« prejÅ¡nja" \ No newline at end of file diff --git a/config/locales/diaspora/sr.yml b/config/locales/diaspora/sr.yml index a446031b32e6888464a3f36ff22794476a40f2dd..685fb44a586a2b38db2056a108779256fe545962 100644 --- a/config/locales/diaspora/sr.yml +++ b/config/locales/diaspora/sr.yml @@ -6,10 +6,7 @@ sr: _applications: "Ðпликације" - _comments: "Коментари" _contacts: "Контакти" - _home: "Почетна" - _photos: "Фотографије" _services: "УÑлуге" account: "Ðалог" activerecord: @@ -40,13 +37,7 @@ sr: username: invalid: "је неиÑправно. Дозвољени Ñу Ñамо Ñлова, бројеви и доње црте." taken: "је већ заузето." - ago: "пре %{time}" all_aspects: "Сви погледи" - application: - helper: - unknown_person: "непозната оÑоба" - video_title: - unknown: "непознат наÑлов видеа" are_you_sure: "ЈеÑте ли Ñигурни?" are_you_sure_delete_account: "ЈеÑте ли Ñигурни да желите да затворите налог? Ово Ñе не може повратити!" aspect_memberships: @@ -60,16 +51,8 @@ sr: success: "ОÑоба уÑпешно додата у поглед." aspect_listings: add_an_aspect: "+ Додај поглед" - deselect_all: "Ðе означи ни један" - edit_aspect: "Измени %{name}" - select_all: "Означи Ñве" aspect_stream: stay_updated: "Буди у току" - contacts_not_visible: "Контакти у овом погледу неће моћи да виде једни друге." - contacts_visible: "Контакти у овом погледу ће моћи да виде једни друге." - create: - failure: "ÐеуÑпешно прављење погледа." - success: "Твој нови поглед %{name} је направљен." destroy: failure: "%{name} није празан и не може Ñе уклонити." success: "Поглед %{name} је уÑпешно уклоњен." @@ -77,21 +60,13 @@ sr: aspect_list_is_not_visible: "ÑпиÑак погледа је невидљив оÑталима у погледу" aspect_list_is_visible: "ÑпиÑак погледа је видљив оÑталима у погледу" confirm_remove_aspect: "ЈеÑте ли Ñигурни да желите да обришете овај поглед?" - make_aspect_list_visible: "Учини контакте у овом погледу видљиве једне другима?" - remove_aspect: "Обриши овај поглед" rename: "Преименуј" update: "Ðжурирај" updating: "ажурирање" index: - diaspora_id: - content_1: "Твој ДијаÑпора ИД је:" - content_2: "Дај га било коме и моћи ће да те нађе на ДијаÑпори." - heading: "ДијаÑпора ИД" donate: "Донирај" - handle_explanation: "Ово је твој ДијаÑпора ИД. Можеш га дати људима као и имејл адреÑу, да могу да те нађу." help: do_you: "Да ли:" - email_feedback: "Ðко више волиш, пошаљи нам %{link}" feature_suggestion: "...имаш %{link}?" find_a_bug: "...Ñте нашли %{link}?" have_a_question: "...имаш %{link}?" @@ -105,25 +80,15 @@ sr: follow: "Прати %{link} и поздрављај нове кориÑнике ДијаÑпоре*!" learn_more: "Ðаучи више" title: "Поздрави нове кориÑнике" - no_contacts: "Ðема контаката" - no_tags: "+ Ðађи ознаке за праћење" - people_sharing_with_you: "Људи који деле Ñа тобом" - post_a_message: "објави поруку >>" services: content: "Можеш повезати Ñледеће Ñајтове Ñа ДијаÑпором:" heading: "Повежи Ñајтове" - unfollow_tag: "Ðе прати више #%{tag}" welcome_to_diaspora: "Добродошли на ДијаÑпору, %{name}!" - new: - create: "Ðаправи" - name: "Име (видљиво Ñамо теби)" no_contacts_message: community_spotlight: "заједницом" or_spotlight: "Или можеш поделити Ñа %{link}" try_adding_some_more_contacts: "Можеш тражити или позвати још контаката." you_should_add_some_more_contacts: "Требало би да додаш контакте!" - no_posts_message: - start_talking: "Још нико ништа није рекао!" seed: acquaintances: "Познаници" family: "Породица" @@ -132,20 +97,14 @@ sr: update: failure: "Твој поглед, %{name}, има предугачак назив да би Ñе Ñачувао." success: "Твој поглед, %{name}, је уÑпешно измењен." - back: "Ðазад" bookmarklet: post_something: "Објави на ДијаÑпори" - post_success: "Објављено! Затварам!" cancel: "Откажи" comments: new_comment: comment: "Коментариши" commenting: "Коментарише Ñе..." - one: "1 коментар" - zero: "Ðема коментара" contacts: - create: - failure: "ÐеуÑпело креирање контакта" index: all_contacts: "Сви контакти" community_spotlight: "Погледи заједнице" @@ -154,9 +113,6 @@ sr: only_sharing_with_me: "Деле Ñамо Ñа вама:" start_a_conversation: "Започни разговор" title: "Контакти" - your_contacts: "Твоји контакти" - sharing: - people_sharing: "Људи који деле Ñа вама:" spotlight: community_spotlight: "Погледи заједнице" conversations: @@ -165,10 +121,8 @@ sr: sent: "Порука поÑлата" index: inbox: "Сандуче" - no_conversation_selected: "Разговор није означен" no_messages: "Ðема порука" new: - abandon_changes: "Откажи промене:" send: "Пошаљи" sending: "Шаљем..." subject: "наÑлов" @@ -182,33 +136,19 @@ sr: error_messages: helper: correct_the_following_errors_and_try_again: "ИÑправи Ñледеће грешке и покушај поново." - invalid_fields: "Погрешно попуњена поља" fill_me_out: "ИÑпуни ме" find_people: "Тражи људе или #тагове" - hide: "Сакриј" invitations: a_facebook_user: "ФејÑбук кориÑник" check_token: not_found: "Токен позивнице није пронађен" create: - already_contacts: "Већ Ñте повезани Ñа овом оÑобом." - already_sent: "Већ Ñте позвали ову оÑобу." no_more: "Ðемате више позивница." - own_address: "Ðе можете поÑлати позивницу на Ñвоју адреÑу." rejected: "Ове email адреÑе имају проблеме: " - edit: - accept_your_invitation: "Прихвати позивницу" - your_account_awaits: "Ваш налог чека!" new: - already_invited: "Сљедеће оÑобе ниÑу прихватиле вашу позивницу:" - check_out_diaspora: "Провјери diaspora*!" invite_someone_to_join: "Позовите некога да Ñе придружи diaspora*!" language: "Језик" - personal_message: "Лична порука" - resend: "Пошаљи поново" send_an_invitation: "Пошаљи позивницу" - send_invitation: "Пошаљи позивницу" - to: "За" layouts: application: back_to_top: "Ðазад на врх" @@ -216,18 +156,12 @@ sr: toggle: "Мобилна верзија" whats_new: "Ðово" header: - admin: "ÐдминиÑтратор" - blog: "Блог" code: "Код" - login: "Пријава" logout: "Одјава" profile: "Профил" - recent_notifications: "Ðедавна обавештења" settings: "Подешавања" - view_all: "Прикажи Ñве" limited: "Ограничено" more: "Још" - next: "Ñледеће" no_results: "Ðема резултата" notifications: index: @@ -240,8 +174,6 @@ sr: click_here: "Кликните овде" liked: view_post: "Погледајте објаву" - mentioned: - mentioned: "Ñпоменуо/ла Ð²Ð°Ñ Ñƒ објави:" private_message: reply_to_or_view: "Одговорите или погледајте овај разговор:" reshared: @@ -255,43 +187,20 @@ sr: to_change_your_notification_settings: "да биÑте променили подешавање обавештења" nsfw: "Ðије пригодно за поÑао" ok: "У реду" - or: "или" - password: "Лозинка" - password_confirmation: "Понови лозинку" people: - add_contact_small: - add_contact_from_tag: "Додај контакт из ознаке" index: no_one_found: "...и нико није пронађен." no_results: "Хеј! Требате нешто потражити." - one: "1 оÑоба" person: - add_contact: "Додајте контакт" - already_connected: "Већ Ñте повезани" - pending_request: "Захтеви на чекању" thats_you: "То Ñте ви!" profile_sidebar: bio: "Биографија" born: "Дат.рођења" - edit_my_profile: "Уреди ÑопÑтвени профил" gender: "Пол" location: "Локација" - remove_contact: "Уклони контакт" show: closed_account: "Овај налог је затворен." does_not_exist: "ОÑоба не поÑтоји!" - mention: "Споменуо/ла Ð²Ð°Ñ Ñƒ објави" - message: "Порука" - not_connected: "Ðе делите Ñа овом оÑобом" - recent_posts: "Ðедавне објаве" - recent_public_posts: "Ðедавне јавне објаве" - see_all: "Погледајте Ñве" - start_sharing: "Почните делити" - sub_header: - add_some: "Додајте неке" - edit: "Уреди" - you_have_no_tags: "Ðемате ознака!" - zero: "Без оÑоба" photos: create: integrity_error: "Ðжурирање Ñлике није уÑпело. ЈеÑте ли Ñигурни да је то Ñлика?" @@ -299,36 +208,15 @@ sr: type_error: "Ðжурирање Ñлике није уÑпело. ЈеÑте ли Ñигурни да Ñте Ñлику додали?" destroy: notice: "Слика обриÑана" - edit: - editing: "Уређивање" - new: - back_to_list: "Ðазад ка лиÑти" - new_photo: "Ðова Ñлика" - post_it: "Објави!" new_profile_photo: upload: "Додајте нову профилну Ñлику!" show: - delete_photo: "Обриши Ñлику" - edit: "Уреди" - edit_delete_photo: "Уреди Ð¾Ð¿Ð¸Ñ Ñлике / обриши Ñлику" - make_profile_photo: "ПоÑтави профилну Ñлику" show_original_post: "Прикажи оригиналну објаву" - update_photo: "Ðжурирај Ñлику" - update: - error: "ÐеуÑпело уређивање Ñлике" - notice: "Слика уÑпешно ажурирана." - posts: - show: - destroy: "Обриши" - not_found: "Жао нам је, ниÑмо уÑпели пронаћи такву објаву." - previous: "претходно" privacy: "ПриватноÑÑ‚" - privacy_policy: "Политика приватноÑти" profile: "Профил" profiles: edit: allow_search: "Дозволите оÑобама да Ð²Ð°Ñ Ñ‚Ñ€Ð°Ð¶Ðµ унутар diaspora*" - edit_profile: "Уреди профил" first_name: "Име" last_name: "Презиме" update_profile: "Ðжурирај профил" @@ -338,8 +226,6 @@ sr: your_location: "Ваша локација" your_name: "Ваше име" your_photo: "Ваша Ñлика" - your_private_profile: "Ваш приватни профил" - your_public_profile: "Ваш јавни профил" your_tags: "Опишите Ñебе у 5 ријечи" update: failed: "ÐеуÑпело ажурирање профила" @@ -349,108 +235,41 @@ sr: closed: "РегиÑтрације Ñу затворене за овај diaspora* под" create: success: "Придружили Ñте Ñе diaspora*" - edit: - cancel_my_account: "Поништи мој налог" - leave_blank: "(оÑтавите празно ако не желите да промените)" - password_to_confirm: "(треба нам ваша тренутна лозинка да потврди ваше промене)" - unhappy: "ÐеÑрећни?" - update: "Ðжурирај" new: - create_my_account: "Креирај мој налог!" enter_email: "УнеÑите email" enter_password: "УнеÑите лозинку (шеÑÑ‚ знакова минимално)" enter_password_again: "Поновите лозинку" enter_username: "Изаберите кориÑничко име (Ñамо Ñлова, бројеви и доње линије)" - join_the_movement: "Придружи Ñе покрету!" - sign_up_message: "Друштвена мрежа Ñа ♥" - requests: - create: - sending: "Шаљем" - destroy: - success: "Сада делите." - manage_aspect_contacts: - existing: "ПоÑтојећи контакти" - new_request_to_person: - sent: "ПоÑлато" reshares: - create: - failure: "ДеÑила Ñе грешка приликом делења ове објаве" reshare: deleted: "Изворна објава обриÑана од Ñтране аутора" - reshare_original: "Подели оригинал" reshared_via: "Дељено путем" - show_original: "Прикажи оригинал" search: "Претрага" services: failure: error: "Грешка у току повезивања ÑервиÑа" - finder: - no_friends: "ФејÑбук пријатељи ниÑу пронађени." index: disconnect: "Прекини везу" edit_services: "Уреди ÑервиÑе" logged_in_as: "Пријављен као" - inviter: - click_link_to_accept_invitation: "Следи ову везу да прихватиш Ñвоју позивницу" - join_me_on_diaspora: "Придружи ми Ñе на diaspora*" - remote_friend: - invite: "Позови" - not_on_diaspora: "Ðије још на diaspora*" - resend: "Пошаљи поново" settings: "Подешавања" shared: - add_contact: - add_new_contact: "Додај нови контакт" - create_request: "Пронађи помоћу diaspora* ID" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "УнеÑи diaspora* кориÑничко име:" - know_email: "Знате њихову email адреÑу? Требали биÑте их позвати" - aspect_dropdown: - add_to_aspect: "Додај контакт" - contact_list: - all_contacts: "Сви контакти" invitations: by_email: "Помоћу email" - dont_have_now: "Тренутно нема, али уÑкоро Ñтиже још позивница!" - from_facebook: "Са ФејÑбука" - invite_someone: "Позовите некога" invite_your_friends: "Позовите пријатеље" invites: "Захтеви" - invites_closed: "Захтеви Ñу тренутно затворени за овај diaspora под" public_explain: outside: "Јавне поруке биће видљиве ван diaspora*." share: "Подели" title: "Уреди повезане ÑервиÑе" visibility_dropdown: "КориÑтите овај падајући мени како биÑте променили видљивоÑÑ‚ вашег поÑта. (Предлажемо да први буде јаван.)" publisher: - all: "Сви" - all_contacts: "Сви контакти" discard_post: "Одбаци објаву" - make_public: "Учини јавним" new_user_prefill: invited_by: "Хвала на позиву, " posting: "Објављујем..." - publishing_to: "Објави ка: " share: "Дели" - share_with: "Дели Ñа" whats_on_your_mind: "Шта вам је на уму?" - reshare: - reshare: "Подели" - stream_element: - connect_to_comment: "Повежите Ñе Ñа овим кориÑником како биÑте коментариÑали њихову објаву" - currently_unavailable: "КоментариÑање тренутно недоÑтупно" - dislike: "Ðе Ñвиђа ми Ñе" - hide_and_mute: "Сакриј и утишај објаву" - like: "Свиђа ми Ñе" - show: "Прикажи" - unlike: "Ðе Ñвиђа ми Ñе" - status_messages: - destroy: - failure: "ÐеуÑпело бриÑање објаве" - helper: - no_message_to_display: "Ðема порука за приказати." - stream_helper: - hide_comments: "Сакриј Ñве коментаре" streams: comment_stream: title: "КоментариÑане објаве" @@ -459,14 +278,9 @@ sr: follow: "Пратите" public: title: "Јавна активноÑÑ‚" - tag_followings: - create: - none: "Ðе можете пратити празну објаву!" tags: show: none: "Празна ознака не поÑтоји!" - terms_and_conditions: "УÑлови коришћења" - undo: "Врати?" username: "КориÑничко име" users: edit: @@ -475,9 +289,7 @@ sr: change_password: "Промени лозинку" close_account_text: "Затвори налог" current_password: "Тренутна лозинка" - download_photos: "Преузми моје фотографије" edit_account: "Уреди налог" new_password: "Ðова лозинка" your_email: "Ваш email" - your_handle: "Ваш diaspora* ID" - welcome: "Добородошли!" \ No newline at end of file + your_handle: "Ваш diaspora* ID" \ No newline at end of file diff --git a/config/locales/diaspora/sv.yml b/config/locales/diaspora/sv.yml index 999f6660e879354786ddf6150972ebbdd3dd3e7a..da01b223ecb0c241c0482b0435312f1903f8f916 100644 --- a/config/locales/diaspora/sv.yml +++ b/config/locales/diaspora/sv.yml @@ -6,11 +6,8 @@ sv: _applications: "Applikationer" - _comments: "Kommentarer" _contacts: "Kontakter" _help: "Hjälp" - _home: "Hem" - _photos: "Bilder" _services: "Tjänster" _statistics: "Statistik" _terms: "Användningsvillkor" @@ -53,12 +50,19 @@ sv: taken: "används redan." admins: admin_bar: + dashboard: "Instrumentpanel" pages: "Sidor" + pod_network: "Podnätverk" pod_stats: "Podstatistik" report: "Anmälningar" sidekiq_monitor: "Sidekiq-övervakare" user_search: "Användarsökning" weekly_user_stats: "Veckovis användarstatistik" + dashboard: + fetching_diaspora_version: "Listar ut senaste versionen av Diaspora*..." + pod_status: "Podstatus" + pods: + pod_network: "Podnätverk" stats: 2weeks: "TvÃ¥ veckor" 50_most: "De 50 populäraste taggarna" @@ -92,6 +96,7 @@ sv: email: "E-post" guid: "Globalt identifieringsnummer (GUID)" id: "id" + invite_token: "Inbjudningskort" last_seen: "Sedd senast" ? "no" : Nej @@ -109,7 +114,10 @@ sv: are_you_sure_unlock_account: "Är du säker pÃ¥ att du vill lÃ¥sa upp detta konta?" close_account: "Ta bort konto" email_to: "Skicka ett e-brev för att bjuda in" + invite: "Bjud in" + lock_account: "LÃ¥s konto" under_13: "Visa användare som är yngre än 13 Ã¥r" + unlock_account: "LÃ¥s upp konto" users: one: "En användare hittades" other: "%{count} användare hittades" @@ -125,13 +133,63 @@ sv: other: "Antalet nya användare denna vecka: %{count}" zero: "Antalet nya användare denna vecka: inga" current_server: "Det aktuella serverdatumet är %{date}" - ago: "%{time} sedan" all_aspects: "Alla aspekter" - application: - helper: - unknown_person: "Okänd person" - video_title: - unknown: "Okänd videotitel" + api: + openid_connect: + authorizations: + destroy: + fail: "Försöket att upphäva auktorisering med id %{id} misslyckades." + new: + access: "%{name} vill ha tillgÃ¥ng till:" + approve: "Godkänn" + bad_request: "Klient-id eller omdirigerings-URI fattas." + client_id_not_found: "Ingen klient med client_id %{client_id} med omdirigerings-URI %{redirect_uri} funnen." + deny: "Neka" + no_requirement: "%{name} kräver inga tillstÃ¥nd." + redirection_message: "Är du säker pÃ¥ att du vill ge tillgÃ¥ng till %{redirect_uri}?" + error_page: + contact_developer: "Du borde kontakta tillämpningsutvecklaren och bifoga följande felmeddelande:" + could_not_authorize: "Denna tillämpning kunde inte auktoriseras." + login_required: "Du mÃ¥ste logga in innan du kan auktorisera denna tillämpning." + title: "Rackarns! NÃ¥got gick Ã¥t pipan." + scopes: + aud: + description: "Detta skänker aud-rättigheter till applikationen" + name: "aud" + name: + description: "Det här beviljar namnrättigheter till applikationen." + name: "namn" + nickname: + description: "Det här beviljar smeknamnsrättigheter till applikationen." + name: "smeknamn" + openid: + description: "Detta lÃ¥ter tillämpningar att läsa din grundprofil." + name: "grundprofil" + picture: + description: "Det här beviljar bildrättigheter till applikationen." + name: "bild" + profile: + description: "Det här beviljar rättigheter att se din utökade profil till applikationen." + name: "utökad profil" + read: + description: "Detta lÃ¥ter tillämpningar att läsa din ström, dina konversationer och hela din profil." + name: "läs profil, ström och konversationer" + sub: + description: "Det här skänker dig underprivilegier för denna tillämpning." + name: "under" + write: + description: "Detta lÃ¥ter tillämpningar att skicka nya bilder, författa konversationer och skicka reaktioner" + name: "göra inlägg, konversationer och reaktioner" + user_applications: + index: + access: "%{name} har tillgÃ¥ng till:" + edit_applications: "Tillämpningar" + no_requirement: "%{name} kräver inga tillstÃ¥nd." + title: "Auktoriserade tillämpningar" + no_applications: "Du har inga auktoriserade tillämpningar." + policy: "Kika pÃ¥ tillämpningens integritetsriktlinjer" + revoke_autorization: "Upphäv" + tos: "Kika pÃ¥ tillämpningens användarvillkor." are_you_sure: "Är du säker?" are_you_sure_delete_account: "Är du säker pÃ¥ att du vill avsluta ditt konto? Detta kan inte Ã¥ngras!" aspect_memberships: @@ -147,48 +205,27 @@ sv: success: "Personen lades till i aspekten." aspect_listings: add_an_aspect: "+ Lägg till en aspekt" - deselect_all: "Avmarkera alla" - edit_aspect: "Ändra %{name}" - select_all: "Markera alla" aspect_stream: make_something: "Skapa nÃ¥gonting" stay_updated: "HÃ¥ll dig uppdaterad" stay_updated_explanation: "Din huvudström innefattar alla dina kontakter, de taggar du följer och inlägg frÃ¥n nÃ¥gra kreativa medlemmar i gemenskapen." - contacts_not_visible: "Kontakterna i den här aspekten kommer inte att kunna se varandra." - contacts_visible: "Kontakterna i denna aspekt kommer vara synliga för varandra." - create: - failure: "Aspekten kunde inte skapas." - success: "Din nya aspekt %{name} har skapats" destroy: failure: "%{name} är inte tom och kan därför inte tas bort" success: "%{name} togs bort." success_auto_follow_back: "%{name} togs bort. Du använde denna aspekt för att automatiskt följa dem som följde dig. Välj en annan aspekt för dessa bland dina inställningar." edit: - aspect_chat_is_enabled: "Kontakterna i denna aspekt har tillÃ¥telse chatta med dig." - aspect_chat_is_not_enabled: "Kontakter i denna aspekt har inte privilegier för att chatta med dig." aspect_list_is_not_visible: "Aspektens kontakter kan inte se vilka som hör till aspekten." aspect_list_is_visible: "Kontakter i denna aspekt är synliga för varandra." confirm_remove_aspect: "Är du säker pÃ¥ att du vill ta bort aspekten?" - grant_contacts_chat_privilege: "Vill du ge kontakter i aspekten chatprivilegier?" - make_aspect_list_visible: "Ska kontakterna i denna aspekt vara synliga för varandra?" - remove_aspect: "Ta bort den här aspekten" rename: "Byt namn" - set_visibility: "Ange synlighetsgrad" update: "Uppdatera" updating: "Uppdaterar" index: - diaspora_id: - content_1: "Ditt Diaspora*-id är:" - content_2: "Med hjälp av det, kan alla hitta dig pÃ¥ Diaspora*." - heading: "Diaspora*-id" donate: "Donera" - handle_explanation: "Detta är ditt Diaspora*-id. Det är det här du ska ge till dina vänner, om du vill att de ska lägga till dig pÃ¥ Diaspora*." help: any_problem: "Har du nÃ¥got problem?" contact_podmin: "Kontakta din pods administratör." do_you: "Har du:" - email_feedback: "%{link}a din respons, om du föredrar det" - email_link: "E-post" feature_suggestion: "... har du ett %{link}-förslag?" find_a_bug: "... hittat en %{link}?" have_a_question: "... en %{link}?" @@ -201,31 +238,21 @@ sv: tutorial_link_text: "Nybörjar-guider" tutorials_and_wiki: "%{faq}, %{tutorial} och %{wiki} hjälper dig komma igÃ¥ng." introduce_yourself: "Det här är ditt flöde. Hoppa in och presentera dig själv." - keep_diaspora_running: "HÃ¥ll igÃ¥ng Diaspora*'s utveckling med en mÃ¥natlig donation!" keep_pod_running: "HÃ¥ll %{pod} igÃ¥ng och ge servrarna sin kaffefix med en mÃ¥natlig donation!" new_here: follow: "Följ %{link} och hälsa nya användare välkomna!" learn_more: "Läs mer" title: "Välkomna nya användare" - no_contacts: "Inga kontakter" - no_tags: "+ Hitta en tagg att följa" - people_sharing_with_you: "Personer som delar med dig" - post_a_message: "Skriv ett inlägg >>" services: content: "Du kan koppla ihop Diaspora* med följande tjänster:" heading: "Ihopkopplade tjänster" - unfollow_tag: "Sluta följa #%{tag}" welcome_to_diaspora: "Välkommen till Diaspora*, %{name}!" - new: - create: "Skapa" - name: "Namn (endast synligt för dig)" no_contacts_message: community_spotlight: "Gemenskapens rampljus" + invite_link_text: "inbjudan" or_spotlight: "Du kan ocksÃ¥ dela med %{link}" - try_adding_some_more_contacts: "Du kan söka efter eller bjuda in kontakter." + try_adding_some_more_contacts: "Du kan söka efter eller %{invite_link} kontakter." you_should_add_some_more_contacts: "Du borde lägga till fler kontakter!" - no_posts_message: - start_talking: "Ingen har sagt nÃ¥gonting än!" seed: acquaintances: "Bekanta" family: "Familj" @@ -234,34 +261,26 @@ sv: update: failure: "Det namn du valde för din aspekt, %{name}, var för lÃ¥ngt för att kunna sparas." success: "Din aspekt %{name} har nu ändrats." - back: "Tillbaka" blocks: create: - failure: "Jag kunde inte ignorera den användaren. #undvik" + failure: "Jag kunde inte ignorera den användaren. #undvik" success: "NÃ¥väl, du kommer inte att se den användaren i din ström igen. #silencio!" destroy: - failure: "Jag kunde inte sluta ignorera den användaren. #undvik" + failure: "Jag kunde inte sluta ignorera den användaren. #undvik" success: "LÃ¥t oss se vad de har att säga! #hälsa" bookmarklet: explanation: "Bokmärk %{link} för att kunna göra inlägg pÃ¥ Diaspora* varifrÃ¥n som helst." heading: "Bookmarklet" post_something: "Dela pÃ¥ Diaspora*" - post_success: "Skickat! Stänger!" cancel: "Avbryt" comments: new_comment: comment: "Kommentera" commenting: "Kommenterar..." - one: "en kommentar" - other: "%{count} kommentarer" - zero: "Inga kommentarer" contacts: - create: - failure: "Kunde inte skapa kontakt" index: add_a_new_aspect: "Lägg till en ny aspekt" add_contact: "Lägg till kontakt" - add_to_aspect: "Lägg kontakter i %{name}" all_contacts: "Alla kontakter" community_spotlight: "Gemenskapens rampljus" my_contacts: "Mina kontakter" @@ -269,19 +288,13 @@ sv: no_contacts_in_aspect: "Den här aspekten är för närvarande tom. Nedanför kan du se en lista med dina kontakter som du kan lägga till." no_contacts_message: "Kolla in %{community_spotlight}" only_sharing_with_me: "Delar enbart med mig" - remove_contact: "Ta bort kontakt" start_a_conversation: "Inled en konversation" title: "Kontakter" user_search: "Användarsökning" - your_contacts: "Dina kontakter" - sharing: - people_sharing: "Personer som delar med dig:" spotlight: community_spotlight: "Gemenskapens rampljus" suggest_member: "FöreslÃ¥ en medlem" conversations: - conversation: - participants: "Deltagare" create: fail: "Ogiltigt meddelande" no_contact: "HallÃ¥ där! Du mÃ¥ste först lägga till kontakten." @@ -289,20 +302,13 @@ sv: destroy: delete_success: "Konversationen har tagits bort" hide_success: "Konversationen har döljts" - helper: - new_messages: - one: "Ett nytt meddelande" - other: "%{count} nya meddelanden" - zero: "Inga nya meddelanden" index: conversations_inbox: "Konversationer – Inkorg" - create_a_new_conversation: "PÃ¥börja en ny konversation" inbox: "Inkorg" new_conversation: "Ny konversation" - no_conversation_selected: "Ingen konversation vald" no_messages: "Inga meddelanden" new: - abandon_changes: "Ändringarna kommer inte sparas. Vill du fortsätta ändÃ¥?" + message: "Meddelande" send: "Skicka" sending: "Skickar..." subject: "Ämne" @@ -313,6 +319,7 @@ sv: show: delete: "Ta bort konversationen" hide: "Dölj och tysta konversation" + last_message: "Senast mottagna meddelande mottogs %{timeago}" reply: "Besvara" replying: "Svarar..." date: @@ -325,10 +332,7 @@ sv: error_messages: helper: correct_the_following_errors_and_try_again: "Rätta till följande fel och försök igen." - invalid_fields: "Ogiltiga uppgifter" - login_try_again: "Var god <a href='%{login_link}'>logga in</a> och försök igen." - post_not_public: "Du försöker läsa ett inlägg som inte är publikt." - post_not_public_or_not_exist: "Inlägget du försöker att granska är inte publikt. Det, eller sÃ¥ finns det inte!" + need_javascript: "Denna webbplats behöver JavaScript för att fungera ordentligt. Har du inaktiverat JavaScript, fÃ¥r du vara sÃ¥ snäll att aktivera det och ladda om sidan." fill_me_out: "Fyll i mig" find_people: "Hitta personer eller #taggar" help: @@ -548,84 +552,77 @@ sv: tutorial: "Nybörjar-guide" tutorials: "nybörjar-guider" wiki: "wiki" - hide: "Göm" - ignore: "Ignorera" + home: + default: + be_who_you_want_to_be: "Var vem du vill" + be_who_you_want_to_be_info: "MÃ¥nga andra nätverk kräver att du använder din riktiga identitet. Där skiljer sig Diaspora*. Du fÃ¥r själv välja vem du vill vara och dela med av sÃ¥ mycket du vill. Det handlar om hur du vill interagera med andra människor." + byline: "Den sociala världen pÃ¥ nätet där du har kontrollen." + choose_your_audience: "Välj din publik" + choose_your_audience_info: "Med Diasporas aspekter, kan du välja med vilka du delar med dig till. Du kan vara hur offentlig eller privat du vill. Dela med dig av roliga bilder med hela världen eller en hemlighet med dina närmaste vänner. Du bestämmer." + headline: "Välkommen till %{pod_name}" + own_your_data: "Du äger din data" + own_your_data_info: "MÃ¥nga nätverk använder din data för att tjäna pengar genom att analysera dig och använda din data för att sälja reklam riktad mot dig. Diaspora* använder inte din data för nÃ¥got annat än att lÃ¥ta dig kommunicera med andra." + podmin: + admin_panel: "administratörspanel" + byline: "Du är just pÃ¥ väg att förändra Internet. Är du redo för att komma igÃ¥ng?" + configuration_info: "Öppna %{database_path} och %{diaspora_path} i en textredigerare och gÃ¥ igenom dem noggrant. De är fyllda med kommentarer." + configure_your_pod: "Konfigurera din pod" + contact_irc: "kontakta oss genom IRC" + contribute: "Bidra" + contribute_info: "Gör Diaspora* ännu bättre! Hittar du nÃ¥gra buggar, %{report_bugs}." + create_an_account: "Skapa ett konto" + create_an_account_info: "%{sign_up_link} för ett nytt konto." + faq_for_podmins: "Vanliga frÃ¥gor för podadministratörer i vÃ¥r wiki" + getting_help: "FÃ¥ hjälp" + getting_help_info: "Vi har listat nÃ¥gra %{faq} med ytterligare rÃ¥d och problemlösningar för de främsta problemen. Du är även välkommen pÃ¥ %{irc}." + headline: "Välkommen, vän." + make_yourself_an_admin: "Gör dig till administratör" + make_yourself_an_admin_info: "Du hittar instruktioner pÃ¥ %{wiki}. Detta skapar en administratörslänk i din användarmeny när du har loggat in. Där ges du verktyg för att söka och finna statistik för din pod. För fler detaljer om driftaspekterna för din pod, gÃ¥ till %{admin_panel}." + report_bugs: "rapportera dem" + update_instructions: "uppdateringsinstruktioner frÃ¥n Diasporawikin." + update_your_pod: "Uppdatera din pod" + update_your_pod_info: "Du finner %{update_instructions}" invitation_codes: - excited: "%{name} är glad för att du är här." not_valid: "Inbjudningskoden är inte längre giltig." invitations: a_facebook_user: "En Facebookanvändare" check_token: not_found: "Inbjudan kan inte hittas" create: - already_contacts: "Du är redan i kontakt med denna person" - already_sent: "Du har redan bjudit in denna person." empty: "Var snäll och ange minst en e-postadress." no_more: "Du har inga fler inbjudningar." note_already_sent: "Inbjudningar har redan skickats till: %{emails}" - own_address: "Du kan inte skicka inbjudan till din egen adress." rejected: "Det är problem med följande e-postadresser: " sent: "Inbjudningarna har skickats till: %{emails}" - edit: - accept_your_invitation: "Accepterat din inbjudan" - your_account_awaits: "Ditt konto väntar pÃ¥ dig!" new: - already_invited: "Följande har inte accepterat din inbjudan:" - aspect: "Aspekt" - check_out_diaspora: "Kolla in Diaspora*!" codes_left: one: "%{count} inbjudning kvar för denna kod." other: "%{count} inbjudningar kvar för denna kod." zero: "Det finns inga inbjudningar kvar för denna kod." comma_separated_plz: "Du kan ange flera e-postadresser Ã¥tskilda av kommatecken." - if_they_accept_info: "om de accepterar, kommer de läggas till i den aspekt du angav vid inbjudan." invite_someone_to_join: "Bjud in nÃ¥gon till Diaspora*!" language: "SprÃ¥k" paste_link: "Ge denna länk till dina vänner för att bjuda in dem till Diaspora*, eller skicka länken till dem med e-post." - personal_message: "Personligt meddelande" - resend: "Skicka igen" send_an_invitation: "Skicka en inbjudan" - send_invitation: "Skicka inbjudan" sending_invitation: "Sänder invitation..." - to: "Till" layouts: application: back_to_top: "Ã…ter till början" + be_excellent: "Var förträffliga mot varandra! ♥" powered_by: "Drivs med Diaspora*" public_feed: "Offentligt Diaspora*-flöde för %{name}" source_package: "Ladda ned källkodspaketet" statistics_link: "Serverstatistik" toggle: "SlÃ¥ om mobiltelefonanpassning" whats_new: "Vad är nytt?" - your_aspects: "Dina aspekter" header: - admin: "Administratör" - blog: "Blogg" code: "Källkod" - help: "Hjälp" - login: "Logga in" logout: "Logga ut" profile: "Profil" - recent_notifications: "Tidigare" settings: "Inställningar" - view_all: "Visa alla" - likes: - likes: - people_dislike_this: - one: "En person ogillar det här" - other: "%{count} personer ogillar det här" - zero: "Inga ogillar det här" - people_like_this: - one: "En person gillar det här" - other: "%{count} personer gillar det här" - zero: "Inga personer gillar det här" - people_like_this_comment: - one: "En gillar" - other: "%{count} gillar" - zero: "Ingen gillar" + toggle_navigation: "Skifta navigation" limited: "Begränsad" more: "Mer" - next: "Nästa" no_results: "Inga sökresultat" notifications: also_commented: @@ -640,14 +637,6 @@ sv: one: "%{actors} har kommenterat %{post_link}." other: "%{actors} har kommenterat %{post_link}." zero: "Ingen har kommenterat %{post_link}." - helper: - new_notifications: - few: "%{count} nya notiser" - many: "%{count} nya notiser" - one: "En ny notis" - other: "%{count} nya notiser" - two: "TvÃ¥ nya notiser" - zero: "Inga nya notiser" index: all_notifications: "Alla notiser" also_commented: "Även kommenterade" @@ -709,7 +698,6 @@ sv: a_limited_post_comment: "Du har en ny kommentar till ett begränsat inlägg pÃ¥ Diaspora*." a_post_you_shared: "ett inlägg." a_private_message: "Du har fÃ¥tt ett nytt privat meddelande pÃ¥ Diaspora*." - accept_invite: "Acceptera din Diaspora*-inbjudan!" also_commented: limited_subject: "Du har fÃ¥tt en kommentar kommenterad" click_here: "Klicka här" @@ -767,14 +755,15 @@ sv: message: |- Hej! - Du har fÃ¥tt en inbjudan till Diaspora*! + Du har fÃ¥tt en inbjudan till Diaspora* frÃ¥n %{diaspora_id}! - Använd pÃ¥ länken nedanför för att börja + Använd länken nedanför för att börja [%{invite_url}][1] + Annars kan du lägga till %{diaspora_id} bland dina kontakter, om du redan har ett konto. - Med vänlig hälsning, + Hjärtliga hälsningar, Diasporas e-postrobot! @@ -789,10 +778,10 @@ sv: view_post: "Se inlägg >" mentioned: limited_post: "Du nämndes i ett begränsat inlägg." - mentioned: "nämnde dig i ett inlägg:" subject: "%{name} har nämnt dig pÃ¥ Diaspora*" private_message: reply_to_or_view: "Svara pÃ¥ eller läs denna konversation >" + subject: "Du fÃ¥tt ett förtroligt meddelande" remove_old_user: body: |- Hej. @@ -815,6 +804,8 @@ sv: %{type} med id:et %{id} var märkt som stötande. + Orsak: "%{reason}" + [%{url}][1] Var god och se över det snarast! @@ -843,20 +834,9 @@ sv: to_change_your_notification_settings: "för att ändra dina notisinställningar" nsfw: "Vuxet material" ok: "Ok" - or: "eller" - password: "Lösenord" - password_confirmation: "Bekräfta lösenord" people: add_contact: invited_by: "Du blev inbjuden av" - add_contact_small: - add_contact_from_tag: "Lägg till kontakt frÃ¥n tagg" - aspect_list: - edit_membership: "Redigera medlemskap för aspekt" - helper: - is_not_sharing: "%{name} delar inte sina uppdateringar med dig." - is_sharing: "%{name} delar med sig till dig" - results_for: " resultat för %{params}" index: couldnt_find_them: "Fann du dem inte?" looking_for: "Letar du efter inlägg som taggats med %{tag_link}?" @@ -866,87 +846,43 @@ sv: search_handle: "Använd deras Diaspora*-id (användarnamn@pod.domän) för att vara säker pÃ¥ att hitta dina kamrater." searching: "Söker, var god och vänta..." send_invite: "Hittar du ingen? Sänd en inbjudan!" - one: "En person" - other: "%{count} personer" person: - add_contact: "Lägg till kontakt" - already_connected: "Redan ansluten" - pending_request: "Väntande förfrÃ¥gningar" thats_you: "Det är du!" profile_sidebar: bio: "Biografi" born: "Födelsedag" - edit_my_profile: "Ändra min profil" gender: "Kön" - in_aspects: "I aspekter" location: "Plats" - photos: "Foton" - remove_contact: "Ta bort kontakt" - remove_from: "Ta bort %{name} frÃ¥n %{aspect}?" show: closed_account: "Detta konto har stängts." does_not_exist: "Personen finns inte!" has_not_shared_with_you_yet: "%{name} har inte delat nÃ¥gra inlägg med dig än!" - ignoring: "Du ignorerar alla inlägg frÃ¥n %{name}." - incoming_request: "%{name} vill dela med dig" - mention: "Omnämn" - message: "Skicka meddelande" - not_connected: "Du delar inte med dig till den här personen" - recent_posts: "Senaste inlägg" - recent_public_posts: "Senaste publika inläggen" - return_to_aspects: "Ã…tergÃ¥ till översikten" - see_all: "Visa alla" - start_sharing: "Börja dela" - to_accept_or_ignore: "för att acceptera eller ignorera det." - sub_header: - add_some: "Lägg till nÃ¥gra" - edit: "Redigera" - you_have_no_tags: "Du har inga taggar!" - webfinger: - fail: "FörlÃ¥t, vi kunde inte hitta %{handle}." - zero: "Inga" photos: - comment_email_subject: "Ett foto av %{name}" create: integrity_error: "Fotouppladdning misslyckades. Är du säker pÃ¥ att det var en bild?" runtime_error: "Fotouppladdning misslyckades. Har du säkerhetsbältet pÃ¥?" type_error: "Fotouppladdning misslyckades. Är du säker pÃ¥ att en bild blev tillagd?" destroy: notice: "Fotot är borttaget." - edit: - editing: "Ändrar" - new: - back_to_list: "Tillbaka till listan" - new_photo: "Nytt foto" - post_it: "Skicka!" new_photo: empty: "{file} är tom, välj om filerna utan att välja denna." invalid_ext: "{file} har en ogiltig filändelse. Endast {extensions} är tillÃ¥tna." size_error: "{file} är för stor, maximal tillÃ¥ten filstorlek är {sizeLimit}." new_profile_photo: - or_select_one_existing: "eller välj ett av dina tidigare %{photos}" upload: "Ladda upp en ny profilbild!" - photo: - view_all: "Visa alla %{name}s bilder" show: - collection_permalink: "Permanent samlingslänk" - delete_photo: "Ta bort bild" - edit: "Ändra" - edit_delete_photo: "Ändra beskrivning / ta bort bild" - make_profile_photo: "Använd som profilbild" show_original_post: "Visa det ursprungliga inlägget" - update_photo: "Uppdatera bild" - update: - error: "Misslyckades med att ändra fotot." - notice: "Fotot är nu uppdaterat." + polls: + votes: + one: "En röst än sÃ¥ länge." + other: "%{count} röster har lagts." + zero: "Inga röster sÃ¥ här lÃ¥ngt." posts: presenter: title: "Ett inlägg frÃ¥n %{name}" show: - destroy: "Ta bort" forbidden: "Du har inte tillÃ¥telse att göra sÃ¥." - not_found: "Tyvärr, men vi kan inte hitta inlägget." - permalink: "Permanent länk" + location: "Sänt ifrÃ¥n: %{location}" photos_by: few: "%{count} foton av %{author}" many: "%{count} foton av %{author}" @@ -955,19 +891,24 @@ sv: two: "TvÃ¥ foton av %{author}" zero: "Inga foton av %{author}" reshare_by: "Delades vidare av %{author}" - previous: "Förra" privacy: "Sekretess" - privacy_policy: "Integritetspolicy" profile: "Profil" profiles: edit: allow_search: "TillÃ¥t andra att söka efter dig inom Diaspora*" - edit_profile: "Redigera profil" + basic: "Min basprofil" + basic_hint: "Varje del av din profil är frivillig. Din basprofil kommer alltid att vara publik, för vem som helst att skÃ¥da." + extended: "Min utökade profil" + extended_hint: "Tryck pÃ¥ knappen för att göra din utökade profil tillgänglig för allmänheten. Detta betyder att profilen kommer synas för hela Internet. Begränsad Ã¥tkomst kommer Ã¥ andra sidan leda till att bara dem du delar information med explicit ser den." + extended_visibility_text: "Visibilitet för din utökade profil:" first_name: "Förnamn" last_name: "Efternamn" + limited: "Begränsad" nsfw_check: "Markera allting som jag delar som olämpligt för arbetsplatser (NSFW)" nsfw_explanation: "NSFW (\"not safe for work\", inte arbetsplatslämpligt) är Diasporas självständiga samfund för innehÃ¥ll som kanske inte passar sig pÃ¥ arbetsplatser. Om du har planer pÃ¥ att ofta dela med dig av material som är av denna natur, var god och använd inställningen sÃ¥ att dina inlägg döljs i personers strömmar, tills de själva väljer att se inläggen." nsfw_explanation2: "Om du inte använder inställningen, var god och använd taggen #nsfw när du delar sÃ¥dant material." + public: "Publik" + settings: "Profilinställningar" update_profile: "Uppdatera profil" your_bio: "Din biografi" your_birthday: "Din födelsedag" @@ -975,8 +916,6 @@ sv: your_location: "Din plats" your_name: "Ditt namn" your_photo: "Ditt foto" - your_private_profile: "Din privata profil" - your_public_profile: "Din publika profil" your_tags: "Beskriv dig själv med fem ord" your_tags_placeholder: "Som #filmer #kattungar #resande #lärare #newyork" update: @@ -991,26 +930,16 @@ sv: closed: "Registreringsformuläret är avstängt pÃ¥ den här Diaspora*-servern." create: success: "Du har nu gÃ¥tt med i Diaspora*!" - edit: - cancel_my_account: "Avsluta mitt konto" - edit: "Ändra %{name}" - leave_blank: "(lämna tomt om du inte vill ändra det)" - password_to_confirm: "(ditt nuvarande lösenord krävs för att bekräfta ändringar)" - unhappy: "Är du missnöjd?" - update: "Uppdatera" invalid_invite: "Den angivna inbjudningslänken gäller inte längre." new: - create_my_account: "Skapa mitt konto!" email: "E-post" enter_email: "Ange en e-postadress" enter_password: "Skriv in ett lösenord, Ã¥tminstone sex tecken lÃ¥ngt" enter_password_again: "Skriv in samma lösenord som tidigare" enter_username: "Välj ett användarnamn (endast bokstäver, nummer och understreck)" - join_the_movement: "GÃ¥ med i rörelsen!" password: "Lösenord" password_confirmation: "Lösenordsbekräftelse" - sign_up: "Registrera" - sign_up_message: "Socialt nätverkande med ♥" + sign_up: "Skapa konto" submitting: "Sänder..." terms: "Skapar du ett konto, accepterar du vÃ¥ra %{terms_link}." terms_link: "användarvillkor" @@ -1023,45 +952,18 @@ sv: post_label: "<b>Inlägg</b>: %{title}" reason_label: "Orsak: %{text}" reported_label: "<b>Anmält av</b> %{person}" + reported_user_details: "Detaljer gällande anmäld användare" review_link: "Markera som genomgÃ¥nget" status: - created: "En anmälan har skapats" destroyed: "Inlägget har förintats" failed: "NÃ¥gonting gick snett" - marked: "Anmälningen har markerats som genomgÃ¥nget" title: "Översikt av anmälningar" - requests: - create: - sending: "Skickar" - sent: "Du har begärt att dela med %{name}. De kommer att fÃ¥ veta det nästa gÃ¥ng som de loggar in pÃ¥ Diaspora." - destroy: - error: "Var god välj en aspekt!" - ignore: "Ignorerad kontaktförfrÃ¥gan." - success: "Nu delar du." - helper: - new_requests: - one: "En ny förfrÃ¥gan!" - other: "%{count} nya förfrÃ¥gningar!" - zero: "Inga nya förfrÃ¥gningar" - manage_aspect_contacts: - existing: "Befintliga kontakter" - manage_within: "Hantera kontakter inom" - new_request_to_person: - sent: "Skickat!" reshares: comment_email_subject: "%{resharer} har delat vidare ett inlägg av %{author}" - create: - failure: "Ett fel uppstod när inlägget skulle spridas vidare." reshare: deleted: "Det ursprungliga inlägget är raderat." - reshare: - one: "En har delat vidare" - other: "%{count} har delat vidare" - zero: "Dela vidare" reshare_confirmation: "Vill du dela vidare %{author}s inlägg?" - reshare_original: "Dela originalet vidare" reshared_via: "Delades vidare via" - show_original: "Visa det ursprungliga inlägget" search: "Sök" services: create: @@ -1073,10 +975,6 @@ sv: success: "Du har nu kopplat bort tjänsten." failure: error: "Det blev nÃ¥got fel vid anslutning till tjänsten" - finder: - fetching_contacts: "Diaspora fyller listan med dina %{service}-vänner. Var god och kom tillbaka om en stund." - no_friends: "Hittade inga vänner frÃ¥n Facebook." - service_friends: "%{service}-vänner" index: connect: "Anslut" disconnect: "Koppla frÃ¥n" @@ -1086,33 +984,16 @@ sv: not_logged_in: "För nuvarande inte inloggad." really_disconnect: "Vill du koppla frÃ¥n %{service}?" services_explanation: "Genom att ansluta till andra tjänster, möjliggör det dig att skicka dina inlägg till dem när du skriver pÃ¥ Diaspora*." - inviter: - click_link_to_accept_invitation: "Följ länken för att acceptera din inbjudan" - join_me_on_diaspora: "GÃ¥ med mig pÃ¥ Diaspora*" + share_to: "Dela till %{provider}" + title: "Hantera anslutna tjänster" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "Wordpress" - remote_friend: - invite: "Bjud in" - not_on_diaspora: "Ännu inte pÃ¥ Diaspora*" - resend: "Skicka igen" settings: "Inställningar" - share_visibilites: - update: - post_hidden_and_muted: "%{name}s inlägg har dolts kommer inte längre ge notiser." - see_it_on_their_profile: "Om du vill se uppdateringar för detta inlägg, besök %{name}s profilsida." shared: - add_contact: - add_new_contact: "Lägg till en ny kontakt" - create_request: "Sök pÃ¥ Diaspora*-id" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Ange ett användarnamn för Diaspora*:" - know_email: "Kan du deras e-postadress? Du borde bjuda in dem" - your_diaspora_username_is: "Ditt användarnamn pÃ¥ Diaspora* är: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Lägg till kontakt" mobile_row_checked: "%{name} (ta bort)" mobile_row_unchecked: "%{name} (lägg till)" toggle: @@ -1122,23 +1003,11 @@ sv: other: "I %{count} aspekter" two: "I %{count} aspekter" zero: "Lägg till kontakt" - contact_list: - all_contacts: "Alla kontakter" - footer: - logged_in_as: "Inloggad som %{name}" - your_aspects: "Dina aspekter" invitations: by_email: "Via e-post" - dont_have_now: "Du har inga inviter just nu, men fler kommer delas ut inom kort!" - from_facebook: "FrÃ¥n Facebook" - invitations_left: "%{count} kvar" - invite_someone: "Bjud in en kontakt" invite_your_friends: "Bjud in dina vänner" invites: "Inbjudningar" - invites_closed: "För närvarande är inbjudningar avstängda pÃ¥ denna Diaspora*-server" share_this: "Dela med dig av länken via e-post, din blog eller de sociala nätverken!" - notification: - new: "Ny %{type} frÃ¥n %{from}" public_explain: atom_feed: "Atom-flöde" control_your_audience: "Välj din publik" @@ -1150,12 +1019,9 @@ sv: title: "Hantera anslutna tjänster" visibility_dropdown: "Använd den här rullisten för att bestämma vilka som kan se ditt inlägg (vi föreslÃ¥r att du gör det här första inlägget publikt)." publisher: - all: "Samtliga" - all_contacts: "Alla kontakter" discard_post: "Släng inlägg" formatWithMarkdown: "Använd %{markdown_link} för att formatera dina inlägg." get_location: "Hämta din position" - make_public: "Gör publik" new_user_prefill: hello: "Hej allihop, jag är #%{new_user_tag}. " i_like: "Jag är intresserad av %{tags}." @@ -1163,36 +1029,14 @@ sv: newhere: "nyhär" poll: add_a_poll: "Lägg till en undersökning" - add_poll_answer: "Lägg till alternativ" - option: "Alternativ 1" - question: "FrÃ¥ga" - remove_poll_answer: "Ta bort alternativ" - post_a_message_to: "Skicka ett meddelande till %{aspect}" posting: "Skickar..." - preview: "Förhandsgranska" - publishing_to: "Publiceras pÃ¥: " remove_location: "Ta bort platsen" share: "Dela" - share_with: "Dela med" upload_photos: "Ladda upp foton" whats_on_your_mind: "Vad har du pÃ¥ hjärtat?" - reshare: - reshare: "Dela vidare" stream_element: - connect_to_comment: "Anslut till den här användaren för att kunna kommentera deras inlägg" - currently_unavailable: "Det gÃ¥r för närvarande inte att kommentera" - dislike: "Sluta gilla" - hide_and_mute: "Dölj och ignorera" - ignore_user: "Ignorera %{name}" - ignore_user_description: "Ignorera och ta bort användaren frÃ¥n alla aspekter?" - like: "Gilla" - nsfw: "Detta inlägg har blivit flaggat som olämpligt för arbetsplatser av dess författare. %{link}" - shared_with: "Delas med: %{aspect_names}" - show: "Visa" - unlike: "Sluta gilla" via: "Via %{link}" via_mobile: "Via mobiltelefon" - viewable_to_anyone: "Detta inlägg är synligt för alla pÃ¥ nätet" simple_captcha: label: "Skriv in koden i rutan:" message: @@ -1218,24 +1062,12 @@ sv: status_messages: create: success: "Lyckades nämna: %{names}" - destroy: - failure: "Kunde inte ta bort inlägget" - helper: - no_message_to_display: "Inget meddelande att visa." new: mentioning: "Nämner: %{person}" too_long: "Var god hÃ¥ll längden pÃ¥ meddelandet under %{count} tecken. Just nu är det %{current_length} tecken lÃ¥ngt." stream_helper: - hide_comments: "Dölj alla kommentarer" no_more_posts: "Du har nÃ¥tt strömmens slut." no_posts_yet: "Inga inlägg har gjorts än." - show_comments: - few: "Visa %{count} ytterligare kommentarer" - many: "Visa %{count} ytterligare kommentarer" - one: "Visa en ytterligare kommentar" - other: "Visa %{count} ytterligare kommentarer" - two: "Visa tvÃ¥ ytterligare kommentarer" - zero: "Inga fler kommentarer" streams: activity: title: "Min aktivitet" @@ -1262,13 +1094,6 @@ sv: tags: title: "Inlägg taggade med: %{tags}" tag_followings: - create: - failure: "Misslyckades med att följa #%{name}. Du kanske redan gör det." - none: "Du kan inte följa en tom tagg!" - success: "Hurra! Du följer nu #%{name}." - destroy: - failure: "Misslyckades att sluta följa #%{name}. Du kanske redan slutat följa det." - success: "SÃ¥där! Du följer inte längre #%{name}." manage: no_tags: "Du följer inga taggar." title: "Administrera taggar" @@ -1276,15 +1101,12 @@ sv: name_too_long: "Använd taggar med namn kortare än %{count} tecken. Just nu är den %{current_length} lÃ¥ng." show: follow: "Följ #%{tag}" - following: "Följer #%{tag}" none: "Den tomma taggen finns inte!" stop_following: "Sluta följa #%{tag}" tagged_people: one: "En person är taggad med %{tag}" other: "%{count} personer är taggade med %{tag}" zero: "Ingen har taggats med %{tag}" - terms_and_conditions: "Villkor" - undo: "Ã…ngra?" username: "Användarnamn" users: confirm_email: @@ -1299,13 +1121,13 @@ sv: auto_follow_aspect: "Aspekt för de användare som följts automatiskt:" auto_follow_back: "Följ automatiskt dem som börjar följa dig" change: "Ändra" + change_color_theme: "Byt färgtema" change_email: "Ändra e-postadress" change_language: "Ändra sprÃ¥k" change_password: "Ändra lösenord" character_minimum_expl: "mÃ¥ste vara Ã¥tminstone sex tecken" close_account: dont_go: "Snälla, lämna oss inte!" - if_you_want_this: "Är du säker pÃ¥ din sak, skriv ditt lösenord nedan och tryck pÃ¥ \"Stäng kontot\"" lock_username: "Ditt användarnamn kommer att lÃ¥sas för att inte kunna användas pÃ¥ denna pod igen." locked_out: "Du kommer att loggas ut och lÃ¥sas frÃ¥n ditt konto tills det har blivit borttaget." make_diaspora_better: "Det vore fint om du istället för att lämna diaspora* ville hjälpa oss att utveckla och göra det bättre. Men om du nu verkligen bestämt dig kommer följande hända:" @@ -1318,14 +1140,12 @@ sv: current_password_expl: "den som du loggar in med..." download_export: "Ladda ned min profil" download_export_photos: "Ladda ned mina bilder" - download_photos: "Ladda ned mina foton" edit_account: "Ändra konto" email_awaiting_confirmation: "Vi har skickat dig en länk till %{unconfirmed_email} för aktivering. Innan du har aktiverat din nya adress, kommer vi fortsätta att använda %{email}." export_data: "Exportera data" export_in_progress: "Just nu behandlar vi din data. Kom tillbaka om ett slag." export_photos_in_progress: "Vi behandlar just nu dina bilder. Kom tillbaka om en stund." following: "Delningsinställningar" - getting_started: "Inställningar för nya användare" last_exported_at: "(Senast uppdaterad %{timestamp})" liked: "nÃ¥gon gillar dina inlägg" mentioned: "du nämns i ett inlägg." @@ -1352,19 +1172,20 @@ sv: connect_to_facebook_link: "Länka ihop ditt Facebook-konto" hashtag_explanation: "Taggar gör det möjligt att diskutera och följa dina intressen. Det är ocksÃ¥ ett bra sätt att lära känna nya människor pÃ¥ Diaspora*." hashtag_suggestions: "Testa att följa taggar sÃ¥som #konst, #film, #gif, etc." - saved: "Sparat!" well_hello_there: "Hej pÃ¥ dig!" what_are_you_in_to: "Vad gillar du?" who_are_you: "Vem är du?" privacy_settings: ignored_users: "Ignorerade användare" no_user_ignored_message: "Du har inga ignorerade kontakter." - stop_ignoring: "sluta ignorera" + stop_ignoring: "Sluta ignorera" strip_exif: "Rensa bort metadata, sÃ¥som plats, upphovsman och kameramodell frÃ¥n de uppladdade bilderna (rekommenderat)" title: "Sekretessinställningar" public: does_not_exist: "Användaren %{username} finns inte!" update: + color_theme_changed: "Färgtema utbytt." + color_theme_not_changed: "Ett fel uppstod vid färgbyte." email_notifications_changed: "Inställningarna för e-postnotiser har ändrats" follow_settings_changed: "Inställningar för att följa har ändrats" follow_settings_not_changed: "Kunde inte ändra inställningar för att följa." @@ -1376,13 +1197,6 @@ sv: settings_updated: "Inställningarna har ändrats" unconfirmed_email_changed: "E-postadressen har ändrats men behöver aktiveras." unconfirmed_email_not_changed: "Byte av e-postadress misslyckades" - webfinger: - fetch_failed: "Kunde inte hämta webfinger-profil för %{profile_url}" - hcard_fetch_failed: "Kunde inte hämta hcard för %{account}" - no_person_constructed: "Kunde inte skapa en person frÃ¥n detta hcard." - not_enabled: "Webfinger verkar inte vara aktiverat pÃ¥ %{account}s server" - xrd_fetch_failed: "Kunde inte hämta xrd-fil frÃ¥n kontot %{account}" - welcome: "Välkommen!" will_paginate: next_label: "nästa »" previous_label: "« föregÃ¥ende" \ No newline at end of file diff --git a/config/locales/diaspora/ta.yml b/config/locales/diaspora/ta.yml index 260bb9e2866d13e893345f1ed6f5b7eb3b473a6e..f4402193641e7b4ea9db01d58cf0b58d1eb5d47d 100644 --- a/config/locales/diaspora/ta.yml +++ b/config/locales/diaspora/ta.yml @@ -6,10 +6,7 @@ ta: _applications: "பயனà¯à®ªà®¾à®Ÿà¯à®•à®³à¯" - _comments: "à®®à¯à®¨à¯à®¤à¯ˆà®¯" _contacts: "தொடரà¯à®ªà¯à®•à®³à¯" - _home: "à®®à¯à®•à®ªà¯à®ªà¯" - _photos: "பà¯à®•à¯ˆà®ªà¯à®ªà®Ÿà®™à¯à®•à®³à¯" _services: "சேவைகளà¯" account: "கணகà¯à®•à¯" activerecord: @@ -40,22 +37,10 @@ ta: username: invalid: "தவறானதà¯. எஙà¯à®•à®³à®¾à®²à¯ எழà¯à®¤à¯à®¤à¯à®•à¯à®•à®³à¯, எணà¯à®•à®³à¯, மறà¯à®±à¯à®®à¯ அடிகà¯à®•à¯‡à®¾à®Ÿà¯ மடà¯à®Ÿà¯à®®à¯‡ அனà¯à®®à®¤à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯." taken: "à®à®±à¯à®•à®©à®µà¯‡ எடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®µà®¿à®Ÿà¯à®Ÿà®¤à¯" - ago: "%{time}à®®à¯à®©à¯à®ªà¯" all_aspects: "அனைதà¯à®¤à¯ à®…à®®à¯à®šà®™à¯à®•à®³à®¿à®²à¯à®®à¯" - application: - helper: - unknown_person: "தெரியாத நபரà¯" - video_title: - unknown: "தெரியாத ஒளிதோறà¯à®± தலைபà¯à®ªà¯" are_you_sure: "நீஙà¯à®•à®³à¯ உறà¯à®¤à®¿à®¯à®¾à®• இரà¯à®•à¯à®•à®¿à®±à¯€à®°à¯à®•à®³à®¾?" are_you_sure_delete_account: "நீஙà¯à®•à®³à¯ உஙà¯à®•à®³à¯ கணகà¯à®•à¯ˆ மூட வேணà¯à®Ÿà¯à®®à®¾? இதை தவிரà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯!" aspects: - aspect_listings: - deselect_all: "அனைதà¯à®¤à¯ˆà®¯à¯à®®à¯ தேரà¯à®µà¯à®¨à¯€à®•à¯à®•à®®à¯ செயà¯à®•" - edit_aspect: "மாறà¯à®±à¯ %{name}" - select_all: "அனைதà¯à®¤à¯ˆà®¯à¯à®®à¯ தேரà¯à®µà¯ செயà¯" - contacts_not_visible: "இநà¯à®¤ à®…à®®à¯à®šà®¤à¯à®¤à®¿à®²à¯ உளà¯à®³ தொடரà¯à®ªà¯à®•à®³à¯ˆ à®’à®°à¯à®µà®°à¯à®•à¯à®•à¯†à®¾à®°à¯à®µà®°à¯ பாரà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯." - contacts_visible: "இநà¯à®¤ à®…à®®à¯à®šà®¤à¯à®¤à®¿à®²à¯ உளà¯à®³ தொடரà¯à®ªà¯à®•à®³à¯ˆ à®’à®°à¯à®µà®°à¯à®•à¯à®•à¯†à®¾à®°à¯à®µà®°à¯ பாரà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à¯à®®à¯." destroy: failure: "%{name} காலியாக இலà¯à®²à¯ˆ ஆகையால௠நீகà¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ" success: "%{name} வெறà¯à®±à®¿à®•à®°à®®à®¾à®• நீகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯" @@ -63,8 +48,6 @@ ta: aspect_list_is_not_visible: "à®…à®®à¯à®šà®®à¯ படà¯à®Ÿà®¿à®¯à®²à¯ à®…à®®à¯à®šà®™à¯à®•à®³à®¿à®²à¯à®³à¯à®³ மறà¯à®±à®µà®°à¯à®•à®³à¯à®•à¯à®•à¯ மறைகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯" aspect_list_is_visible: "à®…à®®à¯à®šà®®à¯ படà¯à®Ÿà®¿à®¯à®²à¯ à®…à®®à¯à®šà®™à¯à®•à®³à®¿à®²à¯à®³à¯à®³ மறà¯à®±à®µà®°à¯à®•à®³à®¾à®²à¯ பாரà¯à®•à¯à®• இயலà¯à®®à¯" confirm_remove_aspect: "நீஙà¯à®•à®³à¯ இநà¯à®¤ à®…à®®à¯à®šà®¤à¯à®¤à¯ˆ நீகà¯à®• வேணà¯à®Ÿà¯à®®à®¾?" - make_aspect_list_visible: "இநà¯à®¤ à®…à®®à¯à®šà®¤à¯à®¤à®¿à®²à¯ உளà¯à®³ தொடரà¯à®ªà¯à®•à®³à¯ˆ à®’à®°à¯à®µà®°à¯à®•à¯Šà®±à¯à®°à¯à®µà®°à¯ பாரà¯à®•à¯à®• இயலà¯à®®à®¾?" - remove_aspect: "இநà¯à®¤ à®…à®®à¯à®šà®¤à¯à®¤à¯ˆ நீகà¯à®•à¯" rename: "மறà¯à®ªà¯†à®¯à®°à¯" update: "பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®•" updating: "பà¯à®¤à¯à®ªà¯à®ªà®¿à®¤à¯à®¤à®²à¯ நடகà¯à®•à®¿à®±à®¤à¯" @@ -75,49 +58,30 @@ ta: tag_question: "கேளà¯à®µà®¿" new_here: title: "வரவேறà¯à®•à®¿à®±à¯‡à®¾à®®à¯ பà¯à®¤à®¿à®¯ பயனரà¯à®•à®³à¯" - no_contacts: "தொடரà¯à®ªà¯à®•à®³à¯ எதà¯à®µà¯à®®à¯ இலà¯à®²à¯ˆ" - unfollow_tag: "#%{tag} ஠பினà¯à®¤à¯Šà®Ÿà®°à¯à®µà®¤à¯ˆ நிறà¯à®¤à¯à®¤à¯" - new: - create: "உரà¯à®µà®¾à®•à¯à®•à¯" - name: "பெயரà¯(உஙà¯à®•à®³à¯à®•à¯à®•à¯ மடà¯à®Ÿà¯à®®à¯‡ தெரியà¯à®®à¯)" no_contacts_message: community_spotlight: "சமூகதà¯à®¤à®¿à®©à¯ கவனதà¯à®¤à®¿à®²à¯" you_should_add_some_more_contacts: "நீஙà¯à®•à®³à¯ கணà¯à®Ÿà®¿à®ªà¯à®ªà®¾à®• மேலà¯à®®à¯ சில தொடரà¯à®ªà¯à®•à®³à¯ˆ சேரà¯à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯!" - no_posts_message: - start_talking: "யாரà¯à®®à¯ எதà¯à®µà¯à®®à¯ கூறவிலà¯à®²à¯ˆ!" seed: acquaintances: "அறிமà¯à®•à®®à®¾à®©à®µà®°à¯à®•à®³à¯" family: "கà¯à®Ÿà¯à®®à¯à®ªà®®à¯" friends: "நணà¯à®ªà®°à¯à®•à®³à¯" work: "வேலை" - back: "பினà¯" cancel: "ரதà¯à®¤à¯à®šà¯†à®¯à¯" delete: "நீகà¯à®•à¯" email: "மினà¯à®©à®žà¯à®šà®²à¯" error_messages: helper: correct_the_following_errors_and_try_again: "கொடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³ பிழைகளை சரிசெயà¯à®¤à¯ மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à®µà¯à®®à¯." - invalid_fields: "தவறான பà¯à®²à®™à¯à®•à®³à¯" fill_me_out: "எனà¯à®©à¯ˆ நிரபà¯à®ªà¯" find_people: "நபரà¯à®•à®³à¯ˆ/கà¯à®±à®¿à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆ கணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿" - hide: "மறை" limited: "வரமà¯à®ªà¯à®•à¯à®•à¯à®Ÿà¯à®ªà®Ÿà¯à®Ÿ" more: "மேலà¯à®®à¯" - next: "அடà¯à®¤à¯à®¤à¯" no_results: "à®®à¯à®Ÿà®¿à®µà¯à®•à®³à¯ எதà¯à®µà¯à®®à¯ கணà¯à®Ÿà®±à®¿à®¯à®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ" nsfw: "nsfw" ok: "சரி" - or: "அலà¯à®²à®¤à¯" - password: "கடவà¯à®šà¯à®šà¯Šà®²à¯" - password_confirmation: "கடவà¯à®šà¯à®šà¯†à®¾à®²à¯à®²à¯ˆ உரà¯à®¤à®¿à®šà¯†à®¯à¯" - previous: "à®®à¯à®¨à¯à®¤à¯ˆà®¯" privacy: "தனியà¯à®°à®¿à®®à¯ˆ" - privacy_policy: "தனியà¯à®°à®¿à®®à¯ˆ கொளà¯à®•à¯ˆ" profile: "தனà¯à®µà®¿à®µà®°à®®à¯" public: "பொதà¯" search: "தேடலà¯" settings: "அமைபà¯à®ªà¯à®•à®³à¯" - terms_and_conditions: "விதிமà¯à®±à¯ˆà®•à®³à¯ மறà¯à®±à¯à®®à¯ நிபநà¯à®¤à®©à¯ˆà®•à®³à¯" - undo: "செயலà¯à®¤à®µà®¿à®°à¯à®•à¯à®•" - username: "பயனரà¯à®ªà¯†à®¯à®°à¯" - welcome: "நலà¯à®µà®°à®µà¯!" \ No newline at end of file + username: "பயனரà¯à®ªà¯†à®¯à®°à¯" \ No newline at end of file diff --git a/config/locales/diaspora/te.yml b/config/locales/diaspora/te.yml index e9fab31d49da8a459eab938d98e063ea524e400d..2bd38f1a1eaa8c72384e245e506aec85ff1d0d40 100644 --- a/config/locales/diaspora/te.yml +++ b/config/locales/diaspora/te.yml @@ -6,11 +6,8 @@ te: _applications: "à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°²à±" - _comments: "à°µà±à°¯à°¾à°–à±à°¯à°²à±" _contacts: "పరిచయాలà±" _help: "సహాయం" - _home: "à°®à±à°‚గిలి" - _photos: "ఛాయాచితà±à°°à°¾à°²à±" _services: "సేవలà±" _statistics: "గణాంకాలà±" _terms: "à°·à°°à°¤à±à°²à±" @@ -109,13 +106,7 @@ te: other: "à°ˆ వారంలో కొతà±à°¤ వాడà±à°•à°°à±à°² సంఖà±à°¯: %{count}" zero: "à°ˆ వారంలో కొతà±à°¤ వాడà±à°•à°°à±à°² సంఖà±à°¯: ఎవరూలేరà±" current_server: "à°ªà±à°°à°¸à±à°¤à±à°¤ సేవకం తేదీ %{date}" - ago: "%{time} à°•à±à°°à°¿à°¤à°‚" all_aspects: "à°…à°¨à±à°¨à°¿ కోణాలà±" - application: - helper: - unknown_person: "తెలియని à°µà±à°¯à°•à±à°¤à°¿" - video_title: - unknown: "తెలియని వీడియో శీరà±à°·à°¿à°•" are_you_sure: "మీరౠకచà±à°šà°¿à°¤à°‚à°—à°¾ ఉనà±à°¨à°¾à°°à°¾?" are_you_sure_delete_account: "మీరౠనిజంగానే మీ ఖాతాని మూసివేయాలి à°…à°¨à±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à°¾? ఒకసారి మూసివేసà±à°¤à±‡ ఇక తిరిగిరాదà±!" aspect_memberships: @@ -129,18 +120,10 @@ te: success: "పరిచయం కోణానికి విజయవంతంగా జోడించబడింది." aspect_listings: add_an_aspect: "+ కొతà±à°¤ కోణానà±à°¨à°¿ చేరà±à°šà°‚à°¡à°¿" - deselect_all: "ఎంపిక మొతà±à°¤à°‚ à°°à°¦à±à°¦à±à°šà±‡à°¯à°¿" - edit_aspect: "%{name} సవరించà±" - select_all: "à°…à°¨à±à°¨à±€ ఎంపికచేయి" aspect_stream: make_something: "à°à°®à±ˆà°¨à°¾ చెయà±à°¯à°‚à°¡à°¿" stay_updated: "తాజాగా ఉండండి" stay_updated_explanation: "మీ à°ªà±à°°à°§à°¾à°¨ à°ªà±à°°à°µà°¾à°¹à°‚ మొతà±à°¤à°‚ మీ పరిచయాలà±, మీరౠఅనà±à°¸à°°à°¿à°‚చే కొసలà±, మరియౠకొంతమంది సంఘపౠసృజనాతà±à°®à°• à°¸à°à±à°¯à±à°² టపాలతో నిండివà±à°‚à°Ÿà±à°‚ది." - contacts_not_visible: "à°ˆ కోణంలో ఉనà±à°¨ పరిచయాలౠఒకరిని ఒకరౠచూడలేరà±." - contacts_visible: "à°ˆ కోణంలో ఉనà±à°¨ పరిచయాలౠఒకరిని ఒకరౠచూడగలరà±." - create: - failure: "కోణం సృషà±à°¥à°¿à°‚చలేకపోయామà±." - success: "మీ కొతà±à°¤ కోణం %{name} సృషà±à°Ÿà°¿à°‚చబడింది" destroy: failure: "%{name} తీయడం వీలà±à°•à°¾à°¦à±." success: "%{name} విజయవంతంగా తొలగించబడినది" @@ -148,25 +131,15 @@ te: aspect_list_is_not_visible: "à°ˆ కోణంలోని పరిచయాలౠఒకరికొకరౠచూడలేరà±." aspect_list_is_visible: "à°ˆ కోణంలోని పరిచయాలౠఒకరికొకరౠచూడగలరà±." confirm_remove_aspect: "మీరౠనిజంగానే à°ˆ కోణానà±à°¨à°¿ తొలగించాలని à°…à°¨à±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à°¾?" - make_aspect_list_visible: "à°ˆ కోణంలో ఉనà±à°¨ పరిచయాలౠఒకరికొకరౠకనిపిచà±à°šà±‡à°²à°¾ చెయà±à°¯à°¾à°²à°¾?" - remove_aspect: "à°ˆ కోణానà±à°¨à°¿ తొలగించà±" rename: "పేరà±à°®à°¾à°°à±à°šà±" - set_visibility: "à°ªà±à°°à°¤à±à°¯à°•à±à°·à°¤à°¨à± అమరà±à°šà±" update: "నవీకరించà±" updating: "నవీకరిసà±à°¤à±à°¨à±à°¨à°¾à°®à±" index: - diaspora_id: - content_1: "మీ డయాసà±à°ªà±‹à°°à°¾* à°—à±à°°à±à°¤à°¿à°‚à°ªà±:" - content_2: "దీనà±à°¨à°¿ మీరౠఎవరికైనా ఇసà±à°¤à±‡, వారౠదీని à°¦à±à°µà°¾à°°à°¾ మిమà±à°®à°²à±à°¨à°¿ డయాసà±à°ªà±‹à°°à°¾*లో à°•à°¨à±à°—ొనగలరà±." - heading: "డయసà±à°ªà±‹à°°à°¾* à°—à±à°°à±à°¤à°¿à°‚à°ªà±" donate: "విరాలమివà±à°µà°‚à°¡à°¿" - handle_explanation: "ఇది మీ డయాసà±à°ªà±‹à°°à°¾ à°—à±à°šà°¿. ఈమెయిలౠచిరà±à°¨à°¾à°®à°¾ వంటిది, మిమà±à°®à°²à±à°¨à°¿ సంపà±à°°à°¦à°¿à°‚à°šà±à°Ÿà°•à±ˆ దీనిని à°µà±à°¯à°•à±à°¤à±à°²à°•à± ఇవà±à°µà°µà°šà±à°šà±." help: any_problem: "à°à°¦à±ˆà°¨à°¾ సమసà±à°¯à°¾?" contact_podmin: "మీ పాడౠయొకà±à°• నిరà±à°µà°¾à°¹à°•à±à°¨à±à°¨à°¿ సంపà±à°°à°¦à°¿à°‚à°šà°‚à°¡à°¿!" do_you: "మీకౠà°à°®à±ˆà°¨à°¾:" - email_feedback: "మీ à°ªà±à°°à°¤à°¿à°¸à±à°ªà°‚దననౠ%{link}" - email_link: "ఈమెయిలà±" feature_suggestion: "... %{link} సూచన ఇవà±à°µà°¾à°²à°¨à±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à°¾?" find_a_bug: "... %{link} వెతకాలా?" have_a_question: "... %{link} ఉందా?" @@ -179,30 +152,19 @@ te: tutorial_link_text: "ఉపశికà±à°·à°£" tutorials_and_wiki: "%{faq}, %{tutorial} & %{wiki}: మీ తొలి à°…à°¡à±à°—à±à°² కోసం సహాయం" introduce_yourself: "ఇది మీ à°ªà±à°°à°µà°¾à°¹à°‚. లోపలికి దూకి, మీ à°—à±à°°à°¿à°‚à°šà°¿ పరిచయం చేసà±à°•à±‹à°‚à°¡à°¿." - keep_diaspora_running: "నెలవారీ విరాళంతో డయాసà±à°ªà±‹à°°à°¾* à°…à°à°¿à°µà±ƒà°¦à±à°§à°¿à°¨à°¿ వేగవంతం చేయండి!" new_here: follow: "%{link} à°…à°¨à±à°¸à°°à°¿à°‚à°šà°¿, డయాసà±à°ªà±‹à°°à°¾*కౠవచà±à°šà±‡ కొతà±à°¤ వాడà±à°•à°°à±à°²à°¨à± à°¸à±à°µà°¾à°—తించండి!" learn_more: "మరింత తెలà±à°¸à±à°•à±‹à°‚à°¡à°¿" title: "కొతà±à°¤ వాడà±à°•à°°à±à°²à°•à± à°¸à±à°µà°¾à°—తం పలకండి" - no_contacts: "పరిచయాలేమీ లేవà±" - no_tags: "+ à°…à°¨à±à°¸à°°à°¿à°‚చడానికి కొసనౠవెతà±à°•à±" - people_sharing_with_you: "మీతో పంచà±à°•à±à°¨à±‡ à°µà±à°¯à°•à±à°¤à±à°²à±" - post_a_message: "à°’à°• సందేశానà±à°¨à°¿ పోసà±à°Ÿà±à°šà±‡à°¯à°‚à°¡à°¿ >>" services: content: "à°•à±à°°à°¿à°‚ది పేరà±à°•à±Šà°¨à±à°¨ సేవలనౠమీరౠడయాసà±à°ªà±‹à°°à°¾*à°•à± à°…à°¨à±à°¸à°‚ధానం చేయవచà±à°šà±." heading: "సేవలకౠఅనà±à°¸à°‚ధానం à°•à°‚à°¡à°¿" - unfollow_tag: "%{tag}ని à°…à°¨à±à°¸à°°à°¿à°‚à°šà°¡à°‚ మానేయి" welcome_to_diaspora: "%{name}, డయాసà±à°ªà±Šà°°à°¾*à°•à± à°¸à±à°µà°¾à°—తం!" - new: - create: "సృషà±à°Ÿà°¿à°‚à°šà±" - name: "పేరౠ(మీకౠమాతà±à°°à°®à±‡ కనిపిసà±à°¤à±à°‚ది)" no_contacts_message: community_spotlight: "సంఘపౠసà±à°ªà°¾à°Ÿà±â€‹à°²à±ˆà°Ÿà±" or_spotlight: "లేకపోతే %{link} తో పంచà±à°•à±‹à°µà°šà±à°šà±" try_adding_some_more_contacts: "మీరౠమరికొనà±à°¨à°¿ పరిచయాలà±à°¨à°¿ వెతకవచà±à°šà± లేక ఆహà±à°µà°¾à°¨à°¿à°‚చవచà±à°šà±." you_should_add_some_more_contacts: "మీరౠఇంకొంత మంది పరిచయాలà±à°¨à°¿ చేరà±à°šà±à°•à±‹à°µà°¾à°²à°¿!" - no_posts_message: - start_talking: "ఇంకా ఎవరూ à°à°®à±€ చెపà±à°ªà°²à±‡à°¦à±!" seed: acquaintances: "తెలిసినవారà±" family: "à°•à±à°Ÿà±à°‚బం" @@ -211,7 +173,6 @@ te: update: failure: "మీకోణం, %{name}, à°à°¦à±à°°à°ªà°°à±à°šà±à°Ÿà°•à± చాలా పెదà±à°¦ పేరౠఇచà±à°šà°¾à°°à±." success: "మీకోణం, %{name}, విజయవంతంగా సవరించబడింది." - back: "వెనà±à°•à°•à±" blocks: create: failure: "నేనౠఆ వాడà±à°•à°°à°¿à°¨à°¿ విసà±à°®à°°à°¿à°‚చలేకపోతà±à°¨à±à°¨à°¾à°¨à±. #తపà±à°ªà°¿à°‚à°šà±à°•à±‹à°µà°¡à°‚" @@ -223,41 +184,28 @@ te: explanation: "à°ˆ లంకెనౠఇషà±à°Ÿà°¾à°‚శంగా చేరà±à°šà±à°•à±‹à°µà°¡à°‚ à°¦à±à°µà°¾à°°à°¾ డయాసà±à°ªà±‹à°°à°¾*à°•à± à°Žà°•à±à°•à°¡à°¿ à°¨à±à°‚డైనా టపా వేయవచà±à°šà± => %{link}" heading: "à°¬à±à°•à±â€Œà°®à°¾à°°à±à°•à±â€Œà°²à±†à°Ÿà±" post_something: "డయాసà±à°ªà±‹à°°à°¾*కౠటపా వేయండి" - post_success: "టపా వేయబడింది! మూసివేసà±à°¤à±à°¨à±à°¨à°¾à°‚!" cancel: "à°°à°¦à±à°¦à±à°šà±‡à°¯à°¿" comments: new_comment: comment: "à°µà±à°¯à°¾à°–à±à°¯" commenting: "à°µà±à°¯à°¾à°–à±à°¯à°¾à°¨à°¿à°¸à±à°¤à±à°¨à±à°¨à°¾à°®à±..." - one: "1 à°µà±à°¯à°¾à°–à±à°¯" - other: "%{count} à°µà±à°¯à°¾à°–à±à°¯à°²à±" - zero: "à°µà±à°¯à°¾à°•à±à°¯à°²à±‡à°®à±€ లేవà±" contacts: - create: - failure: "పరిచయానà±à°¨à°¿ సృషà±à°Ÿà°¿à°‚à°šà±à°Ÿà°²à±‹ విఫలమైంది" index: add_a_new_aspect: "à°’à°• కొతà±à°¤ కోణానà±à°¨à°¿ జతచేయి" add_contact: "పరిచయానà±à°¨à°¿ జతచేయి" - add_to_aspect: "%{name} à°•à°¿ పరిచయాలనౠజతచేయి" all_contacts: "à°…à°¨à±à°¨à°¿ పరిచయాలà±" community_spotlight: "సంఘపౠసà±à°ªà°¾à°Ÿà±â€‹à°²à±ˆà°Ÿà±" my_contacts: "నా పరిచయాలà±" no_contacts: "మీరౠఇంకా ఎవరà±à°¨à±€ పరిచయాలలో చేరà±à°šà±à°•à±à°¨à±à°¨à°Ÿà±à°²à± లేరà±!" no_contacts_message: "%{community_spotlight}ని సందరà±à°¶à°¿à°‚à°šà°‚à°¡à°¿" only_sharing_with_me: "నాతో మాతà±à°°à°®à±‡ పంచà±à°•à±à°¨à±‡ వారà±" - remove_contact: "పరిచయానà±à°¨à°¿ తీసివేయి" start_a_conversation: "సంà°à°¾à°·à°£à°¨à± à°ªà±à°°à°¾à°°à°‚à°à°¿à°‚à°šà°‚à°¡à°¿" title: "పరిచయాలà±" user_search: "పరిచయం వెతà±à°•à±à°²à°¾à°Ÿ" - your_contacts: "మీ పరిచయాలà±" - sharing: - people_sharing: "మీతో పంచà±à°•à±à°¨à±‡ à°µà±à°¯à°•à±à°¤à±à°²à±:" spotlight: community_spotlight: "సంఘపౠసà±à°ªà°¾à°Ÿà±â€‹à°²à±ˆà°Ÿà±" suggest_member: "à°’à°• à°¸à°à±à°¯à±à°¨à±à°¨à°¿ సూచించండి" conversations: - conversation: - participants: "à°…à°à±à°¯à°°à±à°¥à±à°²à±" create: fail: "చెలà±à°²à°¨à°¿ సందేశం" no_contact: "à°“à°¯à±, à°®à±à°‚à°¦à±à°—à°¾ మీరౠపరిచయానà±à°¨à°¿ జతచేసà±à°•à±‹à°µà°¾à°²à°¿!" @@ -265,23 +213,12 @@ te: destroy: delete_success: "సంà°à°¾à°·à°£ విజయవంతంగా తొలగించబడింది" hide_success: "సంà°à°¾à°·à°£ విజయవంతంగా దాచబడింది" - helper: - new_messages: - few: "%{count} కొతà±à°¤ సందేశాలà±" - many: "%{count} కొతà±à°¤ సందేశాలà±" - one: "1 కొతà±à°¤ సందేశం" - other: "%{count} కొతà±à°¤ సందేశాలà±" - two: "%{count} కొతà±à°¤ సందేశాలà±" - zero: "కొతà±à°¤ సందేశాలౠలేవà±" index: conversations_inbox: "సంà°à°¾à°·à°£à°²à± – ఇనà±â€Œà°¬à°¾à°•à±à°¸à±" - create_a_new_conversation: "కొతà±à°¤ సంà°à°¾à°·à°£à°¨à± à°ªà±à°°à°¾à°°à°‚à°à°¿à°‚à°šà°‚à°¡à°¿" inbox: "తపాలాపెటà±à°Ÿà±†" new_conversation: "కొతà±à°¤ సంà°à°¾à°·à°£" - no_conversation_selected: "ఠసంà°à°¾à°·à°£à°¨à± à°Žà°‚à°šà±à°•à±‹à°²à±‡à°¦à±" no_messages: "సందేశాలేమి లేవà±" new: - abandon_changes: "మారà±à°ªà±à°²à°¨à± వదిలివేయాలా?" send: "పంపండి" sending: "పంపà±à°¤à±à°¨à±à°¨à°¾à°®à±..." subject: "విషయం" @@ -304,9 +241,6 @@ te: error_messages: helper: correct_the_following_errors_and_try_again: "à°•à±à°°à°¿à°‚ది తపà±à°ªà±à°²à°¨à± సరిచేసి, మరలా à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚à°šà°‚à°¡à°¿." - invalid_fields: "చెలà±à°²à°¨à°¿ à°•à±à°·à±‡à°¤à±à°°à°¾à°²à±" - login_try_again: "దయచేసి<a href='%{login_link}'>à°ªà±à°°à°µà±‡à°¶à°¿à°‚à°šà°¿</a>, మరలా à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚à°šà°‚à°¡à°¿." - post_not_public: "మీరౠచూడాలనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨ టపా బహిరంగంగా లేదà±!" fill_me_out: "పూరించండి" find_people: "à°µà±à°¯à°•à±à°¤à±à°²à°¨à± లేదా à°Ÿà±à°¯à°¾à°—à±à°²à°¨à± à°•à°¨à±à°—ొనండి" help: @@ -402,45 +336,27 @@ te: tutorial: "ఉపశికà±à°·à°£" tutorials: "ఉపశికà±à°·à°£" wiki: "వికీ" - hide: "దాచà±" - ignore: "విసà±à°®à°°à°¿à°‚à°šà±" - invitation_codes: - excited: "మిమà±à°®à°²à±à°¨à°¿ ఇకà±à°•à°¡ చూసినందà±à°•à± %{name} ఆనందించారà±." invitations: a_facebook_user: "ఫేసà±â€Œà°¬à±à°•à± వాడà±à°•à°°à°¿" check_token: not_found: "ఆహà±à°µà°¾à°¨ టోకెనౠకనపడలేదà±" create: - already_contacts: "à°ˆ à°µà±à°¯à°•à±à°¤à°¿à°¤à±‹ మీరౠఇదివరకే à°…à°¨à±à°¸à°‚ధానమై ఉనà±à°¨à°¾à°°à±" - already_sent: "à°ˆ à°µà±à°¯à°•à±à°¤à°¿à°¨à°¿ మీరౠఇపà±à°ªà°Ÿà°¿à°•à±‡ ఆహà±à°µà°¾à°¨à°¿à°‚చారà±." empty: "దయచేసి à°’à°•à±à°• ఈమెయిలౠచిరà±à°¨à°¾à°®à°¾à°¨à±ˆà°¨à°¾ ఇవà±à°µà°‚à°¡à°¿." no_more: "మీకౠఆహà±à°µà°¾à°¨à°¾à°²à±‡à°®à±€ లేవà±." note_already_sent: "ఆహà±à°µà°¾à°¨à°¾à°²à± ఇంతకà±à°®à±à°‚దే వీరికి పంపబడà±à°¡à°¾à°¯à°¿: %{emails}" - own_address: "మీరౠమీ సొంత à°šà°¿à°°à±à°¨à°¾à°®à°¾à°•à± ఆహà±à°µà°¾à°¨à°‚ పంపలేరà±." rejected: "à°•à±à°°à°¿à°‚దిపేరà±à°•à±Šà°¨à±à°¨ ఈమెయిలౠచిరà±à°¨à°¾à°®à°¾à°•à± సమసà±à°¯à°²à± ఉనà±à°¨à°¾à°¯à°¿: " sent: "%{emails}:కౠఆహà±à°µà°¾à°¨à°¾à°²à± పంపబడà±à°¡à°¾à°¯à°¿" - edit: - accept_your_invitation: "ఆహà±à°µà°¾à°¨à°¾à°¨à±à°¨à°¿ అంగీకరించండి" - your_account_awaits: "మీ ఖాతా à°Žà°¦à±à°°à±à°šà±‚à°¸à±à°¤à±‚ంది!" new: - already_invited: "à°ˆ à°•à±à°°à°¿à°‚ది à°µà±à°¯à°•à±à°¤à±à°²à± మీ ఆహà±à°µà°¾à°¨à°¾à°¨à±à°¨à°¿ ఇంకా అంగీకరించలేదà±:" - aspect: "కోణం" - check_out_diaspora: "డయసà±à°ªà±‹à°°à°¾*నౠసందరà±à°¶à°¿à°‚à°šà°‚à°¡à°¿!" codes_left: one: "à°ˆ సంకేతంపై à°’à°• ఆహà±à°µà°¾à°¨à°‚ మిగిలివà±à°‚ది" other: "à°ˆ సంకేతంపై %{count} ఆహà±à°µà°¾à°¨à°¾à°²à± మిగిలివà±à°¨à±à°¨à°¾à°¯à°¿" zero: "à°ˆ సంకేతంపై à°Žà°Ÿà±à°µà°‚à°Ÿà°¿ ఆహà±à°µà°¾à°¨à°¾à°²à± మిగిలిలేవà±" comma_separated_plz: "కామాలతో వేరà±à°šà±‡à°¸à°¿ మీరౠబహà±à°³ ఈమెయిలౠచిరà±à°¨à°¾à°®à°¾à°²à°¨à± ఇవà±à°µà°µà°šà±à°šà±." - if_they_accept_info: "ఒకవేళ వారౠసమà±à°®à°¤à°¿à°¸à±à°¤à±‡, మీరౠఆహà±à°µà°¾à°¨à°¿à°‚చే కోణానికి వారౠజతచేయబడతారà±." invite_someone_to_join: "డయాసà±à°ªà±‹à°°à°¾*లో చేరమని ఎవరినైనా ఆహà±à°µà°¾à°¨à°¿à°‚à°šà°‚à°¡à°¿!" language: "à°à°¾à°·" paste_link: "మీ మితà±à°°à±à°²à°¨à± డయాసà±à°ªà±‹à°°à°¾*కౠఆహà±à°µà°¾à°¨à°¿à°‚చడానికి à°ˆ లంకెనౠవారితో పంచà±à°•à±‹à°‚à°¡à°¿, లేదా లంకెనౠనేరà±à°—à°¾ వారికి ఈమెయిలౠచేయండి." - personal_message: "à°µà±à°¯à°•à±à°¤à°¿à°—à°¤ సందేశం" - resend: "మరలా పంపà±" send_an_invitation: "à°’à°• ఆహà±à°µà°¾à°¨à°¾à°¨à±à°¨à°¿ పంపండి" - send_invitation: "సందేశానà±à°¨à°¿ పంపండి" sending_invitation: "ఆహà±à°µà°¾à°¨à°¾à°¨à±à°¨à°¿ పంపà±à°¤à±à°¨à±à°¨à°¾à°®à±..." - to: "వీరికి" layouts: application: back_to_top: "పైకి వెళà±à°³à±" @@ -450,35 +366,13 @@ te: statistics_link: "పాడౠగణాంకాలà±" toggle: "మొబైలà±à°²à°¾ చూడà±" whats_new: "కొతà±à°¤à°—à°¾ à°à°®à±à°¨à±à°¨à°¾à°¯à°¿?" - your_aspects: "మీ కోణాలà±" header: - admin: "నిరà±à°µà°¾à°¹à°•à±à°¡à±" - blog: "à°¬à±à°²à°¾à°—à±" code: "సంకేతం" - help: "సహాయం" - login: "లోనికిరండి" logout: "నిషà±à°•à±à°°à°®à°¿à°‚à°šà°‚à°¡à°¿" profile: "à°ªà±à°°à°µà°°" - recent_notifications: "ఇటీవలి గమనికలà±" settings: "అమరికలà±" - view_all: "à°…à°¨à±à°¨à±€ వీకà±à°·à°¿à°‚à°šà°‚à°¡à°¿" - likes: - likes: - people_dislike_this: - one: "%{count} అయిషà±à°Ÿà°‚" - other: "%{count} అయిషà±à°Ÿà°¾à°²à±" - zero: "అయిషà±à°Ÿà°¾à°²à±‡à°®à°¿ లేవà±" - people_like_this: - one: "%{count} ఇషà±à°Ÿà°‚" - other: "%{count} ఇషà±à°Ÿà°¾à°²à±" - zero: "ఇషà±à°Ÿà°¾à°²à±‡à°®à°¿ లేవà±" - people_like_this_comment: - one: "%{count} ఇషà±à°Ÿà°‚" - other: "%{count} ఇషà±à°Ÿà°¾à°²à±" - zero: "ఇషà±à°Ÿà°¾à°²à±‡à°®à°¿ లేవà±" limited: "పరిమితం" more: "మరినà±à°¨à°¿" - next: "తరà±à°µà°¾à°¤" no_results: "à°Žà°Ÿà±à°µà°‚à°Ÿà°¿ ఫలితాలౠకనపడలేదà±" notifications: also_commented: @@ -493,11 +387,6 @@ te: one: "%{actors} మీ టపా %{post_link} పై à°µà±à°¯à°¾à°–à±à°¯ à°¨à±à°‚చారà±." other: "%{actors} మీ టపా %{post_link} పై à°µà±à°¯à°¾à°–à±à°¯ à°¨à±à°‚చారà±." zero: "%{actors} మీ టపా %{post_link} పై à°µà±à°¯à°¾à°–à±à°¯ à°¨à±à°‚చారà±." - helper: - new_notifications: - one: "1 కొతà±à°¤ గమనిక" - other: "%{count} కొతà±à°¤ గమనికలà±" - zero: "కొతà±à°¤ గమనికలేమీ లేవà±" index: all_notifications: "à°…à°¨à±à°¨à°¿ గమనింపà±à°²à±" and: "మరియà±" @@ -550,7 +439,6 @@ te: zero: "%{actors} మీతో పంచà±à°•à±‹à°µà°¡à°‚ à°ªà±à°°à°¾à°°à°‚à°à°¿à°‚చారà±." notifier: a_post_you_shared: "à°’à°• టపా." - accept_invite: "మీ డయాసà±à°ªà±‹à°°à°¾* ఆహà±à°µà°¾à°¨à°‚ అంగీకరించండి!" also_commented: limited_subject: "మీరౠవà±à°¯à°¾à°–à±à°¯à°¾à°¨à°¿à°‚à°šà°¿à°¨ టపాపై à°’à°• కొతà±à°¤ à°µà±à°¯à°¾à°–à±à°¯ వచà±à°šà°¿à°‚ది" click_here: "ఇకà±à°•à°¡ నొకà±à°•à°‚à°¡à°¿" @@ -592,7 +480,6 @@ te: view_post: "టపానౠచూడండి >" mentioned: limited_post: "à°’à°• పరిమిత టపాలో మీరౠపేరà±à°•à±Šà°¨à°¬à°¡à±à°¡à°¾à°°à±." - mentioned: "మిమà±à°®à°²à±à°¨à°¿ à°’à°• టపాలో à°ªà±à°°à°¸à±à°¤à°¾à°µà°¿à°‚చారà±:" subject: "%{name} డయాసà±à°ªà±Šà°°à°¾*లో మిమà±à°®à°²à±à°¨à°¿ à°ªà±à°°à°¸à±à°¤à°¾à°µà°¿à°‚చారà±" private_message: reply_to_or_view: "à°ˆ సంà°à°¾à°·à°£à°¨à± చూడండి లేదా దానిపై à°¸à±à°ªà°‚దించండి >" @@ -631,20 +518,9 @@ te: to_change_your_notification_settings: "మీ గమనిక అమరికలనౠమారà±à°šà°¾à°²à°‚టే" nsfw: "NSFW" ok: "సరే" - or: "లేదా" - password: "సంకేతపదà°‚" - password_confirmation: "సంకేతపదపౠనిరà±à°§à°¾à°°à°£" people: add_contact: invited_by: "మీరౠవీరిచే ఆహà±à°µà°¾à°¨à°¿à°‚చబడà±à°¡à°¾à°°à±" - add_contact_small: - add_contact_from_tag: "కొస à°¦à±à°µà°¾à°°à°¾ పరిచయానà±à°¨à°¿ జతచేయి" - aspect_list: - edit_membership: "కోణం à°¸à°à±à°¯à°¤à±à°µà°‚ సవరించండి" - helper: - is_not_sharing: "%{name} మీతో పంచà±à°•à±‹à°µà°¡à°‚ లేదà±" - is_sharing: "%{name} మీతో పంచà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à±" - results_for: " %{params} కొరకౠఫలితాలà±" index: couldnt_find_them: "వాటిని à°•à°¨à±à°•à±à°•à±‹à°²à±‡à°•à°ªà±‹à°¤à±à°¨à±à°¨à°¾à°°à°¾?" looking_for: "%{tag_link} కొసతో కూడిన టపాల కోసం చూసà±à°¤à±à°¨à±à°¨à°¾à°°à°¾?" @@ -654,99 +530,46 @@ te: search_handle: "వారి డయాసà±à°ªà±‹à°°à°¾* à°à°¡à±€ వాడండి (username@pod.tld) వాడి మీ à°¸à±à°¨à±‡à°¹à°¿à°¤à±à°²à°¨à± à°•à°¨à±à°—ొనండి." searching: "వెతà±à°•à±à°¤à±à°¨à±à°¨à°¾à°‚, దయచేసి ఓపిక వహించండి…" send_invite: "ఇంకా దొరకలేదా? అయితే à°’à°• ఆహà±à°µà°¾à°¨à°¾à°¨à±à°¨à°¿ పంపండి!" - one: "1 person" - other: "%{count} people" person: - add_contact: "పరిచయానà±à°¨à°¿ జతచేయండి" - already_connected: "ఇదివరకే à°…à°¨à±à°¸à°‚ధానమైనారà±" - pending_request: "పెండింగౠఅà°à±à°¯à°°à±à°¥à°¨" thats_you: "అది మీరే!" profile_sidebar: bio: "à°¸à±à°µà°ªà°°à°¿à°šà°¯à°‚" born: "à°ªà±à°Ÿà±à°Ÿà°¿à°¨ రోజà±" - edit_my_profile: "నా à°ªà±à°°à°µà°°à°¨à± సవరించà±" gender: "లింగం" - in_aspects: "కోణాలలో" location: "à°ªà±à°°à°¾à°‚తం" - photos: "ఛాయాచితà±à°°à°¾à°²à±" - remove_contact: "పరిచయానà±à°¨à°¿ తీసివేయి" - remove_from: "%{aspect} à°¨à±à°‚à°¡à°¿ %{name} నౠతొలగించాలా?" show: closed_account: "à°ˆ ఖాతా మూసివేయబడినది" does_not_exist: "à°…à°Ÿà±à°µà°‚à°Ÿà°¿ à°µà±à°¯à°•à±à°¤à°¿ లేనే లేరà±!" has_not_shared_with_you_yet: "%{name} ఇంకా మీతో టపాలౠà°à°µà±€ పంచà±à°•à±‹à°²à±‡à°¦à±!" - ignoring: "%{name} à°¨à±à°‚à°¡à°¿ వచà±à°šà±‡ à°…à°¨à±à°¨à°¿ టపాలనౠమీరౠవిసà±à°®à°°à°¿à°¸à±à°¤à±à°¨à±à°¨à°¾à°°à±." - incoming_request: "%{name} మీతో పంచà±à°•à±‹à°µà°¾à°²à°¨à±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à±" - mention: "పేరà±à°•à±Šà°¨à±" - message: "సందేశం" - not_connected: "మీరౠఈ à°µà±à°¯à°•à±à°¤à°¿à°¤à±‹ పంచà±à°•à±‹à°µà°Ÿà±à°²à±‡à°¦à±" - recent_posts: "ఇటీవలి టపాలà±" - recent_public_posts: "ఇటీవలి బహిరంగ టపాలà±" - return_to_aspects: "తిరిగి మీ కోణాల à°ªà±à°Ÿà°•à± వెళà±à°³à°‚à°¡à°¿" - see_all: "అందరినీ చూడండి" - start_sharing: "పంచà±à°•à±‹à°µà°Ÿà°‚ మొదలà±à°ªà±†à°Ÿà±à°Ÿà°‚à°¡à°¿" - to_accept_or_ignore: "అంగీకరించà±à°Ÿà°•à± లేదా విసà±à°®à°°à°¿à°‚à°šà±à°Ÿà°•à±" - sub_header: - add_some: "ఇంకొనà±à°¨à°¿ చేరà±à°šà°‚à°¡à°¿" - edit: "సవరించండి" - you_have_no_tags: "మీరౠఠకొసలనౠవాడలేదà±" - webfinger: - fail: "à°•à±à°·à°®à°¿à°‚à°šà°‚à°¡à°¿, మేమౠ%{handle}నౠకనà±à°—ొనలేకపోయాం" - zero: "à°µà±à°¯à°•à±à°¤à±à°²à±†à°µà°°à±‚ లేరà±" photos: - comment_email_subject: "%{name} యొకà±à°• ఛాయాచితà±à°°à°‚" create: integrity_error: "ఛాయాచితà±à°° à°Žà°•à±à°•à°¿à°‚పౠవిఫలమైంది. మీరౠఎకà±à°•à°¿à°‚చింది à°–à°šà±à°›à°¿à°¤à°‚à°—à°¾ బొమà±à°®à±‡à°¨à°¾?" runtime_error: "ఛాయాచితà±à°° à°Žà°•à±à°•à°¿à°‚పౠవిఫలమైంది.  " type_error: "ఛాయాచితà±à°° à°Žà°•à±à°•à°¿à°‚పౠవిఫలమైంది. మీరౠఖచà±à°›à°¿à°¤à°‚à°—à°¾ బొమà±à°®à°¨à±‡ జోడించారా?" destroy: notice: "ఛాయాచితà±à°°à°‚ తొలగించబడింది" - edit: - editing: "మారà±à°šà°¬à°¡à±à°¤à±à°¨à±à°¨à°¦à°¿" - new: - back_to_list: "తిరిగి జాబితాకి వెళà±à°³à±" - new_photo: "కొతà±à°¤ ఛాయాచితà±à°°à°‚" - post_it: "టపా à°•à°Ÿà±à°Ÿà°‚à°¡à°¿!" new_photo: empty: "{file} ఖాళీగావà±à°‚ది, దయచేసి అదికాకà±à°‚à°¡à°¾ వేరే దసà±à°¤à±à°°à°¾à°²à°¨à± à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿." invalid_ext: "{file} చెలà±à°²à°¨à°¿ పొడిగింతనౠకలిగివà±à°‚ది. కేవలం {extensions} మాతà±à°°à°®à±‡ à°…à°¨à±à°®à°¤à°¿à°‚చబడà±à°¨à±." size_error: "{file} చాలా పెదà±à°¦à°—ావà±à°‚ది, à°—à°°à°¿à°·à±à°Ÿ దసà±à°¤à±à°° పరిమాణం {sizeLimit}." new_profile_photo: - or_select_one_existing: "లేదా మీ ఇంతకà±à°®à±à°‚దౠఉనà±à°¨ %{photos} à°² à°¨à±à°‚à°¡à°¿ à°’à°•à°Ÿà°¿ à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿" upload: "à°’à°• కొతà±à°¤ à°ªà±à°°à°µà°° ఛాయాచితà±à°°à°¾à°¨à±à°¨à°¿ à°Žà°•à±à°•à°¿à°‚à°šà°‚à°¡à°¿!" - photo: - view_all: "%{name} యొకà±à°• à°…à°¨à±à°¨à°¿ ఛాయాచితà±à°°à°¾à°²à°¨à± చూడండి" show: - collection_permalink: "సేకరణ à°¸à±à°¥à°¿à°°à°²à°‚కె" - delete_photo: "ఛాయాచితà±à°°à°¾à°¨à±à°¨à°¿ తొలగించà±" - edit: "మారà±à°šà°‚à°¡à°¿" - edit_delete_photo: "ఛాయాచితà±à°°à°‚ యొకà±à°• వివరణనౠమారà±à°šà± లేక à°šà°¿à°¤à±à°°à°¾à°¨à±à°¨à°¿ తొలగించà±" - make_profile_photo: "à°ªà±à°°à°µà°° à°šà°¿à°¤à±à°°à°‚à°—à°¾ చేయి" show_original_post: "అసలౠటపాని చూపించà±" - update_photo: "ఛాయాచితà±à°°à°¾à°¨à±à°¨à°¿ నవీకరించండి" - update: - error: "ఛాయాచితà±à°°à°¾à°¨à±à°¨à°¿ సవరించà±à°Ÿà°²à±‹ వైఫలà±à°¯à°‚." - notice: "ఛాయాచితà±à°°à°‚ విజయవంతంగా నవీకరించబడింది." posts: presenter: title: "%{name} à°¨à±à°‚à°¡à°¿ à°’à°• టపా" show: - destroy: "తొలగించà±" - not_found: "à°•à±à°·à°®à°¿à°‚à°šà°‚à°¡à°¿, à°† టపానౠమేమౠకనà±à°—ొనలేకపోయాం." - permalink: "à°¸à±à°¥à°¿à°°à°²à°‚కె" photos_by: one: "%{author} à°¨à±à°‚à°¡à°¿ à°’à°• ఛాయాచితà±à°°à°‚ ఉంది" other: "%{author} à°¨à±à°‚à°¡à°¿ %{count} ఛాయాచితà±à°°à°¾à°²à± ఉనà±à°¨à°¾à°¯à°¿" zero: "%{author} à°Žà°Ÿà±à°µà°‚à°Ÿà°¿ ఛాయాచితà±à°°à°¾à°²à± పెటà±à°Ÿà°²à±‡à°¦à±" reshare_by: "%{author} చేత మరలాపంచబడింది" - previous: "à°®à±à°¨à±à°ªà°Ÿà°¿" privacy: "అంతరంగికత" - privacy_policy: "గోపà±à°¯à°¤à°¾ విధానం" profile: "à°ªà±à°°à°µà°°" profiles: edit: allow_search: "మీ కోసం డయాసà±à°ªà±‹à°°à°¾*లో వెతకడానికి à°µà±à°¯à°•à±à°¤à±à°²à°¨à± à°…à°¨à±à°®à°¤à°¿à°‚à°šà°‚à°¡à°¿" - edit_profile: "à°ªà±à°°à°µà°°à°¨à± సవరించà±" first_name: "మొదటి పేరà±" last_name: "ఇంటి పేరà±" nsfw_check: "నేనౠపంచà±à°•à±à°¨à±‡ à°ªà±à°°à°¤à±€à°¦à±€ à°Žà°¨à±â€Œà°Žà°¸à±à°Žà°«à±â€Œà°¡à°¬à±à°²à±à°¯à±‚ వలె à°—à±à°°à±à°¤à±à°ªà±†à°Ÿà±à°Ÿà±" @@ -758,8 +581,6 @@ te: your_location: "మీ à°ªà±à°°à°¾à°‚తం" your_name: "మీ పేరà±" your_photo: "మీ ఫొటో" - your_private_profile: "మీ రహసà±à°¯ à°ªà±à°°à°µà°°" - your_public_profile: "మీ బహిరంగ à°ªà±à°°à°µà°°" your_tags: "5 పదాలà±à°²à±‹ మీ à°—à±à°°à°¿à°‚à°šà°¿ చెపà±à°ªà°‚à°¡à°¿" your_tags_placeholder: "#చలనచితà±à°°à°¾à°²à± #à°ªà±à°°à°¯à°¾à°£à°‚ #à°•à±à°°à°¿à°•à±†à°Ÿà± #తెలà±à°—à± #సంగీతం #హైదరాబాదౠవంటివి" update: @@ -774,26 +595,16 @@ te: closed: "à°ˆ డయాసà±à°ªà±‹à°°à°¾* పాడౠపై కొతà±à°¤ à°ªà±à°°à°µà±‡à°¶à°¾à°²à± మూసివేయబడà±à°¡à°¾à°¯à°¿." create: success: "డయాసà±à°ªà±‹à°°à°¾*లో మీ చేరిక విజయవంతం!" - edit: - cancel_my_account: "నా ఖాతానౠరదà±à°¦à±à°šà±‡à°¯à°¿" - edit: "%{name} నౠసవరించà±à°•à±‹à°‚à°¡à°¿" - leave_blank: "(మారà±à°šà±à°•à±‚డదౠఅనà±à°•à±à°‚టే ఖాళీగా వదిలేయండి)" - password_to_confirm: "(మారà±à°ªà±à°²à°¨à± నిరà±à°§à°¾à°°à°¿à°‚చడానకి మీ à°ªà±à°°à°¸à±à°¤à±à°¤ సంకేతపదం కావాలి)" - unhappy: "అసంతృపà±à°¤à°¾?" - update: "నవీకరించà±à°•à±‹à°‚à°¡à°¿" invalid_invite: "మీరౠఇచà±à°šà°¿à°¨ ఆహà±à°µà°¾à°¨à°ªà± లంకె చెలà±à°²à±à°¬à°¾à°Ÿà±à°²à±‹ లేదà±!" new: - create_my_account: "నా ఖాతానౠసృషà±à°Ÿà°¿à°‚à°šà±!" email: "ఈమెయిలà±" enter_email: "à°’à°• ఈమెయిలà±à°¨à± ఇవà±à°µà°‚à°¡à°¿" enter_password: "సంకేతపదానà±à°¨à°¿ ఇవà±à°µà°‚à°¡à°¿ (కనీసం ఆరౠఅకà±à°·à°°à°¾à°²à±)" enter_password_again: "అదే సంకేతపదానà±à°¨à°¿ మళà±à°³à±€ ఇవà±à°µà°‚à°¡à°¿" enter_username: "à°’à°• వాడà±à°•à°°à°¿à°ªà±‡à°°à±à°¨à± à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿ (à°…à°•à±à°·à°°à°¾à°²à±, సంఖà±à°¯à°²à±, మరియౠకà±à°°à°¿à°‚దిగీతలౠమాతà±à°°à°®à±‡ à°¸à±à°µà±€à°•à°°à°¿à°‚చబడà±à°¨à±)" - join_the_movement: "à°ˆ ఉదà±à°¯à°®à°‚లో చేరండి!" password: "సంకేతపదం" password_confirmation: "సంకేతపదం నిరà±à°§à°¾à°°à°£" sign_up: "నమోదవà±à°µà°‚à°¡à°¿" - sign_up_message: "♥ తో à°’à°• సామాజిక à°…à°¨à±à°¸à°‚ధాన వేదిక" submitting: "దాఖలà±à°šà±‡à°¸à±à°¤à±à°¨à±à°¨à°¾à°‚..." terms_link: "సేవా à°·à°°à°¤à±à°²à±" username: "వాడà±à°•à°°à°¿à°ªà±‡à°°à±" @@ -806,42 +617,14 @@ te: reported_label: "%{person} <b>చే నివేదించబడింది</b>" review_link: "సమీకà±à°·à°¿à°‚చినటà±à°²à± à°—à±à°°à±à°¤à±à°ªà±†à°Ÿà±à°Ÿà±" status: - created: "à°’à°• నివేదిక సృషà±à°Ÿà°¿à°‚చబడింది" destroyed: "టపా నాశనం చేయబడింది" failed: "à°à°¦à±‹ పొరపాటౠజరిగింది" - marked: "నివేదిక సమీకà±à°·à°¿à°‚చబడినదిగా à°—à±à°°à±à°¤à±à°ªà±†à°Ÿà±à°Ÿà°¬à°¡à°¿à°‚ది" title: "నివేదికల అవలోకనం" - requests: - create: - sending: "పంపà±à°¤à±à°¨à±à°¨à°¾à°®à±" - sent: "మీరౠ%{name} తో పంచà±à°•à±‹à°µà°¡à°¾à°¨à°¿à°•à°¿ అడిగారà±. వారి తదà±à°ªà°°à°¿ డయాసà±à°ªà±‹à°°à°¾* à°ªà±à°°à°µà±‡à°¶à°‚లో దీనిని చూసà±à°¤à°¾à°°à±." - destroy: - error: "దయచేసి à°’à°• కోణానà±à°¨à°¿ à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿!" - ignore: "పరిచయం à°…à°à±à°¯à°°à±à°¥à°¨ విసà±à°®à°°à°¿à°‚చబడింది." - success: "మీరిపà±à°ªà±à°¡à± పంచà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à±." - helper: - new_requests: - one: "కొతà±à°¤ à°…à°à±à°¯à°°à±à°¥à°¨!" - other: "%{count} కొతà±à°¤ à°…à°à±à°¯à°°à±à°¥à°¨à°²à±!" - zero: "కొతà±à°¤ à°…à°à±à°¯à°°à±à°¥à°¨à°²à±‡à°®à°¿ లేవà±" - manage_aspect_contacts: - existing: "ఉనà±à°¨à°Ÿà±à°µà°‚à°Ÿà°¿ పరిచయాలà±" - manage_within: "ఇందà±à°²à±‹à°¨à±‡ పరిచయాలనౠనిరà±à°µà°¹à°¿à°‚à°šà±" - new_request_to_person: - sent: "పంపబడింది!" reshares: - create: - failure: "à°ˆ టపానౠమరలాపంచà±à°Ÿà°²à±‹ à°’à°• దోషం à°à°°à±à°ªà°¡à°¿à°‚ది." reshare: deleted: "అసలౠటపా రచయితచే తొలగించబడింది." - reshare: - one: "1 పంచà±à°•à±‹à°²à±" - other: "%{count} పంచà±à°•à±‹à°³à±à°³à±" - zero: "పంచà±à°•à±‹à°‚à°¡à°¿" reshare_confirmation: "%{author} యొకà±à°• టపానౠమరలాపంచà±à°¤à°¾à°°à°¾?" - reshare_original: "అసలà±à°¨à°¿ మరలాపంచà±à°•à±‹à°‚à°¡à°¿" reshared_via: "వీరి à°¨à±à°‚à°¡à°¿ మరలాపంచà±à°•à±à°¨à±à°¨à°¾à°°à±" - show_original: "అసలà±à°¨à°¿ చూపించà±" search: "వెతà±à°•à±" services: create: @@ -852,10 +635,6 @@ te: success: "ధృవీకరణ విజయవంతంగా తొలగించబడింది." failure: error: "à°† సేవకౠఅనà±à°¸à°‚ధానించà±à°Ÿà°²à±‹ దోషం సంà°à°µà°¿à°‚చింది." - finder: - fetching_contacts: "మీ %{service} మితà±à°°à±à°²à°¨à± డయాసà±à°ªà±‹à°°à°¾* పాపà±à°²à±‡à°Ÿà± చేసà±à°¤à±‹à°‚ది, దయచేసి కొనà±à°¨à°¿ నిమిషాలలో సరిచూసà±à°•à±‹à°‚à°¡à°¿." - no_friends: "à°Žà°Ÿà±à°µà°‚à°Ÿà°¿ ఫేసà±â€Œà°¬à±à°•à± మితà±à°°à±à°²à± కనపడలేదà±." - service_friends: "%{service} మితà±à°°à±à°²à±" index: connect: "à°…à°¨à±à°¸à°‚ధానించà±" disconnect: "నిరనà±à°¸à°‚ధానించà±" @@ -864,51 +643,22 @@ te: no_services_available: "à°ˆ పాడౠపై à°Žà°Ÿà±à°µà°‚à°Ÿà°¿ సేవలౠఅందà±à°¬à°¾à°Ÿà±à°²à±‹ లేవà±." not_logged_in: "à°ªà±à°°à°¸à±à°¤à±à°¤à°‚ à°ªà±à°°à°µà±‡à°¶à°¿à°‚చిలేరà±." really_disconnect: "%{service} నిరనà±à°¸à°‚ధానించాలా?" - inviter: - click_link_to_accept_invitation: "మీ ఆహà±à°µà°¾à°¨à°¾à°¨à±à°¨à°¿ అంగీకరించà±à°Ÿà°•à± à°ˆ లంకెనౠఅనà±à°¸à°°à°¿à°‚à°šà°‚à°¡à°¿" - join_me_on_diaspora: "డయాసà±à°ªà±‹à°°à°¾*లో ననà±à°¨à± చేరà±à°šà±à°•à±‹à°‚à°¡à°¿" provider: facebook: "ఫేసà±â€Œà°¬à±à°•à±" tumblr: "à°Ÿà°‚à°¬à±à°²à°°à±" twitter: "à°Ÿà±à°µà°¿à°Ÿà±à°Ÿà°°à±" wordpress: "వరà±à°¡à±â€Œà°ªà±à°°à±†à°¸à±" - remote_friend: - invite: "ఆహà±à°µà°¾à°¨à°¿à°‚à°šà°‚à°¡à°¿" - not_on_diaspora: "ఇంకా డయాసà±à°ªà±‹à°°à°¾*లో చేరలేదà±" - resend: "మరలాపంపà±" settings: "అమరికలà±" - share_visibilites: - update: - post_hidden_and_muted: "%{name} యొకà±à°• టపా దాయబడింది, మరియౠగమనింపà±à°²à± నిశà±à°¶à°¬à±à°¦à°¿à°‚చబడినవి." - see_it_on_their_profile: "ఒకవేళ మీరౠఈ టపాపై తాజాకరణలౠకావాలనà±à°•à±à°‚టే, %{name} యొకà±à°• à°ªà±à°°à°µà°° à°ªà±à°Ÿà°¨à± సందరà±à°¶à°¿à°‚à°šà°‚à°¡à°¿." shared: - add_contact: - add_new_contact: "à°’à°• కొతà±à°¤ పరిచయానà±à°¨à°¿ జతచేయండి" - create_request: "డయాసà±à°ªà±‹à°°à°¾* à°—à±à°šà°¿ à°¦à±à°µà°¾à°°à°¾ à°•à°¨à±à°—ొనండి" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "à°’à°• డయాసà±à°ªà±‹à°°à°¾* వాడà±à°•à°°à°¿à°ªà±‡à°°à±à°¨à± ఇవà±à°µà°‚à°¡à°¿:" - know_email: "మీ వారి ఈమెయిలౠచిరà±à°¨à°¾à°®à°¾à°²à± తెలà±à°¸à°¾? అయితే మీరౠవారిని తపà±à°ªà°• ఆహà±à°µà°¾à°¨à°¿à°‚చాలి" - your_diaspora_username_is: "మీ డయసà±à°ªà±‹à°°à°¾* వాడà±à°•à°°à°¿ పేరà±: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "పరిచయానà±à°¨à°¿ జతచేయి" toggle: one: "%{count} కోణంలో" other: "%{count} కోణాలలో" zero: "పరిచయానà±à°¨à°¿ జతచేయి" - contact_list: - all_contacts: "à°…à°¨à±à°¨à°¿ పరిచయాలà±" - footer: - logged_in_as: "%{name} పేరà±à°¤à±‹ లోనికివచà±à°šà°¾à°°à±" - your_aspects: "మీ కోణాలà±" invitations: by_email: "ఈమెయిలౠదà±à°µà°¾à°°à°¾" - dont_have_now: "ఇపà±à°ªà±à°¡à± మీ వదà±à°¦ ఆహà±à°µà°¾à°¨à°¾à°²à± à°à°®à±€ లేదà±, కానీ తరà±à°µà°²à±‹à°¨à±‡ వసà±à°¤à°¾à°¯à°¿!" - from_facebook: "ఫేసà±â€Œà°¬à±à°•à± à°¨à±à°‚à°¡à°¿" - invitations_left: "%{count} ఉనà±à°¨à°¾à°¯à°¿" - invite_someone: "ఎవరినైనా ఆహà±à°µà°¾à°¨à°¿à°‚à°šà°‚à°¡à°¿" invite_your_friends: "మీ మితà±à°°à±à°²à°¨à± ఆహà±à°µà°¾à°¨à°¿à°‚à°šà°‚à°¡à°¿" invites: "ఆహà±à°µà°¾à°¨à°¾à°²à±" - invites_closed: "à°ˆ డయాసà±à°ªà±‹à°°à°¾* పాడౠపై à°ªà±à°°à°¸à±à°¤à±à°¤à°‚ ఆహà±à°µà°¾à°¨à°¾à°²à± మూసివేయబడà±à°¡à°¾à°¯à°¿" share_this: "à°ˆ లంకెనౠఈమెయిలà±, à°¬à±à°²à°¾à°—à±, లేదా సమాజిక à°…à°¨à±à°¸à°‚ధాన వేదికల à°¦à±à°µà°¾à°°à°¾ పంచà±à°•à±‹à°‚à°¡à°¿!" public_explain: atom_feed: "ఆటమౠఫీడà±" @@ -920,12 +670,9 @@ te: title: "à°…à°¨à±à°¸à°‚ధానిత సేవలనౠఅమరà±à°šà°‚à°¡à°¿" visibility_dropdown: "మీ టపా దృగà±à°—ోచరతనౠమారà±à°šà°¡à°¾à°¨à°¿à°•à°¿ à°ˆ జారà±à°¡à±à°ªà°Ÿà±à°Ÿà±€à°¨à°¿ వాడండి. (మొదటి టపానౠబహిరంగంగా ఉంచమని మీకౠసూచిసà±à°¤à±à°¨à±à°¨à°¾à°‚.)" publisher: - all: "à°…à°¨à±à°¨à±€" - all_contacts: "à°…à°¨à±à°¨à°¿ పరిచయాలà±" discard_post: "టపానౠరదà±à°¦à±à°šà±‡à°¯à°¿" formatWithMarkdown: "మీ టపానౠఅలంకరించడానికి %{markdown_link} వాడవచà±à°šà±" get_location: "మీ à°¸à±à°¥à°¾à°¨à°¾à°¨à±à°¨à°¿ పొందండి" - make_public: "బహిరà±à°—తం చేయి" new_user_prefill: hello: "అందరికీ నమసà±à°•à°¾à°°à°‚, నేనౠ#%{new_user_tag}. " i_like: "%{tags} లలో నాకౠఆసకà±à°¤à°¿ ఉంది. " @@ -933,36 +680,14 @@ te: newhere: "NewHere" poll: add_a_poll: "à°’à°• à°Žà°¨à±à°¨à°¿à°•à°¨à± జతచేయి" - add_poll_answer: "ఎంపికనౠజతచేయి" - option: "ఎంపిక 1" - question: "à°ªà±à°°à°¶à±à°¨" - remove_poll_answer: "ఎంపికనౠతొలగించà±" - post_a_message_to: "%{aspect} à°•à± à°’à°• సందేశం పంపండి" posting: "టపాకడà±à°¤à±‚ంది..." - preview: "à°®à±à°¨à±à°œà±‚à°ªà±" - publishing_to: "వీటికి à°ªà±à°°à°šà±à°°à°¿à°¸à±à°¤à±‹à°‚ది: " remove_location: "à°¸à±à°¥à°¾à°¨à°¾à°¨à±à°¨à°¿ తీసివేయి" share: "పంచà±à°•à±‹à°‚à°¡à°¿" - share_with: "వీరితో పంచà±à°•à±‹à°‚à°¡à°¿" upload_photos: "ఛాయాచితà±à°°à°¾à°²à°¨à± à°Žà°•à±à°•à°¿à°‚à°šà°‚à°¡à°¿" whats_on_your_mind: "మీ à°¬à±à°°à±à°°à°²à±‹ à°à°‚ మెదà±à°²à±à°¤à±‹à°‚ది?" - reshare: - reshare: "మరలపంచà±à°•à±‹à°‚à°¡à°¿" stream_element: - connect_to_comment: "టపాపై à°µà±à°¯à°¾à°–à±à°¯à°¾à°¨à°¿à°‚à°šà±à°Ÿà°•à± à°ˆ వాడà±à°•à°°à°¿à°¤à±‹ à°…à°¨à±à°¸à°‚ధానమవà±à°µà°‚à°¡à°¿" - currently_unavailable: "à°µà±à°¯à°¾à°–à±à°¯à°¾à°¨à°¿à°‚à°šà±à°Ÿ à°ªà±à°°à°¸à±à°¤à±à°¤à°‚ à°…à°‚à°¦à±à°¬à°¾à°Ÿà±à°²à±‹à°²à±‡à°¦à±" - dislike: "అయిషà±à°Ÿà°‚" - hide_and_mute: "టపానౠదాచి, నిశà±à°¶à°¬à±à°¦à°¿à°‚à°šà±" - ignore_user: "%{name}నౠవిసà±à°®à°°à°¿à°‚à°šà°‚à°¡à°¿" - ignore_user_description: "à°…à°¨à±à°¨à°¿ కోణాల à°¨à±à°‚à°¡à°¿ వాడà±à°•à°°à°¿à°¨à°¿ విసà±à°®à°°à°¿à°‚à°šà°¿, తీసివేయాలా?" - like: "ఇషà±à°Ÿà°‚" - nsfw: "à°ˆ టపా రచయితచే NSFW à°—à°¾ à°—à±à°°à±à°¤à±à°ªà±†à°Ÿà±à°Ÿà°¬à°¡à°¿à°‚ది. %{link}" - shared_with: "వీటిలో పంచà±à°•à±à°¨à±à°¨à°¾à°°à±: %{aspect_names}" - show: "చూపించà±" - unlike: "అయిషà±à°Ÿà°‚" via: "%{link} à°¦à±à°µà°¾à°°à°¾" via_mobile: "మొబైలౠదà±à°µà°¾à°°à°¾" - viewable_to_anyone: "à°ˆ టపానౠజాలంలో ఎవరైనా చూడగలరà±" simple_captcha: label: "కోడà±à°¨à± పేటికలో à°ªà±à°°à°µà±‡à°¶à°ªà±†à°Ÿà±à°Ÿà°‚à°¡à°¿:" message: @@ -985,20 +710,11 @@ te: status_messages: create: success: "విజయవంతంగా పేరà±à°•à±Šà°¨à±à°¨à°¾à°°à±: %{names}" - destroy: - failure: "టపాని తొలగించలేకపోయామà±" - helper: - no_message_to_display: "చూపించడానికి ఠసందేశాలౠలేవà±." new: mentioning: "పేరà±à°•à±‹à°²à±: %{person}" too_long: "{\"one\"=>\"దయచేసి మీ à°¸à±à°¥à°¿à°¤à°¿ సందేశాలలో à°…à°•à±à°·à°°à°¾à°² సంఖà±à°¯ %{count} కంటే తకà±à°•à±à°µ ఉండేటటà±à°²à± చూసà±à°•à±‹à°‚à°¡à°¿\", \"other\"=>\"దయచేసి మీ à°¸à±à°¥à°¿à°¤à°¿ సందేశాలలో à°…à°•à±à°·à°°à°¾à°² సంఖà±à°¯ %{count} కంటే తకà±à°•à±à°µ ఉండేటటà±à°²à± చూసà±à°•à±‹à°‚à°¡à°¿\", \"zero\"=>\"దయచేసి మీ à°¸à±à°¥à°¿à°¤à°¿ సందేశాలలో à°…à°•à±à°·à°°à°¾à°² సంఖà±à°¯ %{count} కంటే తకà±à°•à±à°µ ఉండేటటà±à°²à± చూసà±à°•à±‹à°‚à°¡à°¿\"}" stream_helper: - hide_comments: "à°…à°¨à±à°¨à°¿ à°µà±à°¯à°¾à°–à±à°¯à°²à°¨à± దాచà±" no_posts_yet: "à°…à°•à±à°•à°¡ ఇంకా ఠటపాలౠలేవà±." - show_comments: - one: "మరొకà±à°• à°µà±à°¯à°¾à°–à±à°¯à°¨à± చూపించà±" - other: "మరో %{count} à°µà±à°¯à°¾à°–à±à°¯à°²à°¨à± చూపించà±" - zero: "ఇంకేమీ à°µà±à°¯à°¾à°–à±à°¯à°²à± లేవà±" streams: activity: title: "నా à°•à±à°°à°¿à°¯à°¾à°¶à±€à°²à°¤" @@ -1021,23 +737,14 @@ te: public: title: "బహిరంగ à°•à±à°°à°¿à°¯à°¾à°¶à±€à°²à°¤" tag_followings: - create: - failure: "#%{name} à°…à°¨à±à°¸à°°à°¿à°‚à°šà±à°Ÿà°²à±‹ విఫలం. మీరౠఇంతకà±à°®à±à°‚దౠనà±à°‚డే à°…à°¨à±à°¸à°°à°¿à°¸à±à°¤à±à°¨à±à°¨à°¾à°°à°¾?" - none: "మీరౠఖాళీ కొసనౠఅనà±à°¸à°°à°¿à°‚చలేరà±!" - success: "à°¹à±à°°à±à°°à±‡! మీరిపà±à°ªà±à°¡à± #%{name} నౠఅనà±à°¸à°°à°¿à°¸à±à°¤à±à°¨à±à°¨à°¾à°°à±." - destroy: - failure: "#%{name} à°…à°¨à±à°¸à°°à°£ ఆపà±à°Ÿà°²à±‹ విఫలం. మీరౠఇంతకà±à°®à±à°‚దే à°…à°¨à±à°¸à°°à°£à°¨à± ఆపివేసివà±à°‚డవచà±à°šà±?" manage: no_tags: "మీరౠఎటà±à°µà°‚à°Ÿà°¿ కొసలనౠఅనà±à°¸à°°à°¿à°‚à°šà±à°Ÿà°²à±‡à°°à±." title: "à°…à°¨à±à°¸à°°à°¿à°‚చే కొసలనౠనిరà±à°µà°¹à°¿à°‚à°šà°‚à°¡à°¿" tags: show: follow: "#%{tag}నౠఅనà±à°¸à°°à°¿à°‚à°šà±" - following: "#%{tag}నౠఅనà±à°¸à°°à°¿à°¸à±à°¤à±à°¨à±à°¨à°¾à°°à±" none: "ఖాళీ కొస చెలà±à°²à°¦à±!" stop_following: "#%{tag}నౠఅనà±à°¸à°°à°¿à°‚à°šà°¡à°‚ మానివేయి" - terms_and_conditions: "నియమాలౠమరియౠనిబంధనలà±" - undo: "à°°à°¦à±à°¦à±à°šà±‡à°¯à°¾à°²à°¾?" username: "వాడà±à°•à°°à°¿à°ªà±‡à°°à±" users: confirm_email: @@ -1069,12 +776,10 @@ te: current_password_expl: "మీరౠపà±à°°à°µà±‡à°¶à°¿à°‚చే దానితో..." download_export: "నా à°ªà±à°°à°µà°°à°¨à± దింపà±" download_export_photos: "నా ఛాయాచితà±à°°à°¾à°²à°¨à± దింపà±à°®à±" - download_photos: "నా ఛాయాచితà±à°°à°¾à°²à°¨à± దింపà±à°®à±" edit_account: "ఖాతానౠసవరించà±" email_awaiting_confirmation: "మేమౠమీకొక à°•à±à°°à°¿à°¯à°¾à°¶à±€à°²à°¿à°‚చౠలంకెనౠ%{unconfirmed_email} కౠపంపామà±. మీరౠఈ లంకెనౠఅనà±à°¸à°°à°¿à°‚à°šà°¿ కొతà±à°¤ à°šà°¿à°°à±à°¨à°¾à°®à°¾à°¨à± à°•à±à°°à°¿à°¯à°¾à°¶à±€à°²à°¿à°‚చేంతవరకూ, మీ అసలౠచిరà±à°¨à°¾à°®à°¾ %{email} నౠవాడతామà±." export_data: "దతà±à°¤à°¾à°‚శానà±à°¨à°¿ à°Žà°—à±à°®à°¤à°¿à°‚à°šà±" following: "పంచà±à°•à±‹à°²à± అమరికలà±" - getting_started: "కొతà±à°¤ వాడà±à°•à°°à°¿ à°…à°à°¿à°°à±à°šà±à°²à±" liked: "ఎవరో మీ టపానౠమెచà±à°šà±à°•à±à°¨à±à°¨à°¾à°°à±" mentioned: "మీరౠటపాలో à°ªà±à°°à°¸à±à°¤à°¾à°µà°¿à°‚చబడà±à°¡à°¾à°°à±" new_password: "కొతà±à°¤ సంకేతపదం" @@ -1098,7 +803,6 @@ te: community_welcome: "మిమà±à°®à°²à±à°¨à°¿ కలిగివà±à°‚à°¡à°‚à°Ÿà°‚ డయాసà±à°ªà±‹à°°à°¾* à°•à°®à±à°¯à±‚నిటీ సంతోషంగా à°à°¾à°µà°¿à°¸à±à°¤à±à°‚ది!" connect_to_facebook_link: "మీ ఫేసà±â€Œà°¬à±à°•à± ఖాతాతో లంకె వేసà±à°¤à±à°¨à±à°¨à°¾à°‚" hashtag_suggestions: "#art, #movies, #gif, వంటి తదితర కొసలనౠఅనà±à°¸à°°à°¿à°‚à°šà°¿ చూడండి." - saved: "à°à°¦à±à°°à°ªà°°à°šà°¬à°¡à°¿à°‚ది!" well_hello_there: "హలో ఎలావà±à°¨à±à°¨à°¾à°°à±..." what_are_you_in_to: "మీకౠà°à°‚ ఇషà±à°Ÿà°‚?" who_are_you: "మీరెవరà±?" @@ -1121,12 +825,6 @@ te: settings_updated: "అమరికలౠనవీకరించబడà±à°¡à°¾à°¯à°¿" unconfirmed_email_changed: "ఈమెయిలౠమారà±à°šà°¬à°¡à°¿à°‚ది. ఉతà±à°¤à±‡à°œà°¨à°‚ అవసరం" unconfirmed_email_not_changed: "ఈమెయిలౠమారà±à°ªà± విఫలం" - webfinger: - hcard_fetch_failed: "%{account} కోసం హెచà±â€Œà°•à°¾à°°à±à°¡à± తెచà±à°šà±à°Ÿà°²à±‹ à°’à°• సమసà±à°¯ ఉంది" - no_person_constructed: "à°ˆ హెచà±â€Œà°•à°¾à°°à±à°¡à± à°¨à±à°‚à°¡à°¿ à° à°µà±à°¯à°•à±à°¤à°¿ నిరà±à°®à°¿à°‚చబడడà±." - not_enabled: "వెబà±â€Œà°«à°¿à°‚à°—à°°à± %{account} హోసà±à°Ÿà± కోసం చేతనపరచి ఉనà±à°¨à°Ÿà±à°²à± లేదà±" - xrd_fetch_failed: "%{account} ఖాతా à°¨à±à°‚à°¡à°¿ à°Žà°•à±à°¸à±â€Œà°†à°°à±â€Œà°¡à±€ పొందà±à°Ÿà°²à±‹ à°’à°• సమసà±à°¯ ఉంది" - welcome: "à°¸à±à°µà°¾à°—తం!" will_paginate: next_label: "తదà±à°ªà°°à°¿à°µà°¿ »" previous_label: "« à°®à±à°¨à±à°ªà°Ÿà°¿à°µà°¿" \ No newline at end of file diff --git a/config/locales/diaspora/tr.yml b/config/locales/diaspora/tr.yml index 9ac59b680157399fcde841741026611b4e45782f..bcb9ef223d9eb1ef1e06fd90d342cf0b046f931a 100644 --- a/config/locales/diaspora/tr.yml +++ b/config/locales/diaspora/tr.yml @@ -6,11 +6,8 @@ tr: _applications: "Uygulamalar" - _comments: "Yorumlar" _contacts: "KiÅŸiler" _help: "Yardım" - _home: "Ev" - _photos: "fotoÄŸraflar" _services: "Servisler" _terms: "Kurallar" account: "Hesap" @@ -96,13 +93,7 @@ tr: other: "bu haftaki kullanıcı sayısı: %{count}" zero: "bu haftaki kullanıcı sayısı: yok" current_server: "Åžu andaki sunucu tarihi %{date}" - ago: "%{time} önce" all_aspects: "Tüm Yönler" - application: - helper: - unknown_person: "bilinmeyen kiÅŸi" - video_title: - unknown: "Geçersiz Video BaÅŸlığı" are_you_sure: "Emin misin?" are_you_sure_delete_account: "Hesabını kapatmak istediÄŸinden emin misin? Bu geri alınamaz!" aspect_memberships: @@ -117,18 +108,10 @@ tr: success: "KiÅŸi baÅŸarıyla yöne eklendi." aspect_listings: add_an_aspect: "+ Yeni yön ekle" - deselect_all: "Tümünü kaldır" - edit_aspect: "Düzenle %{name}" - select_all: "Tümünü seç" aspect_stream: make_something: "Bir ÅŸeyler yapın" stay_updated: "Güncel Kalın" stay_updated_explanation: "Ana akışınızda takip ettiÄŸiniz kiÅŸiler, takip ettiÄŸiniz etiketler ve topluluk üyelerinin gönderileri bulunur." - contacts_not_visible: "KiÅŸilerin bu yönde birbirlerini görmesi mümkün olmayacaktır." - contacts_visible: "Bu yöndekiler birbirlerini görebilecektir." - create: - failure: "Yön oluÅŸturulamadı." - success: "Yeni yön'ün %{name} yaratıldı" destroy: failure: "%{name} boÅŸ deÄŸil, silinemedi." success: "%{name} baÅŸarıyla silindi." @@ -136,24 +119,15 @@ tr: aspect_list_is_not_visible: "yön listesi yöndeki diÄŸer kiÅŸilere gösterilmiyor" aspect_list_is_visible: "yön listesi yöndeki diÄŸer kiÅŸilere gösteriliyor" confirm_remove_aspect: "Bu yönü silmek istediÄŸinden emin misin?" - make_aspect_list_visible: "Bu yöndeki kiÅŸilerin birbirlerini görmesine izin verilsin mi?" - remove_aspect: "Yönü sil" rename: "yeniden adlandır" update: "güncelle" updating: "güncelleniyor" index: - diaspora_id: - content_1: "Diaspora ID'niz:" - content_2: "Diaspora'da sizi bulabilmelerini istediÄŸiniz kiÅŸilere verebilirsiniz." - heading: "Diaspora ID (Diaspora KimliÄŸi)" donate: "Bağış yap" - handle_explanation: "Bu Diaspora kimliÄŸindir. Bir e-posta adresi gibi, bunu insanlara sana ulaÅŸması için verebilirsin." help: any_problem: "Bir sorun var mı?" contact_podmin: "Podunuzun yöneticisiyle iliÅŸkiye geçin!" do_you: "Seçim:" - email_feedback: "%{link} ile yolla mesajını, bu yolu tercih ediyorsan" - email_link: "E-posta" feature_suggestion: "... bir %{link} önerin var mı?" find_a_bug: "... bulduÄŸun %{link} mı var?" have_a_question: "... bir %{link} mu sormak istiyorsun?" @@ -166,31 +140,20 @@ tr: tutorial_link_text: "Öğreticiler" tutorials_and_wiki: "%{tutorial} & %{wiki}: Ä°lk adımlarınız için yardım." introduce_yourself: "Bu sizin akışınızdır. Atla ve kendini tanıt." - keep_diaspora_running: "Diaspora'nın geliÅŸmesini aylık bir bağışınızla hızlandırın." keep_pod_running: "%{pod}u hızlı çalıştırmaya devam edin ve sunucularına aylık bir bağışla kahve ikram edin." new_here: follow: "%{link} baÄŸlantısını tıkla ve yeni diaspora* kullanıcılarıyla tanış!" learn_more: "Daha fazla bilgi" title: "Yeni KiÅŸilerle Tanış" - no_contacts: "KiÅŸi yok" - no_tags: "+ Takip etmek için bir etiket bul" - people_sharing_with_you: "Seninle paylaşımda bulunanlar" - post_a_message: "mesaj gönder >>" services: content: "Diaspora'ya aÅŸağıdaki hizmetleri baÄŸlayabilirsin:" heading: "Servisleri iliÅŸkilendir" - unfollow_tag: "#%{tag}'i takip etmeyi bırak" welcome_to_diaspora: "Diaspora'ya HoÅŸ Geldin, %{name}!" - new: - create: "OluÅŸtur:" - name: "Ä°sim (sadece siz görebilirsiniz)" no_contacts_message: community_spotlight: "topluluk gönderileri" or_spotlight: "Ya da %{link} ile paylaÅŸabilirsin" try_adding_some_more_contacts: "Daha fazla kiÅŸi arayabilir ya da davet edebilirsin." you_should_add_some_more_contacts: "Daha fazla kiÅŸi eklemelisin!" - no_posts_message: - start_talking: "Hiçbir ÅŸey söylemedi!" seed: acquaintances: "Tanıdıklar" family: "Aile" @@ -199,7 +162,6 @@ tr: update: failure: "%{name} yönünün ismi çok uzundu ve kaydedilmedi." success: "Yönünüz, %{name}, baÅŸarıyla düzeltildi." - back: "Geri" blocks: create: failure: "Bu kullanıcıyı görmezden gelemedim. #evasion" @@ -211,21 +173,14 @@ tr: explanation: "Diaspora'ya istediÄŸin her yerden gönderi yapmak için %{link} baÄŸlantısını yer imlerine ekle." heading: "Diaspora yer iÅŸareti" post_something: "Diaspora için bir ÅŸey gönder" - post_success: "Gönderildi! Kapatılıyor!" cancel: "Ä°ptal Et" comments: new_comment: comment: "Yorum yaz" commenting: "Yorumlanıyor..." - one: "1 yorum" - other: "%{count} yorum" - zero: "yorum yok" contacts: - create: - failure: "KiÅŸi oluÅŸturma baÅŸarısız" index: add_a_new_aspect: "Yeni yön ekle" - add_to_aspect: "%{name} unsuruna kiÅŸi ekle" all_contacts: "Tüm KiÅŸiler" community_spotlight: "Topluluk Haberleri" my_contacts: "KiÅŸilerim" @@ -234,32 +189,20 @@ tr: only_sharing_with_me: "Benimle paylaşım yapan" start_a_conversation: "Bir iletiÅŸim baÅŸlatın" title: "KiÅŸiler" - your_contacts: "KiÅŸiler" - sharing: - people_sharing: "Sizinle paylaşıyor:" spotlight: community_spotlight: "Topluluk Gönderileri" suggest_member: "Bir üye önerin." conversations: - conversation: - participants: "Katilimcılar" create: fail: "Geçersiz mesaj" no_contact: "Hey, önce bir baÄŸlantı ekleyin!" sent: "Mesaj gönderildi" - helper: - new_messages: - other: "%{count} yeni ileti" - zero: "Yeni ileti yok" index: conversations_inbox: "Yazışmalar — Gelen kutusu" - create_a_new_conversation: "Bir yazışma baÅŸlat" inbox: "Gelen Kutusu" new_conversation: "Yeni yazışma" - no_conversation_selected: "hiç ileti seçilmedi" no_messages: "mesaj yok" new: - abandon_changes: "DeÄŸiÅŸiklikler silinsin mi?" send: "Gönder" sending: "Gönderiliyor..." subject: "konu" @@ -280,10 +223,6 @@ tr: error_messages: helper: correct_the_following_errors_and_try_again: "Alttaki yanlıșları düzeltin ve tekrar deneyin." - invalid_fields: "Geçersiz Alanlar" - login_try_again: "Lütfen <a href='%{login_link}'>giriÅŸ yapın</a> ve tekrar deneyin!" - post_not_public: "Görüntülemeye çalıştığınız gönderi aleni deÄŸildir!" - post_not_public_or_not_exist: "Görüntülemeye çalıştığınız gönderi ya hiç yok ya da genel gönderi deÄŸil!" fill_me_out: "Beni doldur" find_people: "KiÅŸi ve #tag bul" help: @@ -300,6 +239,8 @@ tr: move_pods_q: "Tohumumu (hesabımı) baÅŸka bir poda nasıl taşırım?" title: "Hesap ve veri yönetimi" aspects: + change_aspect_of_post_a: "Hayır, ama aynı içerikte baÅŸka bir gönderi hazırlayıp bunu farklı bir bakış yönünde gönderebilirsiniz." + change_aspect_of_post_q: "Bir gönderiyi paylaÅŸtıktan sonra onu gören hedef bakışları deÄŸiÅŸtirebilir miyim?" contacts_know_aspect_a: "Hayır. Bakışın adını hiçbir ÅŸekilde göremezler." contacts_know_aspect_q: "DiÄŸerleri onları hangi bakışlara koyduÄŸumu bilebilir mi?" person_multiple_aspects_a: "Evet. KiÅŸiler sayfasına gidin ve kiÅŸilerime tıklayın. Her biri için saÄŸdaki menüyü kullanarak, istediÄŸiniz kadar çok bakışa ekleyip istediÄŸiniz kadarından çıkarabilirsiniz. Profil sayfasındaki bakış seçicisine tıklayarak da bunu yapabilirsiniz. Hatta, imleci adının üzerine götürdüğünüzde çıkan 'kartı' kullanarak da aynı ÅŸeyi yapabilirsiniz." @@ -357,12 +298,16 @@ tr: what_is_a_pod_a: "Pod diaspora* yazılımını çalıştıran ve diaspora* ağına baÄŸlı bir sunucudur. Bitkilerin tohum saplarının uçlarına, sunucuların kullanıcı sayısı açısından, benzediÄŸi için bu ad verilmiÅŸtir. Bir çok pod vardır. DiÄŸer podlardan arkadaÅŸlar ekleyebilir ve onlarla haberleÅŸebilirsiniz. (diasora*yı bir e-mektup saÄŸlayıcısına benzetebilirsiniz: Açık podlar, özel podlar, hatta biraz çaba ile kendiniz bile bir pod açabilirsiniz)." what_is_a_pod_q: "Pod nedir?" posts_and_posting: + char_limit_services_a: "O halde, göndereceÄŸiniz diÄŸer hizmetin uzunluk sınırına uygun yazmanızı öneririz. AÅŸmanız halinde, metin orada kırpılacak, ve diaspora* gönderisine bir baÄŸlantı verilecektir. Gönderinizi kısa tutmaya yardımcı olmak için baÄŸlı hizmetin uzunluk sınırına kalan deÄŸer(Tumblr için 1000, Twitter için 140) gönderi sırasında hatırlatılacaktır." + char_limit_services_q: "Gönderimi uzunluk sınırı olan bir baÄŸlı servise gönderdiÄŸimde uzun gönderilerime ne olur?" character_limit_a: "65,535 karakter. Yani, Twitter'da izin verilenden 65,395 daha fazla karakter! ;)" character_limit_q: "En fazla kaç karakter gönderebilirim?" embed_multimedia_a: "Genelde URL'yi yapıştırmanız gömme iÅŸleminin gerçekleÅŸmesi için yeterli olur: YouTube, Vimeo, SoundCloud, Flickr ve birkaç site daha desteklenir. diaspora* bunu oEmbed yardımıyla gerçekleÅŸtirir. Her an yeni sitelere açığız. Basit göndermeyi unutmayın: tam baÄŸlantılar:kısaltma servisler kulllanmayın; temel URL'den sonra ?#&!= kullanmayın; ve önizlemeyi görebilmek için bir süre bekleyin." embed_multimedia_q: "Bir gönderiye video, ses ya da baÅŸka bir içerik nasıl eklerim?" format_text_a: "%{markdown} sistemini kullanarak. Tüm Markdown sözdizimine %{here} eriÅŸebilirsiniz. Önizleme düğmesinin yardımı dokunur, böylece paylaÅŸmadan önce nasıl görüneceÄŸine bakabilirsiniz." format_text_q: "Gönderilerimi nasıl biçimlendirebilirim(kalın, Ä°talik, vs.)?" + hide_posts_a: "Fareyi gönderinin üzerinde getirdiÄŸinizde saÄŸ tarafta X belirir. Ona tıkladığınızda gönderiyi gizleyip bildirimleri susturmuÅŸ olursunuz. Ancak bu, gönderenin profilini ziyaret ettiÄŸinizde gönderiyi görmenizi engellemez." + hide_posts_q: "Gönderilerimi nasıl gizlerim?" image_text: "resim metni" image_url: "resim url'si" insert_images_comments_a1: "AÅŸağıda not düşülen kod" @@ -406,43 +351,26 @@ tr: tutorial: "öğretici" tutorials: "öğreticiler" wiki: "wiki" - hide: "Gizle" - invitation_codes: - excited: "%{name}, sizi burada gördüğü için heyecanlı." invitations: a_facebook_user: "Bir Facebook kullanıcısı" check_token: not_found: "Davetiye bulunamadı." create: - already_contacts: "Bu kiÅŸiyle zaten baÄŸlantı kurdun" - already_sent: "Bu kiÅŸiyi zaten davet ettin." empty: "En az bir e-posta adresi girin." no_more: "BaÅŸka davetiyeniz yok." note_already_sent: "Davetiyeler %{emails}ne gönderilmiÅŸtir." - own_address: "Kendi adresinize davetiye gönderemezsiniz." rejected: "Bu e-posta adreslerinde sorun oluÅŸtu:" sent: "Davetiyeler ÅŸu adeslere gönderildi: %{emails}" - edit: - accept_your_invitation: "Daveti kabul et" - your_account_awaits: "Hesabın bekliyor!" new: - already_invited: "AÅŸağıdaki kiÅŸiler davetinizi kabul etmedi:" - aspect: "Yön" - check_out_diaspora: "Diaspora'yı deneyin!" codes_left: other: "Bu kodda %{count} davetiye kaldı" zero: "Bu kodda hiç davetiye kalmadı" comma_separated_plz: "" - if_they_accept_info: "kabul ederseler, yönünüze eklenecekler." invite_someone_to_join: "Diaspora'ya birilerini davet et!" language: "Dil" paste_link: "ArkadaÅŸlarınızı Diaspora*'ya davet etmek için bu baÄŸlantıyı paylaşın, ya da baÄŸlantıyı onlara direk eposta olarak atın." - personal_message: "KiÅŸisel mesaj" - resend: "Tekrar gönder" send_an_invitation: "Bir davet yolla" - send_invitation: "Davetiye yolla" sending_invitation: "Davet gönderiliyor..." - to: "Kime" layouts: application: back_to_top: "Sayfa başına dön" @@ -451,43 +379,13 @@ tr: source_package: "kaynak kodu paketini indir" toggle: "mobil site" whats_new: "neler yeni?" - your_aspects: "sizin yönleriniz" header: - admin: "yönetici" - blog: "aÄŸ günlüğü" code: "kod" - login: "giriÅŸ yap" logout: "Çıkış yap" profile: "Profil" - recent_notifications: "Son bildirimler" settings: "Ayarlar" - view_all: "Tümünü göster" - likes: - likes: - people_dislike_this: - few: "%{count} kiÅŸi beÄŸenmedi" - many: "%{count} kiÅŸi beÄŸenmedi" - one: "1 kiÅŸi beÄŸenmedi" - other: "%{count} kiÅŸi beÄŸenmedi" - two: "%{count} beÄŸenmeme" - zero: "beÄŸenmeyen yok" - people_like_this: - few: "%{count} kiÅŸi beÄŸendi" - many: "%{count} kiÅŸi beÄŸendi" - one: "1 kiÅŸi beÄŸendi" - other: "%{count} kiÅŸi beÄŸendi" - two: "%{count} kiÅŸi beÄŸendi" - zero: "beÄŸenme yok" - people_like_this_comment: - few: "%{count} kiÅŸi bunu beÄŸendi" - many: "%{count} kiÅŸi bunu beÄŸendi!" - one: "%{count} beÄŸenme" - other: "%{count} beÄŸenme" - two: "%{count} kiÅŸi bunu beÄŸendi" - zero: "beÄŸenen yok" limited: "Sınırlı" more: "Daha fazla" - next: "sonraki" no_results: "Sonuç Bulunamadı" notifications: also_commented: @@ -503,10 +401,6 @@ tr: comment_on_post: other: "%{actors} %{post_link} gönderinizi yorumladı." zero: "%{actors} %{post_link} gönderinizi yorumladı." - helper: - new_notifications: - other: "%{count} yeni bildirim" - zero: "Yeni bildirim yok" index: and: "ve" and_others: @@ -548,7 +442,6 @@ tr: zero: "%{actors} sizinle paylaşıma baÅŸladı." notifier: a_post_you_shared: "gönderi" - accept_invite: "Diaspora* davetini kabul et!" click_here: "buraya" comment_on_post: reply: "Yanıtla ya da %{name} gönderisini görüntüle >" @@ -580,7 +473,6 @@ tr: liked: "%{name} gönderini iÄŸneledi." view_post: "Gönderiyi görüntüle >" mentioned: - mentioned: "gönderisinde senden bahsetti:" subject: "%{name} sana Diaspora*'da özel mesaj gönderdi " private_message: reply_to_or_view: "Yanıtla ya da konuÅŸmayı görüntüle >" @@ -613,20 +505,9 @@ tr: to_change_your_notification_settings: "tıklayarak bildirim ayarlarınızı deÄŸiÅŸtirebilirsiniz" nsfw: "NSFW" ok: "Tamam" - or: "ya da" - password: "Parola" - password_confirmation: "Parola doÄŸrulama" people: add_contact: invited_by: "tarafından davet edildin" - add_contact_small: - add_contact_from_tag: "kiÅŸi etiketle" - aspect_list: - edit_membership: "yön üyelik düzenle" - helper: - is_not_sharing: "%{name} sizinle ÅŸunu paylaÅŸmıyor" - is_sharing: "%{name} sizinle ÅŸunu paylaÅŸtı" - results_for: "sonuçları %{params}" index: looking_for: "%{tag_link} ile etiketlenmiÅŸ gönderileri mi arıyorsun?" no_one_found: "...ve hiç kimse bulunamadı." @@ -635,98 +516,45 @@ tr: search_handle: "ArkadaÅŸlarınızı bulmak için kullaniciadi@pod biçimindeki diaspora* kimliklerini kullanın." searching: "aranıyor, biraz sabırlı olun..." send_invite: "Hâlâ mı bir ÅŸey yok? Birilerini davet edin!" - one: "1 kiÅŸi" - other: "%{count} kiÅŸi" person: - add_contact: "kiÅŸi ekle" - already_connected: "Zaten baÄŸlı" - pending_request: "Bekletilen istek" thats_you: "Bu sensin!" profile_sidebar: bio: "hakkında" born: "doÄŸum günü" - edit_my_profile: "Profilimi düzenle" gender: "cinsiyet" - in_aspects: "yönleriyle" location: "yer" - photos: "FotoÄŸraflar" - remove_contact: "kiÅŸiyi kaldır" - remove_from: "%{name}, %{aspect} yönünden kaldırılsın mı?" show: closed_account: "Bu hesap kapatılmıştır." does_not_exist: "KiÅŸi yok!" has_not_shared_with_you_yet: "%{name} seninle henüz bir ÅŸey paylaÅŸmamış!" - ignoring: "%{name} isimli kullanıcının tüm gönderilerini görmezden geliyorsun." - incoming_request: "%{name} seninle paylaşımda bulunmak istiyor" - mention: "Bahset" - message: "Mesaj" - not_connected: "Bu kiÅŸiyle paylaşımda bulunmuyorsun" - recent_posts: "Son Gönderiler" - recent_public_posts: "Son Genel Gönderiler" - return_to_aspects: "Yönler sayfasına geri dön" - see_all: "Hepsini gör" - start_sharing: "paylaşıma baÅŸla" - to_accept_or_ignore: "kabul etmek veya yoksaymak için." - sub_header: - add_some: "biraz ekle" - edit: "düzenle" - you_have_no_tags: "etiket yok!" - webfinger: - fail: "Ãœzgünüz, %{handle} bulunamadı." - zero: "kiÅŸi yok" photos: - comment_email_subject: "%{name}'ın fotoÄŸrafı" create: integrity_error: "FotoÄŸraf yükleme baÅŸarısız oldu. Gerçekten bir fotoÄŸraf mıydı?" runtime_error: "FotoÄŸraf yüklenmesinde hata oluÅŸtu. Emniyet kemerin takılı olduÄŸudan emin misin?" type_error: "FotoÄŸraf yüklemesi baÅŸarısız oldu. Bir görüntünün eklendiÄŸinden emin misin?" destroy: notice: "FotoÄŸraf silindi." - edit: - editing: "Düzeltiliyor" - new: - back_to_list: "Listeye geri dön" - new_photo: "Yeni FotoÄŸraf" - post_it: "gönder!" new_photo: empty: "{file} boÅŸ bir dosya, bu olmadan dosyaları tekrar seçin." invalid_ext: "{file} geçersiz uzantıya sahip. sadece {extensions} uzantılarına izin verilir." size_error: "{file} çok büyük, en büyük dosya boyutu {sizeLimit}." new_profile_photo: - or_select_one_existing: "ya da varolan fotoÄŸraflardan seç %{photos}" upload: "Yeni bir profil fotoÄŸrafı yükle!" - photo: - view_all: "%{name}'in bütün fotoÄŸraflarını göster" show: - collection_permalink: "sabit baÄŸlantı koleksiyonu" - delete_photo: "FotoÄŸrafı Sil" - edit: "düzenle" - edit_delete_photo: "FotoÄŸrafın açıklamasını düzenle / sil" - make_profile_photo: "profil fotoÄŸrafı yap" show_original_post: "Orijinal gönderiyi göster" - update_photo: "FotoÄŸrafı Güncelle" - update: - error: "FotoÄŸraf düzeltme baÅŸarısız oldu." - notice: "FotoÄŸraf baÅŸarıyla güncellendi." posts: presenter: title: "%{name} 'den bir gönderi" show: - destroy: "Sil" - not_found: "Ãœzgünüz, bu gönderi bulamadı." - permalink: "kalıcı baÄŸlantı" photos_by: other: "%{author} tarafından %{count} fotoÄŸraf" zero: "%{author} tarafından fotoÄŸraf yok" reshare_by: "%{author} tarafından tekrar paylaşım" - previous: "önceki" privacy: "Gizlilik" - privacy_policy: "Gizlilik Politikası" profile: "Profil" profiles: edit: allow_search: "Diaspora aramaları ile bulunmana izin ver" - edit_profile: "Profil düzenle" first_name: "Ad" last_name: "Soyad" nsfw_check: "PaylaÅŸtığım herÅŸeyi Ä°2GD olarak iÅŸaretle" @@ -739,8 +567,6 @@ tr: your_location: "BulunduÄŸun yer" your_name: "Adın" your_photo: "FotoÄŸrafın" - your_private_profile: "Özel profil" - your_public_profile: "Genel profil" your_tags: "Kendini 5 kelime ile anlat" your_tags_placeholder: "#diaspora #ironing #kittens #music gibi" update: @@ -754,64 +580,26 @@ tr: closed: "Ãœyelik bu Diaspora'da kapandı." create: success: "Diasporaya katıldınız!" - edit: - cancel_my_account: "Hesabımı iptal et" - edit: "Düzenle %{name}" - leave_blank: "(EÄŸer deÄŸiÅŸtirmek istemiyorsanız boÅŸ bırakın.)" - password_to_confirm: "(DeÄŸiÅŸikliklerin onaylanması için ÅŸu anki parolanız gerekmektedir)" - unhappy: "Mutsuz?" - update: "Güncelle" invalid_invite: "GönderdiÄŸiniz davetiye baÄŸlantısı artık geçerli deÄŸil!" new: - create_my_account: "Hesabımı oluÅŸtur!" email: "E-POSTA" enter_email: "Bir e-posta girin" enter_password: "Bir parola girin" enter_password_again: "Daha önce olduÄŸu gibi aynı parolayı girin." enter_username: "Bir kullanıcı adı seçin (sadece harfler, rakamlar ve alt çizgi)" - join_the_movement: "Harekete katılın!" password: "PAROLA" password_confirmation: "PAROLA ONAYI" sign_up: "KAYDOL" - sign_up_message: "♥ ile Sosyal AÄŸ" submitting: "Gönderiliyor..." terms: "Bir hesap oluÅŸturarak %{terms_link}'teki koÅŸulları kabul etmiÅŸ sayılırsınız." terms_link: "hizmet koÅŸulları" username: "KULLANICI ADI" - requests: - create: - sending: "Gönderiliyor..." - sent: "%{name} ile paylaÅŸmak istedin. Diaspora'ya tekrar baÄŸlandığında görecektir." - destroy: - error: "Lütfen bir yön seçiniz!" - ignore: "ArkadaÅŸ isteÄŸini reddettin." - success: "Artık paylaşıyorsunuz." - helper: - new_requests: - few: "%{count} yeni istek!" - many: "%{count} yeni istek!" - one: "yeni istek!" - other: "%{count} yeni istek!" - two: "%{count} yeni istek!" - zero: "yeni istek yok" - manage_aspect_contacts: - existing: "Mevcut rehber" - manage_within: "KiÅŸileri yönetin" - new_request_to_person: - sent: "yollandı!" reshares: comment_email_subject: "%{resharer}, %{author} kiÅŸisinin gönderisini tekrar paylaÅŸtı" - create: - failure: "Bu gönderi tekrar paylaşılırken hata oluÅŸtu." reshare: deleted: "Gönderi yazarı tarafından silindi." - reshare: - other: "%{count} tekrar paylaşım" - zero: "Tekrar paylaÅŸ" reshare_confirmation: "Tekrar paylaÅŸ %{author} - %{text}?" - reshare_original: "Orijinali tekrar paylaÅŸ" reshared_via: "tekrar paylaşıldı, bununla:" - show_original: "Orijinali görüntüle" search: "Ara" services: create: @@ -823,58 +611,23 @@ tr: success: "DoÄŸrulama baÅŸarılı bir ÅŸekilde kaldırıldı." failure: error: "hizmete baÄŸlanırken hata oluÅŸtu" - finder: - fetching_contacts: "Diaspora %{service} arkadaÅŸlarını dolduruyor, lütfen birkaç dakika sonra tekrar bak." - no_friends: "Hiç Facebook arkadaşı bulunamadı." - service_friends: "%{service} ArkadaÅŸları" index: disconnect: "baÄŸlantıyı kes" edit_services: "Servisleri düzenle" logged_in_as: "olarak baÄŸlandınız" really_disconnect: "%{service} ile baÄŸlantı kesilsin mi?" services_explanation: "Hizmetlere baÄŸlanmak, gönderilerinizi Diaspora'da yazdığınız sırada yayınlama olanağı verir." - inviter: - click_link_to_accept_invitation: "Daveti kabul etmek bu baÄŸlantıya tıklayın" - join_me_on_diaspora: "Benimle diaspora*'da buluÅŸ" - remote_friend: - invite: "davet et" - not_on_diaspora: "Henüz Diaspora'da deÄŸil" - resend: "tekrar gönder" settings: "Ayarlar" - share_visibilites: - update: - post_hidden_and_muted: "%{name} isimli kullanıcının gönderisi saklandı ve bildirimleri susturuldu." - see_it_on_their_profile: "Bu gönderi hakkında güncellemeleri görmek istiyorsan, %{name} isimli kullanıcının profil sayfasını ziyaret et." shared: - add_contact: - add_new_contact: "Yeni kiÅŸi ekle" - create_request: "Diaspora ID ile bul" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Diaspora kullanıcı adınızı giriniz:" - know_email: "E-posta adresini biliyor musun? O zaman onu davet et" - your_diaspora_username_is: "Diaspora kullanıcı adın: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Yönüne ekle" toggle: other: "%{count} yönde" zero: "Yönüne ekle" - contact_list: - all_contacts: "Bütün kiÅŸiler" - footer: - logged_in_as: "%{name} adıyla giriÅŸ yapıldı" - your_aspects: "Yönler" invitations: by_email: "E-posta ile" - dont_have_now: "Åžu an davetiyen yok, ama yakında gelir!" - from_facebook: "Facebook'dan" - invitations_left: "%{count} kaldı" - invite_someone: "Birisini davet et" invite_your_friends: "ArkadaÅŸlarını davet et" invites: "Davetiyeler" - invites_closed: "Bu Diaspora'da davet kapalı görünüyor" share_this: "Bu e-posta yoluyla baÄŸlantı, blog ya da favori sosyal ağını paylaÅŸ!" - notification: - new: "%{from}'den yeni %{type}" public_explain: atom_feed: "Atom beslemesi" control_your_audience: "Hedef Kitle Kontrolü" @@ -886,42 +639,21 @@ tr: title: "BaÄŸlı hizmetler" visibility_dropdown: "Açılan menüden gönderinizin görünürlüğünü deÄŸiÅŸtirebilirsiniz. (Ä°lk olarak Genel yapmanızı öneririz.)" publisher: - all: "hepsi" - all_contacts: "tüm baÄŸlantılar" discard_post: "Gönderiyi sil" formatWithMarkdown: "Gönderilerinizi biçimlendirmek için Markdown( %{markdown_link} ) kullanabilirsiniz" get_location: "Konumunu ayarla" - make_public: "herkese görünür yap" new_user_prefill: hello: "Hey herkes, Ben #%{new_user_tag}. " i_like: "Ä°lgimi çeken ÅŸunlardır: %{tags}." invited_by: "Davet için teÅŸekkürler, " newhere: "YeniyimBurada" - post_a_message_to: "%{aspect} yönüne mesaj gönder " posting: "Gönderiliyor..." - preview: "Önizleme" - publishing_to: "buraya yayınlanıyor:" share: "PaylaÅŸ" - share_with: "paylaÅŸ" upload_photos: "FotoÄŸraf yükle" whats_on_your_mind: "Ne düşünüyorsun?" - reshare: - reshare: "Yeniden paylaÅŸ" stream_element: - connect_to_comment: "Gönderisini yorumlamak için bu kullanıcıya baÄŸlan" - currently_unavailable: "yorum kullanılamıyor" - dislike: "BeÄŸenme" - hide_and_mute: "Gönderiyi gizle ve sustur" - ignore_user: "%{name} isimli kullanıcıyı görmezden gel" - ignore_user_description: "Kullanıcı görmezden gelinip tüm yönlerden kaldırılsın mı?" - like: "BeÄŸen" - nsfw: "Bu gönderi yazarı tarafından NSFW ile etiketlenmiÅŸtir. %{link}" - shared_with: "%{aspect_names} ile paylaşıldı" - show: "göster" - unlike: "BeÄŸenme" via: "%{link} ile" via_mobile: "cepten" - viewable_to_anyone: "Bu gönderi web üzerindeki herkes tarafından görünebilir." simple_captcha: label: "Kutudaki kodu yazın:" message: @@ -932,18 +664,9 @@ tr: status_messages: create: success: "BaÅŸarıyla bahsedildi: %{names}" - destroy: - failure: "Mesaj silme baÅŸarısız" - helper: - no_message_to_display: "Gösterilecek mesaj yok." new: mentioning: "Bahseden: %{person}" too_long: "{\"other\"=>\"durum mesajları %{count} karakterden az olmalıdır.\", \"zero\"=>\"durum mesajları %{count} karakterden az olmalıdır.\"}" - stream_helper: - hide_comments: "Yorumları gizle" - show_comments: - other: "%{count} ek yorum göster" - zero: "Daha fazla yorum yok" streams: activity: title: "Etkinliklerim" @@ -969,25 +692,14 @@ tr: title: "Genel Aktiviteler" tags: title: "Gönderi etiketlendi: %{tags}" - tag_followings: - create: - failure: "Takip etmek baÅŸarısız: #%{name}. Zaten onu takip eden var mı?" - none: "BoÅŸ bir etiketi izleyemezsin!" - success: "Vay! Artık ÅŸunu takip ediyorsun: #%{name}." - destroy: - failure: "#%{name} takibini durdurmak baÅŸarısız oldu. Takibi zaten durdurmuÅŸ olmayasın?" - success: "Yazık! #%{name} takibi durduruldu, onu izlemiyorsun artık." tags: show: follow: "Takip et: #%{tag}" - following: "#%{tag} takip ediliyor" none: "BoÅŸ etiketi yoktur!" stop_following: "Takibi Durdur #%{tag}" tagged_people: other: "%{count} kiÅŸi %{tag} ile etiketlendi" zero: "%{tag} ile hiç kimse etiketlenmedi" - terms_and_conditions: "Kurallar ve KoÅŸullar" - undo: "Geri Al?" username: "Kullanıcı Adı" users: confirm_email: @@ -1008,7 +720,6 @@ tr: character_minimum_expl: "en az 6 harfli olmalı" close_account: dont_go: "Hey, gitme lütfen!" - if_you_want_this: "Bunu yapmak istediÄŸinden eminsen, aÅŸağıda parolanı gir ve 'Hesabı Kapat' düğmesini tıkla" lock_username: "Bu, geri gelmek istersen bulunması için kullanıcı ismini kilitleyecektir." locked_out: "Oturumdan çıkacak ve hesabına tekrar giriÅŸ yapamayacaksın." make_diaspora_better: "Diaspora'yı daha da iyi yapmamıza yardım etmeni isteriz, dolayısıyla hesabı kapatmak yerine bize yardımcı olmanı tercih ederiz. Hesabı gerçekten kapatmak istiyorsan, bundan sonra olacakları dikkatine sunarız." @@ -1020,12 +731,10 @@ tr: current_password: "Mevcut parola" current_password_expl: "giriÅŸ yaptığınız..." download_export: "Profilimi indir" - download_photos: "fotoÄŸraflarımı indir" edit_account: "Hesap düzenle" email_awaiting_confirmation: "EtkinleÅŸtirme baÄŸlantısını %{unconfirmed_email} adresine gönderdik. Bu baÄŸlantıyı izleyip yeni adresi etkinleÅŸtirmediÄŸin sürece önceki %{email} adresini kullanmaya devam edeceÄŸiz." export_data: "Bilgilerimi Dışarı taşı" following: "Ä°zleme ayarları" - getting_started: "Yeni Kullanıcı Tercihleri" last_exported_at: "En son %{timestamp} anında güncellendi" liked: "...birisi gönderimi iÄŸnelediÄŸinde?" mentioned: "...benden bahsedildiÄŸinde?" @@ -1047,7 +756,6 @@ tr: connect_to_facebook_link: "Facebook hesabınıza baÄŸlanmak" hashtag_explanation: "Etiketler, hakkında konuÅŸmak ve ilgi alanlarını takip etmenize izin verir. Ayrıca yeni insanları Diaspora üzerinde bulmak için harika bir yoldur." hashtag_suggestions: "SevdiÄŸiniz etiketleri takip etmeyi deneyin #resim, #film, #gif, vb." - saved: "Kaydedildi!" well_hello_there: "Merhaba!" what_are_you_in_to: "Ne yapıyorsun?" who_are_you: "Sen kimsin?" @@ -1069,13 +777,6 @@ tr: settings_updated: "Ayarlar güncellendi" unconfirmed_email_changed: "E-posta deÄŸiÅŸti. Aktivasyon gerekli." unconfirmed_email_not_changed: "E-posta deÄŸiÅŸikliÄŸi baÅŸarısız oldu" - webfinger: - fetch_failed: "%{profile_url} için webfinger profili alımı baÅŸarısız oldu" - hcard_fetch_failed: "#{@account} için hcard alınımında hata oluÅŸtu" - no_person_constructed: "Bu hcard ile hiçbir kimse oluÅŸturulamadı." - not_enabled: "%{account} hesabının bilgisayarında webfinger etkinleÅŸtirilmemiÅŸ gibi görünüyor" - xrd_fetch_failed: "%{account} hesabından xrd alınımında bir hata oluÅŸtu" - welcome: "HoÅŸ Geldin!" will_paginate: next_label: "sonraki »" previous_label: "« önceki" \ No newline at end of file diff --git a/config/locales/diaspora/uk.yml b/config/locales/diaspora/uk.yml index 52109f2e7e130d66b6bc48fe6a2ce93916271891..980cbd7e7280e2f9529191fd3ded19daf552ee80 100644 --- a/config/locales/diaspora/uk.yml +++ b/config/locales/diaspora/uk.yml @@ -6,11 +6,8 @@ uk: _applications: "Додатки" - _comments: "Коментарі" _contacts: "Контакти" _help: "Довідка" - _home: "Головна" - _photos: "Фотографії" _services: "СервіÑи" _statistics: "СтатиÑтика" _terms: "Умови" @@ -139,13 +136,7 @@ uk: other: "%{count} нових кориÑтувачів цього тижнÑ" zero: "Ðемає нових кориÑтувачів цього тижнÑ" current_server: "Дата зараз на Ñервері: %{date}" - ago: "%{time} тому назад" all_aspects: "УÑÑ– категорії" - application: - helper: - unknown_person: "Ðевідома перÑона" - video_title: - unknown: "Ðевідома назва відеозапиÑу" are_you_sure: "Ви впевнені?" are_you_sure_delete_account: "Ви впевнені, що хочете закрити Ñвій обліковий запиÑ? Цю процедуру неможливо ÑкаÑувати!" aspect_memberships: @@ -159,47 +150,26 @@ uk: success: "Друг доданий в аÑпект." aspect_listings: add_an_aspect: "+ Додати аÑпект" - deselect_all: "Вимкнути вÑÑ–" - edit_aspect: "Редагувати %{name}" - select_all: "Включити вÑÑ–" aspect_stream: make_something: "Створіть що-небудь" stay_updated: "Будьте в курÑÑ–" stay_updated_explanation: "Ваш оÑновний потік наповнюєтьÑÑ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ контактами, мітками, за Ñкими ви Ñтежите Ñ– запиÑами декількох популÑрних членів товариÑтва." - contacts_not_visible: "Контакти в цьому аÑпекті не зможуть бачити один одного." - contacts_visible: "Контакти в цьому аÑпекті можуть бачити один одного." - create: - failure: "Ðе вдалоÑÑ Ñтворити аÑпект." - success: "Ваш новий аÑпект %{name} Ñтворений" destroy: failure: "%{name} не порожній Ñ– не може бути вилучений." success: "%{name} уÑпішно видалений." edit: - aspect_chat_is_enabled: "Контакти з цієї категорії можуть ÑпілкуватиÑÑ Ð· вами." - aspect_chat_is_not_enabled: "Контакти з цієї категорії не можуть ÑпілкуватиÑÑ Ð· вами." aspect_list_is_not_visible: "Контакти, з цього аÑпекту, не можуть бачити один одного." aspect_list_is_visible: "Контакти, із цього аÑпекту, можуть бачити один одного." confirm_remove_aspect: "Ви впевнені, що хочете вилучити цей аÑпект?" - grant_contacts_chat_privilege: "надати контактам в аÑпекті можливіÑÑ‚ÑŒ ÑпілкуватиÑÑ?" - make_aspect_list_visible: "Зробити контакти у цій категорії видимими один одному?" - remove_aspect: "Видалити цей аÑпект" rename: "Перейменувати" - set_visibility: "Ð’Ñтановити видиміÑÑ‚ÑŒ" update: "Оновити" updating: "ОновленнÑ" index: - diaspora_id: - content_1: "Ваш ідентифікатор в ДіаÑпорі*:" - content_2: "За ним будь-хто зможе знайти Ð²Ð°Ñ Ñƒ ДіаÑпорі." - heading: "Ідентифікатор в ДіаÑпорі*" donate: "Пожертвувати" - handle_explanation: "Це ваш ідентифікатор у ДіаÑпорі. Подібно до електронної адреÑи, ви можете давати його людÑм Ð´Ð»Ñ Ð·Ð²'Ñзку з вами." help: any_problem: "Виникли проблеми?" contact_podmin: "Зв'ÑжітьÑÑ Ð· адмініÑтратором вашого пода!" do_you: "Ви:" - email_feedback: "%{link} ще один ÑпоÑіб зв'Ñзку з нами." - email_link: "ÐадіÑлати на email" feature_suggestion: "...хочете запропонувати нову %{link}?" find_a_bug: "... знайшли помилку (%{link})?" have_a_question: "... хочете поÑтавити Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ (%{link})?" @@ -212,31 +182,20 @@ uk: tutorial_link_text: "ÐаÑтанови" tutorials_and_wiki: "%{faq},%{tutorial} Ñ– %{wiki}: Допомога при перших кроках." introduce_yourself: "Це ваш потік. Пірнайте Ñ– оÑвоюйтеÑÑ." - keep_diaspora_running: "Допоможіть розвитку ДіаÑпори* щоміÑÑчним внеÑком!" keep_pod_running: "Допоможіть %{pod} працювати швидко — придбайте нашим Ñерверам горнÑтко кави, зробивши щоміÑÑчний внеÑок!" new_here: follow: "Стежте за міткою %{link} Ñ– вітайте нових кориÑтувачів у ДіаÑпорі*!" learn_more: "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ" title: "Вітаємо нових кориÑтувачів" - no_contacts: "Контакти відÑутні" - no_tags: "+ Знайти мітку" - people_sharing_with_you: "Люди, Ñкі додали ваÑ" - post_a_message: "Опублікувати Ð·Ð°Ð¿Ð¸Ñ >>" services: content: "Ви можете під’єднати до ДіаÑпори такі Ñлужби:" heading: "ÐŸÑ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ñлужб" - unfollow_tag: "Ðе Ñтежити за міткою #%{tag}" welcome_to_diaspora: "ЛаÑкаво проÑимо до ДіаÑпори*, %{name}!" - new: - create: "Створити" - name: "Ім'Ñ (видно тільки вам)" no_contacts_message: community_spotlight: "У центрі уваги" or_spotlight: "Чи ви можете ділитиÑÑ Ð· %{link}" try_adding_some_more_contacts: "Ви можете знайти або запроÑити інших кориÑтувачів." you_should_add_some_more_contacts: "Додайте більше контактів!" - no_posts_message: - start_talking: "Тут ще ніхто нічого не Ñказав." seed: acquaintances: "Знайомі" family: "Сім'Ñ" @@ -245,7 +204,6 @@ uk: update: failure: "Ваш аÑпект %{name} має занадто довге ім'Ñ Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ." success: "Ваш аÑпект %{name} уÑпішно відредагований." - back: "Ðазад" blocks: create: failure: "Ðеможливо заблокувати цього кориÑтувача. #evasion" @@ -257,22 +215,15 @@ uk: explanation: "Пишіть до ДіаÑпори з будь-Ñкої Ñторінки (з відуÑідь), викориÑтовуючи %{link}." heading: "Інтерактивна закладка ДіаÑпори" post_something: "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ ДіаÑпори" - post_success: "Опубліковано! ЗакриттÑ!" cancel: "СкаÑувати" comments: new_comment: comment: "Коментувати" commenting: "КоментуваннÑ..." - one: "1 коментар" - other: "%{count} коментарів" - zero: "Ðемає коментарів" contacts: - create: - failure: "Ðе вдалоÑÑ Ñтворити контакт" index: add_a_new_aspect: "Ðовий аÑпект" add_contact: "Додати контакт" - add_to_aspect: "Додати контакти до %{name}" all_contacts: "УÑÑ– контакти" community_spotlight: "У центрі уваги" my_contacts: "Мої контакти" @@ -280,19 +231,13 @@ uk: no_contacts_in_aspect: "Ви не маєте жодного контакту у цій категорії. Ðижче наведено ÑпиÑок дійÑних контактів, Ñкі Ви можете долучити до цієї категорії." no_contacts_message: "Зазирніть до %{community_spotlight}" only_sharing_with_me: "Що тільки додали мене" - remove_contact: "Видалити контакт" start_a_conversation: "Почати беÑіду" title: "Контакти" user_search: "Пошук кориÑтувача" - your_contacts: "Ваші контакти" - sharing: - people_sharing: "ділÑÑ‚ÑŒÑÑ Ð· вами:" spotlight: community_spotlight: "У центрі уваги" suggest_member: "Запропонуйте учаÑника" conversations: - conversation: - participants: "УчаÑники" create: fail: "Ðеправильне повідомленнÑ" no_contact: "Ей, вам потрібно Ñпочатку додати контакт!" @@ -300,23 +245,12 @@ uk: destroy: delete_success: "Діалог уÑпішно видалений" hide_success: "Діалог уÑпішно прихований" - helper: - new_messages: - few: "Ðові повідомленнÑ: %{count}" - many: "Ðові повідомленнÑ: %{count}" - one: "1 нове повідомленнÑ" - other: "Ðові повідомленнÑ: %{count}" - two: "%{count} нових повідомлень" - zero: "Ðових повідомлень немає" index: conversations_inbox: "Розмови - ÐадіÑлані повідомленнÑ" - create_a_new_conversation: "Розпочати нову розмову" inbox: "Вхідні" new_conversation: "Ðова розмова" - no_conversation_selected: "Розмова не вибрана" no_messages: "Ðемає повідомлень" new: - abandon_changes: "ВідмовитиÑÑ Ð²Ñ–Ð´ змін?" send: "Відправити" sending: "ÐадÑиланнÑ..." subject: "Тема" @@ -338,10 +272,6 @@ uk: error_messages: helper: correct_the_following_errors_and_try_again: "Виправіть такі помилки Ñ– Ñпробуйте знову." - invalid_fields: "ÐедійÑні полÑ" - login_try_again: "Будь лаÑка, <a href='%{login_link}'>увійдіть</a> Ñ– Ñпробуйте знову." - post_not_public: "ПовідомленнÑ, Ñке ви намагаєтеÑÑŒ переглÑнути, не Ñ” публічним." - post_not_public_or_not_exist: "ЗапиÑ, Ñкий ви хочете відкрити не публічний або не Ñ–Ñнує!" fill_me_out: "Заповнити" find_people: "Пошук людей або #міток" help: @@ -550,30 +480,17 @@ uk: tutorial: "наÑтанова" tutorials: "наÑтанови" wiki: "вікі" - hide: "Приховати" - ignore: "Ігнорувати" - invitation_codes: - excited: "%{name} радий(-а) бачити Ð²Ð°Ñ Ñ‚ÑƒÑ‚." invitations: a_facebook_user: "КориÑтувач Facebook" check_token: not_found: "Код Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð½Ðµ знайдений" create: - already_contacts: "Ви вже пов'Ñзані з цією людиною" - already_sent: "Ви вже запроÑили цю людину." empty: "Будь-лаÑка, введіть хоча б одну електронну пошту." no_more: "У Ð²Ð°Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ð»Ð¸ÑÑ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ." note_already_sent: "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð²Ð¶Ðµ були надіÑлані на %{emails}" - own_address: "Ви не можете відправити Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð½Ð° вашу влаÑну адреÑу." rejected: "Такі адреÑи електронної пошти мають проблеми: " sent: "Ваші Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ñ–: %{emails}" - edit: - accept_your_invitation: "ПрийнÑти ваше запрошеннÑ" - your_account_awaits: "Ваш аккаунт чекає ваÑ!" new: - already_invited: "ÐаÑтупні люди не прийнÑли ваше запрошеннÑ:" - aspect: "ÐÑпект" - check_out_diaspora: "Спробуйте ДіаÑпору*!" codes_left: few: "За цим кодом залишилоÑÑŒ запрошень: %{count}" many: "За цим кодом залишилоÑÑŒ запрошень: %{count}" @@ -581,16 +498,11 @@ uk: other: "За цим кодом залишилоÑÑŒ запрошень: %{count}" zero: "За цим кодом не залишилоÑÑŒ запрошень." comma_separated_plz: "Ви можете додати кілька Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти, розділивши Ñ—Ñ… комами." - if_they_accept_info: "піÑÐ»Ñ Ð·Ð³Ð¾Ð´Ð¸ з їхнього боку, вони будуть додані в запропонований вами аÑпект." invite_someone_to_join: "ЗапроÑити когоÑÑŒ до ДіаÑпори*!" language: "Мова" paste_link: "ПоділітьÑÑ Ñ†Ð¸Ð¼ поÑиланнÑм з друзÑми, щоб запроÑити Ñ—Ñ… до ДіаÑпори*." - personal_message: "ОÑобиÑте повідомленнÑ" - resend: "Ще раз поÑлати" send_an_invitation: "Відправити запрошеннÑ" - send_invitation: "Відправити запрошеннÑ" sending_invitation: "Ð’Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ" - to: "ДлÑ" layouts: application: back_to_top: "Ðагору" @@ -599,41 +511,13 @@ uk: source_package: "завантажити початковий код" toggle: "Звичайний/мобільний Ñайт" whats_new: "Що нового?" - your_aspects: "Ваші категорії" header: - admin: "ÐдмініÑтратор" - blog: "Блог" code: "Код" - help: "Довідка" - login: "Увійти" logout: "вийти" profile: "профіль" - recent_notifications: "ОÑтанні ÑповіщеннÑ" settings: "налаштуваннÑ" - view_all: "ПодивитиÑÑ ÑƒÑе" - likes: - likes: - people_dislike_this: - few: "%{count} не ÑподобалоÑÑ" - many: "%{count} не ÑподобалоÑÑ" - one: "%{count} не ÑподобалоÑÑ" - other: "%{count} не ÑподобалоÑÑ" - zero: "Ðікому не ÑподобалоÑÑ" - people_like_this: - few: "%{count} ÑподобалоÑÑ" - many: "%{count} ÑподобалоÑÑ" - one: "%{count} ÑподобалоÑÑ" - other: "%{count} ÑподобалоÑÑ" - zero: "Ðікому не ÑподобалоÑÑ" - people_like_this_comment: - few: "%{count} ÑподобалоÑÑ" - many: "%{count} ÑподобалоÑÑ" - one: "%{count} ÑподобалоÑÑ" - other: "%{count} ÑподобалоÑÑ" - zero: "Ðікому не ÑподобалоÑÑ" limited: "Обмежена" more: "Ще" - next: "Далі" no_results: "Результатів не знайдено" notifications: also_commented: @@ -654,13 +538,6 @@ uk: one: "%{actors} прокоментував(-ла) вашу %{post_link}." other: "%{actors} прокоментували вашу %{post_link}." zero: "%{actors} прокоментували вашу %{post_link}." - helper: - new_notifications: - few: "%{count} нових Ñповіщеннь" - many: "%{count} нових Ñповіщеннь" - one: "1 нове ÑповіщеннÑ" - other: "Ðові ÑповіщеннÑ: %{count}" - zero: "Ðових Ñповіщень немає" index: all_notifications: "УÑÑ– ÑповіщеннÑ" also_commented: "Також прокоментували" @@ -741,7 +618,6 @@ uk: a_limited_post_comment: "Вам надійшов новий коментар на обмежену поштову Ñкриньку." a_post_you_shared: "запиÑ." a_private_message: "Вам надійшло нове приватне Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ diaspora*." - accept_invite: "Прийміть ваше Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ ДіаÑпори*!" click_here: "ÐатиÑніть Ñюди" comment_on_post: reply: "ВідповіÑти або подивитиÑÑ %{name} Ð·Ð°Ð¿Ð¸Ñ >" @@ -810,7 +686,6 @@ uk: liked: "%{name} ÑподобалоÑÑ Ð’Ð°ÑˆÐµ повідомленнÑ" view_post: "ПодивитиÑÑ Ð·Ð°Ð¿Ð¸Ñ >" mentioned: - mentioned: "Ð²Ð°Ñ Ð·Ð³Ð°Ð´Ð°Ð»Ð¸ у допиÑÑ–:" subject: "%{name} згадав Ð²Ð°Ñ Ñƒ ДіаÑпорі*" private_message: reply_to_or_view: "ВідповіÑти або подивитиÑÑ Ñ†ÑŽ беÑіду >" @@ -855,20 +730,9 @@ uk: to_change_your_notification_settings: "щоб змінити ваші Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ" nsfw: "18+" ok: "Гаразд" - or: "або" - password: "Пароль" - password_confirmation: "ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ" people: add_contact: invited_by: "Ð²Ð°Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñив кориÑтувач" - add_contact_small: - add_contact_from_tag: "додати контакт з мітки" - aspect_list: - edit_membership: "редагувати учаÑників аÑпекту" - helper: - is_not_sharing: "%{name} не додав ваÑ" - is_sharing: "%{name} ділитьÑÑ Ð· вами" - results_for: "результати Ð´Ð»Ñ %{params}" index: couldnt_find_them: "Ðе змогли знайти?" looking_for: "ПовідомленнÑ, відмічені Ñк %{tag_link}?" @@ -878,86 +742,36 @@ uk: search_handle: "ВикориÑтайте ідентифікатори ДіаÑпори (ім'Ñ@домен.зона) щоб знайти ваших друзів." searching: "Триває пошук. Будь лаÑка, зачекайте." send_invite: "Ð’Ñе ще порожньо? ЗапроÑÑ–Ñ‚ÑŒ кого-небудь!" - one: "1 людина" - other: "%{count} людина[-и]" person: - add_contact: "Додати контакт" - already_connected: "Вже підключений" - pending_request: "Ð’ очікуванні запиту" thats_you: "Це ви!" profile_sidebar: bio: "Про Ñебе" born: "день народженнÑ" - edit_my_profile: "Редагувати профіль" gender: "Ñтать" - in_aspects: "У категоріÑÑ…" location: "розташуваннÑ" - photos: "Світлини" - remove_contact: "Вилучити контакт" - remove_from: "Видалити %{name} з %{aspect}?" show: closed_account: "Цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ² закритий." does_not_exist: "ПерÑони не Ñ–Ñнує!" has_not_shared_with_you_yet: "%{name} ще не діливÑÑ Ð·Ð°Ð¿Ð¸Ñами з вами!" - ignoring: "Ви блокуєте уÑÑ– запиÑи кориÑтувача %{name}." - incoming_request: "%{name} хоче поділитиÑÑ Ð· вами" - mention: "Згадати" - message: "ПовідомленнÑ" - not_connected: "Ви не ділитеÑÑ Ð· цією людиною" - recent_posts: "Ðещодавні публікації" - recent_public_posts: "ОÑтанні публічні допиÑи" - return_to_aspects: "ПовернутиÑÑ Ð½Ð° Ñторінку аÑпектів" - see_all: "Показати уÑе" - start_sharing: "ПоділитиÑÑ" - to_accept_or_ignore: "прийнÑти або ігнорувати." - sub_header: - add_some: "Додати" - edit: "Редагувати" - you_have_no_tags: "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” міток!" - webfinger: - fail: "Ðа жаль, ми не змогли знайти %{handle}." - zero: "Ðемає нікого" photos: - comment_email_subject: "Ð¤Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ñ–Ñ %{name}" create: integrity_error: "Помилка при завантаженні Ñвітлини. Ви впевнені, що це графічний файл?" runtime_error: "Збій при завантаженні Ñвітлини." type_error: "Збій при завантаженні Ñвітлини. Ви впевнені, що додали графічний файл?" destroy: notice: "Фотографію вилучено." - edit: - editing: "РедагуваннÑ" - new: - back_to_list: "ПовернутиÑÑ Ð´Ð¾ ÑпиÑку" - new_photo: "Ðова Ñвітлина" - post_it: "Опублікувати!" new_photo: empty: "{file} порожній, будь лаÑка, виберіть файли ще раз, але без нього." invalid_ext: "{file} має неприпуÑтиме розширеннÑ. Дозволені тільки {extensions}." size_error: "{file} занадто великий, макÑимальний розмір файлу: {sizeLimit}." new_profile_photo: - or_select_one_existing: "чи виберіть одну із вже завантажених %{photos}" upload: "Завантажити нове фото Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ!" - photo: - view_all: "ПодивитиÑÑ ÑƒÑÑ– Ñвітлини %{name}" show: - collection_permalink: "поÑтійне поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° колекцію" - delete_photo: "Вилучити Ñвітлину" - edit: "редагувати" - edit_delete_photo: "Змінити Ð¾Ð¿Ð¸Ñ Ñвітлини / вилучити Ñвітлину" - make_profile_photo: "зробити Ñвітлиною профілю" show_original_post: "Показати початковий запиÑ" - update_photo: "Оновити Ñвітлину" - update: - error: "Ðе вдалоÑÑ Ð·Ð¼Ñ–Ð½Ð¸Ñ‚Ð¸ Ñвітлину." - notice: "Світлина завантажена вдало." posts: presenter: title: "Ð—Ð°Ð¿Ð¸Ñ %{name}" show: - destroy: "Вилучити" - not_found: "Вибачте, ми не змогли знайти цей запиÑ." - permalink: "поÑÑ‚iйне поÑиланнÑ" photos_by: few: "%{count} Ñвітлини кориÑтувача %{author}" many: "%{count} Ñвітлин кориÑтувача %{author}" @@ -965,14 +779,11 @@ uk: other: "%{count} Ñвітлин кориÑтувача %{author}" zero: "Ðемає Ñвітлин кориÑтувача %{author}" reshare_by: "Поширено %{author}" - previous: "ПопереднÑ" privacy: "КонфіденційніÑÑ‚ÑŒ" - privacy_policy: "Політика конфіденційноÑÑ‚Ñ–" profile: "Профіль" profiles: edit: allow_search: "Дозволити уÑім шукати Ð²Ð°Ñ Ð² ДіаÑпорі" - edit_profile: "Редагувати профіль" first_name: "Ім'Ñ" last_name: "Прізвище" nsfw_check: "Відмітити уÑÑ– мої запиÑи Ñк NSFW" @@ -985,8 +796,6 @@ uk: your_location: "Ваше міÑце розташуваннÑ" your_name: "Ваше ім'Ñ" your_photo: "Ваша Ñвітлина" - your_private_profile: "Ваш оÑобиÑтий профіль" - your_public_profile: "Ваш публічний профіль" your_tags: "Опишіть Ñебе в п'Ñти Ñловах" your_tags_placeholder: "наприклад, #кіно #кошенÑта #подорожі #вчитель #київ" update: @@ -1003,26 +812,16 @@ uk: closed: "У цій чаÑтині ДіаÑпори реєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð·Ð°ÐºÑ€Ð¸Ñ‚Ð°." create: success: "ЛаÑкаво проÑимо в ДіаÑпору!, Ви приєдналиÑÑ Ð´Ð¾ ДіаÑпори!" - edit: - cancel_my_account: "Закрити мій аккаунт" - edit: "Редагувати %{name}" - leave_blank: "(Залиште порожнім, Ñкщо не хочете мінÑти)" - password_to_confirm: "(введіть ваш поточний пароль Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ð½)" - unhappy: "Ðезадоволені?" - update: "Відновити" invalid_invite: "Це Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð²Ð¶Ðµ недійÑне!" new: - create_my_account: "Створити мій аккаунт!" email: "Пошта" enter_email: "Введіть email" enter_password: "Введіть пароль (щонайменьше шіÑÑ‚ÑŒ Ñимволів)" enter_password_again: "Повторіть пароль" enter_username: "Виберіть ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача (дозволені тільки латинÑькі букви, цифри Ñ– підкреÑленнÑ)" - join_the_movement: "ПриєднуйтеÑÑ Ð´Ð¾ руху!" password: "Пароль" password_confirmation: "ПІДТВЕРДЖЕÐÐЯ ПÐРОЛЯ" sign_up: "РеєÑтраціÑ" - sign_up_message: "Соціальна мережа з ♥" submitting: "Відправка..." terms: "ЗареєÑтрувавшиÑÑŒ, Ви приймаєте %{terms_link}." terms_link: "умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг" @@ -1037,48 +836,15 @@ uk: reported_label: "<b>Ð”Ð¾Ð½Ð¾Ñ Ð²Ñ–Ð´</b> %{person}" review_link: "Відмітити Ñк проглÑнутий" status: - created: "Ð”Ð¾Ð½Ð¾Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ð¹" destroyed: "Ð—Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ² знищений" failed: "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°" - marked: "Ð”Ð¾Ð½Ð¾Ñ Ð±ÑƒÐ² помічений Ñк проглÑнутий" title: "ПереглÑд доноÑів" - requests: - create: - sending: "ÐадÑиланнÑ" - sent: "Ви проÑили поділитиÑÑ Ð· %{name}. Вони повинні побачити це при наÑтупному вході в ДіаÑпору*." - destroy: - error: "Виберіть, будь лаÑка, один аÑпект!" - ignore: "Ð†Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð² на дружбу." - success: "Тепер ви друзі." - helper: - new_requests: - few: "%{count} нових заÑвок!" - many: "%{count} нових заÑвок!" - one: "новий запит!" - other: "%{count} нових заÑвок!" - zero: "нових запитів немає" - manage_aspect_contacts: - existing: "ÐаÑвні контакти" - manage_within: "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð°Ð¼Ð¸ в" - new_request_to_person: - sent: "надіÑлано!" reshares: comment_email_subject: "%{resharer} поширює Ð´Ð¾Ð¿Ð¸Ñ %{author}" - create: - failure: "Помилка при Ñпробі поділитиÑÑ Ñ†Ð¸Ð¼ запиÑом." reshare: deleted: "Початковий Ð·Ð°Ð¿Ð¸Ñ Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð¾ автором." - reshare: - few: "ПоділилиÑÑ: %{count}" - many: "ПоділилиÑÑ: %{count}" - one: "ПоділивÑÑ: 1" - other: "ПоділилиÑÑ: %{count}" - two: "ПоділилиÑÑ: %{count}" - zero: "ПоділитиÑÑ" reshare_confirmation: "ПоділитиÑÑ Ð·Ð°Ð¿Ð¸Ñом %{author}?" - reshare_original: "ПоділитиÑÑ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ð¼ запиÑом" reshared_via: "поділивÑÑ ÐºÐ¾Ñ€Ð¸Ñтувач" - show_original: "Показати початковий запиÑ" search: "Пошук" services: create: @@ -1090,38 +856,15 @@ uk: success: "Ðвтентифікацію уÑпішно вилучено." failure: error: "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при підключенні цього ÑервіÑу" - finder: - fetching_contacts: "ДіаÑпора* додає ваших друзів із %{service}. Будь лаÑка, зачекайте." - no_friends: "Ðе знайдено друзів з Facebook." - service_friends: "Друзі з %{service}" index: disconnect: "роз'єднати" edit_services: "Редагувати ÑервіÑи" logged_in_as: "Ви увійшли Ñк" really_disconnect: "відключити %{service}?" services_explanation: "З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· Ñторонніми ÑервіÑами дає вам можливіÑÑ‚ÑŒ публікувати ваші поÑти в тому виглÑді, у Ñкому ви напиÑали Ñ—Ñ… у ДіаÑпорі*." - inviter: - click_link_to_accept_invitation: "Перейдіть за цим поÑиланнÑм Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¹Ð½ÑÑ‚Ñ‚Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ запрошеннÑ" - join_me_on_diaspora: "ПриєднуйтеÑÑ Ð´Ð¾ мене в ДіаÑпорі*" - remote_friend: - invite: "запрошеннÑ" - not_on_diaspora: "Ще немає в ДіаÑпорі" - resend: "відправити повторно" settings: "ÐалаштуваннÑ" - share_visibilites: - update: - post_hidden_and_muted: "Ð—Ð°Ð¿Ð¸Ñ ÐºÐ¾Ñ€Ð¸Ñтувача %{name} приховано, а Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ñ–." - see_it_on_their_profile: "Якщо ви хочете бачити Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиÑу, відвідаєте профіль кориÑтувача %{name}." shared: - add_contact: - add_new_contact: "Додати контакт" - create_request: "Пошук за ідентифікатором у ДіаÑпорі*" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Введіть ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача ДіаÑпори* :" - know_email: "Знаєте їхні електронні адреÑи? Ви повинні запроÑити Ñ—Ñ…" - your_diaspora_username_is: "Ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача ДіаÑпори* : %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Додати аÑпект" mobile_row_checked: "%{name} (видалити)" mobile_row_unchecked: "%{name} (додати)" toggle: @@ -1131,23 +874,11 @@ uk: other: "У %{count} аÑпектах" two: "У %{count} аÑпектах" zero: "Додати аÑпект" - contact_list: - all_contacts: "УÑÑ– контакти" - footer: - logged_in_as: "увійшли Ñк %{name}" - your_aspects: "ваші аÑпекти" invitations: by_email: "Електронною поштою" - dont_have_now: "У Ð²Ð°Ñ Ð±Ñ–Ð»ÑŒÑˆÐµ немає запрошень, але нові будуть вже Ñкоро!" - from_facebook: "З Facebook" - invitations_left: "залишилоÑÑ %{count}" - invite_someone: "ЗапроÑити кого-небудь" invite_your_friends: "ЗапроÑити друзів" invites: "ЗапрошеннÑ" - invites_closed: "Ð’ даний момент можливіÑÑ‚ÑŒ запрошень закрита на цьому поді ДіаÑпори*" share_this: "ПоділітьÑÑ Ñ†Ð¸Ð¼ поÑиланнÑм поштою, додайте до блогу або до Ñоціальної мережі!" - notification: - new: "Ðовий %{type} з %{from}" public_explain: atom_feed: "Стрічка Atom" control_your_audience: "Вибирайте Ñвою аудиторію" @@ -1159,12 +890,9 @@ uk: title: "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ… поÑлуг" visibility_dropdown: "ВикориÑтайте це випадне меню Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ видимоÑÑ‚Ñ– вашого запиÑу (ми пропонуємо вам зробити перший Ð·Ð°Ð¿Ð¸Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ð¼)." publisher: - all: "уÑÑ–" - all_contacts: "вÑÑ– контакти" discard_post: "Відкинути допиÑ" formatWithMarkdown: "Ви можете викориÑтати %{markdown_link}, щоб відформатувати текÑÑ‚." get_location: "Додати міÑцезнаходженнÑ" - make_public: "зробити публічним" new_user_prefill: hello: "Привіт вÑім, Ñ Ñ‚ÑƒÑ‚ #%{new_user_tag}." i_like: "Я цікавлюÑÑ %{tags}." @@ -1172,36 +900,14 @@ uk: newhere: "Ðовачок" poll: add_a_poll: "Додати опитуваннÑ" - add_poll_answer: "Додати варіант" - option: "Варіант 1" - question: "ПитаннÑ" - remove_poll_answer: "Прибрати варіант" - post_a_message_to: "Опублікувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ %{aspect}" posting: "ÐадÑиланнÑ..." - preview: "ПередпереглÑд" - publishing_to: "Ð¿ÑƒÐ±Ð»Ñ–ÐºÐ°Ñ†Ñ–Ñ Ð²:" remove_location: "Видалити міÑцезнаходженнÑ" share: "ПоділитиÑÑ" - share_with: "поділитиÑÑ Ð·" upload_photos: "Завантажити Ñвітлини" whats_on_your_mind: "Про що ви думаєте?" - reshare: - reshare: "ПоділитиÑÑ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾" stream_element: - connect_to_comment: "ПідключитиÑÑ Ð´Ð¾ цього кориÑтувача Ð´Ð»Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ" - currently_unavailable: "ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ñ€Ð°Ð· не доÑтупне" - dislike: "Ðе подобаєтьÑÑ" - hide_and_mute: "Приховати Ñ– вимкнути повідомленнÑ" - ignore_user: "Блокувати кориÑтувача %{name}" - ignore_user_description: "Блокувати й вилучити кориÑтувача з уÑÑ–Ñ… аÑпектів?" - like: "Мені подобаєтьÑÑ" - nsfw: "Ðвтор позначив цей Ð·Ð°Ð¿Ð¸Ñ Ñк такий, що тільки Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих\". %{link}" - shared_with: "Ð”Ð»Ñ Ð°Ñпектів: %{aspect_names}" - show: "показати" - unlike: "Ðе подобаєтьÑÑ" via: "через %{link}" via_mobile: "з мобільного приÑтрою" - viewable_to_anyone: "Цей Ð·Ð°Ð¿Ð¸Ñ Ð¼Ð¾Ð¶Ðµ бачити будь-хто в Інтернеті" simple_captcha: label: "Введіть код в поле:" message: @@ -1227,24 +933,12 @@ uk: status_messages: create: success: "УÑпішно згадано: %{names}" - destroy: - failure: "Ðе вдалоÑÑ Ð²Ð¸Ð»ÑƒÑ‡Ð¸Ñ‚Ð¸ повідомленнÑ" - helper: - no_message_to_display: "Ðових повідомлень немає." new: mentioning: "Згадати: %{person}" too_long: "{\"few\"=>\"Ñкоротіть, будь лаÑка, ваше Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ %{count} Ñимволів\", \"many\"=>\"Ñкоротіть, будь лаÑка, ваше Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ %{count} Ñимволів\", \"one\"=>\"Ñкоротіть, будь лаÑка, ваше Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ %{count} Ñимволів\", \"other\"=>\"Ñкоротіть, будь лаÑка, ваше Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ %{count} Ñимволів\", \"zero\"=>\"Ñкоротіть, будь лаÑка, ваше Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ %{count} Ñимволів\"}" stream_helper: - hide_comments: "Приховати уÑÑ– коментарі" no_more_posts: "Ви доÑÑгли ÐºÑ–Ð½Ñ†Ñ Ð³Ñ–Ð»ÐºÐ¸." no_posts_yet: "Ще немає жодного запиÑу." - show_comments: - few: "Показати ще %{count} коментарів" - many: "Показати ще %{count} коментарів" - one: "Показати ще коментарі" - other: "Показати ще %{count} коментарів" - two: "Показати ще два коментарі" - zero: "Більше немає коментарів" streams: activity: title: "ÐœÐ¾Ñ Ð´Ñ–ÑльніÑÑ‚ÑŒ" @@ -1270,19 +964,10 @@ uk: title: "Публічна діÑльніÑÑ‚ÑŒ" tags: title: "ЗапиÑи, позначені: %{tags}" - tag_followings: - create: - failure: "Помилка відÑÑ‚ÐµÐ¶ÑƒÐ²Ð°Ð½Ð½Ñ #%{name}" - none: "Ðе можна Ñтежити за порожньою міткою!" - success: "Ура! Тепер ви Ñтежите за міткою #%{name}." - destroy: - failure: "Ðе вдалоÑÑŒ переÑтати Ñтежити за міткою #%{name}. Можливо, ви вже відпиÑалиÑÑ Ð²Ñ–Ð´ неї?" - success: "Шкода! Ви більше не Ñтежите за міткою #%{name}." tags: name_too_long: "Будь лаÑка, зробіть Ñвоє тег ім'Ñ Ð¼ÐµÐ½ÑŒÑˆÐµ, ніж %{count} Ñимволів. Зараз це %{current_length} Ñимволів." show: follow: "Стежити за міткою #%{tag}" - following: "Ви Ñтежите за міткою #%{tag}" none: "Порожньої мітки немає!" stop_following: "Ðе Ñтежити за міткою #%{tag}" tagged_people: @@ -1291,8 +976,6 @@ uk: one: "Одна людина відмічена %{tag}" other: "%{count} люди, відмічні %{tag}" zero: "Ðіхто не відмічений %{tag}" - terms_and_conditions: "Умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг" - undo: "Повернути?" username: "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача" users: confirm_email: @@ -1313,7 +996,6 @@ uk: character_minimum_expl: "щонайменьше шіÑÑ‚ÑŒ Ñимволів" close_account: dont_go: "Будь лаÑка, не йдіть!" - if_you_want_this: "Якщо ви дійÑно хочете це зробити, введіть ваш пароль Ñ– натиÑніть 'Закрити аккаунт'." lock_username: "Це зарезервує ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача на випадок, Ñкщо ви захочете знову зареєÑтруватиÑÑ." locked_out: "Буде зроблено вихід , Ñ– ви будете відключені від вашого облікового запиÑу" make_diaspora_better: "Ми хотіли б, щоб ви допомогли нам зробити ДіаÑпору кращою заміÑÑ‚ÑŒ того, щоб проÑто піти звідÑи. Якщо ви дійÑно вирішили піти, ми хочемо, щоб ви знали, що ÑтанетьÑÑ Ð´Ð°Ð»Ñ–." @@ -1326,14 +1008,12 @@ uk: current_password_expl: "Ñкий ви викориÑтовуєте Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ..." download_export: "Завантажити мій профіль" download_export_photos: "Завантажити мої фотографії" - download_photos: "Звантажити мої Ñвітлини" edit_account: "Редагувати аккаунт" email_awaiting_confirmation: "Ми надіÑлали поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— на %{unconfirmed_email}. Поки ви не ÑкориÑтаєтеÑÑŒ ним Ñ– не активуєте нову адреÑу, ми викориÑтовуватимемо ваш колишній Ñщик %{email}." export_data: "ЕкÑпорт інформації" export_in_progress: "Ðа даний момент ми оброблюємо Ваші дані. Будь лаÑка, перевірте раз через декілька хвилин." export_photos_in_progress: "Ðа даний момент ми оброблÑємо Ваші фотографії. Будь лаÑка, перевірте через декілька хвилин." following: "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´ÑлідковуваннÑ" - getting_started: "Ðові Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувача" last_exported_at: "(ОÑтаннє Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð² %{timestamp})" liked: "комуÑÑŒ подобаєтьÑÑ Ð²Ð°Ñˆ запиÑ" mentioned: "Ð²Ð°Ñ Ð·Ð³Ð°Ð´Ð°Ð»Ð¸ у запиÑÑ–" @@ -1359,7 +1039,6 @@ uk: connect_to_facebook_link: "Підключаємо ваш Facebook аккаунт" hashtag_explanation: "Мітки дозволÑÑŽÑ‚ÑŒ вам обговорювати Ñ– Ñтежити за темами, що цікавлÑÑ‚ÑŒ ваÑ. Це також відмінний ÑпоÑіб пошуку однодумців в ДіаÑпорі." hashtag_suggestions: "Спробуйте, наприклад, мітки #миÑтецтво, #кіно, #gif Ñ– Ñ‚.п." - saved: "Збережено!" well_hello_there: "Вітаємо ваÑ!" what_are_you_in_to: "Чим ви цікавитеÑÑ?" who_are_you: "Хто ви?" @@ -1383,13 +1062,6 @@ uk: settings_updated: "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ñ–" unconfirmed_email_changed: "Email змінивÑÑ. Потрібна активаціÑ." unconfirmed_email_not_changed: "Помилка зміни Email" - webfinger: - fetch_failed: "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ профіль %{profile_url}" - hcard_fetch_failed: "Виникла проблема при отриманні hcard Ð´Ð»Ñ %{account}" - no_person_constructed: "Жодна оÑоба не може бути зібрана з цієї hcard." - not_enabled: "webfinger не буде включений Ð´Ð»Ñ Ñ…Ð¾Ñта %{account}'s" - xrd_fetch_failed: "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні xrd з %{account}" - welcome: "ЛаÑкаво проÑимо!" will_paginate: next_label: "вперед »" previous_label: "« назад" \ No newline at end of file diff --git a/config/locales/diaspora/ur-PK.yml b/config/locales/diaspora/ur-PK.yml index ab3f5f9a749c5a5c3cf5e549da24895949a4dfc8..c26c3815435266489e7c01bbdfb16f9ea9746348 100644 --- a/config/locales/diaspora/ur-PK.yml +++ b/config/locales/diaspora/ur-PK.yml @@ -6,10 +6,7 @@ ur-PK: _applications: "ایپلی کیشنز" - _comments: "تبصرے" _contacts: "رابطے" - _home: "صÙØÛ Ø§ÙˆÙ„" - _photos: "تصاویر" _services: "سÛولیات" account: "اکاؤنٹ" activerecord: @@ -40,13 +37,7 @@ ur-PK: username: invalid: "غلط ÛÛ’. ÛÙ… صر٠Øرو٠، Ûندسوں اور مرتب Ú©ÛŒ اجازت دیتے Ûیں" taken: ".Ù¾ÛÙ„Û’ ÛÛŒ لیا جا چکا ÛÛ’" - ago: "%{قبل {وقت" all_aspects: "تمام Ù¾Ûلو" - application: - helper: - unknown_person: "نامعلوم شخص" - video_title: - unknown: "نامعلوم ویڈیو عنوان" are_you_sure: "کیا آپکو یقین ÛÛ’ØŸ" aspect_memberships: destroy: @@ -59,11 +50,6 @@ ur-PK: success: "Ø±Ø§Ø¨Ø·Û Ú©Ø§Ù…ÛŒØ§Ø¨ÛŒ سے Ù¾Ûلو میں شامل کر دیا گیا ÛÛ’Û”" aspect_listings: add_an_aspect: "ایک Ù¾Ûلو شامل کریں +" - contacts_not_visible: "اس Ù¾Ûلو میں رابطے ایک دوسرے Ú©Ùˆ دیکھ Ù†Ûیں سکیں Ú¯Û’Û”" - contacts_visible: "اس Ù¾Ûلو میں رابطے ایک دوسرے Ú©Ùˆ دیکھ سکیں Ú¯Û’Û”" - create: - failure: "Ù¾Ûلو بنانے میں ناکامی۔" - success: "آپکا نیا Ù¾Ûلو Ùª {name} تشکیل دے دیا گیا" destroy: failure: "%{name} .خالی Ù†Ûیں ÛÛ’ اور اسے ختم Ù†Ûیں کیا جا سکتا" success: "%{name} کامیابی سے Ûٹا دیا گیا۔" @@ -71,39 +57,22 @@ ur-PK: aspect_list_is_not_visible: "Ù¾Ûلو Ú©ÛŒ ÙÛرست' Ù¾Ûلو میں دوسروں سے Ú†Ú¾Ù¾ÛŒ Ûوئ ÛÛ’'" aspect_list_is_visible: "Ù¾Ûلو Ú©ÛŒ ÙÛرست' Ù¾Ûلو میں دوسروں Ú©Ùˆ دکھائی دے رÛÛŒ ÛÛ’'" confirm_remove_aspect: "کیا آپکو یقین ÛÛ’ Ú©Û Ø¢Ù¾ اس Ù¾Ûلو Ú©Ùˆ خذ٠کرنا چاÛتے Ûیں؟" - make_aspect_list_visible: "کیا Ù¾Ûلو Ú©ÛŒ ÙÛرست نظر Ø¢Û“ØŸ" - remove_aspect: "Ù¾Ûلو Øذ٠کریں" rename: "نام تبدیل کریں" update: "تازÛ" updating: "ØªØ§Ø²Û Ú©ÛŒØ§ جا رھا ÛÛ’" index: - diaspora_id: - content_1: "آپکی ڈایسپورا شناخت" - content_2: "ÛŒÛ Ú©Ø³ÛŒ Ú©Ùˆ بھی دیں تو ÙˆÛ Ø¢Ù¾Ú©Ùˆ تلاش کر Ù„Û’ گا۔" - heading: "ڈایسپورا شناخت" donate: "Ø¹Ø·ÛŒÛ Ø¯ÛŒØ¬ÛŒÛ’" - handle_explanation: "ÛŒÛ Ø¢Ù¾ Ú©ÛŒ ڈایسپورا شناخت ÛÛ’Û” ایک ای میل ایڈریس Ú©ÛŒ طرØØŒ آپ اسے لوگوں Ú©Ùˆ خود تک Ù¾ÛÙ†Ú†Ù†Û’ Ú©Û’ لئے دے سکتے Ûیں۔" help: here_to_help: "Diaspora community is here to help!" tag_bug: "#bug" tag_feature: "#feature" tag_question: "#question" - no_contacts: "کوئ Ø±Ø§Ø¨Ø·Û Ù†Ûیں" - no_tags: "پیروی کرنے Ú©Û’ لئے ایک Ø§ØµØ·Ù„Ø§Ø ØªÙ„Ø§Ø´ کریں +" - people_sharing_with_you: "آپ Ú©Û’ ساتھ اشتراک کرنے والے اÙراد" - post_a_message: "ایک پیغام شائع کیجیے" services: content: "آپ ڈایسپورا Ú©Û’ لئے Ù…Ù†Ø¯Ø±Ø¬Û Ø°ÛŒÙ„ خدمات شامل کر سکتے Ûیں :" heading: "خدمات Ú©Ùˆ جوڑیے" - unfollow_tag: "پیروی بند کیجیے #%{tag}" - new: - create: "بنایۓ" - name: "نام" no_contacts_message: try_adding_some_more_contacts: "آب مزید رابطے تلاش (top) یا مدعو (right) کر سکتے Ûیں۔" you_should_add_some_more_contacts: "آپ Ú©Ùˆ Ú©Ú†Ú¾ مزید رابطے شامل کرنا چاÛیئں!" - no_posts_message: - start_talking: "ابھی تک کسی Ù†Û’ Ú©Ú†Ú¾ Ù†Ûیں Ú©Ûا!" seed: acquaintances: "جاننے والے" family: "خاندان" @@ -112,20 +81,9 @@ ur-PK: update: failure: "آپکے Ù¾Ûلو کا نام, %{name}, Ù…ØÙوظ کرنے Ú©ÛŒ Øد سے لمبا ÛÛ’Û”" success: "آپکے Ù¾Ûلو, %{name}, میں ترمیم ÛÙˆ گئ ÛÛ’Û”" - back: "واپس" contacts: index: - add_to_aspect: "Add contacts to %{name}" no_contacts: "No contacts." - conversations: - helper: - new_messages: - few: "%{count} new messages" - many: "%{count} new messages" - one: "1 new messages" - other: "%{count} new messages" - two: "%{count} new messages" - zero: "No new messages" layouts: application: toggle: "toggle mobile site" @@ -133,29 +91,6 @@ ur-PK: logout: "log out" profile: "profile" settings: "settings" - likes: - likes: - people_dislike_this: - few: "%{count} dislikes" - many: "%{count} dislikes" - one: "%{count} dislike" - other: "%{count} dislikes" - two: "%{count} dislikes" - zero: "no dislikes" - people_like_this: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" - people_like_this_comment: - few: "%{count} likes" - many: "%{count} likes" - one: "%{count} like" - other: "%{count} likes" - two: "%{count} likes" - zero: "no likes" notifications: also_commented: few: "%{actors} also commented on %{post_author}'s %{post_link}." @@ -178,14 +113,6 @@ ur-PK: other: "%{actors} commented on your %{post_link}." two: "%{actors} commented on your %{post_link}." zero: "%{actors} commented on your %{post_link}." - helper: - new_notifications: - few: "%{count} new notifications" - many: "%{count} new notifications" - one: "1 new notifications" - other: "%{count} new notifications" - two: "%{count} new notifications" - zero: "No new notifications" index: and_others: few: "and %{count} others" @@ -273,34 +200,8 @@ ur-PK: other: "%{count} reactions" two: "%{count} reactions" zero: "0 reactions" - registrations: - new: - create_my_account: "Create my account" - sign_up_message: "Social Networking with a <3" - requests: - helper: - new_requests: - few: "%{count} new requests!" - many: "%{count} new requests!" - one: "new request!" - other: "%{count} new requests!" - two: "%{count} new requests!" - zero: "no new requests" - reshares: - reshare: - reshare: - few: "%{count} reshares" - many: "%{count} reshares" - one: "1 reshare" - other: "%{count} reshares" - two: "%{count} reshares" - zero: "Reshare" - services: - inviter: - click_link_to_accept_invitation: "Click this link to accept your invitation" shared: aspect_dropdown: - add_to_aspect: "Add to aspect" toggle: few: "In %{count} aspects" many: "In %{count} aspects" @@ -311,30 +212,13 @@ ur-PK: publisher: new_user_prefill: i_like: "I'm interested in %{tags}." - stream_element: - hide_and_mute: "Hide and Mute" status_messages: too_long: "{\"few\"=>\"please make your status messages less than %{count} characters\", \"many\"=>\"please make your status messages less than %{count} characters\", \"one\"=>\"please make your status messages less than %{count} character\", \"other\"=>\"please make your status messages less than %{count} characters\", \"two\"=>\"please make your status messages less than %{count} characters\", \"zero\"=>\"please make your status messages less than %{count} characters\"}" - stream_helper: - show_comments: - few: "Show %{count} more comments" - many: "Show %{count} more comments" - one: "Show one more comment" - other: "Show %{count} more comments" - two: "Show two more comments" - zero: "No more comments" streams: aspects: title: "Your Aspects" mentions: title: "Your Mentions" - tag_followings: - create: - failure: "Failed to follow: #%{name}" - success: "Successfully following: #%{name}" - destroy: - failure: "Failed to stop following: #%{name}" - success: "Successfully stopped following: #%{name}" users: edit: auto_follow_back: "Automatically follow back if a someone follows you" diff --git a/config/locales/diaspora/vi.yml b/config/locales/diaspora/vi.yml index 4d4d18fcb356cd827769281bfafd48cf0b82743e..610d783f57fb3a6a0a64642c897b0e42db270f23 100644 --- a/config/locales/diaspora/vi.yml +++ b/config/locales/diaspora/vi.yml @@ -6,11 +6,8 @@ vi: _applications: "Ứng dụng" - _comments: "Bình luáºn" _contacts: "Liên lạc" _help: "Trợ giúp" - _home: "Trang chủ" - _photos: "ảnh" _services: "Dịch vụ" account: "Tà i khoản" activerecord: @@ -82,13 +79,7 @@ vi: other: "số ngÆ°á»i dùng má»›i của tuần nà y: %{count}" zero: "tuần nà y không có ngÆ°á»i dùng má»›i" current_server: "Ngà y hiện tại của máy chủ là %{date}" - ago: "%{time} trÆ°á»›c" all_aspects: "Tất cả mối quan hệ" - application: - helper: - unknown_person: "ngÆ°á»i lạ" - video_title: - unknown: "ChÆ°a biết tá»±a Ä‘á» video" are_you_sure: "Bạn có chắc không?" are_you_sure_delete_account: "Bạn có chắc đóng vÄ©nh viá»…n tà i khoản không? Má»i dữ liệu vá» bạn sẽ bị xóa khá»i hệ thống!" aspect_memberships: @@ -102,17 +93,9 @@ vi: success: "Äã thêm liên lạc và o mối quan hệ." aspect_listings: add_an_aspect: "+ Thêm mối quan hệ" - deselect_all: "Bá» chá»n tất cả" - edit_aspect: "Cáºp nháºt %{name}" - select_all: "Chá»n tất cả" aspect_stream: stay_updated: "Vẫn còn cáºp nháºt" stay_updated_explanation: "Luồng chÃnh của bạn hầu hết là từ các liên lạc, thẻ, và tin từ má»™t và i thà nh viên trong cá»™ng đồng." - contacts_not_visible: "Các liên lạc trong mối quan hệ nà y không thể nhìn thấy nhau." - contacts_visible: "Các liên lạc trong mối quan hệ nà y có thể nhìn thấy nhau." - create: - failure: "Tạo mối quan hệ thất bại." - success: "Mối quan hệ %{name} đã được tạo" destroy: failure: "%{name} không rá»—ng và không thể bị loại bá»." success: "%{name} đã bị loại bá»." @@ -120,23 +103,14 @@ vi: aspect_list_is_not_visible: "danh sách mối quan hệ bị ẩn vá»›i ngÆ°á»i khác trong mối quan hệ" aspect_list_is_visible: "những ngÆ°á»i trong mối quan hệ nà y nhìn thấy nhau" confirm_remove_aspect: "Bạn có chắc là muốn xoá mối quan hệ nà y không?" - make_aspect_list_visible: "các liên lạc trong mối quan hệ nà y có thể thấy nhau?" - remove_aspect: "Xoá mối quan hệ nà y" rename: "đổi tên" update: "cáºp nháºt" updating: "Ä‘ang cáºp nháºt" index: - diaspora_id: - content_1: "ID Diaspora:" - content_2: "Cho ngÆ°á»i khác biết và há» có thể tìm thấy bạn trên Diaspora." - heading: "ID Diaspora" donate: "Quyên góp" - handle_explanation: "Äây là id diaspora của bạn. Giống nhÆ° má»™t địa chỉ thÆ° Ä‘iện tá», ngÆ°á»i khác có thể liên lạc vá»›i bạn thông qua nó." help: any_problem: "Có vấn Ä‘á»?" do_you: "Bạn muốn:" - email_feedback: "%{link} phản hồi hoặc góp ý" - email_link: "ThÆ° Ä‘iện tá»" feature_suggestion: "... Ä‘á» nghị tÃnh năng %{link}?" find_a_bug: "... báo lá»—i %{link}?" have_a_question: "... gá»i câu há»i %{link}?" @@ -147,31 +121,20 @@ vi: tag_question: "#question" tutorial_link_text: "HÆ°á»›ng dẫn" introduce_yourself: "Äây là luồng của bạn. Hãy tá»± giá»›i thiệu mình ở đây." - keep_diaspora_running: "Äóng góp hà ng tháng để giúp phát triển Diaspora nhanh hÆ¡n!" keep_pod_running: "Äóng góp hà ng tháng để giúp %{pod} chạy nhanh và duy trì các phà khác!" new_here: follow: "Theo dõi %{link} và chà o đón ngÆ°á»i dùng má»›i đến vá»›i Diaspora*!" learn_more: "Tìm hiểu thêm" title: "Chà o đón ngÆ°á»i dùng má»›i" - no_contacts: "Không có liên lạc" - no_tags: "+ Tìm thẻ để theo dõi" - people_sharing_with_you: "Äang chia sẻ vá»›i bạn" - post_a_message: "đăng má»™t tin >>" services: content: "Bạn có thể kết nối những dịch vụ sau vá»›i Diaspora:" heading: "Kết nối dịch vụ" - unfollow_tag: "Ngừng theo dõi #%{tag}" welcome_to_diaspora: "Chà o mừng đến vá»›i Diaspora, %{name}!" - new: - create: "Tạo" - name: "Tên (chỉ bạn nhìn thấy)" no_contacts_message: community_spotlight: "nổi báºt từ cá»™ng đồng" or_spotlight: "Hoặc bạn có thể chia sẻ vá»›i %{link}" try_adding_some_more_contacts: "Bạn có thể tìm hoặc má»i thêm bạn." you_should_add_some_more_contacts: "Bạn có thể thêm má»™t và i liên lạc!" - no_posts_message: - start_talking: "ChÆ°a có ai nói gì!" seed: acquaintances: "NgÆ°á»i quen" family: "Gia đình" @@ -180,7 +143,6 @@ vi: update: failure: "Mối quan hệ %{name} có tên quá dà i, không thể lÆ°u." success: "Mối quan hệ %{name} đã được chỉnh sá»a." - back: "Trở lại" blocks: create: failure: "Không thể bá» qua ngÆ°á»i dùng. #evasion" @@ -192,21 +154,14 @@ vi: explanation: "Äăng tin lên Diaspora từ bất kì đâu bằng cách đánh dấu %{link}." heading: "Äánh dấu" post_something: "Äăng tin lên Diaspora" - post_success: "Äã đăng bà i! Äang đóng!" cancel: "Hủy bá»" comments: new_comment: comment: "Bình luáºn" commenting: "Äang gá»i bình luáºn..." - one: "1 bình luáºn" - other: "%{count} bình luáºn" - zero: "không có bình luáºn" contacts: - create: - failure: "Tạo liên lạc má»›i thất bại" index: add_a_new_aspect: "Thêm mối quan hệ má»›i" - add_to_aspect: "thêm liên lạc và o %{name}" all_contacts: "Tất cả liên lạc" community_spotlight: "Nổi báºt từ cá»™ng đồng" my_contacts: "Liên lạc của tôi" @@ -215,33 +170,18 @@ vi: only_sharing_with_me: "Chỉ chia sẻ vá»›i tôi" start_a_conversation: "Bắt đầu má»™t cuá»™c trò chuyện" title: "Liên lạc" - your_contacts: "Liên lạc của bạn" - sharing: - people_sharing: "NgÆ°á»i Ä‘ang chia sẻ vá»›i bạn:" spotlight: community_spotlight: "Nổi báºt từ cá»™ng đồng" suggest_member: "Gợi ý má»™t thà nh viên" conversations: - conversation: - participants: "NgÆ°á»i tham gia" create: fail: "Tin nhắn không hợp lệ" no_contact: "Bạn cần phải thêm liên lạc trÆ°á»›c đã!" sent: "Äã gá»i tin nhắn" - helper: - new_messages: - few: "%{count} tin nhắn má»›i" - many: "%{count} tin nhắn má»›i" - one: "1 tin nhắn má»›i" - other: "%{count} tin nhắn má»›i" - two: "%{count} tin nhắn má»›i" - zero: "Không có tin nhắn má»›i" index: inbox: "Há»™p thÆ° đến" - no_conversation_selected: "không có cuá»™c trò chuyện nà o được chá»n" no_messages: "không có tin nhắn" new: - abandon_changes: "Huá»· bá» thay đổi?" send: "Gá»i" sending: "Äang gá»i..." subject: "tá»±a Ä‘á»" @@ -260,9 +200,6 @@ vi: error_messages: helper: correct_the_following_errors_and_try_again: "Sá»a những lá»—i sau và thá» lại." - invalid_fields: "TrÆ°á»ng không hợp lệ" - login_try_again: "Vui lòng <a href='%{login_link}'>đăng nháºp</a> và thá» lại." - post_not_public: "Bà i đăng bạn muốn xem không được công khai!" fill_me_out: "Äiá»n đầy đủ" find_people: "Tìm ngÆ°á»i hoặc #tags" help: @@ -273,43 +210,26 @@ vi: tutorial: "hÆ°á»›ng dẫn" tutorials: "hÆ°á»›ng dẫn" wiki: "wiki" - hide: "Ẩn" - invitation_codes: - excited: "%{name} muốn nhìn thấy bạn ở đây." invitations: a_facebook_user: "NgÆ°á»i dùng Facebook" check_token: not_found: "Không tìm thấy khoá má»i" create: - already_contacts: "Bạn đã kết nối vá»›i ngÆ°á»i nà y" - already_sent: "Bạn đã má»i ngÆ°á»i nà y." empty: "Nháºp Ãt nhất má»™t địa chỉ thÆ° Ä‘iện tá»." no_more: "Bạn đã hết thÆ° má»i." note_already_sent: "Äã gá»i lá»i má»i đến địa chỉ: %{emails}" - own_address: "Bạn không thể gá»i lá»i má»i đến địa chỉ riêng của bạn." rejected: "Äịa chỉ thÆ° Ä‘iện tá» sau có vấn Ä‘á»: " sent: "ThÆ° má»i đã được gá»i đến: %{emails}" - edit: - accept_your_invitation: "Chấp nháºn lá»i má»i của bạn" - your_account_awaits: "Tà i khoản của bạn Ä‘ang chỠđợi!" new: - already_invited: "Những ngÆ°á»i sau không chấp nháºn lá»i má»i của bạn:" - aspect: "Mối quan hệ" - check_out_diaspora: "Kiểm tra Diaspora!" codes_left: other: "Còn lại %{count} lượt má»i cho liên kết nà y" zero: "Liên kết nà y không còn hiệu lá»±c" comma_separated_plz: "Bạn có thể nháºp nhiá»u địa chỉ thÆ° và ngăn cách chúng bằng dấu phẩy." - if_they_accept_info: "nếu chấp nháºn, há» sẽ được thêm và o mối quan hệ mà bạn đã má»i." invite_someone_to_join: "Má»i ngÆ°á»i khác tham gia Diaspora!" language: "Ngôn ngữ" paste_link: "Chia sẻ liên kết nà y hoặc gá»i qua thÆ° cho ngÆ°á»i khác để má»i há» tham gia Diaspora*." - personal_message: "Tin nhắn cá nhân" - resend: "Gá»i lại" send_an_invitation: "Gá»i thÆ° má»i" - send_invitation: "Gá»i thÆ° má»i" sending_invitation: "Äang gá»i thÆ° má»i..." - to: "Äến" layouts: application: back_to_top: "Cuá»™n lên trên" @@ -318,35 +238,13 @@ vi: source_package: "tải vá» gói mã nguồn" toggle: "báºt/tắt di Ä‘á»™ng" whats_new: "có gì má»›i?" - your_aspects: "các mối quan hệ" header: - admin: "quản trị" - blog: "blog" code: "mã nguồn" - login: "đăng nháºp" logout: "Äăng xuất" profile: "Hồ sÆ¡" - recent_notifications: "Thông báo gần đây" settings: "Thiết láºp" - view_all: "Xem tất cả" - likes: - likes: - people_dislike_this: - few: "%{count} ngÆ°á»i không thÃch" - many: "%{count} ngÆ°á»i không thÃch" - one: "%{count} ngÆ°á»i không thÃch" - other: "%{count} ngÆ°á»i không thÃch" - two: "%{count} ngÆ°á»i không thÃch" - zero: "chÆ°a có ngÆ°á»i không thÃch" - people_like_this: - other: "%{count} ngÆ°á»i thÃch" - zero: "không có ai thÃch" - people_like_this_comment: - other: "%{count} ngÆ°á»i thÃch" - zero: "không có ai thÃch" limited: "Giá»›i hạn" more: "Xem thêm" - next: "tiếp theo" no_results: "Không có kết quả" notifications: also_commented: @@ -362,14 +260,6 @@ vi: other: "%{actors} đã bình luáºn tin %{post_link} của bạn." two: "%{actors} đã bình luáºn tin %{post_link} của bạn." zero: "%{actors} đã bình luáºn tin %{post_link} của bạn." - helper: - new_notifications: - few: "%{count} thông báo má»›i" - many: "%{count} thông báo má»›i" - one: "1 thông báo má»›i" - other: "%{count} thông báo má»›i" - two: "%{count} thông báo má»›i" - zero: "Không có thông báo má»›i" index: and: "và " and_others: @@ -409,7 +299,6 @@ vi: zero: "%{actors} đã bắt đầu chia sẻ vá»›i bạn." notifier: a_post_you_shared: "má»™t bà i đăng." - accept_invite: "Chấp nháºn lá»i má»i từ Diaspora*!" click_here: "nhấn và o đây" comment_on_post: reply: "Trả lá»i hoặc xem bà i đăng của %{name}" @@ -438,7 +327,6 @@ vi: liked: "%{name} vừa thÃch bà i đăng của bạn" view_post: "Xem bà i đăng >" mentioned: - mentioned: "đã nhắc đến bạn trong má»™t bà i đăng." subject: "%{name} đã nhắc đến bạn trên Diaspora*" private_message: reply_to_or_view: "Trả lá»i hoặc xem cuá»™c trò chuyện nà y >" @@ -456,116 +344,54 @@ vi: to_change_your_notification_settings: "để đổi thiết láºp thông báo" nsfw: "NSFW" ok: "OK" - or: "hoặc" - password: "Máºt khẩu" - password_confirmation: "Xác nháºn máºt khẩu má»›i" people: add_contact: invited_by: "bạn được má»i bởi" - add_contact_small: - add_contact_from_tag: "thêm liên lạc từ thẻ" - helper: - is_not_sharing: "%{name} hiện không chia sẻ vá»›i bạn" - is_sharing: "%{name} Ä‘ang chia sẻ vá»›i bạn" - results_for: " kết quả cho %{params}" index: looking_for: "Tìm các bà i đăng có thẻ %{tag_link}?" no_one_found: "...và không tìm thấy ai." no_results: "Bạn cần tìm gì đó." results_for: "kết quả tìm kiếm cho" searching: "Ä‘ang tìm, vui lòng chá»..." - one: "1 ngÆ°á»i" - other: "%{count} ngÆ°á»i" person: - add_contact: "thêm liên lạc" - already_connected: "Äã kết nối" - pending_request: "Yêu cầu Ä‘ang chá»" thats_you: "Äó là bạn!" profile_sidebar: bio: "Tiểu sá»" born: "Ngà y sinh" - edit_my_profile: "Chỉnh sá»a hồ sÆ¡" gender: "Giá»›i tÃnh" - in_aspects: "trong mối quan hệ" location: "NÆ¡i ở" - photos: "Hình ảnh" - remove_contact: "loại bá» liên lạc" - remove_from: "Loại bá» %{name} khá»i %{aspect}?" show: closed_account: "Tà i khoản nà y đã bị đóng." does_not_exist: "NgÆ°á»i không tồn tại!" has_not_shared_with_you_yet: "%{name} chÆ°a từng chia sẻ gì vá»›i bạn!" - ignoring: "Bạn Ä‘ang từ chối tất cả bà i đăng từ %{name}." - incoming_request: "%{name} muốn chia sẻ vá»›i bạn" - mention: "Nhắc đến" - message: "Tin nhắn" - not_connected: "Hiện bạn không chia sẻ vá»›i ngÆ°á»i nà y" - recent_posts: "Bà i đăng gần đây" - recent_public_posts: "Bà i đăng công khai gần đây" - return_to_aspects: "Trở vá» trang các mối quan hệ" - see_all: "Xem tất cả" - start_sharing: "bắt đầu chia sẻ" - to_accept_or_ignore: "để chấp nháºn hoặc từ chối." - sub_header: - add_some: "thêm" - edit: "sá»a" - you_have_no_tags: "bạn không có thẻ nà o!" - webfinger: - fail: "Xin lá»—i, chúng tôi không thể tìm %{handle}." - zero: "không có ai" photos: - comment_email_subject: "Ảnh của %{name}" create: integrity_error: "Tải ảnh lên thất bại. Bạn có chắc đó là má»™t tấm ảnh?" runtime_error: "Tải ảnh lên thất bại. Bạn có chắc an toà n không?" type_error: "Tải ảnh lên thất bại, Bạn có chắc ảnh đã được thêm?" destroy: notice: "Äã xóa ảnh." - edit: - editing: "Chỉnh sá»a" - new: - back_to_list: "Trở vá» danh sách" - new_photo: "Ảnh má»›i" - post_it: "đăng nó!" new_photo: empty: "{file} rá»—ng, chá»n lại táºp tin." invalid_ext: "{file} có phần mở rá»™ng không hợp lệ. Chỉ chấp nháºn phần mở rá»™ng {extensions}." size_error: "{file} quá to, dung lượng tối Ä‘a cho phép là {sizeLimit}." new_profile_photo: - or_select_one_existing: "hoặc chá»n từ ảnh Ä‘ang có trong %{photos}" upload: "Tải lên ảnh má»›i" - photo: - view_all: "xem tất cả ảnh của %{name}" show: - collection_permalink: "Ä‘Æ°á»ng dẫn của bá»™ sÆ°u táºp" - delete_photo: "Xoá ảnh" - edit: "sá»a" - edit_delete_photo: "Sá»a mô tả/xoá ảnh" - make_profile_photo: "là m ảnh hồ sÆ¡" show_original_post: "Xem bà i đăng gốc" - update_photo: "Cáºp nháºt ảnh" - update: - error: "Không thể chỉnh sá»a ảnh." - notice: "Äã cáºp nháºt ảnh." posts: presenter: title: "Má»™t bà i đăng từ %{name}" show: - destroy: "Xoá" - not_found: "Xin lá»—i, chúng tôi không tìm thấy bà i đăng đó." - permalink: "Ä‘Æ°á»ng dẫn cố định" photos_by: other: "%{count} ảnh của %{author}" zero: "Không có ảnh của %{author}" reshare_by: "Chia sẻ lại từ %{author}" - previous: "trÆ°á»›c" privacy: "Bảo máºt" - privacy_policy: "ChÃnh sách bảo máºt" profile: "Hồ sÆ¡" profiles: edit: allow_search: "Cho phép ngÆ°á»i khác trong Diaspora tìm thấy tôi" - edit_profile: "Chỉnh sá»a hồ sÆ¡" first_name: "Tên" last_name: "Há»" update_profile: "Cáºp nháºt hồ sÆ¡" @@ -575,8 +401,6 @@ vi: your_location: "NÆ¡i ở" your_name: "Há» và tên" your_photo: "Ảnh hồ sÆ¡" - your_private_profile: "Hồ sÆ¡ cá nhân" - your_public_profile: "Hồ sÆ¡ công khai" your_tags: "Mô tả bản thân qua 5 từ" your_tags_placeholder: "và dụ: #movies #kittens #travel #teacher #newyork" update: @@ -590,57 +414,23 @@ vi: closed: "Pod DIASPORA nà y không cho đăng kà nữa." create: success: "Bạn đã tham gia và o Diaspora!" - edit: - cancel_my_account: "Huá»· tà i khoản" - edit: "Chỉnh sá»a %{name}" - leave_blank: "(để trống nếu bạn không muốn thay đổi)" - password_to_confirm: "(bạn cần cung cấp máºt khẩu hiện tai để xác nháºn thay đổi)" - unhappy: "Không vui?" - update: "Cáºp nháºt" invalid_invite: "Liên kết má»i bạn cung cấp không còn hợp lệ!" new: - create_my_account: "Tạo tà i khoản" email: "THƯ ÄIỆN TỬ" enter_email: "Nháºp địa chỉ thÆ° Ä‘iện tá»" enter_password: "Nháºp máºt khẩu (Ãt nhất sáu kà tá»±)" enter_password_again: "Nháºp lại máºt khẩu" enter_username: "Tên ngÆ°á»i dùng (chỉ gồm chữ cái, số và dấu gạch dÆ°á»›i _)" - join_the_movement: "Tham gia chuyển đổi!" password: "MẬT KHẨU" password_confirmation: "XÃC NHẬN MẬT KHẨU" sign_up: "ÄÄ‚NG KÃ" - sign_up_message: "Social Networking with a <3" username: "TÊN NGƯỜI DÙNG" - requests: - create: - sending: "Gá»i" - sent: "Bạn đã yêu cầu chia sẻ vá»›i %{name}. Há» sẽ nhìn thấy trong lần đăng nháºp sau và o Diaspora." - destroy: - error: "Vui lòng chá»n má»™t mối quan hệ!" - ignore: "Từ chối yêu cầu liên lạc." - success: "Bạn Ä‘ang chia sẻ." - helper: - new_requests: - other: "%{count} yêu cầu má»›i!" - zero: "không có yêu cầu má»›i" - manage_aspect_contacts: - existing: "Liên lạc Ä‘ang tồn tại" - manage_within: "Quản là liên lạc" - new_request_to_person: - sent: "đã gá»i!" reshares: comment_email_subject: "Bà i chia sẻ lại của %{resharer} từ %{author}" - create: - failure: "Có lá»—i khi chia sẻ lại bà i đăng nà y." reshare: deleted: "Bà i đăng gốc đã bị tác giả xoá." - reshare: - other: "%{count} lượt chia sẻ" - zero: "Không có ai chia sẻ lại" reshare_confirmation: "Chia sẻ lại bà i đăng của %{author}?" - reshare_original: "Chia sẻ lại bà i gốc" reshared_via: "được chia sẻ lại bởi" - show_original: "Hiện bà i đăng gốc" search: "Tìm kiếm" services: create: @@ -651,58 +441,23 @@ vi: success: "Äã xoá xác thá»±c." failure: error: "có lá»—i khi kết nối đến dịch vụ đó" - finder: - fetching_contacts: "Diaspora Ä‘ang má»i bạn trên %{service} của bạn, hãy kiểm tra lại sau và i phút." - no_friends: "Không tìm thấy bạn Facebook." - service_friends: "Bạn bè %{service}" index: disconnect: "ngắt kết nối" edit_services: "Chỉnh sá»a dịch vụ" logged_in_as: "đã đăng nháºp vá»›i tên" really_disconnect: "ngắt kết nối vá»›i %{service}?" services_explanation: "Kết nối các dịch vụ để có thể đăng tin lên chúng thông qua Diaspora." - inviter: - click_link_to_accept_invitation: "Theo dõi liên kết nà y để chấp nháºn lá»i má»i của bạn" - join_me_on_diaspora: "Tham gia DIASPORA*" - remote_friend: - invite: "má»i" - not_on_diaspora: "ChÆ°a có trên Diaspora" - resend: "gá»i lại" settings: "Thiết láºp" - share_visibilites: - update: - post_hidden_and_muted: "Bà i đăng của %{name} đã bị ẩn, và các thông báo đã bị tắt." - see_it_on_their_profile: "Nếu bạn muốn xem cáºp nháºt từ bà i đăng nà y, xem trang hồ sÆ¡ của %{name}." shared: - add_contact: - add_new_contact: "Thêm liên lạc má»›i" - create_request: "Tìm bằng ID Diaspora" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Nháºp tên ngÆ°á»i dùng Diaspora:" - know_email: "Biết địa chỉ thÆ° Ä‘iện tá» của há»? Bạn có thể má»i há»." - your_diaspora_username_is: "Tên ngÆ°á»i dùng Diaspora của bạn là : %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "Thêm liên lạc" toggle: other: "Trong %{count} mối quan hệ" zero: "Thêm liên lạc" - contact_list: - all_contacts: "Tất cả liên lạc" - footer: - logged_in_as: "Ä‘ã đăng nháºp vá»›i tên %{name}" - your_aspects: "các mối quan hệ" invitations: by_email: "Gá»i thÆ° má»i" - dont_have_now: "Bạn đã hết lượt má»i, nhÆ°ng sẽ có thêm nữa!" - from_facebook: "Facebook" - invitations_left: "Còn lại %{count}" - invite_someone: "Má»i và i ngÆ°á»i" invite_your_friends: "Má»i bạn" invites: "Má»i" - invites_closed: "Pod DIASPORA nà y không còn thÆ° má»i nữa" share_this: "Chia sẻ liên kết nà y qua thÆ°, blog, hay mạng xã há»™i!" - notification: - new: "%{type} má»›i từ %{from}" public_explain: atom_feed: "Nguồn tin" control_your_audience: "Kiểm soát phạm vi chia sẻ" @@ -714,57 +469,27 @@ vi: title: "Cà i đặt các dịch vụ đã được kết nối" visibility_dropdown: "Dùng nút thả xuống nà y để ẩn/hiện bà i đăng của bạn. (Bạn nên công khai bà i đăng đầu tiên.)" publisher: - all: "tất cả" - all_contacts: "tất cả liên lạc" discard_post: "Huá»· bà i đăng" get_location: "Lấy thông tin vị trÃ" - make_public: "công khai hoá" new_user_prefill: hello: "Xin chà o má»i ngÆ°á»i,\n\ %{new_user_tag}. " i_like: "I'm interested in %{tags}." invited_by: "Cám Æ¡n vì lá»i má»i, " newhere: "NewHere" - post_a_message_to: "Gá»i tin nhắn đến %{aspect}" posting: "Äăng bà i..." - preview: "Xem trÆ°á»›c" - publishing_to: "chia sẻ vá»›i: " share: "Chia sẻ" - share_with: "chia sẻ vá»›i" upload_photos: "Tải ảnh lên" whats_on_your_mind: "Bạn Ä‘ang nghÄ© gì?" - reshare: - reshare: "Chia sẻ lại" stream_element: - connect_to_comment: "Kết nối đến ngÆ°á»i dùng nà y để bình luáºn trong bà i đăng của há»" - currently_unavailable: "hiện không bình luáºn được" - dislike: "Không thÃch" - hide_and_mute: "Ẩn và tắt bà i đăng" - ignore_user: "Bá» qua %{name}" - ignore_user_description: "Bá» qua và loại bá» ngÆ°á»i dùng từ tất cả mối quan hệ?" - like: "ThÃch" - nsfw: "Bà i đăng được đánh dấu NSFW bởi tác giả. %{link}" - shared_with: "Äã chia sẻ vá»›i: %{aspect_names}" - show: "hiện" - unlike: "Bá» thÃch" via: "thông qua %{link}" via_mobile: "qua di Ä‘á»™ng" - viewable_to_anyone: "Bà i đăng nà y được má»i ngÆ°á»i trên web nhìn thấy" status_messages: create: success: "Äã nhắc đến: %{names}" - destroy: - failure: "Không thể xoá bà i đăng" - helper: - no_message_to_display: "Không có tin nhắn." new: mentioning: "Äang nhắc đến: %{person}" too_long: "{\"other\"=>\"trạng thái của bạn phải có Ãt hÆ¡n %{count} kà tá»±\", \"zero\"=>\"trạng thái của bạn phải có Ãt hÆ¡n %{count} kà tá»±\"}" - stream_helper: - hide_comments: "Ẩn tất cả bình luáºn" - show_comments: - other: "Hiện thêm %{count} bình luáºn" - zero: "Không còn bình luáºn" streams: activity: title: "Hoạt Ä‘á»™ng của tôi" @@ -790,22 +515,11 @@ vi: title: "Hoạt Ä‘á»™ng công khai" tags: title: "Những bà i đăng được gán thẻ: #%{tags}" - tag_followings: - create: - failure: "Theo dõi thất bại: #%{name}" - none: "Bạn không thể theo dõi má»™t thẻ trống!" - success: "Theo dõi thà nh công: #%{name}" - destroy: - failure: "Dừng theo dõi #%{name} thất bại. Có lẽ bạn đã dừng theo dõi rồi?" - success: "Äã dừng theo dõi: #%{name}" tags: show: follow: "Theo dõi #%{tag}" - following: "Äang theo dõi #%{tag}" none: "Thẻ rá»—ng không tồn tại!" stop_following: "Dừng theo dõi #%{tag}" - terms_and_conditions: "Äiá»u khoản và điá»u kiện" - undo: "Hoà n lại?" username: "Tên ngÆ°á»i dùng" users: confirm_email: @@ -826,7 +540,6 @@ vi: character_minimum_expl: "Ãt nhất sáu kà tá»±" close_account: dont_go: "Äừng Ä‘i!" - if_you_want_this: "Nếu bạn muốn, nháºp máºt khẩu và nhấn 'Äóng tà i khoản'" lock_username: "Tên đăng nháºp của bạn sẽ bị khoá nếu bạn quyết định đăng kà lại." locked_out: "Bạn sẽ bị đăng xuất và khoá tà i khoản." make_diaspora_better: "Chúng tôi muốn bạn cùng phát triển Diaspora tốt hÆ¡n, vì váºy bạn nên giúp đỡ thay vì rá»i Ä‘i. Nếu bạn không muốn ở lại, chúng tôi muốn biết chuyện gì sẽ xảy ra tiếp theo." @@ -837,12 +550,10 @@ vi: comment_on_post: "...có ngÆ°á»i bình luáºn và o bà i đăng của tôi?" current_password: "Máºt khẩu hiện tại" current_password_expl: "bạn dùng để đăng nháºp..." - download_photos: "ảnh chụp của tôi" edit_account: "Chỉnh sá»a tà i khoản" email_awaiting_confirmation: "Chúng tôi đã gá»i Ä‘Æ°á»ng dẫn kÃch hoạt đến %{unconfirmed_email}. Chúng tôi vẫn dùng địa chỉ gốc của bạn %{email} cho đến khi bạn xác nháºn địa chỉ má»›i." export_data: "Xuất dữ liệu" following: "Thiết láºp theo dõi" - getting_started: "Tuỳ chỉnh ngÆ°á»i dùng má»›i" liked: "...có ngÆ°á»i thÃch bà i đăng của tôi?" mentioned: "...tôi được nhắc đến trong má»™t bà i đăng?" new_password: "Máºt khẩu má»›i" @@ -861,7 +572,6 @@ vi: connect_to_facebook_link: "Liên kết vá»›i tà i khoản Facebook của bạn" hashtag_explanation: "Thẻ cho phép bạn trò chuyện và theo dõi những gì bạn quan tâm. Chúng cÅ©ng giúp bạn tìm bạn má»›i trên Diaspora." hashtag_suggestions: "Thá» theo dõi các thẻ nhÆ° #art, #movies, #gif, v.v..." - saved: "Äã lÆ°u!" well_hello_there: "Chà o bạn!" what_are_you_in_to: "Bạn Ä‘ang ở đâu?" who_are_you: "Bạn là ai?" @@ -883,11 +593,6 @@ vi: settings_updated: "Äã cáºp nháºt thiết láºp" unconfirmed_email_changed: "Äã đổi địa chỉ thÆ° Ä‘iện tá». Cần kÃch hoạt ngay." unconfirmed_email_not_changed: "Äổi địa chỉ thÆ° Ä‘iện tá» thất bại" - webfinger: - hcard_fetch_failed: "có vấn Ä‘á» khi tải hcard cho %{account}" - no_person_constructed: "Không Ä‘á»c được thông tin từ hcard nà y." - xrd_fetch_failed: "có lá»—i khi lấy xrd từ tà i khoản %{account}" - welcome: "Chà o mừng!" will_paginate: next_label: "sau »" previous_label: "« trÆ°á»›c" \ No newline at end of file diff --git a/config/locales/diaspora/wo.yml b/config/locales/diaspora/wo.yml index 1fff3b1e274bc9a577f0dbee41b77f9fe92019ce..20f4ee3714de203379a424a8ee0373c2d58adb9a 100644 --- a/config/locales/diaspora/wo.yml +++ b/config/locales/diaspora/wo.yml @@ -5,8 +5,6 @@ wo: - _home: "Kër gi" - _photos: "nataal" admins: admin_bar: pages: "Xët yi" @@ -16,16 +14,10 @@ wo: month: "Weer" week: "Ayubés" aspects: - aspect_listings: - edit_aspect: "Soppil %{name}" index: - diaspora_id: - content_1: "Sa Limu Diaspora mooy:" - heading: "Limu Diaspora" help: any_problem: "Am Nga Jafejafe?" do_you: "Danga" - email_link: "Email" find_a_bug: "... fekk %{link}?" have_a_question: "... am %{link}?" here_to_help: "Mbooloo mu Diaspora fii nekk!" @@ -34,13 +26,11 @@ wo: new_here: follow: "Toppal ci %{link} te wax dalal-jà mm ci jëfandikukat yu bees ci Diaspora*!" title: "Dalal-jà mm Jëfandikukat yu Bees" - people_sharing_with_you: "Nit ñu bokk ak yow" welcome_to_diaspora: "Dalal-jà mm ci Diaspora, %{name}!" seed: family: "Waakër" friends: "Xarit" work: "Ligéey" - back: "Dellu" blocks: destroy: success: "Ayca nu gis liñu wax! #nuyu" @@ -53,22 +43,17 @@ wo: new: to: "ci" email: "Email" - hide: "Nëbbal" invitations: a_facebook_user: "Facebooku jëfandikukat" new: language: "Là kk" - to: "Ci" layouts: application: whats_new: "lu bees?" header: - login: "xammeeku" logout: "Génnu" profile: "Xibaar yu la Ñeel" settings: "Tà nneef" - view_all: "Xoolal yëpp" - next: "bi di ñëw" notifications: index: and: "ak" @@ -79,42 +64,16 @@ wo: view_profile: "Xoolal xibaar yu %{name} ñeel" thanks: "Jërëjëf," ok: "Ayca" - or: "walla" - password: "Baatujà ll" people: - one: "1 nit" - other: "%{count}i nit" person: thats_you: "Yow la!" profile_sidebar: born: "besu judd" - edit_my_profile: "Soppil xibaar yu ma ñeel" location: "dëkk" - show: - see_all: "Gisal ñëpp" - sub_header: - edit: "soppil" - photos: - comment_email_subject: "Nataalu %{name}" - edit: - editing: "Coppite" - new: - back_to_list: "Ca Liim Ba" - new_photo: "Nataal Bu Bees" - photo: - view_all: "xoolal yëpp nataali %{name}" - show: - edit: "soppil" - posts: - show: - permalink: "lëkkalekaay yu fi nekkandi" - previous: "bi weesu" privacy: "Mbóot" - privacy_policy: "Politigu Mbóot" profile: "Xibaar yu la Ñeel" profiles: edit: - edit_profile: "Soppil xibaar yu la ñeel" first_name: "Tur bi" last_name: "Sant wi" your_birthday: "Sa besu judd" @@ -123,9 +82,6 @@ wo: your_photo: "Sa nataal" your_tags_placeholder: "ni #film #muus #tukki #jà ngalekat #newyork" registrations: - edit: - edit: "Soppi %{name}" - unhappy: "Kontaanul?" new: email: "EMAIL" enter_email: "Duggal email" @@ -135,29 +91,17 @@ wo: search: "Seetal" settings: "Tà nneef" shared: - add_contact: - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "Duggal turu jëfandikukatu Diaspora" - your_diaspora_username_is: "Sa turu jëfandikukat ci Diaspora: %{diaspora_handle} la" invitations: by_email: "Ci email" public_explain: logged_in: "Danga xammeeku ci %{service}" share: "Bokkal" publisher: - all: "yëpp" new_user_prefill: hello: "Na ngeen def? %{new_user_tag}. " newhere: "BeesNaaFii" whats_on_your_mind: "Lu bees?" - reshare: - reshare: "Bokkaat" stream_element: - dislike: "Bëggul" - like: "Bëgg" - shared_with: "Dafa bokk ak: %{aspect_names}" - show: "wonel" - unlike: "Du bëgg" via: "cib %{link}" streams: followed_tag: @@ -169,7 +113,6 @@ wo: tags: show: follow: "Toppal #%{tag}" - following: "Dangay topp #%{tag}" stop_following: "Bul Topp #%{tag}" username: "Turu Jëfandikukat" users: @@ -181,14 +124,12 @@ wo: current_password: "Baatujà ll bi fi nekk" current_password_expl: "bi xammeeku ak..." following: "Tà nneefi Topp" - getting_started: "Tà nneefi Jëfandikukat bu Bees" new_password: "Baatujà ll bu bees" stream_preferences: "Tà nneefi Seyaan" your_email: "Sa email" your_handle: "Sa limu Diaspora" getting_started: awesome_take_me_to_diaspora: "Baax na! Indi ma ci Diaspora*" - saved: "Denc na!" well_hello_there: "Asalaamu aleykum! Na nga def?" what_are_you_in_to: "Loo bëgg?" who_are_you: "Kan nga?" @@ -196,5 +137,4 @@ wo: title: "Tà nneefi Mbóot" update: language_changed: "Là kk dafa soppi" - password_changed: "Baatujà ll dafa soppi. Léegi danga mën xammeeku ak sa baatujà ll bu bees." - welcome: "Dalal-jà mm!" \ No newline at end of file + password_changed: "Baatujà ll dafa soppi. Léegi danga mën xammeeku ak sa baatujà ll bu bees." \ No newline at end of file diff --git a/config/locales/diaspora/yi.yml b/config/locales/diaspora/yi.yml index e00eeb14f9248b39684061f118ced7581d6e1f81..0c8ad3a5469c42f3e16a2f8d90dccce790a121fe 100644 --- a/config/locales/diaspora/yi.yml +++ b/config/locales/diaspora/yi.yml @@ -6,7 +6,6 @@ yi: _help: "העלף" - _home: "×”×™×™×" activerecord: errors: models: @@ -22,20 +21,17 @@ yi: daily: "טעגלעך" month: "חודש" week: "וו×ָך" - ago: "%{time} צוריק" aspects: aspect_stream: make_something: "מ×ַך עפּעס" index: help: do_you: "טוסטו:" - email_link: "בליצפּ×ָסט" tag_question: "פֿר×Ö·×’×¢" seed: family: "משפּחה" friends: "חבֿרי×" work: "×ַרבעט" - back: "צוריק" cancel: "×Ö·× ×•×œ×™×¨" conversations: new: @@ -53,35 +49,21 @@ yi: invitations: new: language: "לשון" - to: "צו" - layouts: - header: - blog: "קוועטשל" - help: "העלף" - view_all: "×–×¢ ×ַלט" more: "מער" notifier: hello: "שלומ ×¢×œ×™×›× %{name}!" thanks: "×Ö· ד×Ö·× ×§," ok: "גוט" - or: "×ָדער" profiles: edit: your_name: "דײַן × ×ָמען" registrations: new: email: "בליצפּ×ָסט" - requests: - new_request_to_person: - sent: "געשיקט!" search: "זוך" shared: - contact_list: - all_contacts: "×ַלע ק×Ö¸× ×˜×ַקטן" invitations: by_email: "מיט בליצפּ×ָסט" - undo: "×ויפֿמ×ַכן?" users: getting_started: - who_are_you: "וווּ ביסטו?" - welcome: "×©×œ×•× ×¢×œ×™×›×!" \ No newline at end of file + who_are_you: "וווּ ביסטו?" \ No newline at end of file diff --git a/config/locales/diaspora/zh-CN.yml b/config/locales/diaspora/zh-CN.yml index db064804c721ebab9bb5a413e5444f92d4c4edda..00266f409d3e25997c52a403e24739afea62b31c 100644 --- a/config/locales/diaspora/zh-CN.yml +++ b/config/locales/diaspora/zh-CN.yml @@ -6,10 +6,7 @@ zh-CN: _applications: "应用" - _comments: "评论" _contacts: "好å‹" - _home: "首页" - _photos: "照片" _services: "æœåŠ¡" account: "å¸å·" activerecord: @@ -82,13 +79,7 @@ zh-CN: other: "本周新用户数目:%{count}" zero: "本周新用户数目:0" current_server: "æœåŠ¡å™¨å½“å‰æ—¥æœŸï¼š%{date}" - ago: "%{time} å‰" all_aspects: "所有分组" - application: - helper: - unknown_person: "未知用户" - video_title: - unknown: "æœªçŸ¥å½±ç‰‡æ ‡é¢˜" are_you_sure: "您确定å—?" are_you_sure_delete_account: "您真的确定è¦å…³é—您的å¸å·å—? æ¤æ“作ä¸å¯æ’¤é”€ã€‚" aspect_memberships: @@ -102,18 +93,10 @@ zh-CN: success: "将好å‹æ·»åŠ 到分组æˆåŠŸã€‚" aspect_listings: add_an_aspect: "+ 新增分组" - deselect_all: "清空选择" - edit_aspect: "编辑 %{name}" - select_all: "全选" aspect_stream: make_something: "åšç‚¹ä»€ä¹ˆ" stay_updated: "éšæ—¶æ›´æ–°" stay_updated_explanation: "您的主动æ€ä¼šå……满您的好å‹ï¼Œæ‚¨å…³æ³¨çš„æ ‡ç¾ï¼Œå’Œæœ‰è¶£çš„群的内容。" - contacts_not_visible: "æ¤åˆ†ç»„ä¸çš„好å‹ç›¸äº’ä¸å¯è§ã€‚" - contacts_visible: "æ¤åˆ†ç»„ä¸çš„好å‹ç›¸äº’å¯è§ã€‚" - create: - failure: "æ·»åŠ åˆ†ç»„å¤±è´¥ã€‚" - success: "æ·»åŠ æ–°åˆ†ç»„ %{name} æˆåŠŸ" destroy: failure: "æ— æ³•åˆ é™¤ %{name} ,它ä¸æ˜¯ç©ºçš„。" success: "åˆ é™¤ %{name} æˆåŠŸã€‚" @@ -121,22 +104,13 @@ zh-CN: aspect_list_is_not_visible: "分组ä¸çš„好å‹ä¸èƒ½çœ‹è§æ¤åˆ†ç»„的好å‹åˆ—表" aspect_list_is_visible: "分组ä¸çš„好å‹èƒ½å¤Ÿçœ‹è§æ¤åˆ†ç»„的好å‹åˆ—表" confirm_remove_aspect: "您确定è¦åˆ 除这个分组?" - make_aspect_list_visible: "是å¦è®©å…¶ä»–人å¯ä»¥çœ‹è§æ¤åˆ†ç»„的好å‹åˆ—表?" - remove_aspect: "åˆ é™¤è¿™ä¸ªåˆ†ç»„" rename: "é‡å‘½å" update: "æ›´æ–°" updating: "æ›´æ–°ä¸" index: - diaspora_id: - content_1: "您的 Diaspora 通行è¯æ˜¯ï¼š" - content_2: "把它告诉其他人,让他们å¯ä»¥åœ¨ Diaspora 找到您。" - heading: "Diaspora 通行è¯" donate: "æ助" - handle_explanation: "这是您的 Diaspora å¸å·ï¼Œ å°±åƒæ˜¯é‚®ç®±ä¸€æ ·ï¼Œæ‚¨å¯ä»¥æŠŠå®ƒæä¾›ç»™æƒ³æ·»åŠ æ‚¨ä¸ºå¥½å‹çš„人。" help: do_you: "您是å¦ï¼š" - email_feedback: "也å¯ä»¥æ¥ %{link} å‘表您的æ„è§" - email_link: "寄信" feature_suggestion: "...想建议 %{link}?" find_a_bug: "...æ‰¾åˆ°ä¸€åª %{link}?" have_a_question: "...有 %{link} ?" @@ -146,31 +120,20 @@ zh-CN: tag_feature: "#特色" tag_question: "#问题" introduce_yourself: "这是您的动æ€ã€‚介ç»ä¸€ä¸‹è‡ªå·±å§ï¼" - keep_diaspora_running: "æ¯æœˆæèµ è®© Diaspora å¼€å‘更快速ï¼" keep_pod_running: "让 %{pod} 高速è¿è½¬ï¼Œéœ€è¦æ‚¨çš„æ¯æœˆæ助,供应æœåŠ¡å™¨çš„耗æï¼" new_here: follow: "关注 %{link} 。欢迎新用户ï¼" learn_more: "了解更多" title: "欢迎新用户ï¼" - no_contacts: "å°šæœªæ·»åŠ å¥½å‹" - no_tags: "+ å¯»æ‰¾å¹¶å…³æ³¨ä¸€ä¸ªæ ‡ç¾" - people_sharing_with_you: "与您分享的人" - post_a_message: "å‘布站内信>>" services: content: "您å¯ä»¥å°†ä»¥ä¸‹æœåŠ¡è¿žæŽ¥è‡³ Diaspora:" heading: "连接æœåŠ¡" - unfollow_tag: "å–消关注 #%{tag}" welcome_to_diaspora: "%{name}ï¼Œæ¬¢è¿ŽåŠ å…¥ Diaspora!" - new: - create: "创建" - name: "åå—" no_contacts_message: community_spotlight: "社区çƒç‚¹" or_spotlight: "或者您也å¯ä»¥å’Œ %{link} 分享内容" try_adding_some_more_contacts: "您å¯ä»¥åœ¨é¡¶ç«¯æœç´¢ï¼Œæˆ–者在å³ä¾§é‚€è¯·æ›´å¤šå¥½å‹ã€‚" you_should_add_some_more_contacts: "æ·»åŠ æ›´å¤šå¥½å‹ï¼" - no_posts_message: - start_talking: "还没人å‘布过内容。您å‘布第一æ¡å§ï¼" seed: acquaintances: "熟人" family: "家人" @@ -179,7 +142,6 @@ zh-CN: update: failure: "分组 %{name} å称太长了,ä¸èƒ½ä¿å˜" success: "分组 %{name} 编辑æˆåŠŸã€‚" - back: "åŽé€€" blocks: create: failure: "æ— æ³•å¿½ç•¥ç”¨æˆ·ã€‚#借å£" @@ -191,21 +153,14 @@ zh-CN: explanation: "收è—<a href='%{link}'>这个链接</a>,å³å¯éšæ—¶å‘布新内容" heading: "Diaspora 收è—夹" post_something: "å‘布新内容到 Diaspora" - post_success: "å‘布完æˆï¼å…³é—ä¸ã€‚" cancel: "å–消" comments: new_comment: comment: "回å¤" commenting: "回å¤ä¸â€¦â€¦" - one: "1æ¡å›žå¤" - other: "%{count} æ¡å›žå¤" - zero: "æš‚æ— å›žå¤" contacts: - create: - failure: "æ·»åŠ å¥½å‹å¤±è´¥" index: add_a_new_aspect: "åŠ å…¥æ–°åˆ†ç»„" - add_to_aspect: "将好å‹æ·»åŠ 到 %{name}" all_contacts: "所有好å‹" community_spotlight: "社区çƒç‚¹" my_contacts: "我的好å‹" @@ -214,25 +169,16 @@ zh-CN: only_sharing_with_me: "和我分享内容的人" start_a_conversation: "开始对è¯" title: "好å‹" - your_contacts: "您的好å‹" - sharing: - people_sharing: "与您分享的人:" spotlight: community_spotlight: "社区çƒç‚¹" conversations: create: fail: "æ— æ•ˆçš„ä¿¡æ¯" sent: "消æ¯å‘é€æˆåŠŸ" - helper: - new_messages: - other: "%{count} æ¡æ–°æ¶ˆæ¯" - zero: "æš‚æ— æ–°æ¶ˆæ¯" index: inbox: "收件箱" - no_conversation_selected: "未选择任何对è¯" no_messages: "没消æ¯" new: - abandon_changes: "放弃当å‰ä¿®æ”¹ï¼Ÿ" send: "å‘é€" sending: "å‘é€ä¸..." subject: "主题" @@ -251,46 +197,26 @@ zh-CN: error_messages: helper: correct_the_following_errors_and_try_again: "ä¿®æ£ä»¥ä¸‹é”™è¯¯åŽé‡è¯•ã€‚" - invalid_fields: "æ— æ•ˆæ ç›®" - login_try_again: "请<a href='%{login_link}'>登入</a>åŽé‡è¯•" - post_not_public: "您查看的内容没有公开" fill_me_out: "补全信æ¯" find_people: "找人或#æ ‡ç¾" - hide: "éšè—" - invitation_codes: - excited: "%{name} 很高兴è§åˆ°æ‚¨ã€‚" invitations: a_facebook_user: "Facebook 用户" check_token: not_found: "找ä¸åˆ°è¯¥é‚€è¯·ç " create: - already_contacts: "您已ç»å°†å…¶åŠ 为好å‹äº†" - already_sent: "您已ç»é‚€è¯·è¿‡è¿™ä¸ªäººäº†ã€‚" empty: "请至少填写一个邮箱" no_more: "æ‚¨æš‚æ— é‚€è¯·å‡½ã€‚" - own_address: "您ä¸èƒ½å‘é€é‚€è¯·ç»™è‡ªå·±ã€‚" rejected: "下列电å信箱有问题: " sent: "邀请函已ç»å¯„ç»™: " - edit: - accept_your_invitation: "接å—邀请" - your_account_awaits: "您的å¸å·åœ¨ç‰å¾…您ï¼" new: - already_invited: "已邀请过" - aspect: "分组" - check_out_diaspora: "æ¥ Diaspora 看看å§ï¼" codes_left: other: "还å¯ä»¥é‚€è¯· %{count} 人" zero: "您已没有邀请函" comma_separated_plz: "å¯ä»¥é€šè¿‡é€—å·åˆ†å‰²è¾“入多个电å邮箱" - if_they_accept_info: "如果他们接å—ï¼Œå°±ä¼šè‡ªåŠ¨è¢«åŠ å…¥åˆ°æ‚¨æ‰€é‚€è¯·çš„åˆ†ç»„ä¸ã€‚" invite_someone_to_join: "邀请好å‹åŠ å…¥ Diasporaï¼" language: "è¯è¨€" paste_link: "将这个链接分享给您的朋å‹ï¼Œé‚€è¯·ä»–ä»¬åŠ å…¥ Diaspora*,或者直接用电å邮件å‘é€ç»™ä»–们。" - personal_message: "个人信æ¯" - resend: "é‡å¯„" send_an_invitation: "å‘é€é‚€è¯·å‡½" - send_invitation: "å‘é€é‚€è¯·å‡½" - to: "收件人" layouts: application: back_to_top: "回到上é¢" @@ -299,31 +225,13 @@ zh-CN: source_package: "下载æºä»£ç 包" toggle: "切æ¢åˆ°æ‰‹æœºç‰ˆ" whats_new: "有什么新鲜事?" - your_aspects: "您的分组" header: - admin: "管ç†å‘˜" - blog: "åšå®¢" code: "æºç " - login: "登录" logout: "登出" profile: "个人档案" - recent_notifications: "新通知" settings: "设置" - view_all: "查看所有" - likes: - likes: - people_dislike_this: - other: "%{count} 个差" - zero: "æš‚æ— å·®" - people_like_this: - other: "%{count} 个赞" - zero: "æš‚æ— èµž" - people_like_this_comment: - other: "%{count} 个赞" - zero: "æš‚æ— èµž" limited: "é™åˆ¶" more: "更多" - next: "下一æ¥" no_results: "没有找到符åˆæ¡ä»¶çš„内容" notifications: also_commented: @@ -335,10 +243,6 @@ zh-CN: comment_on_post: other: "%{actors} 回å¤äº†æ‚¨çš„ %{post_link}。" zero: "%{actors} 回å¤äº†æ‚¨çš„ %{post_link}。" - helper: - new_notifications: - other: "%{count} 个新消æ¯" - zero: "æš‚æ— æ–°æ¶ˆæ¯" index: and: "å’Œ" and_others: @@ -374,7 +278,6 @@ zh-CN: zero: "%{actors} 开始与您分享内容。" notifier: a_post_you_shared: "一篇内容。" - accept_invite: "æŽ¥å— Diaspora* 的邀请å§ï¼" click_here: "点这里" comment_on_post: reply: "回å¤æˆ–查看 %{name} 的内容" @@ -403,7 +306,6 @@ zh-CN: liked: "%{name} 刚赞了您å‘布的内容:" view_post: "查看内容 >" mentioned: - mentioned: "在 Diaspora* å‘布的内容ä¸æ到了您:" subject: "%{name} 在 Diaspora* 上å‘布的内容ä¸æ到了您" private_message: reply_to_or_view: "回å¤æˆ–æŸ¥çœ‹å¯¹è¯ >" @@ -421,115 +323,54 @@ zh-CN: to_change_your_notification_settings: "æ¥ä¿®æ”¹æ¶ˆæ¯é€šçŸ¥çš„设置" nsfw: "NSFW(工作ä¸å®œ)" ok: "确定" - or: "或" - password: "密ç " - password_confirmation: "密ç 确认" people: add_contact: invited_by: "邀请您的用户" - add_contact_small: - add_contact_from_tag: "é€šè¿‡æ ‡ç¾æ·»åŠ 好å‹" - aspect_list: - edit_membership: "编辑所属分组" - helper: - results_for: " %{params} çš„æœç´¢ç»“æžœ" index: looking_for: "åœ¨æ‰¾æ ‡è®°ä¸º %{tag_link} 的内容å—?" no_one_found: "找ä¸åˆ°ç›¸å…³å†…容。" no_results: "å˜¿ï¼ æœç´¢å¿…é¡»è¦æœ‰ç›®æ ‡å‘€ã€‚" results_for: "æœç´¢ç»“果:" searching: "æœç´¢ä¸ï¼Œè¯·ç¨å€™â€¦" - one: "1 个好å‹" - other: "%{count} 个好å‹" person: - add_contact: "åŠ ä¸ºå¥½å‹" - already_connected: "å·²åŠ ä¸ºå¥½å‹" - pending_request: "请求ç‰å€™ä¸" thats_you: "这是您自己ï¼" profile_sidebar: bio: "自我介ç»" born: "生日" - edit_my_profile: "编辑我的个人档案" gender: "性别" - in_aspects: "所属分组" location: "ä½ç½®" - remove_contact: "解除好å‹å…³ç³»" - remove_from: "è¦ä»Ž %{aspect} åˆ é™¤ %{name} å—?" show: closed_account: "æ¤å¸å·å·²ç»å…³é—" does_not_exist: "好å‹ä¸å˜åœ¨ï¼" has_not_shared_with_you_yet: "%{name} 暂未和您分享内容ï¼" - ignoring: "您忽略了 %{name} 的所有内容" - incoming_request: "%{name} 希望能与您分享" - mention: "æåŠ" - message: "消æ¯" - not_connected: "您没有与他分享内容" - recent_posts: "最近的内容" - recent_public_posts: "最近的公开内容" - return_to_aspects: "回到您的分组主页" - see_all: "查看全部" - start_sharing: "开始分享" - to_accept_or_ignore: "接å—或忽略它。" - sub_header: - add_some: "åŠ å…¥ä¸€äº›" - edit: "编辑" - you_have_no_tags: "æ‚¨æ²¡æœ‰ä»»ä½•æ ‡ç¾ï¼" - webfinger: - fail: "抱æ‰ï¼Œæ‰¾ä¸åˆ° %{handle}。" - zero: "æš‚æ— å¥½å‹" photos: - comment_email_subject: "%{name} 的相片" create: integrity_error: "ç…§ç‰‡ä¸Šä¼ å¤±è´¥ã€‚æ‚¨ç¡®å®šå®ƒæ˜¯å›¾ç‰‡å—?" runtime_error: "ç…§ç‰‡ä¸Šä¼ å¤±è´¥ã€‚æ‚¨ç¡®å®šæœ‰æ‰£å®‰å…¨å¸¦å—?" type_error: "ç…§ç‰‡ä¸Šä¼ å¤±è´¥ã€‚æ‚¨ç¡®å®šæœ‰é€‰æ‹©ä»»ä½•å›¾ç‰‡å—?" destroy: notice: "ç…§ç‰‡åˆ é™¤æˆåŠŸã€‚" - edit: - editing: "编辑ä¸" - new: - back_to_list: "回列表" - new_photo: "新照片" - post_it: "å‘布ï¼" new_photo: empty: "文件 {file} 是空的,请é‡æ–°é€‰æ‹©æ–‡ä»¶ï¼Œå¹¶ä¸”ä¸è¦é€‰ä¸å®ƒã€‚" invalid_ext: "ä¸æ”¯æŒæ–‡ä»¶ {file} çš„æ ¼å¼ã€‚åªæŽ¥å— {extensions}。" size_error: "文件 {file} 太大了,上é™æ˜¯ {sizeLimit}。" new_profile_photo: - or_select_one_existing: "或从您现有的 %{photos} ä¸æŒ‘é€‰ä¸€å¼ " upload: "ä¸Šä¼ æ–°çš„å¤´åƒï¼" - photo: - view_all: "查看 %{name} 所有的照片" show: - collection_permalink: "相册的永久链接" - delete_photo: "åˆ é™¤ç…§ç‰‡" - edit: "编辑" - edit_delete_photo: "编辑照片æè¿°æˆ–åˆ é™¤ç…§ç‰‡" - make_profile_photo: "选为个人头åƒ" show_original_post: "显示原文" - update_photo: "更新照片" - update: - error: "照片更新失败。" - notice: "照片更新æˆåŠŸã€‚" posts: presenter: title: "æ¥è‡ª %{name} 的内容" show: - destroy: "åˆ é™¤" - not_found: "抱æ‰ï¼Œæ‰¾ä¸åˆ°è¯¥å†…容。" - permalink: "永久连接" photos_by: other: "%{author} çš„ %{count} å¼ ç…§ç‰‡" zero: "æš‚æ— æ¥è‡ª %{author} 的照片" reshare_by: "%{author} 转å‘" - previous: "上一æ¥" privacy: "éšç§" - privacy_policy: "éšç§æ”¿ç–" profile: "个人档案" profiles: edit: allow_search: "å…许别人在 Diaspora* ä¸æœç´¢åˆ°æ‚¨" - edit_profile: "编辑个人档案" first_name: "å" last_name: "姓" update_profile: "更新个人档案" @@ -539,8 +380,6 @@ zh-CN: your_location: "您的ä½ç½®" your_name: "您的åå—" your_photo: "您的照片" - your_private_profile: "您的ç§äººæ¡£æ¡ˆ" - your_public_profile: "您的公开档案" your_tags: "用五个#æ ‡ç¾ æ述您自己" your_tags_placeholder: "比如 #diaspora #çƒ«å‘ #猫咪 #音ä¹" update: @@ -554,57 +393,23 @@ zh-CN: closed: "æ¤ Diaspora pod ä¸å¼€æ”¾æ³¨å†Œã€‚" create: success: "您已æˆåŠŸåŠ å…¥ Diaspora 了ï¼" - edit: - cancel_my_account: "å…³é—我的å¸å·" - edit: "编辑 %{name}" - leave_blank: "(ä¸æƒ³ä¿®æ”¹è¯·ç•™ç©º)" - password_to_confirm: "(我们需è¦æ‚¨çŽ°åœ¨çš„密ç 以确认您è¦ä¿®æ”¹)" - unhappy: "ä¸æ»¡æ„?" - update: "æ›´æ–°" invalid_invite: "您æ供的邀请链接已失效" new: - create_my_account: "创建我的å¸å·" email: "电å邮箱" enter_email: "输入电å邮箱" enter_password: "输入密ç (至少6个å—符)" enter_password_again: "å†è¾“入一é密ç " enter_username: "输入用户å(å称åªèƒ½åŒ…å«å—æ¯ï¼Œæ•°å—和下划线“_â€)" - join_the_movement: "å‚åŠ æ¤è¡ŒåŠ¨" password: "密ç " password_confirmation: "密ä¿ä¿¡æ¯" sign_up: "注册" - sign_up_message: "有 <3 的社交网络" username: "用户å" - requests: - create: - sending: "å‘é€ä¸" - sent: "您已ç»è¯·æ±‚与 %{name} 分享内容。他们下次登入 Diaspora 时就会看è§æ‚¨çš„请求。" - destroy: - error: "请选择一个分组ï¼" - ignore: "忽略建立好å‹çš„请求。" - success: "ä½ ä»¬çŽ°åœ¨äº’ç›¸åˆ†äº«äº†ã€‚" - helper: - new_requests: - other: "%{count}个新请求ï¼" - zero: "æš‚æ— æ–°è¯·æ±‚" - manage_aspect_contacts: - existing: "当å‰å¥½å‹" - manage_within: "管ç†å¥½å‹ï¼š" - new_request_to_person: - sent: "å‘é€æˆåŠŸï¼" reshares: comment_email_subject: "%{resharer} 转å‘了 %{author} 的内容" - create: - failure: "转å‘时错误" reshare: deleted: "åŽŸå†…å®¹å·²è¢«ä½œè€…åˆ é™¤" - reshare: - other: "%{count}个转å‘" - zero: "转å‘" reshare_confirmation: "您è¦è½¬å‘ %{author} 的内容å—?" - reshare_original: "转å‘原文" reshared_via: "转å‘自" - show_original: "显示原文" search: "æœç´¢" services: create: @@ -615,57 +420,22 @@ zh-CN: success: "验è¯åˆ 除æˆåŠŸã€‚" failure: error: "与该æœåŠ¡è¿žæŽ¥æ—¶æœ‰é”™è¯¯" - finder: - fetching_contacts: "Diaspora æ£åœ¨èŽ·å–您在 %{service} 的好å‹åˆ—è¡¨ï¼Œè¯·å‡ åˆ†é’ŸåŽå†æ¥æŸ¥çœ‹ã€‚" - no_friends: "没有 Facebook 好å‹" - service_friends: "%{service} 好å‹" index: disconnect: "æ–开连接" edit_services: "编辑æœåŠ¡" logged_in_as: "登录为" really_disconnect: "切æ–与 %{service} 的连接?" - inviter: - click_link_to_accept_invitation: "点击这个链接以接å—邀请" - join_me_on_diaspora: "è·Ÿæˆ‘ä¸€èµ·åŠ å…¥ DIASPORA*" - remote_friend: - invite: "邀请" - not_on_diaspora: "ä¸åœ¨ Diaspora ä¸" - resend: "é‡æ–°å‘é€" settings: "设置" - share_visibilites: - update: - post_hidden_and_muted: "%{name} 的内容已ç»éšè—,也ä¸ä¼šå‡ºçŽ°å’Œå…¶ç›¸å…³çš„通知。" - see_it_on_their_profile: "如果您希望看到æ¤å†…容的更新,请查看 %{name} 的个人页é¢ã€‚" shared: - add_contact: - add_new_contact: "åŠ å…¥æ–°å¥½å‹" - create_request: "通过 Diaspora å¸å·æœç´¢" - diaspora_handle: "diaspora@handle.org" - enter_a_diaspora_username: "输入 Diaspora å¸å·ï¼š" - know_email: "知é“他们的电åä¿¡ç®±å—? 您å¯ä»¥é‚€è¯·ä»–ä»¬åŠ å…¥ã€‚" - your_diaspora_username_is: "您的 Diaspora å¸å·æ˜¯: %{diaspora_handle}" aspect_dropdown: - add_to_aspect: "æ·»åŠ åˆ°åˆ†ç»„" toggle: other: "在 %{count} 个分组ä¸" zero: "æ·»åŠ åˆ°åˆ†ç»„" - contact_list: - all_contacts: "全部好å‹" - footer: - logged_in_as: "已用 %{name} 登录" - your_aspects: "您的分组" invitations: by_email: "通过电å邮件" - dont_have_now: "ç›®å‰æ‚¨è¿˜ä¸èƒ½é‚€è¯·ä»»ä½•äººï¼Œä½†å¾ˆå¿«å°±å¯ä»¥äº†ï¼" - from_facebook: "从 Facebook" - invitations_left: "(剩余 %{count} å¼ )" - invite_someone: "邀请别人" invite_your_friends: "邀请您的好å‹" invites: "邀请" - invites_closed: "ç›®å‰æ¤ Diaspora pod ä¸å¼€æ”¾é‚€è¯·åŠŸèƒ½" share_this: "用这个链接æ¥åˆ†äº«åœ¨ç”µå邮件,åšå®¢æˆ–其他您喜爱的社交网络上ï¼" - notification: - new: "%{from} 有新的 %{type}" public_explain: atom_feed: "Atom 订阅" control_your_audience: "控制您的å¬ä¼—" @@ -677,54 +447,25 @@ zh-CN: title: "设定连线æœåŠ¡" visibility_dropdown: "用这个下拉èœå•æ¥æ”¹å˜å†…容的å¯è§èŒƒå›´ã€‚ (建议您的第一篇内容为公开)" publisher: - all: "全部" - all_contacts: "全部的好å‹" discard_post: "丢弃内容" - make_public: "公开" new_user_prefill: hello: "大家好,我是 #%{new_user_tag}。 " i_like: "我对 %{tags} 感兴趣。 " invited_by: "谢谢您的邀请, " newhere: "新用户" - post_a_message_to: "在 %{aspect} å‘布信æ¯" posting: "å‘布ä¸â€¦â€¦" - publishing_to: "å‘布至:" share: "分享" - share_with: "与他分享:" upload_photos: "上载照片" whats_on_your_mind: "您想到了什么?" - reshare: - reshare: "é‡æ–°åˆ†äº«" stream_element: - connect_to_comment: "请和作者建立è”系,以对其内容评论" - currently_unavailable: "ç›®å‰æ— 法å‘表评论" - dislike: "å·®" - hide_and_mute: "éšè—" - ignore_user: "忽略 %{name}" - ignore_user_description: "是å¦å¿½ç•¥æ¤ç”¨æˆ·ï¼Œå¹¶å°†å…¶ä»Žæ‰€æœ‰åˆ†ç»„ä¸åˆ 除?" - like: "赞" - nsfw: "è¿™ç¯‡å†…å®¹è¢«ä½œè€…æ ‡è®°ä¸º NSFW(工作ä¸å®œï¼‰ã€‚%{link}" - shared_with: "与 %{aspect_names} 分享" - show: "显示" - unlike: "å·®" via: "通过 %{link}" via_mobile: "通过移动设备" - viewable_to_anyone: "任何互è”网用户都能看到这篇内容" status_messages: create: success: "æˆåŠŸæŽ¨è了: %{names}" - destroy: - failure: "åˆ é™¤å†…å®¹å¤±è´¥" - helper: - no_message_to_display: "æš‚æ— ä¿¡æ¯å¯æ˜¾ç¤ºã€‚" new: mentioning: "æåŠå‘布ä¸: %{person}" too_long: "{\"other\"=>\"请确ä¿æ‚¨çš„状æ€ä¿¡æ¯ä¸è¶…过 %{count} 个å—符\", \"zero\"=>\"请确ä¿æ‚¨çš„状æ€ä¿¡æ¯ä¸è¶…过 %{count} 个å—符\"}" - stream_helper: - hide_comments: "éšè—评论" - show_comments: - other: "还有 %{count} æ¡è¯„论" - zero: "æ— æ›´å¤šè¯„è®º" streams: activity: title: "我的活动" @@ -750,22 +491,11 @@ zh-CN: title: "公开活动" tags: title: "æœ‰ä»¥ä¸‹æ ‡ç¾çš„内容:%{tags}" - tag_followings: - create: - failure: "æ— æ³•å…³æ³¨ #%{name}" - none: "ä¸èƒ½å…³æ³¨ç©ºç™½æ ‡ç¾ï¼" - success: "已关注 #%{name}" - destroy: - failure: "æ— æ³•å–消对 #%{name} 的关注" - success: "å·²ç»å–消对 #%{name} 的关注" tags: show: follow: "关注 #%{tag}" - following: "æ£åœ¨å…³æ³¨ #%{tag}" none: "ä¸å˜åœ¨ç©ºç™½æ ‡ç¾ï¼" stop_following: "åœæ¢å…³æ³¨ #%{tag}" - terms_and_conditions: "æœåŠ¡æ¡æ¬¾ä¸Žç»†åˆ™" - undo: "撤消?" username: "å¸å·" users: confirm_email: @@ -786,7 +516,6 @@ zh-CN: character_minimum_expl: "至少需è¦å…个å—符。" close_account: dont_go: "请ä¸è¦ç¦»å¼€ï¼" - if_you_want_this: "如果您真的希望如æ¤ï¼Œåœ¨ä¸‹é¢è¾“入您的密ç ,然åŽæŒ‰â€œå…³é—å¸å·â€" lock_username: "您的用户å会被é”定,ä¸èƒ½é‡æ–°æ³¨å†Œã€‚" locked_out: "接下æ¥æ‚¨ä¼šè¢«é€€å‡ºï¼Œå¸å·å°†å…³é—。" make_diaspora_better: "希望您能帮助我们让 Diaspora 更好,而ä¸æ˜¯é€‰æ‹©ç¦»å¼€ã€‚如果您åšæŒï¼Œæˆ‘们也希望让您知é“未æ¥çš„å‘展。" @@ -797,12 +526,10 @@ zh-CN: comment_on_post: "…当有人对您的内容å‘表评论时?" current_password: "当å‰å¯†ç " current_password_expl: "登入的那个…" - download_photos: "下载我的照片" edit_account: "编辑å¸å·" email_awaiting_confirmation: "æˆ‘ä»¬å°†å‘ %{unconfirmed_email} å‘é€ä¸€ä¸ªç¡®è®¤é‚®ä»¶ã€‚在确认之å‰ï¼Œæˆ‘们将沿用 %{email} 这个è”系方å¼ã€‚" export_data: "资料导出" following: "关注设置" - getting_started: "新用户设置" liked: "…当有人赞您å‘布的内容?" mentioned: "…当贴文ä¸æ到您时?" new_password: "新密ç " @@ -820,7 +547,6 @@ zh-CN: community_welcome: "Diaspora 社区欢迎您的到æ¥" hashtag_explanation: "æ ‡ç¾è®©æ‚¨å¯ä»¥è®¨è®ºå…³æ³¨æ‚¨çš„兴趣。并且也是在 Diaspora 找到新朋å‹çš„好办法。" hashtag_suggestions: "试试看关注如 #艺术,#电影, #gif ä¹‹ç±»çš„æ ‡ç¾ã€‚" - saved: "å·²ä¿å˜" well_hello_there: "嗨,您好ï¼" what_are_you_in_to: "您对什么有兴趣?" who_are_you: "您是哪ä½ï¼Ÿ" @@ -842,13 +568,6 @@ zh-CN: settings_updated: "设置已更新" unconfirmed_email_changed: "电å邮箱地å€å·²ä¿®æ”¹ï¼Œéœ€è¦æ¿€æ´»ã€‚" unconfirmed_email_not_changed: "电å邮箱地å€ä¿®æ”¹å¤±è´¥" - webfinger: - fetch_failed: "èŽ·å– %{profile_url} çš„ webfinger 个人档案失败" - hcard_fetch_failed: "èŽ·å– %{account} çš„ hcard 资料时å‘生错误" - no_person_constructed: "从这份 hcard èµ„æ–™æ— æ³•ç»„å»ºå‡ºè”络人。" - not_enabled: "%{account} 的主机似乎暂未å¯ç”¨ webfinger" - xrd_fetch_failed: "从 %{account} 这个å¸å·å–å¾— xrd æ—¶å‘生错误" - welcome: "欢迎ï¼" will_paginate: next_label: "åŽé¢ »" previous_label: "« å‰é¢" \ No newline at end of file diff --git a/config/locales/diaspora/zh-TW.yml b/config/locales/diaspora/zh-TW.yml index 80d58b20882d7b530740db7752cdd936ae1574d1..292a4ca6c273dee50a09b80c12426084337617da 100644 --- a/config/locales/diaspora/zh-TW.yml +++ b/config/locales/diaspora/zh-TW.yml @@ -6,11 +6,8 @@ zh-TW: _applications: "應用程å¼" - _comments: "留言" _contacts: "è¯çµ¡äºº" _help: "說明" - _home: "我家" - _photos: "相片" _services: "外部æœå‹™" _statistics: "統計" _terms: "使用æ¢æ¬¾" @@ -49,16 +46,23 @@ zh-TW: person: invalid: "ä¸åˆæ ¼ã€‚" username: - invalid: "ä¸åˆæ ¼ã€‚åªèƒ½å¤ 使用å—æ¯ï¼Œæ•¸å—,以åŠåº•ç·šç¬¦è™Ÿã€‚" + invalid: "ä¸åˆæ ¼ã€‚åªèƒ½å¤ 使用å—æ¯ã€æ•¸å—ã€ä»¥åŠåº•ç·šç¬¦è™Ÿã€‚" taken: "已經有人使用了。" admins: admin_bar: + dashboard: "儀表æ¿" pages: "分é " + pod_network: "豆莢網路" pod_stats: "豆莢統計資料" report: "å›žå ±" sidekiq_monitor: "Sidekiq 監視器" user_search: "使用者æœå°‹" weekly_user_stats: "ä½¿ç”¨è€…çµ±è¨ˆé€±å ±" + dashboard: + fetching_diaspora_version: "判斷 diaspora* 的最新版本ä¸..." + pod_status: "豆莢狀態" + pods: + pod_network: "豆莢網路" stats: 2weeks: "兩個禮拜" 50_most: "最夯的50個標籤" @@ -88,6 +92,7 @@ zh-TW: email: "é›»åä¿¡ç®±" guid: "全域唯一è˜åˆ¥ç¢¼(GUID)" id: "è˜åˆ¥ç¢¼" + invite_token: "邀請信物" last_seen: "最後看見時間" ? "no" : å¦ @@ -105,7 +110,10 @@ zh-TW: are_you_sure_unlock_account: "ä½ ç¢ºå®šè¦æŠŠå¸³è™Ÿè§£éŽ–嗎?" close_account: "關閉帳號" email_to: "寄電å郵件邀請" + invite: "邀請" + lock_account: "鎖定帳號" under_13: "顯示低於 13 æ²çš„使用者(基於美國兒童網路隱ç§ä¿è·æ³•æ¡ˆ, COPPA)" + unlock_account: "解鎖帳號" users: other: "找到%{count}個使用者" zero: "找到%{count}個使用者" @@ -118,13 +126,63 @@ zh-TW: other: "本週新使用者數目:%{count}" zero: "本週新使用者數目:0" current_server: "伺æœå™¨ç¾åœ¨çš„日期是%{date}" - ago: "%{time}å‰" all_aspects: "所有社交é¢" - application: - helper: - unknown_person: "ä¸æ˜Žè¯çµ¡äºº" - video_title: - unknown: "影片標題ä¸æ˜Ž" + api: + openid_connect: + authorizations: + destroy: + fail: "撤銷è˜åˆ¥ç¢¼æ˜¯ %{id} 的客戶端授權失敗" + new: + access: "%{name}需è¦ä»¥ä¸‹å˜å–權:" + approve: "åŒæ„" + bad_request: "沒有客戶端è˜åˆ¥ç¢¼æˆ–是è¦è½‰å€çš„ URI" + client_id_not_found: "沒有符åˆå®¢æˆ¶ç«¯è˜åˆ¥ç¢¼ %{client_id} 以åŠè½‰å€ URI %{redirect_uri} 的客戶端紀錄" + deny: "拒絕" + no_requirement: "%{name}ä¸éœ€è¦ä»»ä½•æ¬Šé™" + redirection_message: "確定è¦å°‡å˜å–權給 %{redirect_uri} 嗎?" + error_page: + contact_developer: "è«‹è¯çµ¡é€™å€‹æ‡‰ç”¨ç¨‹å¼çš„開發人員,並將以下詳細錯誤訊æ¯çµ¦ä»–們:" + could_not_authorize: "無法授權給這個應用程å¼" + login_required: "ä½ å¿…é ˆå…ˆç™»å…¥æ‰èƒ½æŽˆæ¬Šçµ¦é€™å€‹æ‡‰ç”¨ç¨‹å¼" + title: "呃ï¼å‡ºäº‹äº† :(" + scopes: + aud: + description: "å…許應用程å¼å˜å–客戶端è˜åˆ¥ç¢¼" + name: "客戶端" + name: + description: "å…許應用程å¼å˜å–姓å" + name: "姓å" + nickname: + description: "å…å–應用程å¼å˜å–別å" + name: "別å" + openid: + description: "å…許應用程å¼è®€å–ä½ çš„åŸºæœ¬å€‹äººæª”æ¡ˆ" + name: "基本個人檔案" + picture: + description: "å…許應用程å¼å˜å–相片" + name: "相片" + profile: + description: "å…許應用程å¼è®€å–ä½ çš„é€²éšŽå€‹äººæª”æ¡ˆ" + name: "進階個人檔案" + read: + description: "å…許應用程å¼è®€å–ä½ çš„æµæ°´å¸³ã€å°è©±å…§å®¹ã€ä»¥åŠå®Œæ•´çš„個人檔案" + name: "讀å–個人檔案ã€æµæ°´å¸³ã€ä»¥åŠå°è©±å…§å®¹" + sub: + description: "å…許應用程å¼å˜å–使用者è˜åˆ¥ç¢¼" + name: "使用者" + write: + description: "å…許應用程å¼ç™¼è¡¨æ–°çš„貼文ã€å°è©±ã€ä»¥åŠå›žæ‡‰" + name: "發表貼文ã€å°è©±ã€ä»¥åŠå›žæ‡‰" + user_applications: + index: + access: "%{name}有以下å˜å–權:" + edit_applications: "應用程å¼" + no_requirement: "%{name}ä¸éœ€è¦ä»»ä½•æ¬Šé™" + title: "已授權的應用程å¼" + no_applications: "ä½ æ²’æœ‰æŽˆæ¬Šçµ¦ä»»ä½•æ‡‰ç”¨ç¨‹å¼" + policy: "檢視這個應用程å¼çš„éš±ç§åŽŸå‰‡" + revoke_autorization: "撤銷" + tos: "檢視這個應用程å¼çš„æœå‹™æ¢æ¬¾" are_you_sure: "確定嗎?" are_you_sure_delete_account: "確定è¦é—œé–‰å¸³è™Ÿå—Žï¼Ÿå¸³è™Ÿç„¡æ³•å¾©åŽŸå–”ï¼" aspect_memberships: @@ -140,85 +198,54 @@ zh-TW: success: "å°‡è¯çµ¡äººåŠ 進社交é¢æˆåŠŸã€‚" aspect_listings: add_an_aspect: "+ 新增社交é¢" - deselect_all: "å…¨ä¸é¸" - edit_aspect: "編輯%{name}" - select_all: "å…¨é¸" aspect_stream: make_something: "åšé»žä»€éº¼" stay_updated: "隨時ä¿æŒæœ€æ–°ç‹€æ…‹" stay_updated_explanation: "ä½ çš„ä¸»æµæ°´å¸³æœƒå……æ»¿äº†ä½ çš„è¯çµ¡äººï¼Œè¿½è¹¤çš„標籤,以åŠå…¶ä»–有創æ„的社群æˆå“¡çš„貼文。" - contacts_not_visible: "讓這一é¢ä¸çš„è¯çµ¡äººç„¡æ³•äº’相看見。" - contacts_visible: "讓這一é¢ä¸çš„è¯çµ¡äººå¯ä»¥äº’相看見。" - create: - failure: "é€ ç¤¾äº¤é¢å¤±æ•—。" - success: "新社交é¢%{name}å·²ç¶“é€ å‡ºä¾†äº†" destroy: failure: "無法刪除%{name}。" success: "æˆåŠŸåˆªé™¤%{name}了。" success_auto_follow_back: "æˆåŠŸåˆªé™¤%{name}äº†ã€‚ä½†æ˜¯å› ç‚ºä½ ä¹‹å‰ç”¨é€™å€‹ç¤¾äº¤é¢ä¾†è‡ªå‹•åå‘è¿½è¹¤ï¼Œä½ æ‡‰è©²è¦åˆ°ä½¿ç”¨è€…è¨å®šåŽ»æŒ‡å®šæ–°çš„社交é¢ã€‚" edit: - aspect_chat_is_enabled: "這一é¢çš„è¯çµ¡äººå¯ä»¥å’Œä½ èŠå¤©ã€‚" - aspect_chat_is_not_enabled: "這一é¢çš„è¯çµ¡äººä¸èƒ½å’Œä½ èŠå¤©ã€‚" aspect_list_is_not_visible: "這一é¢ä¸çš„連絡人無法互相看見。" aspect_list_is_visible: "這一é¢ä¸çš„連絡人å¯ä»¥äº’相看見。" confirm_remove_aspect: "確定è¦åˆªé™¤é€™å€‹ç¤¾äº¤é¢å—Žï¼Ÿ" - grant_contacts_chat_privilege: "è¦æŠŠèŠå¤©çš„權é™çµ¦é€™ä¸€é¢çš„è¯çµ¡äººå—Žï¼Ÿ" - make_aspect_list_visible: "è¦è®“這一é¢ä¸çš„è¯çµ¡äººå¯ä»¥çœ‹å¾—到彼æ¤å—Žï¼Ÿ" - remove_aspect: "刪除這個社交é¢" rename: "改å" - set_visibility: "è¨å®šå¯è¦‹ç¯„åœ" update: "æ›´æ–°" updating: "æ›´æ–°ä¸" index: - diaspora_id: - content_1: "ä½ çš„ diaspora* è˜åˆ¥ç¢¼æ˜¯ï¼š" - content_2: "é€éŽå¸³è™Ÿå稱,其他人就å¯ä»¥åœ¨ diaspora* æ‰¾åˆ°ä½ ã€‚" - heading: "diaspora* è˜åˆ¥ç¢¼" donate: "æ助" - handle_explanation: "é€™æ˜¯ä½ çš„ diaspora* è˜åˆ¥ç¢¼ã€‚å°±åƒé›»å信箱一樣,其他人å¯ä»¥é€éŽå®ƒä¾†è¯çµ¡ä½ 。" help: any_problem: "有å•é¡Œå—Žï¼Ÿ" contact_podmin: "è¯çµ¡è±†èŽ¢ç®¡ç†å“¡ï¼" do_you: "ä½ æ˜¯å¦ï¼š" - email_feedback: "也å¯ä»¥%{link}ä½ çš„æ„見來" - email_link: "寄信" feature_suggestion: "...想建è°%{link}嗎?" find_a_bug: "...找到一隻%{link}嗎?" have_a_question: "...有個%{link}嗎?" - here_to_help: "diaspora* 社群在這裡了ï¼" - mail_podmin: "莢主的電郵信箱" + here_to_help: "diaspora* 社群來了ï¼" + mail_podmin: "莢主的電åä¿¡ç®±" need_help: "è¦å¹«å¿™å—Žï¼Ÿ" tag_bug: "è‡èŸ²" tag_feature: "功能" tag_question: "å•é¡Œ" tutorial_link_text: "個別指導" - tutorials_and_wiki: "%{faq},%{tutorial},還有%{wiki}ï¼šè®“ä½ é †åˆ©ä¸Šæ‰‹çš„å¥½å¹«æ‰‹ã€‚" + tutorials_and_wiki: "還有%{faq},%{tutorial},以åŠ%{wiki}ï¼šè®“ä½ é †åˆ©ä¸Šæ‰‹çš„å¥½å¹«æ‰‹ã€‚" introduce_yourself: "é€™æ˜¯ä½ çš„æµæ°´å¸³ã€‚è·³é€²ä¾†ä»‹ç´¹ä½ è‡ªå·±å§ã€‚" - keep_diaspora_running: "æ¯å€‹æœˆå›ºå®šæ款幫助 diaspora* ç ”ç™¼æˆé•·" keep_pod_running: "æ¡è¿Žæ¯æœˆå›ºå®šæ¨‚æ,讓 %{pod} å¯ä»¥é«˜é€Ÿé‹è½‰ï¼Œä»¥åŠæ»¿è¶³ä¼ºæœå™¨çš„咖啡癮。" new_here: follow: "追蹤 %{link} 來æ¡è¿Ž diaspora* 的新人ï¼" learn_more: "進一æ¥äº†è§£" title: "æ¡è¿Žæ–°ä½¿ç”¨è€…" - no_contacts: "沒有任何è¯çµ¡äºº" - no_tags: "+ 找個標籤來追蹤" - people_sharing_with_you: "è·Ÿä½ åˆ†äº«çš„äºº" - post_a_message: "è²¼è¨Šæ¯ >>" services: content: "ä½ å¯ä»¥å°‡ä»¥ä¸‹å¤–部æœå‹™è·Ÿ diaspora* 連çµï¼š" heading: "連çµå¤–部æœå‹™" - unfollow_tag: "åœæ¢è¿½è¹¤ #%{tag}" welcome_to_diaspora: "%{name},æ¡è¿Žä¾†åˆ° diaspora*ï¼" - new: - create: "建立" - name: "åå—(åªæœ‰ä½ 自己看得到)" no_contacts_message: community_spotlight: "社群焦點" - or_spotlight: "æˆ–è€…ä½ ä¹Ÿå¯ä»¥å’Œ %{link} 分享" - try_adding_some_more_contacts: "ä½ å¯ä»¥æœå°‹æˆ–邀請更多è¯çµ¡äººã€‚" + invite_link_text: "邀請" + or_spotlight: "æˆ–è€…ä½ ä¹Ÿå¯ä»¥è·Ÿ %{link} 分享" + try_adding_some_more_contacts: "ä½ å¯ä»¥æœå°‹æˆ–是%{invite_link}更多è¯çµ¡äººã€‚" you_should_add_some_more_contacts: "新增更多è¯çµ¡äººå§ï¼" - no_posts_message: - start_talking: "都還沒有人出è²ï¼" seed: acquaintances: "èªè˜çš„人" family: "家人" @@ -227,7 +254,6 @@ zh-TW: update: failure: "ä½ çš„ç¤¾äº¤é¢%{name}å稱太長了無法儲å˜ã€‚" success: "ä½ çš„ç¤¾äº¤é¢%{name}編輯完æˆäº†ã€‚" - back: "上一æ¥" blocks: create: failure: "我無法忽視這個使用者。 #è—‰å£" @@ -239,72 +265,55 @@ zh-TW: explanation: "å°‡æ¤é€£çµåŠ 入書籤 => %{link},å¯ä»¥éš¨æ™‚在diaspora*貼文。" heading: "書籤å°ç¨‹å¼" post_something: "貼到 diaspora*" - post_success: "貼好了ï¼é—œæŽ‰ä¸ï¼" cancel: "å–消" comments: new_comment: comment: "留言" commenting: "發表留言ä¸..." - one: "1則留言" - other: "%{count}則留言" - zero: "沒有留言" contacts: - create: - failure: "建立è¯ç¹«å¤±æ•—" index: add_a_new_aspect: "åŠ å…¥æ–°ç¤¾äº¤é¢" add_contact: "åŠ è¯çµ¡äºº" - add_to_aspect: "把è¯çµ¡äººåŠ 進%{name}" all_contacts: "所有è¯çµ¡äºº" community_spotlight: "社群焦點" my_contacts: "我的è¯çµ¡äºº" - no_contacts: "ä½ å¥½åƒæ‡‰è©²è¦å¤šåŠ 點è¯çµ¡äººï¼" + no_contacts: "ä½ å¥½åƒæ‡‰è©²è¦å¤šåŠ 一些è¯çµ¡äººï¼" no_contacts_in_aspect: "ä½ åœ¨é€™ä¸€é¢ä¸é‚„沒有任何è¯çµ¡äººã€‚下é¢æ˜¯ä½ å¯ä»¥åŠ 進這一é¢çš„è¯çµ¡äººåˆ—表。" no_contacts_message: "來看看 %{community_spotlight}" - only_sharing_with_me: "和我分享的人" - remove_contact: "刪è¯çµ¡äºº" + only_sharing_with_me: "跟我分享的人" start_a_conversation: "開始å°è©±" title: "è¯çµ¡äºº" user_search: "使用者æœå°‹" - your_contacts: "ä½ çš„è¯çµ¡äºº" - sharing: - people_sharing: "è·Ÿä½ åˆ†äº«çš„äººï¼š" spotlight: community_spotlight: "社群焦點" + no_members: "ç›®å‰é‚„沒有æˆå“¡ã€‚" suggest_member: "推薦會員" conversations: - conversation: - participants: "åƒåŠ 人員" create: fail: "無效的訊æ¯" - no_contact: "å–‚ï¼Œä½ è¦å…ˆæ–°å¢žè¯çµ¡äººæ‰è¡Œï¼" + no_contact: "å–‚ï¼Œä½ è¦å…ˆåŠ è¯çµ¡äººæ‰è¡Œï¼" sent: "訊æ¯é€å‡ºåŽ»äº†" destroy: delete_success: "å°è©±æˆåŠŸåˆªæŽ‰äº†" hide_success: "å°è©±æˆåŠŸéš±è—起來了" - helper: - new_messages: - other: "有%{count}則新訊æ¯" - zero: "沒有新訊æ¯" index: - conversations_inbox: "交談 - 收件匣" - create_a_new_conversation: "開始新的交談" - inbox: "收件匣" - new_conversation: "開始交談" - no_conversation_selected: "沒有é¸å–任何å°è©±" + conversations_inbox: "å°è©± - 收訊匣" + inbox: "收訊匣" + new_conversation: "開始å°è©±" no_messages: "沒有訊æ¯" new: - abandon_changes: "放棄目å‰è®Šå‹•å—Žï¼Ÿ" + message: "訊æ¯" send: "傳é€" sending: "傳é€ä¸..." subject: "主旨" subject_default: "沒標題" - to: "收件人" + to: "收訊人" new_conversation: fail: "訊æ¯ç„¡æ•ˆ" show: delete: "刪除å°è©±" hide: "把å°è©±éš±è—並且消音" + last_message: "在%{timeago}收到最新訊æ¯" reply: "回覆" replying: "回覆ä¸..." date: @@ -317,17 +326,14 @@ zh-TW: error_messages: helper: correct_the_following_errors_and_try_again: "è«‹ä¿®æ£ä»¥ä¸‹éŒ¯èª¤å¾Œå†è©¦ä¸€æ¬¡ã€‚" - invalid_fields: "欄ä½ç„¡æ•ˆ" - login_try_again: "è«‹<a href='%{login_link}'>登入</a>後å†è©¦ä¸€æ¬¡ã€‚" - post_not_public: "ä½ è¦çœ‹çš„貼文沒有公開ï¼" - post_not_public_or_not_exist: "ä½ è¦çœ‹çš„è²¼æ–‡æ²’æœ‰å…¬é–‹ï¼Œæˆ–æ˜¯æ ¹æœ¬ä¸å˜åœ¨ï¼" - fill_me_out: "填寫æ¤æ¬„" + need_javascript: "é€™å€‹ç¶²ç«™éœ€è¦ JavaScript 功能æ‰èƒ½æ£å¸¸é‹ä½œã€‚å¦‚æžœä½ é—œæŽ‰äº† JavaScript 的話,請打開它後é‡æ–°è¼‰å…¥ç¶²é 來使用。" + fill_me_out: "填寫這裡" find_people: "找人或 #標籤" help: account_and_data_management: close_account_a: åˆ°ä½ çš„è¨å®šé é¢çš„最下é¢ï¼ŒæŒ‰"關帳號"的按鈕。需è¦è¼¸å…¥å¯†ç¢¼ä¾†å®Œæˆæ•´å€‹ç¨‹åºã€‚æé†’ä½ ï¼Œé—œé–‰å¸³è™Ÿå¾Œå°±<strong>å†ä¹Ÿä¸èƒ½</strong>用åŒä¸€å€‹å¸³è™Ÿåœ¨é€™å€‹è±†èŽ¢è¨»å†Šäº†ã€‚ close_account_q: "è¦æ€Žæ¨£åˆªæŽ‰æˆ‘的豆å(帳號)?" - data_other_podmins_a: "ç•¶ä½ é–‹å§‹å’Œå…¶å®ƒè±†èŽ¢è£¡çš„æŸäººåˆ†äº«ä»¥å¾Œï¼Œä½ 和他們分享的任何貼文,以åŠä½ 的帳號資料,都會儲å˜(或是暫å˜)åœ¨ä»–å€‘çš„è±†èŽ¢è£¡ï¼Œå› æ¤ä»–們豆莢的資料庫管ç†å“¡å°±æœ‰è¾¦æ³•å¯ä»¥è®€å¾—åˆ°ã€‚ç•¶ä½ åˆªæŽ‰è²¼æ–‡æˆ–æ˜¯å¸³è™Ÿè³‡æ–™ï¼Œé€™äº›è³‡æ–™ä¸ä½†æœƒå¾žä½ 的豆莢刪掉,也會傳é€åˆªæŽ‰çš„請求給之å‰æœ‰å„²å˜é€™äº›è³‡æ–™çš„å…¶ä»–è±†èŽ¢ã€‚ä½ çš„åœ–ç‰‡å‰‡åªæœƒå„²å˜åœ¨å¸³è™Ÿæ‰€å±¬çš„豆莢裡,其他豆莢åªæœƒæ”¶åˆ°é€£çµã€‚" + data_other_podmins_a: "ç•¶ä½ é–‹å§‹è·Ÿå…¶å®ƒè±†èŽ¢è£¡çš„æŸäººåˆ†äº«ä»¥å¾Œï¼Œä½ 和他們分享的任何貼文,以åŠä½ 的帳號資料,都會儲å˜(或是暫å˜)åœ¨ä»–å€‘çš„è±†èŽ¢è£¡ï¼Œå› æ¤ä»–們豆莢的資料庫管ç†å“¡å°±æœ‰è¾¦æ³•å¯ä»¥è®€å¾—åˆ°ã€‚ç•¶ä½ åˆªæŽ‰è²¼æ–‡æˆ–æ˜¯å¸³è™Ÿè³‡æ–™ï¼Œé€™äº›è³‡æ–™ä¸ä½†æœƒå¾žä½ 的豆莢刪掉,也會傳é€åˆªæŽ‰çš„請求給之å‰æœ‰å„²å˜é€™äº›è³‡æ–™çš„å…¶ä»–è±†èŽ¢ã€‚ä½ çš„åœ–ç‰‡å‰‡åªæœƒå„²å˜åœ¨å¸³è™Ÿæ‰€å±¬çš„豆莢裡,其他豆莢åªæœƒæ”¶åˆ°é€£çµã€‚" data_other_podmins_q: "其它豆莢的管ç†å“¡å¯ä»¥çœ‹åˆ°å¤šå°‘我的資料?" data_visible_to_podmin_a: "è±†èŽ¢å’Œè±†èŽ¢é–“çš„é€šè¨Šæœƒå…¨ç¨‹åŠ å¯†(用 SSL å’Œ diaspora* è‡ªå·±çš„å‚³è¼¸å±¤åŠ å¯†),但是å˜åœ¨è±†èŽ¢ç†çš„è³‡æ–™æ˜¯æ²’æœ‰åŠ å¯†çš„ã€‚æ‰€ä»¥ï¼Œå¦‚æžœè³‡æ–™åº«ç®¡ç†å“¡(通常也是管ç†è±†èŽ¢çš„人)想看的話,他/她å¯ä»¥çœ‹åˆ°ä½ 全部的個人資料,以åŠä½ 發表的任何æ±è¥¿(其實å°æ–¼å¤§å¤šæ•¸çš„,有å˜æ”¾å€‹äººè³‡æ–™çš„網站來說,這點都是一樣的)ã€‚å› æ¤å¦‚æžœä½ èƒ½ç®¡ç†ä½ 自己的豆莢,當然更能確ä¿ä½ çš„éš±ç§ï¼Œå› 為資料庫的å˜å–æ¬Šä¹Ÿæ˜¯ç”±ä½ æŽ§åˆ¶ã€‚" data_visible_to_podmin_q: "我所在豆莢的管ç†å“¡å¯ä»¥çœ‹åˆ°å¤šå°‘我的資料?" @@ -345,7 +351,7 @@ zh-TW: contacts_visible_q: "\"讓社交é¢ä¸çš„è¯çµ¡äººå¯ä»¥äº’相看見\"是什麼æ„æ€ï¼Ÿ" delete_aspect_a: 請從æµæ°´å¸³ç•«é¢çš„å´é‚Šæ¬„點一下"我的社交é¢"ï¼Œç„¶å¾Œé»žä¸€ä¸‹ä½ æƒ³åˆªæŽ‰çš„é‚£ä¸€é¢æ—邊的鉛ç†åœ–ç¤ºã€‚æˆ–æ˜¯åˆ°ä½ çš„è¯çµ¡äººç•«é¢ï¼Œé»žé¸ä½ 想刪掉的那一é¢ã€‚接著點一下é é¢å³ä¸Šæ–¹çš„垃圾桶圖示就å¯ä»¥äº†ã€‚ delete_aspect_q: "è¦æ€Žæ¨£åˆªæŽ‰ç¤¾äº¤é¢ï¼Ÿ" - person_multiple_aspects_a: å¯ä»¥ã€‚在"è¯çµ¡äºº"é é¢é»žä¸€ä¸‹"我的è¯çµ¡äºº",å¯ä»¥çœ‹åˆ°è¯çµ¡äººçš„列表。æ¯å€‹è¯çµ¡äººçš„å³é‚Šæœ‰å€‹ç¤¾äº¤é¢çš„é¸å–®ï¼Œå¯ä»¥è®“ä½ æŠŠå¥¹/ä»–åŠ é€²ç¤¾äº¤é¢ï¼Œç„¡è«–幾個都å¯ä»¥ï¼Œæˆ–是從æŸä¸€é¢ä¸ç§»é™¤æŽ‰ã€‚ä½ ä¹Ÿå¯ä»¥å¾žè¯çµ¡äººçš„個人檔案é é¢ï¼Œé»žç¤¾äº¤é¢çš„é¸æ“‡æŒ‰éˆ•ï¼Œä¾†æŠŠä»–å€‘åŠ é€²æŸä¸€é¢æˆ–從ä¸ç§»é™¤ã€‚ä½ é‚„å¯ä»¥åœ¨æµæ°´å¸³ä¸ï¼ŒæŠŠæ¸¸æ¨™ç§»åˆ°è¯çµ¡äººçš„åå—上é¢ï¼Œæµ®å‹•å¡ç‰‡å°±æœƒè·³å‡ºä¾†ï¼Œè®“ä½ ä¹Ÿå¯ä»¥è¨å®šä»–們所屬的社交é¢ã€‚ + person_multiple_aspects_a: å¯ä»¥ã€‚在"è¯çµ¡äºº"é é¢é»žä¸€ä¸‹"我的è¯çµ¡äºº",å¯ä»¥çœ‹åˆ°è¯çµ¡äººçš„列表。æ¯å€‹è¯çµ¡äººçš„å³é‚Šæœ‰å€‹ç¤¾äº¤é¢çš„é¸å–®ï¼Œå¯ä»¥è®“ä½ æŠŠå¥¹/ä»–åŠ é€²ç¤¾äº¤é¢ï¼Œç„¡è«–幾個都å¯ä»¥ï¼Œæˆ–是從æŸä¸€é¢ä¸ç§»é™¤æŽ‰ã€‚ä½ ä¹Ÿå¯ä»¥å¾žè¯çµ¡äººçš„個人檔案é é¢ï¼Œé»žç¤¾äº¤é¢çš„é¸æ“‡æŒ‰éˆ•ï¼Œä¾†æŠŠä»–å€‘åŠ é€²æŸä¸€é¢æˆ–從ä¸ç§»é™¤ã€‚ä½ é‚„å¯ä»¥åœ¨æµæ°´å¸³ä¸ï¼ŒæŠŠæ¸¸æ¨™ç§»åˆ°è¯çµ¡äººçš„åå—上é¢ï¼Œç›®æ¨™å¡ç‰‡å°±æœƒè·³å‡ºä¾†ï¼Œè®“ä½ ä¹Ÿå¯ä»¥è¨å®šä»–們所屬的社交é¢ã€‚ person_multiple_aspects_q: "我å¯ä»¥æŠŠæŸäººåŠ 到好幾個社交é¢ä¸å—Žï¼Ÿ" post_multiple_aspects_a: å¯ä»¥ã€‚ç•¶ä½ åœ¨å¯«è²¼æ–‡æ™‚ï¼Œå¯ä»¥ç”¨ç¤¾äº¤é¢é¸æ“‡æŒ‰éˆ•ä¾†æŒ‡å®šæˆ–å–消,é è¨æ˜¯"所有社交é¢"ã€‚ç™¼è¡¨å¾Œæ‰€æœ‰ä½ é¸æ“‡çš„社交é¢éƒ½å¯ä»¥çœ‹åˆ°é‚£ç¯‡è²¼æ–‡ã€‚ä½ ä¹Ÿå¯ä»¥å¾žå´é‚Šæ¬„é¸æ“‡ä½ è¦ç™¼è¡¨å‡ºåŽ»çš„社交é¢ã€‚ç•¶ä½ ç™¼è¡¨æ–°è²¼æ–‡æ™‚ï¼Œåœ¨å·¦å´ä½ 所é¸æ“‡çš„社交é¢æœƒæ˜¯é è¨è¦ç™¼è¡¨çš„å°è±¡ã€‚ post_multiple_aspects_q: "我å¯ä»¥åŒæ™‚發表貼文到很多社交é¢åŽ»å—Žï¼Ÿ" @@ -451,7 +457,7 @@ zh-TW: size_of_images_a: "ä¸è¡Œã€‚åœ–ç‰‡æœƒæ ¹æ“šç›®å‰æ˜¯æµæ°´å¸³æˆ–單一貼文的版é¢ä¾†è‡ªå‹•èª¿æ•´å¤§å°ã€‚Markdown 並沒有è¨å®šåœ–片大å°çš„語法。" size_of_images_q: "我å¯ä»¥è¨å®šè²¼æ–‡æˆ–留言ä¸çš„圖片大å°å—Žï¼Ÿ" stream_full_of_posts_a1: "ä½ çš„æµæ°´å¸³ä¾†è‡ªä¸‰ç¨®è²¼æ–‡ï¼š" - stream_full_of_posts_li1: "ä½ æœ‰è·Ÿä»–å€‘åˆ†äº«çš„äººçš„è²¼æ–‡ï¼›é‚„å¯ä»¥ç´°åˆ†ç‚ºå…©ç¨®ï¼šä¸€ç¨®æ˜¯å…¬é–‹çš„貼文,å¦ä¸€ç¨®æ˜¯å—é™çš„è²¼æ–‡ï¼Œä½†æ˜¯ä½ åœ¨è©²è²¼æ–‡çš„ç›®æ¨™ç¤¾äº¤é¢è£¡é¢ã€‚è¦è®“é€™ç¨®è²¼æ–‡å¾žä½ çš„æµæ°´å¸³æ¶ˆå¤±ï¼Œåªè¦åœæ¢å’Œé‚£å€‹äººåˆ†äº«å°±å¯ä»¥äº†ã€‚" + stream_full_of_posts_li1: "ä½ æœ‰è·Ÿä»–å€‘åˆ†äº«çš„äººçš„è²¼æ–‡ï¼›é‚„å¯ä»¥ç´°åˆ†ç‚ºå…©ç¨®ï¼šä¸€ç¨®æ˜¯å…¬é–‹çš„貼文,å¦ä¸€ç¨®æ˜¯å—é™çš„è²¼æ–‡ï¼Œä½†æ˜¯ä½ åœ¨è©²è²¼æ–‡çš„ç›®æ¨™ç¤¾äº¤é¢è£¡é¢ã€‚è¦è®“é€™ç¨®è²¼æ–‡å¾žä½ çš„æµæ°´å¸³æ¶ˆå¤±ï¼Œåªè¦åœæ¢è·Ÿé‚£å€‹äººåˆ†äº«å°±å¯ä»¥äº†ã€‚" stream_full_of_posts_li2: "å«æœ‰ä½ 追蹤的標籤的公開貼文。è¦è®“這種貼文ä¸å‡ºç¾ï¼Œå°±ä¸è¦å†è¿½è¹¤é‚£å€‹æ¨™ç±¤ã€‚" stream_full_of_posts_li3: 列在社群焦點那些人的公開貼文。åªè¦åœ¨ä½ 的帳號è¨å®šä¸ä¸è¦å‹¾é¸"在æµæ°´å¸³é¡¯ç¤ºç¤¾ç¾¤ç„¦é»ž",就ä¸æœƒæœ‰é€™ç¨®è²¼æ–‡äº†ã€‚ stream_full_of_posts_q: "為什麼我的æµæ°´å¸³è£¡é¢éƒ½æ˜¯ä¸€äº›æˆ‘ä¸èªè˜ä¹Ÿæ²’跟他們分享的人的貼文?" @@ -461,7 +467,7 @@ zh-TW: can_comment_q: "誰å¯ä»¥å°æˆ‘çš„éžå…¬é–‹è²¼æ–‡ç•™è¨€æˆ–按讚?" can_reshare_a: "沒有人å¯ä»¥ã€‚éžå…¬é–‹çš„貼文是ä¸èƒ½è½‰è²¼çš„。ä¸éŽï¼Œé‚£äº›å› ç‚ºåœ¨ä½ çš„ç¤¾äº¤é¢ä¸ï¼Œè€Œå¯ä»¥åœ¨ç™»å…¥æ™‚看到貼文的人,也å¯èƒ½ç”¨è¤‡è£½ã€è²¼ä¸Šçš„æ–¹å¼è½‰è²¼ã€‚è¦ä¸è¦ä¿¡ä»»ä»–å€‘å°±ç•™çµ¦ä½ è‡ªå·±æ±ºå®šå›‰ï¼" can_reshare_q: "誰å¯ä»¥è½‰è²¼æˆ‘çš„éžå…¬é–‹è²¼æ–‡ï¼Ÿ" - see_comment_a: "åªæœ‰è©²ç¯‡è²¼æ–‡çš„分享å°è±¡(也就是當åˆåŽŸä½œè€…所é¸æ“‡ç¤¾äº¤é¢ä¸çš„人)æ‰å¯ä»¥çœ‹åˆ°è²¼æ–‡çš„留言和讚。" + see_comment_a: "åªæœ‰è©²ç¯‡è²¼æ–‡çš„分享å°è±¡(也就是當åˆåŽŸä½œè€…所é¸æ“‡ç¤¾äº¤é¢ä¸çš„人)æ‰å¯ä»¥çœ‹åˆ°è²¼æ–‡çš„留言和稱讚。" see_comment_q: "如果我å°éžå…¬é–‹è²¼æ–‡ç•™è¨€æˆ–按讚,誰å¯ä»¥çœ‹å¾—到?" title: "éžå…¬é–‹è²¼æ–‡" who_sees_post_a: "åªæœ‰åœ¨ä½ 發表該篇éžå…¬é–‹è²¼æ–‡å‰ï¼Œå°±å·²ç¶“在那一é¢ä¸çš„使用者æ‰å¯ä»¥çœ‹å¾—åˆ°ï¼Œä¸¦ä¸”å¿…é ˆè¦åœ¨ç™»å…¥ diaspora* 的狀態下。" @@ -470,7 +476,7 @@ zh-TW: title: "ç§äººæª”案" whats_in_profile_a: "ç§äººæª”案裡é¢å¯ä»¥æœ‰è‡ªå‚³ã€æ‰€åœ¨åœ°ã€æ€§åˆ¥ã€é‚„æœ‰ç”Ÿæ—¥ã€‚ä½ å¯ä»¥é¸æ“‡è¦æä¾›å“ªäº›çµ¦äººçœ‹ï¼Œæ²’æœ‰ä¸€é …æ˜¯å¿…éœ€è¦å¡«çš„。åªæœ‰é‚£äº›ä½ æŠŠä»–å€‘åŠ åˆ°ç¤¾äº¤é¢ä¸çš„人,在登入的狀態下å¯ä»¥çœ‹åˆ°ä½ çš„ç§äººæª”æ¡ˆã€‚ç•¶ä»–å€‘çœ‹ä½ çš„å€‹äººæª”æ¡ˆæ™‚ï¼Œé™¤äº†ä½ çš„å…¬é–‹è²¼æ–‡ä¹‹å¤–ï¼Œé‚„å¯ä»¥çœ‹åˆ°ä»–們所屬社交é¢çš„éžå…¬é–‹è²¼æ–‡ã€‚" whats_in_profile_q: "ç§äººæª”案裡é¢æœ‰ä»€éº¼ï¼Ÿ" - who_sees_profile_a: "ä»»ä½•ä½ æœ‰å’Œä»–å€‘åˆ†äº«çš„äºº(ä¹Ÿå°±æ˜¯é‚£äº›ä½ æŠŠä»–å€‘åŠ åˆ°ç¤¾äº¤é¢ä¸çš„人)都å¯ä»¥ã€‚é‚£äº›æœ‰è¿½è¹¤ä½ ï¼Œä½†æ˜¯ä½ æ²’æœ‰è¿½è¹¤ä»–å€‘çš„äººï¼Œåªèƒ½å¤ çœ‹åˆ°ä½ çš„å…¬é–‹æª”æ¡ˆã€‚" + who_sees_profile_a: "ä»»ä½•ä½ æœ‰è·Ÿä»–å€‘åˆ†äº«çš„äºº(ä¹Ÿå°±æ˜¯é‚£äº›ä½ æŠŠä»–å€‘åŠ åˆ°ç¤¾äº¤é¢ä¸çš„人)都å¯ä»¥ã€‚é‚£äº›æœ‰è¿½è¹¤ä½ ï¼Œä½†æ˜¯ä½ æ²’æœ‰è¿½è¹¤ä»–å€‘çš„äººï¼Œåªèƒ½å¤ çœ‹åˆ°ä½ çš„å…¬é–‹æª”æ¡ˆã€‚" who_sees_profile_q: "誰看得到我的ç§äººæª”案?" who_sees_updates_a: "ä»»ä½•åœ¨ä½ çš„ç¤¾äº¤é¢ä¸çš„人都å¯ä»¥çœ‹å¾—åˆ°ä½ ç§äººæª”案的改變。" who_sees_updates_q: "我的ç§äººæª”案更新時,誰å¯ä»¥çœ‹å¾—到?" @@ -481,14 +487,14 @@ zh-TW: deselect_aspect_posting_q: "我在發表公開貼文時,ä¸é¸æŸå€‹æˆ–æŸäº›é¢æœƒæœ‰ä»€éº¼å½±éŸ¿ï¼Ÿ" find_public_post_a: "è¿½è¹¤ä½ çš„äººæœƒåœ¨ä»–å€‘çš„æµæ°´å¸³çœ‹åˆ°ã€‚å¦‚æžœä½ åœ¨è²¼æ–‡ä¸åŠ 了 #標籤 ,那麼任何追蹤該標籤的人都會在他們的æµæ°´å¸³çœ‹åˆ°ã€‚æ¯ä¸€ç¯‡å…¬é–‹è²¼æ–‡éƒ½æœ‰å°ˆå±¬çš„網å€ï¼Œè®“任何人ä¸ç”¨ç™»å…¥éƒ½å¯ä»¥ç”¨é‚£å€‹ç¶²å€çœ‹åˆ°ã€‚å› æ¤ï¼Œå…¬é–‹è²¼æ–‡çš„連çµå¯ä»¥ç›´æŽ¥è²¼åˆ° Twitter​ã€éƒ¨è½æ ¼ã€æˆ–是其他地方去。公開貼文也有å¯èƒ½æœƒè¢«æœå°‹å¼•æ“Žæ”¶é›†ä¸¦ç·¨å…¥ç´¢å¼•ã€‚" find_public_post_q: "其他人è¦æ€Žæ¨£æ‰¾åˆ°æˆ‘的公開貼文?" - see_comment_reshare_like_a: "公開貼文的留言ã€è®šã€æˆ–是轉貼,也都是公開的。任何登入 diaspora* 的使用者,以åŠå…¶ä»–使用網際網路的人,都å¯ä»¥çœ‹åˆ°ä½ å°è©²ç¯‡è²¼æ–‡çš„åƒèˆ‡ã€‚" + see_comment_reshare_like_a: "公開貼文的留言ã€ç¨±è®šã€æˆ–是轉貼,也都是公開的。任何登入 diaspora* 的使用者,以åŠå…¶ä»–使用網際網路的人,都å¯ä»¥çœ‹åˆ°ä½ å°è©²ç¯‡è²¼æ–‡çš„åƒèˆ‡ã€‚" see_comment_reshare_like_q: "當我å°ä¸€ç¯‡å…¬é–‹è²¼æ–‡ç•™è¨€ã€è½‰è²¼ã€æˆ–是按讚時,誰å¯ä»¥çœ‹å¾—到?" title: "公開貼文" who_sees_post_a: "任何用網際網路的人都有å¯èƒ½çœ‹åˆ°ä½ å…¬é–‹çš„è²¼æ–‡ï¼Œå› æ¤è«‹å‹™å¿…ç¢ºå®šä½ å¸Œæœ›è©²è²¼æ–‡è¦å…¬é–‹å‡ºåŽ»ã€‚這是一個和世界æºé€šçš„好方法。" who_sees_post_q: "當我公開貼文時,誰å¯ä»¥çœ‹å¾—到?" public_profiles: title: "公開檔案" - what_do_tags_do_a: "å¹«åŠ©åˆ¥äººäº†è§£ä½ ã€‚å¦å¤–,在這些標籤的專é çš„å·¦å´ä¹Ÿæœƒç§€ä½ 和其他檔案ä¸æœ‰è©²æ¨™ç±¤çš„人的檔案照片。" + what_do_tags_do_a: "å¹«åŠ©åˆ¥äººäº†è§£ä½ ã€‚å¦å¤–,在這些標籤的專é çš„å·¦å´ä¹Ÿæœƒç§€ä½ 和其他檔案ä¸æœ‰è©²æ¨™ç±¤çš„人的個人照。" what_do_tags_do_q: "個人檔案裡的標籤有什麼用?" whats_in_profile_a: "ä½ çš„å…¬é–‹æª”æ¡ˆå¯èƒ½åŒ…å«äº†ä½ çš„åå—ã€æè¿°ä½ è‡ªå·±çš„äº”å€‹æ¨™ç±¤ã€ä»¥åŠä½ çš„ç›¸ç‰‡ã€‚ä½ å¯ä»¥é¸æ“‡è¦æä¾›å“ªäº›çµ¦åˆ¥äººçœ‹ï¼Œæ²’æœ‰ä¸€é …æ˜¯å¿…é ˆè¦å¡«çš„ã€‚éš¨ä½ é«˜èˆˆè¦è®“它一眼就知é“æ˜¯ä½ ï¼Œé‚„æ˜¯å®Œå…¨èªä¸å‡ºä¾†æ˜¯èª°ã€‚ä½ çš„å€‹äººæª”æ¡ˆä¹Ÿæœƒé¡¯ç¤ºä½ ç™¼è¡¨éŽçš„公開貼文。" whats_in_profile_q: "公開檔案的內容有什麼?" @@ -497,11 +503,11 @@ zh-TW: who_sees_updates_a: "ä»»ä½•ä¾†çœ‹ä½ çš„å€‹äººæª”æ¡ˆé é¢çš„人都å¯ä»¥ã€‚" who_sees_updates_q: "誰會看到我的公開檔案的更新?" resharing_posts: - reshare_private_post_aspects_a: "ä¸è¡Œï¼Œéžå…¬é–‹è²¼æ–‡æ˜¯ä¸èƒ½åˆ†äº«çš„。這是為了è¦å°Šé‡åŽŸä½œè€…çš„æ„é¡˜ï¼Œå› ç‚ºå¥¹/ä»–åªæƒ³è·Ÿç‰¹å®šçš„一群人分享。" - reshare_private_post_aspects_q: "我å¯ä»¥åˆ†äº«ä¸€ç¯‡éžå…¬é–‹è²¼æ–‡çµ¦ç‰¹å®šçš„社交é¢å—Žï¼Ÿ" - reshare_public_post_aspects_a: "ä¸è¡Œï¼Œåˆ†äº«å…¬é–‹è²¼æ–‡ç‰æ–¼æ˜¯è®“它變æˆä½ çš„å…¬é–‹è²¼æ–‡ã€‚å¦‚æžœä½ åªæƒ³è¦è·Ÿç‰¹å®šçš„社交é¢åˆ†äº«ï¼Œåªèƒ½æŠŠé‚£ç¯‡å…¬é–‹è²¼æ–‡çš„內容複製,å†è²¼åˆ°ä¸€ç¯‡æ–°çš„å—é™è²¼æ–‡åŽ»ã€‚" - reshare_public_post_aspects_q: "我å¯ä»¥åˆ†äº«ä¸€ç¯‡å…¬é–‹è²¼æ–‡çµ¦ç‰¹å®šçš„社交é¢å—Žï¼Ÿ" - title: "分享貼文" + reshare_private_post_aspects_a: "ä¸è¡Œï¼Œéžå…¬é–‹è²¼æ–‡æ˜¯ä¸èƒ½è½‰è²¼çš„。這是為了è¦å°Šé‡åŽŸä½œè€…çš„æ„é¡˜ï¼Œå› ç‚ºå¥¹/ä»–åªæƒ³è·Ÿç‰¹å®šçš„一群人分享。" + reshare_private_post_aspects_q: "我å¯ä»¥è½‰è²¼ä¸€ç¯‡éžå…¬é–‹è²¼æ–‡åˆ°ç‰¹å®šçš„社交é¢å—Žï¼Ÿ" + reshare_public_post_aspects_a: "ä¸è¡Œï¼Œè½‰è²¼å…¬é–‹è²¼æ–‡ç‰æ–¼æ˜¯è®“它變æˆä½ çš„å…¬é–‹è²¼æ–‡ã€‚å¦‚æžœä½ åªæƒ³è¦è·Ÿç‰¹å®šçš„社交é¢åˆ†äº«ï¼Œåªèƒ½æŠŠé‚£ç¯‡å…¬é–‹è²¼æ–‡çš„內容複製,å†è²¼åˆ°ä¸€ç¯‡æ–°çš„å—é™è²¼æ–‡åŽ»ã€‚" + reshare_public_post_aspects_q: "我å¯ä»¥è½‰è²¼ä¸€ç¯‡å…¬é–‹è²¼æ–‡åˆ°ç‰¹å®šçš„社交é¢å—Žï¼Ÿ" + title: "轉貼貼文" sharing: add_to_aspect_a1: "å‡è¨æ˜¥å¬ŒæŠŠå¿—æ˜ŽåŠ é€²æŸä¸€é¢ï¼Œä½†æ˜¯å¿—æ˜Žé‚„æ²’æœ‰æŠŠæ˜¥å¬ŒåŠ é€²ä»»ä½•ç¤¾äº¤é¢ï¼š" add_to_aspect_a2: "這就å«åšä¸å°ç¨±çš„åˆ†äº«ã€‚å¦‚æžœå¿—æ˜Žä¹ŸæŠŠæ˜¥å¬ŒåŠ é€²æŸä¸€é¢çš„話,那就會變æˆäº’相分享了。他們的公開貼文,和å°æ‡‰åˆ°äº’相指定社交é¢çš„éžå…¬é–‹è²¼æ–‡ï¼Œå°±æœƒé–‹å§‹å‡ºç¾åœ¨å½¼æ¤çš„æµæ°´å¸³ä¸ã€‚而且春嬌也å¯ä»¥çœ‹å¿—明的ç§äººæª”案了。之後他們還å¯ä»¥é€ç§äººè¨Šæ¯çµ¦å°æ–¹ã€‚" @@ -511,13 +517,13 @@ zh-TW: add_to_aspect_li4: "志明ä¸æœƒåœ¨ä»–çš„æµæ°´å¸³çœ‹åˆ°æ˜¥å¬Œçš„公開或éžå…¬é–‹è²¼æ–‡ã€‚" add_to_aspect_li5: "但是如果志明去看春嬌的個人檔案é é¢çš„è©±ï¼Œä»–å°±æœƒçœ‹åˆ°æ˜¥å¬Œè²¼åˆ°å¥¹æ‰€åŠ ä»–çš„é‚£å€‹ç¤¾äº¤é¢çš„éžå…¬é–‹è²¼æ–‡(ç•¶ç„¶é‚„æœ‰å¥¹çš„å…¬é–‹è²¼æ–‡ï¼Œå› ç‚ºæ¯å€‹äººéƒ½å¯ä»¥çœ‹å¾—到)。" add_to_aspect_li6: "志明也å¯ä»¥çœ‹æ˜¥å¬Œçš„ç§äººæª”案(包å«è‡ªå‚³ã€æ‰€åœ¨åœ°ã€æ€§åˆ¥ã€ä»¥åŠç”Ÿæ—¥)。" - add_to_aspect_li7: 春嬌會出ç¾åœ¨å¿—明è¯çµ¡äººé é¢ä¸çš„"和我分享的人"裡é¢ã€‚ + add_to_aspect_li7: 春嬌會出ç¾åœ¨å¿—明è¯çµ¡äººé é¢ä¸çš„"跟我分享的人"裡é¢ã€‚ add_to_aspect_li8: "春嬌也開始å¯ä»¥åœ¨è²¼æ–‡è£¡ @指指點點 志明。" add_to_aspect_q: "當我把æŸäººåŠ 進æŸä¸€é¢ï¼Œæˆ–是當æŸäººæŠŠæˆ‘åŠ é€²å¥¹/ä»–çš„æŸä¸€é¢æ™‚,會發生什麼事?" list_not_sharing_a: "æ²’æœ‰ï¼Œä½†æ˜¯ä½ å¯ä»¥çœ‹æŸäººçš„個人檔案來檢查她/他是å¦æœ‰è·Ÿä½ 分享。如果有的話,社交é¢çš„æŒ‰éˆ•æœƒé¡¯ç¤ºä½ æ‰€åŠ å¥¹/他的那個或那些é¢ï¼›å¦‚果沒有的話,按鈕會是ç°è‰²çš„。" list_not_sharing_q: "有那個è¯çµ¡äººåˆ—è¡¨æ˜¯æˆ‘æŠŠä»–å€‘åŠ é€²æŸä¸€é¢è£¡é¢ï¼Œä½†æ˜¯ä»–們å»æ²’æœ‰åŠ æˆ‘çš„å—Žï¼Ÿ" - only_sharing_a: é€™äº›äººå·²ç¶“æŠŠä½ åŠ é€²ä»–å€‘çš„ç¤¾äº¤é¢äº†ï¼Œä½†æ˜¯ä½ 的社交é¢ä¸é‚„æ²’æœ‰ä»–å€‘ã€‚ä¹Ÿå°±æ˜¯èªªä»–å€‘æœ‰è·Ÿä½ åˆ†äº«ï¼Œä½†æ˜¯ä½ å»(é‚„)沒有跟他們分享,就好åƒæ˜¯ä»–å€‘åœ¨è¿½è¹¤ä½ ã€‚å¦‚æžœä½ æŠŠä»–å€‘åŠ é€²ä»»ä½•ä¸€é¢ï¼Œä»–們就會出ç¾åœ¨é‚£ä¸€é¢çš„列表ä¸ï¼Œè€Œä¸æœƒåœ¨"和我分享的人"裡é¢äº†ã€‚請看上é¢çš„說明。 - only_sharing_q: 出ç¾åœ¨è¯çµ¡äººé é¢ä¸"和我分享的人"裡é¢çš„人是誰? + only_sharing_a: é€™äº›äººå·²ç¶“æŠŠä½ åŠ é€²ä»–å€‘çš„ç¤¾äº¤é¢äº†ï¼Œä½†æ˜¯ä½ 的社交é¢ä¸é‚„æ²’æœ‰ä»–å€‘ã€‚ä¹Ÿå°±æ˜¯èªªä»–å€‘æœ‰è·Ÿä½ åˆ†äº«ï¼Œä½†æ˜¯ä½ å»(é‚„)沒有跟他們分享,就好åƒæ˜¯ä»–å€‘åœ¨è¿½è¹¤ä½ ã€‚å¦‚æžœä½ æŠŠä»–å€‘åŠ é€²ä»»ä½•ä¸€é¢ï¼Œä»–們就會出ç¾åœ¨é‚£ä¸€é¢çš„列表ä¸ï¼Œè€Œä¸æœƒåœ¨"跟我分享的人"裡é¢äº†ã€‚請看上é¢çš„說明。 + only_sharing_q: è¯çµ¡äººé é¢ä¸æœ‰"跟我分享的人",出ç¾åœ¨è£¡é¢çš„人是誰? see_old_posts_a: "ä¸è¡Œï¼Œä»–們åªèƒ½çœ‹åˆ°ä½ å°é‚£ä¸€é¢çš„新貼文。並且就跟其他人一樣,他們也å¯ä»¥å¾žä½ 的個人檔案é é¢ï¼Œçœ‹åˆ°ä½ éŽåŽ»çš„公開貼文,說ä¸å®šä»–們也å¯ä»¥åœ¨è‡ªå·±çš„æµæ°´å¸³çœ‹åˆ°ã€‚" see_old_posts_q: "如果我把æŸäººåŠ 進æŸä¸€é¢ï¼Œå¥¹/ä»–å¯ä»¥çœ‹åˆ°æˆ‘å°é‚£å€‹ç¤¾äº¤é¢éŽåŽ»çš„貼文嗎?" sharing_notification_a: "當æ¯æ¬¡æœ‰äººé–‹å§‹è·Ÿä½ åˆ†äº«æ™‚ï¼Œä½ æ‡‰è©²éƒ½æœƒæ”¶åˆ°ä¸€å‰‡æ¶ˆæ¯ã€‚" @@ -540,80 +546,76 @@ zh-TW: tutorial: "個別指導" tutorials: "個別指導" wiki: "ç¶åŸº" - hide: "éš±è—" - ignore: "忽略" + home: + default: + be_who_you_want_to_be: "åšä½ 希望的自己" + be_who_you_want_to_be_info: "å¾ˆå¤šç¤¾ç¾¤ç¶²è·¯å …æŒè¦ä½ 用官方身份。diaspora* ä¸æ˜¯ã€‚åœ¨é€™è£¡ä½ å¯ä»¥é¸æ“‡æƒ³è¦æˆç‚ºèª°ï¼Œä¸¦ä¸”隨心所欲分享關於自己的一切,å¯ä»¥å¾ˆå¤šä¹Ÿå¯ä»¥å¾ˆå°‘。想è¦æ€Žæ¨£è·Ÿåˆ¥äººäº’å‹•ä½ å¯ä»¥è‡ªå·±æ±ºå®šã€‚" + byline: "ä½ èƒ½æŽŒæŽ§çš„ç·šä¸Šç¤¾äº¤ä¸–ç•Œ" + choose_your_audience: "é¸æ“‡è½çœ¾" + choose_your_audience_info: "diaspora* 用社交é¢ä¾†è®“ä½ é¸æ“‡è¦åˆ†äº«çš„å°è±¡ã€‚å¯ä»¥éžå¸¸å…¬é–‹ï¼Œä¹Ÿå¯ä»¥éžå¸¸ç§å¯†ã€‚比如說跟全世界分享一張好笑的相片,或是åªå’Œä½ 的密å‹åˆ†äº«ä¸€å€‹å¤§ç¥•å¯†ã€‚éƒ½åœ¨ä½ çš„æŽŒæŽ§ä¸ã€‚" + headline: "æ¡è¿Žä¾†åˆ°%{pod_name}" + own_your_data: "控制自己的資料" + own_your_data_info: "å¾ˆå¤šç¤¾ç¾¤ç¶²è·¯ç”¨ä½ çš„è³‡æ–™ä¾†è³ºéŒ¢ï¼Œåƒæ˜¯åˆ†æžä½¿ç”¨è¡Œç‚ºï¼Œç„¶å¾Œç”¨é€™äº›è³‡è¨Šä¾†å°ä½ åšå»£å‘ŠæŽ¨éŠ·ã€‚diaspora* åªæœƒç”¨ä½ çš„è³‡æ–™ä¾†è®“ä½ å’Œåˆ¥äººè¯ç¹«å’Œåˆ†äº«ï¼Œä¸æœƒæ‹¿ä¾†åšå…¶ä»–用途。" + podmin: + admin_panel: "管ç†é¢æ¿" + byline: "æº–å‚™ä¾†æ”¹è®Šç¶²éš›ç¶²è·¯äº†ã€‚æˆ‘å€‘ä¾†å¹«ä½ æº–å‚™å°±ç·’ï¼Œå¥½å—Žï¼Ÿ" + configuration_info: "è«‹ç”¨ä½ æ…£ç”¨çš„ç·¨è¼¯å™¨ï¼Œæ‰“é–‹è¨å®šæª” %{database_path} ä»¥åŠ %{diaspora_path},仔細檢查並修改它們,裡é¢æœ‰å¾ˆè©³ç´°çš„註解。" + configure_your_pod: "è¨å®šè±†èŽ¢" + contact_irc: "來​ IRC 跟我們è¯çµ¡" + contribute: "è²¢ç»" + contribute_info: "幫助 diaspora* 變得更好ï¼æ‰¾åˆ°è‡èŸ²å°±è«‹ä¾†%{report_bugs}。" + create_an_account: "註冊帳號" + create_an_account_info: "%{sign_up_link}一個新帳號" + faq_for_podmins: "豆莢管ç†å“¡çš„常見å•ç”集" + getting_help: "求助" + getting_help_info: "我們在ç¶åŸºä¸Šæ•´ç†äº†%{faq},包å«ä¸€äº›è¨£ç«…ã€èŠ±æ‹›ã€ä»¥åŠå¸¸è¦‹å•é¡Œçš„解法。åŒæ™‚也æ¡è¿Ž%{irc}。" + headline: "æ¡è¿Žä½ 來,朋å‹ã€‚" + make_yourself_an_admin: "æˆç‚ºç®¡ç†å“¡" + make_yourself_an_admin_info: "%{wiki}裡é¢æœ‰æ¥é©Ÿèªªæ˜Žã€‚åšå®Œä¹‹å¾Œï¼Œåœ¨ä½ ç™»å…¥æ™‚é ‚éƒ¨çš„ä½¿ç”¨è€…åŠŸèƒ½è¡¨æ‡‰è©²å°±æœƒå¤šä¸€å€‹ã€Œç®¡ç†ã€é …目。這個功能å¯ä»¥è®“ä½ æœå°‹è±†èŽ¢è£¡çš„使用者ã€æª¢è¦–統計資料ç‰ç‰ã€‚更深度的豆莢ç¶é‹é …目請用%{admin_panel}。" + report_bugs: "å›žå ±" + update_instructions: "在 diaspora* ç¶åŸºä¸Šçš„æ›´æ–°æ¥é©Ÿèªªæ˜Ž" + update_your_pod: "更新豆莢" + update_your_pod_info: "這是%{update_instructions}。" invitation_codes: - excited: "%{name} çœ‹åˆ°ä½ ä¾†è¦ºå¾—å¾ˆèˆˆå¥®ã€‚" not_valid: "邀請碼已經失效了" invitations: a_facebook_user: "Facebook 使用者" check_token: not_found: "找ä¸åˆ°è©²é‚€è«‹ä¿¡ç‰©" create: - already_contacts: "ä½ å·²ç¶“å’Œé€™å€‹äººç›¸é€£äº†" - already_sent: "ä½ é‚€è«‹éŽé€™å€‹äººäº†ã€‚" - empty: "請至少輸入一個電郵信箱" + empty: "請輸入至少一個電åä¿¡ç®±" no_more: "ä½ æ²’æœ‰é‚€è«‹å¡äº†ã€‚" note_already_sent: "邀請å¡å·²ç¶“寄到這些信箱了:%{emails}" - own_address: "ä¸èƒ½å¯„邀請å¡åˆ°ä½ 自己的信箱。" rejected: "以下的電å信箱有å•é¡Œï¼š" sent: "邀請å¡å·²ç¶“寄到這些信箱了:%{emails}" - edit: - accept_your_invitation: "接å—邀請" - your_account_awaits: "ä½ çš„å¸³è™Ÿåœ¨ç‰ä½ ï¼" new: - already_invited: "這些人還沒有接å—ä½ çš„é‚€è«‹ï¼š" - aspect: "社交é¢" - check_out_diaspora: "來 diaspora* 看看å§ï¼" codes_left: other: "é‚„å¯ä»¥é‚€è«‹%{count}個人" zero: "ä¸èƒ½é‚€è«‹æ›´å¤šäººäº†" comma_separated_plz: "å¯ä»¥ç”¨é€—號分隔來輸入多個電å信箱。" - if_they_accept_info: "如果他們接å—ï¼Œå°±æœƒè¢«åŠ é€²ä½ æ‰€é‚€è«‹çš„ç¤¾äº¤é¢ã€‚" invite_someone_to_join: "é‚€è«‹å…¶ä»–äººåŠ å…¥ diaspora*ï¼" language: "語言" paste_link: "將這個連çµåˆ†äº«çµ¦ä½ 的朋å‹ï¼Œä¾†é‚€è«‹ä»–å€‘åŠ å…¥ diaspora*,或者也å¯ä»¥ç›´æŽ¥å¯„é›»å郵件給他們。" - personal_message: "個人訊æ¯" - resend: "é‡å¯„" send_an_invitation: "寄邀請å¡" - send_invitation: "寄邀請å¡" sending_invitation: "æ£åœ¨é‚€è«‹å¡..." - to: "收件人" layouts: application: back_to_top: "回最上é¢" + be_excellent: "用最好的方å¼äº’相å°å¾…ï¼â™¥" powered_by: "強力é…ç½® diaspora*" public_feed: "%{name} 在 diaspora* 的公開資訊æº" source_package: "下載æºç¢¼å°è£æª”" statistics_link: "豆莢統計資料" toggle: "行動檢視切æ›" whats_new: "更新了什麼?" - your_aspects: "ä½ çš„ç¤¾äº¤é¢" header: - admin: "管ç†" - blog: "部è½æ ¼" code: "æºç¢¼" - help: "說明" - login: "登入" logout: "登出" profile: "個人檔案" - recent_notifications: "最新消æ¯" settings: "è¨å®š" - view_all: "檢視全部" - likes: - likes: - people_dislike_this: - other: "有%{count}個人說éœ" - zero: "沒人說éœ" - people_like_this: - other: "有%{count}個人說讚" - zero: "沒人說讚" - people_like_this_comment: - other: "有%{count}個人說讚" - zero: "沒人說讚" + toggle_navigation: "ç€è¦½æ¨¡å¼åˆ‡æ›" limited: "å—é™" more: "更多" - next: "後é¢" no_results: "æœå°‹æ²’有çµæžœ" notifications: also_commented: @@ -625,10 +627,6 @@ zh-TW: comment_on_post: other: "%{actors} ç•™è¨€åœ¨ä½ çš„è²¼æ–‡%{post_link}。" zero: "%{actors} ç•™è¨€åœ¨ä½ çš„è²¼æ–‡%{post_link}。" - helper: - new_notifications: - other: "有%{count}則新的通知" - zero: "沒有新的通知" index: all_notifications: "全部的通知" also_commented: "其他人留言" @@ -641,7 +639,7 @@ zh-TW: two: "以åŠå…¶ä»–%{count}個" zero: "以外沒有其他人" comment_on_post: "貼文有留言" - liked: "被說讚" + liked: "被稱讚" mark_all_as_read: "全部標示為已讀" mark_all_shown_as_read: "把目å‰é¡¯ç¤ºçš„都標示æˆè®€éŽäº†" mark_read: "標示為看éŽäº†" @@ -657,7 +655,7 @@ zh-TW: other: "%{actors} ç¨±è®šäº†ä½ çš„è²¼æ–‡%{post_link}。" zero: "%{actors} ç¨±è®šäº†ä½ çš„è²¼æ–‡%{post_link}。" liked_post_deleted: - other: "%{actors} ç¨±è®šäº†èªªä½ åˆªæŽ‰çš„è²¼æ–‡ã€‚" + other: "%{actors} ç¨±è®šäº†ä½ åˆªæŽ‰çš„è²¼æ–‡ã€‚" zero: "%{actors} ç¨±è®šäº†ä½ åˆªæŽ‰çš„è²¼æ–‡ã€‚" mentioned: other: "%{actors} 在貼文%{post_link}ä¸æåˆ°äº†ä½ " @@ -667,8 +665,8 @@ zh-TW: zero: "%{actors} 在已刪掉的貼文ä¸æåˆ°äº†ä½ ã€‚" post: "貼文" private_message: - other: "%{actors} 寫了訊æ¯çµ¦ä½ 。" - zero: "%{actors} 寫了訊æ¯çµ¦ä½ 。" + other: "%{actors} é€è¨Šæ¯çµ¦ä½ 。" + zero: "%{actors} é€è¨Šæ¯çµ¦ä½ 。" reshared: other: "%{actors} è½‰è²¼äº†ä½ çš„è²¼æ–‡%{post_link}。" zero: "%{actors} è½‰è²¼äº†ä½ çš„è²¼æ–‡%{post_link}。" @@ -679,10 +677,9 @@ zh-TW: other: "%{actors} é–‹å§‹è·Ÿä½ åˆ†äº«äº†ã€‚" zero: "%{actors} é–‹å§‹è·Ÿä½ åˆ†äº«äº†ã€‚" notifier: - a_limited_post_comment: "ä½ åœ¨ diaspora* 有一篇è¨é™è²¼æ–‡ä¸Šçš„新留言å¯çœ‹ã€‚" - a_post_you_shared: "一篇貼文." + a_limited_post_comment: "ä½ åœ¨ diaspora* çš„è¨é™è²¼æ–‡æœ‰ä¸€å‰‡æ–°ç•™è¨€ã€‚" + a_post_you_shared: "一篇貼文。" a_private_message: "ä½ åœ¨ diaspora* 有一則新的ç§äººè¨Šæ¯ã€‚" - accept_invite: "接å—來自 diaspora* 的邀請å§ï¼" also_commented: limited_subject: "ä½ ç•™è¨€éŽçš„貼文åˆæœ‰ä¸€å‰‡æ–°çš„留言" click_here: "按這裡" @@ -690,8 +687,8 @@ zh-TW: limited_subject: "ä½ çš„è²¼æ–‡æœ‰ä¸€å‰‡æ–°ç•™è¨€" reply: "回或看 %{name} 的貼文 >" confirm_email: - click_link: "請點以下連çµï¼Œä¾†å•Ÿç”¨ä½ æ–°çš„é›»åä¿¡ç®± %{unconfirmed_email}:" - subject: "è«‹å•Ÿç”¨ä½ æ–°çš„é›»åä¿¡ç®± %{unconfirmed_email}" + click_link: "請點以下連çµï¼Œä¾†é–‹é€šä½ æ–°çš„é›»åä¿¡ç®± %{unconfirmed_email}:" + subject: "è«‹é–‹é€šä½ æ–°çš„é›»åä¿¡ç®± %{unconfirmed_email}" email_sent_by_diaspora: "這å°é›»å郵件是從 %{pod_name} å¯„å‡ºã€‚å¦‚æžœä½ ä¸æƒ³å†æ”¶åˆ°é€™é¡žçš„信件," export_email: body: |- @@ -730,12 +727,13 @@ zh-TW: message: |- ä½ å¥½ï¼ - æœ‰äººé‚€è«‹ä½ åŠ å…¥ diaspora* å›‰ï¼ + %{diaspora_id} é‚€è«‹ä½ åŠ å…¥ diaspora* å›‰ï¼ è«‹æŒ‰é€™å€‹é€£çµä¾†é–‹å§‹ä½¿ç”¨å§ï¼š [%{invite_url}][1] + å¦‚æžœä½ å·²ç¶“æœ‰ diaspora* 帳號的話,å¯ä»¥ç›´æŽ¥æŠŠ %{diaspora_id} åŠ åˆ°ä½ çš„è¯çµ¡äººå–”。 ç¥é †åˆ©ï¼ @@ -747,15 +745,15 @@ zh-TW: [2]: %{diasporafoundation_url} invited_you: "%{name} é‚€è«‹ä½ ä¾†ç”¨ diaspora*" liked: - liked: "%{name} èªªä½ çš„è²¼æ–‡å¾ˆè®š" + liked: "%{name} ç¨±è®šä½ çš„è²¼æ–‡" limited_post: "%{name} ç¨±è®šä½ ä¸€ç¯‡è¨é™çš„貼文" view_post: "看貼文 >" mentioned: limited_post: "ä½ åœ¨ä¸€ç¯‡è¨é™çš„貼文ä¸è¢«æ到了。" - mentioned: "在貼文ä¸æåˆ°äº†ä½ ï¼š" subject: "%{name} 在 diaspora* æåˆ°äº†ä½ " private_message: reply_to_or_view: "回或看這次å°è©± >" + subject: "ä½ æœ‰ä¸€å‰‡æ–°çš„ç§äººè¨Šæ¯ã€‚" remove_old_user: body: |- ä½ å¥½ï¼Œ @@ -775,7 +773,8 @@ zh-TW: report_email: body: |- ä½ å¥½ï¼Œ - è˜åˆ¥ç¢¼%{id}çš„%{type}被標記為有人身攻擊。 + è˜åˆ¥ç¢¼ %{id} çš„%{type}被標記為有人身攻擊。 + ç†ç”±æ˜¯ï¼š%{reason} [%{url}][註1] éº»ç…©ç›¡å¿«æª¢æŸ¥çœ‹çœ‹ï¼ @@ -801,127 +800,76 @@ zh-TW: to_change_your_notification_settings: "來更改消æ¯é€šçŸ¥çš„è¨å®š" nsfw: "NSFW(上ç時ä¸å®œ)" ok: "確定" - or: "或是" - password: "密碼" - password_confirmation: "確èªå¯†ç¢¼" people: add_contact: invited_by: "é‚€è«‹ä½ çš„ä½¿ç”¨è€…" - add_contact_small: - add_contact_from_tag: "從標籤新增è¯çµ¡äºº" - aspect_list: - edit_membership: "編輯所屬社交é¢" - helper: - is_not_sharing: "%{name} æ²’æœ‰è·Ÿä½ åˆ†äº«" - is_sharing: "%{name} æ£åœ¨è·Ÿä½ 分享ä¸" - results_for: "%{params}çš„æœå°‹çµæžœ" index: couldnt_find_them: "找ä¸åˆ°ä»–們嗎?" looking_for: "在找標記為 %{tag_link} 的貼文嗎?" no_one_found: "...找ä¸åˆ°ä»»ä½•æ±è¥¿ã€‚" - no_results: "å–‚ï¼æœå°‹è¦æœ‰ç›®æ¨™ã€‚" + no_results: "嘿ï¼æœå°‹è¦æœ‰ç›®æ¨™ã€‚" results_for: "符åˆ%{search_term}的使用者:" search_handle: "確定è¦ç”¨ä½ 朋å‹å€‘çš„ diaspora* è˜åˆ¥ç¢¼ä¾†æ‰¾åˆ°ä»–們。" searching: "æœå°‹ä¸ï¼Œè«‹è€å¿ƒç‰å¾…..." send_invite: "還是找ä¸åˆ°äººå—Žï¼Ÿå¯„一å°é‚€è«‹å¡å§ï¼" - one: "1個è¯çµ¡äºº" - other: "%{count}個è¯çµ¡äºº" person: - add_contact: "åŠ å…¥è¯çµ¡äºº" - already_connected: "已經連çµäº†" - pending_request: "請求ç‰å€™ä¸" - thats_you: "é‚£æ˜¯ä½ è€¶ï¼" + thats_you: "é‚£æ˜¯ä½ å–”ï¼" profile_sidebar: bio: "自我介紹" born: "生日" - edit_my_profile: "編輯個人檔案" gender: "性別" - in_aspects: "所屬社交é¢" location: "地點" - photos: "相片" - remove_contact: "刪除è¯çµ¡äºº" - remove_from: "è¦å¾ž %{aspect} 刪除 %{name} 嗎?" show: closed_account: "帳號已經關閉了。" does_not_exist: "è¯çµ¡äººä¸å˜åœ¨ï¼" has_not_shared_with_you_yet: "%{name} é‚„æ²’è·Ÿä½ åˆ†äº«ä»»ä½•è²¼æ–‡ï¼" - ignoring: "ä½ ç›®å‰æœƒå¿½è¦– %{name} 的所有貼文。" - incoming_request: "%{name} å¸Œæœ›èƒ½å’Œä½ åˆ†äº«" - mention: "指指點點" - message: "é€è¨Šæ¯" - not_connected: "ä½ ä¸è·Ÿé€™å€‹äººåˆ†äº«" - recent_posts: "最新貼文" - recent_public_posts: "最新公開貼文" - return_to_aspects: "å›žä½ çš„ç¤¾äº¤é¢ä¸»é " - see_all: "看全部" - start_sharing: "開始分享" - to_accept_or_ignore: "接å—或ä¸ç®¡å®ƒã€‚" - sub_header: - add_some: "åŠ å…¥ä¸€äº›" - edit: "編輯" - you_have_no_tags: "ä½ æ²’æœ‰ä»»ä½•æ¨™ç±¤ï¼" - webfinger: - fail: "抱æ‰ï¼Œæ‰¾ä¸åˆ° %{handle}。" - zero: "沒有è¯çµ¡äºº" photos: - comment_email_subject: "%{name} 的相片" create: integrity_error: "ç›¸ç‰‡ä¸Šå‚³å¤±æ•—ã€‚ä½ ç¢ºå®šå®ƒæ˜¯åœ–ç‰‡å—Žï¼Ÿ" - runtime_error: "ç›¸ç‰‡ä¸Šå‚³å¤±æ•—ã€‚ä½ ç¢ºå®šå®‰å…¨å¸¶æœ‰æ‰£ä¸Šå—Žï¼Ÿ" + runtime_error: "ç›¸ç‰‡ä¸Šå‚³å¤±æ•—ã€‚ä½ ç¢ºå®šæœ‰æ‰£ä¸Šå®‰å…¨å¸¶å—Žï¼Ÿ" type_error: "ç›¸ç‰‡ä¸Šå‚³å¤±æ•—ã€‚ä½ ç¢ºå®šæœ‰åŠ å…¥ä»»ä½•åœ–ç‰‡å—Žï¼Ÿ" destroy: notice: "相片刪掉了。" - edit: - editing: "編輯ä¸" - new: - back_to_list: "回列表" - new_photo: "新相片" - post_it: "貼上ï¼" new_photo: empty: "檔案 {file} 是空的,請é‡æ–°æŒ‘é¸æª”案,且ä¸è¦å†é¸å®ƒã€‚" invalid_ext: "檔案 {file} 的副檔åä¸åˆæ ¼ã€‚åªæŽ¥å—{extensions}。" size_error: "檔案 {file} 太大了,上é™æ˜¯{sizeLimit}。" new_profile_photo: - or_select_one_existing: "æˆ–å¾žä½ æ—¢æœ‰çš„%{photos}ä¸æŒ‘é¸ä¸€å¼µ" upload: "上傳新的個人照ï¼" - photo: - view_all: "檢視 %{name} 所有的相片" show: - collection_permalink: "收集的éœæ…‹é€£çµ" - delete_photo: "刪除相片" - edit: "編輯" - edit_delete_photo: "編輯相片敘述或刪除相片" - make_profile_photo: "é¸ç‚ºå€‹äººç…§" show_original_post: "顯示原文" - update_photo: "更新相片" - update: - error: "相片編輯失敗。" - notice: "相片更新æˆåŠŸã€‚" + polls: + votes: + other: "ç›®å‰ç‚ºæ¢æœ‰%{count}個人投票" + zero: "ç›®å‰ç‚ºæ¢æ²’人投票" posts: presenter: title: "來自 %{name} 的貼文" show: - destroy: "刪除" forbidden: "ä½ ä¸èƒ½é€™éº¼åš" - not_found: "抱æ‰ï¼Œæ‰¾ä¸åˆ°è©²ç¯‡è²¼æ–‡ã€‚" - permalink: "éœæ…‹é€£çµ" + location: "貼文地點:%{location}" photos_by: other: "%{author} æ‹çš„%{count}張相片" zero: "沒有 %{author} æ‹çš„相片" reshare_by: "%{author} 轉貼" - previous: "å‰é¢" privacy: "éš±ç§" - privacy_policy: "éš±ç§æ¬Šæ”¿ç–" profile: "個人檔案" profiles: edit: allow_search: "讓其他 diaspora* 使用者å¯ä»¥æœå°‹ä½ " - edit_profile: "編輯個人檔案" + basic: "基本個人檔案" + basic_hint: "個人檔案ä¸çš„æ¯å€‹é …目都å¯ä»¥ä¸å¡«ã€‚基本個人檔案永é 都是公開的。" + extended: "進階個人檔案" + extended_hint: "點一下切æ›æŒ‰éˆ•å¯ä»¥è¨å®šé€²éšŽå€‹äººæª”案資料的能見度。公開是指網路上的人都å¯ä»¥çœ‹å¾—到,å—é™å‰‡æ˜¯åªæœ‰è·Ÿä½ 分享的人æ‰èƒ½çœ‹å¾—到裡é¢çš„內容。" + extended_visibility_text: "進階個人檔案的能見度:" first_name: "åå—(å‰)" last_name: "åå—(後)" + limited: "å—é™" nsfw_check: "把我分享的所有æ±è¥¿éƒ½æ¨™ç¤ºç‚ºä¸Šç時ä¸å®œ(NSFW)" nsfw_explanation: "在 diaspora* 社群裡,å°æ–¼ä¸é©åˆåœ¨ä¸Šç時看的內容,是採用\"上ç時ä¸å®œ\"(NSFW)這種自我管ç†æ©Ÿåˆ¶ã€‚å¦‚æžœä½ æœƒå¸¸å¸¸ç™¼è¡¨é€™é¡žé¡Œæ,å¯ä»¥å‹¾é¸é€™å€‹é¸é …ï¼Œé‚£éº¼ä½ åˆ†äº«çš„æ±è¥¿å°±ä¸æœƒç›´æŽ¥é¡¯ç¤ºåœ¨å…¶å®ƒäººçš„æµæ°´å¸³ä¸ï¼Œé™¤éžä»–們去點來看。" nsfw_explanation2: "å¦‚æžœä½ æ²’æœ‰å‹¾é¸é€™å€‹é¸é …ï¼Œé‚£éº¼ç•¶ä½ è¦åˆ†äº«ä¸Šç時ä¸å®œçš„é¡Œææ™‚ï¼Œè«‹åŠ ä¸Š #nsfw 這個標籤。" + public: "公開" + settings: "個人檔案è¨å®š" update_profile: "更新個人檔案" your_bio: "ä½ çš„è‡ªæˆ‘ä»‹ç´¹" your_birthday: "ä½ çš„ç”Ÿæ—¥" @@ -929,10 +877,8 @@ zh-TW: your_location: "ä½ æ‰€åœ¨çš„åœ°æ–¹" your_name: "ä½ çš„åå—" your_photo: "ä½ çš„ç›¸ç‰‡" - your_private_profile: "ä½ çš„ç§äººæª”案" - your_public_profile: "ä½ çš„å…¬é–‹æª”æ¡ˆ" your_tags: "用五個詞來表ç¾ä½ 自己" - your_tags_placeholder: "åƒæ˜¯: #電影 #貓咪 #æ—…è¡Œ #è€å¸« #ç´ç´„" + your_tags_placeholder: "åƒæ˜¯: #電影 #喵星人 #æ—…è¡Œ #è€å¸« #å°åŒ—" update: failed: "個人檔案更新失敗" updated: "個人檔案已經更新了" @@ -944,26 +890,16 @@ zh-TW: closed: "這個 diaspora* 豆莢ä¸é–‹æ”¾è¨»å†Šã€‚" create: success: "ä½ å·²ç¶“æˆåŠŸåŠ å…¥ diaspora* 了ï¼" - edit: - cancel_my_account: "å–消我的帳號" - edit: "編輯 %{name}" - leave_blank: "(ä¸æƒ³è®Šæ›´å‰‡è«‹ç•™ç™½)" - password_to_confirm: "(我們需è¦ä½ ç›®å‰çš„密碼以確èªä½ è¦è®Šæ›´)" - unhappy: "ä¸æ»¿æ„嗎?" - update: "æ›´æ–°" invalid_invite: "ä½ æ供的邀請連çµå·²ç¶“失效了ï¼" new: - create_my_account: "開我的帳號ï¼" email: "é›»åä¿¡ç®±" enter_email: "輸入電åä¿¡ç®±" enter_password: "輸入密碼(至少å…個å—)" enter_password_again: "輸入與å‰é¢ç›¸åŒçš„密碼" - enter_username: "é¸å€‹ä½¿ç”¨è€…å稱(å稱åªèƒ½åŒ…å«æ‹‰ä¸å—æ¯ï¼Œæ•¸å—,以åŠåº•ç·šå—å…ƒ)" - join_the_movement: "åƒèˆ‡é€™å€‹é‹å‹•ï¼" + enter_username: "é¸å€‹ä½¿ç”¨è€…å稱(å稱åªèƒ½åŒ…å«æ‹‰ä¸å—æ¯ã€æ•¸å—ã€ä»¥åŠåº•ç·šå—å…ƒ)" password: "密碼" password_confirmation: "密碼確èª" - sign_up: "註冊" - sign_up_message: "有♥的社交網路" + sign_up: "註冊新帳號" submitting: "æ交ä¸..." terms: "ä¸€æ—¦è¨»å†Šå¸³è™Ÿå°±è¡¨ç¤ºä½ æŽ¥å— %{terms_link} 。" terms_link: "æœå‹™æ¢æ¬¾" @@ -976,47 +912,18 @@ zh-TW: post_label: "<b>貼文</b>: %{title}" reason_label: "ç†ç”±: %{text}" reported_label: "<b>å›žå ±äºº<b> %{person}" + reported_user_details: "è¢«èˆ‰å ±ä½¿ç”¨è€…çš„è©³ç´°è³‡æ–™" review_link: "標記為看éŽäº†" status: - created: "ç”¢ç”Ÿäº†ä¸€ä»½å›žå ±" destroyed: "貼文已經被銷毀了" failed: "發生å•é¡Œäº†" - marked: "å·²ç¶“æŠŠé€™ä»½å›žå ±æ¨™è¨˜ç‚ºçœ‹éŽäº†" title: "å›žå ±ç¸½è¦½" - requests: - create: - sending: "傳é€ä¸" - sent: "已經è¦æ±‚å’Œ %{name} 分享貼文了。他們下次登入diaspora* 時就會看見。" - destroy: - error: "è«‹é¸æŸä¸€é¢ï¼" - ignore: "ä¸ç†æœƒå»ºç«‹è¯ç¹«çš„請求。" - success: "ä½ å€‘ç¾åœ¨äº’相分享了。" - helper: - new_requests: - other: "有%{count}個新請求ï¼" - zero: "沒有新請求" - manage_aspect_contacts: - existing: "既有è¯çµ¡äºº" - manage_within: "管ç†ä»¥ä¸‹ç¤¾äº¤é¢ä¸çš„è¯çµ¡äººï¼š" - new_request_to_person: - sent: "é€å‡ºåŽ»äº†ï¼" reshares: comment_email_subject: "%{resharer} 轉貼了 %{author} 的貼文" - create: - failure: "轉貼這篇貼文時發生錯誤。" reshare: deleted: "原貼文已經被作者刪除了。" - reshare: - few: "被轉貼%{count}次" - many: "被轉貼%{count}次" - one: "被轉貼1次" - other: "被轉貼%{count}次" - two: "%{count}次轉貼" - zero: "轉貼" reshare_confirmation: "è¦è½‰è²¼ %{author} 的貼文嗎?" - reshare_original: "轉貼原文" reshared_via: "轉貼來自" - show_original: "顯示原文" search: "æœå°‹" services: create: @@ -1028,72 +935,35 @@ zh-TW: success: "èªè‰åˆªé™¤æˆåŠŸã€‚" failure: error: "與該外部æœå‹™é€£çµæ™‚發生錯誤" - finder: - fetching_contacts: "diaspora* æ£åœ¨å–å¾—ä½ åœ¨ %{service} 的朋å‹è³‡æ–™ï¼Œè«‹å¹¾åˆ†é˜å¾Œå†ä¾†çœ‹çœ‹ã€‚" - no_friends: "沒有 Facebook 朋å‹ã€‚" - service_friends: "%{service} 朋å‹" index: connect: "連çµ" disconnect: "åœæ¢é€£çµ" edit_services: "編輯外部æœå‹™" logged_in_as: "已經以 %{nickname} 登入了。" - no_services_available: "這個豆莢目å‰ä¸æ供跟外部æœå‹™é€£çµã€‚" + no_services_available: "這個豆莢目å‰ä¸æ供跟第三方æœå‹™é€£çµã€‚" not_logged_in: "ç›®å‰é‚„沒登入。" really_disconnect: "è¦åœæ¢å’Œ %{service} 連çµå—Žï¼Ÿ" - services_explanation: "和其他外部æœå‹™é€£çµå¯ä»¥è®“ä½ åœ¨ diaspora* 貼文時åŒæ™‚發表到這些æœå‹™åŽ»ã€‚" - inviter: - click_link_to_accept_invitation: "請按這個連çµä¾†æŽ¥å—邀請" - join_me_on_diaspora: "è·Ÿæˆ‘ä¸€èµ·åŠ å…¥ diaspora*" + services_explanation: "和第三方æœå‹™é€£çµå¯ä»¥è®“ä½ åœ¨ diaspora* 貼文時,åŒæ™‚發表到這些æœå‹™åŽ»ã€‚" + share_to: "分享到%{provider}" + title: "管ç†é€£çµä¸çš„外部æœå‹™" provider: facebook: "Facebook" tumblr: "Tumblr" twitter: "Twitter" wordpress: "WordPress" - remote_friend: - invite: "邀請" - not_on_diaspora: "還沒在 diaspora* 註冊" - resend: "é‡é€" settings: "è¨å®š" - share_visibilites: - update: - post_hidden_and_muted: "%{name} 的貼文已經隱è—了,異動時也ä¸æœƒæœ‰æ¶ˆæ¯é€šçŸ¥ã€‚" - see_it_on_their_profile: "å¦‚æžœä½ æƒ³çœ‹é€™ç¯‡è²¼æ–‡çš„æ›´æ–°ï¼Œè«‹åˆ° %{name} 的個人é é¢ã€‚" shared: - add_contact: - add_new_contact: "åŠ å…¥æ–°è¯çµ¡äºº" - create_request: "用 diaspora* 帳號æœå°‹" - diaspora_handle: "diaspora@pod.org" - enter_a_diaspora_username: "輸入 diaspora* 使用者å稱:" - know_email: "知é“他們的電åä¿¡ç®±å—Žï¼Ÿä½ æ‡‰è©²é‚€è«‹ä»–å€‘ä¾†" - your_diaspora_username_is: "ä½ çš„ diaspora* 使用者å稱是:%{diaspora_handle}" aspect_dropdown: - add_to_aspect: "åŠ è¯çµ¡äºº" mobile_row_checked: "%{name} (移除)" mobile_row_unchecked: "%{name} (新增)" toggle: - few: "在%{count}個é¢å‘ä¸" - many: "在%{count}個é¢å‘ä¸" - one: "在%{count}個é¢å‘ä¸" other: "在%{count}個社交é¢ä¸" - two: "在%{count}個é¢å‘ä¸" zero: "åŠ è¯çµ¡äºº" - contact_list: - all_contacts: "所有è¯çµ¡äºº" - footer: - logged_in_as: "已經以 %{name} 登入" - your_aspects: "ä½ çš„ç¤¾äº¤é¢" invitations: by_email: "用電å郵件" - dont_have_now: "ç›®å‰ä½ é‚„ä¸èƒ½é‚€è«‹ä»»ä½•äººï¼Œä½†å¾ˆå¿«å°±å¯ä»¥äº†ï¼" - from_facebook: "從 Facebook" - invitations_left: "剩餘%{count}å¼µ" - invite_someone: "邀請æŸäººä¾†" invite_your_friends: "é‚€è«‹ä½ çš„æœ‹å‹" invites: "邀請" - invites_closed: "這個 diaspora* 豆莢目å‰ä¸é–‹æ”¾é‚€è«‹" share_this: "將這個連çµé€éŽé›»å郵件ã€éƒ¨è½æ ¼ï¼Œæˆ–其他社交網站分享出去ï¼" - notification: - new: "%{from} 有新的%{type}" public_explain: atom_feed: "Atom 資訊æº" control_your_audience: "æŽ§åˆ¶ä½ çš„è½çœ¾" @@ -1105,12 +975,9 @@ zh-TW: title: "è¨å®šå¤–部æœå‹™é€£çµ" visibility_dropdown: "用這個下拉å¼é¸å–®ä¾†æ”¹è®Šè²¼æ–‡çš„å¯è¦‹ç¯„åœã€‚(建è°ä½ 這篇首貼è¨ç‚ºå…¬é–‹ã€‚)" publisher: - all: "全部" - all_contacts: "所有è¯çµ¡äºº" discard_post: "æ¨æ£„貼文" formatWithMarkdown: "ä½ å¯ä»¥ç”¨%{markdown_link}å°‡è²¼æ–‡åŠ æ ¼å¼" get_location: "å–å¾—ä½ æ‰€åœ¨çš„åœ°é»ž" - make_public: "公開" new_user_prefill: hello: "大家好,我是 #%{new_user_tag}。" i_like: "æˆ‘å° %{tags} 有興趣。" @@ -1118,36 +985,14 @@ zh-TW: newhere: "新來的" poll: add_a_poll: "新增一輪投票" - add_poll_answer: "å¢žåŠ é¸é …" - option: "é¸é … 1" - question: "å•é¡Œ" - remove_poll_answer: "移除é¸é …" - post_a_message_to: "å°%{aspect}發表訊æ¯" posting: "發表ä¸..." - preview: "é 覽" - publishing_to: "發表至:" remove_location: "移除ä½ç½®è³‡è¨Š" share: "分享" - share_with: "è·Ÿä»–/她分享:" - upload_photos: "上傳照片" + upload_photos: "上傳相片" whats_on_your_mind: "在想什麼呢?" - reshare: - reshare: "轉貼" stream_element: - connect_to_comment: "請先和作者建立è¯ç¹«æ‰èƒ½ç•™è¨€åœ¨ä»–們的貼文" - currently_unavailable: "ç›®å‰ä¸èƒ½ç•™è¨€" - dislike: "éœ" - hide_and_mute: "éš±è—貼文並消音" - ignore_user: "忽視 %{name}" - ignore_user_description: "是å¦è¦å¿½è¦–這個使用者,並把他/她從所有社交é¢ä¸ç§»é™¤å‘¢ï¼Ÿ" - like: "讚" - nsfw: "這篇貼文被作者標示為 NSFW (上ç時ä¸å®œ)。 %{link}" - shared_with: "分享給:%{aspect_names}" - show: "顯示" - unlike: "收回讚" via: "經由%{link}" via_mobile: "經由行動è£ç½®" - viewable_to_anyone: "任何上網的人都能看到這篇貼文" simple_captcha: label: "請輸入方塊ä¸é¡¯ç¤ºçš„密碼:" message: @@ -1161,9 +1006,9 @@ zh-TW: closed: "關閉" disabled: "ä¸å¯ç”¨" enabled: "å¯ç”¨" - local_comments: "本機留言發表é‡" - local_posts: "當地貼文é‡" - name: "åå—" + local_comments: "本地留言發表é‡" + local_posts: "本地貼文é‡" + name: "å稱" network: "網路" open: "開放" registrations: "註冊狀態" @@ -1173,20 +1018,12 @@ zh-TW: status_messages: create: success: "指指點點æˆåŠŸï¼š%{names}" - destroy: - failure: "刪除貼文失敗" - helper: - no_message_to_display: "沒有訊æ¯å¯é¡¯ç¤ºã€‚" new: mentioning: "指指點點ä¸ï¼š%{person}" too_long: "狀態訊æ¯è«‹åœ¨ %{count} å—內。目å‰å—數是 %{current_length}" stream_helper: - hide_comments: "éš±è—所有留言" no_more_posts: "ä½ å·²ç¶“æŠµé”æµæ°´å¸³çš„最下游了。" no_posts_yet: "ç›®å‰é‚„沒有任何貼文。" - show_comments: - other: "顯示å¦å¤–%{count}則留言" - zero: "沒有其它留言" streams: activity: title: "我的活動" @@ -1202,7 +1039,7 @@ zh-TW: title: "#追蹤ä¸çš„標籤" followed_tags_stream: "#追蹤ä¸çš„標籤" like_stream: - title: "讚的æµæ°´å¸³" + title: "稱讚的æµæ°´å¸³" mentioned_stream: "@指指點點" mentions: title: "@指指點點" @@ -1213,13 +1050,6 @@ zh-TW: tags: title: "有以下標籤的貼文:%{tags}" tag_followings: - create: - failure: "追蹤 #%{name} 失敗。是å¦å·²ç¶“在追蹤了?" - none: "ä¸èƒ½å¤ 追蹤空白標籤ï¼" - success: "喔耶ï¼ä½ 已經開始追蹤 #%{name} 了。" - destroy: - failure: "åœæ¢è¿½è¹¤æ¨™ç±¤ #%{name} å¤±æ•—ã€‚ä¹Ÿè¨±ä½ å·²ç¶“æ²’åœ¨è¿½è¹¤äº†å§ï¼Ÿ" - success: "唉ï¼ä½ 從æ¤ä¸å†è¿½è¹¤æ¨™ç±¤ #%{name} 了。" manage: no_tags: "ä½ æ²’æœ‰è¿½è¹¤ä»»ä½•æ¨™ç±¤ã€‚" title: "管ç†è¿½è¹¤ä¸çš„標籤" @@ -1227,19 +1057,16 @@ zh-TW: name_too_long: "請讓標籤長度少於 %{count} 個å—元。目å‰å—元數是 %{current_length}" show: follow: "追蹤 #%{tag}" - following: "æ£åœ¨è¿½è¹¤ #%{tag}" none: "ä¸å˜åœ¨ç©ºç™½æ¨™ç±¤ï¼" stop_following: "åœæ¢è¿½è¹¤ #%{tag}" tagged_people: other: "有 %{count} 個人貼了標籤 %{tag}" zero: "沒有人貼了標籤 %{tag}" - terms_and_conditions: "æœå‹™æ¢æ¬¾èˆ‡ç´°å‰‡" - undo: "還原?" username: "使用者å稱" users: confirm_email: - email_confirmed: "é›»åä¿¡ç®± %{email} 已經啟用了" - email_not_confirmed: "無法啟用電å信箱。連çµä¸å°å—Žï¼Ÿ" + email_confirmed: "é›»åä¿¡ç®± %{email} 已經開通了" + email_not_confirmed: "無法開通電å信箱。連çµä¸å°å—Žï¼Ÿ" destroy: no_password: "è«‹è¼¸å…¥ä½ ç›®å‰çš„密碼來關帳號。" success: "ä½ çš„å¸³è™Ÿå·²ç¶“éŽ–å®šäº†ã€‚å®Œæˆé—œé–‰å¸³è™Ÿå¤§ç´„é‚„éœ€è¦ 20 分é˜çš„時間,感è¬ä½ 試用 diaspora*" @@ -1247,19 +1074,19 @@ zh-TW: edit: also_commented: "æœ‰äººä¹Ÿç•™è¨€åœ¨ä½ ç•™è¨€éŽçš„貼文" auto_follow_aspect: "è‡ªå‹•è¢«åŠ å…¥è¯çµ¡äººçš„所屬社交é¢ï¼š" - auto_follow_back: "å°ä¸»å‹•è¦æ±‚è·Ÿä½ åˆ†äº«çš„ä½¿ç”¨è€…è‡ªå‹•é–‹å§‹åˆ†äº«" + auto_follow_back: "å°ä¸»å‹•è¦æ±‚è·Ÿä½ åˆ†äº«çš„ä½¿ç”¨è€…è‡ªå‹•é–‹å§‹äº’ç›¸åˆ†äº«" change: "更改" + change_color_theme: "改色彩主題" change_email: "更改電åä¿¡ç®±" change_language: "更改語言" change_password: "更改密碼" character_minimum_expl: "至少è¦å…個å—" close_account: dont_go: "啊,請ä¸è¦èµ°ï¼" - if_you_want_this: "å¦‚æžœä½ ç¢ºå®šè¦é—œé–‰å¸³è™Ÿï¼Œè«‹åœ¨ä¸‹æ–¹è¼¸å…¥ä½ 的密碼,然後按'關閉帳號'" lock_username: "ä½ çš„ä½¿ç”¨è€…å稱會被鎖定,在åŒä¸€å€‹è±†èŽ¢å…§ä¸èƒ½ç”¨èˆŠå¸³è™Ÿé‡æ–°è¨»å†Šã€‚" locked_out: "ç³»çµ±æœƒå°‡ä½ ç™»å‡ºï¼Œä¸”ç„¡æ³•é‡æ–°ç™»å…¥ï¼Œæœ€å¾Œå¸³è™Ÿæœƒè¢«åˆªæŽ‰ã€‚" make_diaspora_better: "å¸Œæœ›ä½ èƒ½å¹«åŠ©æˆ‘å€‘è®“ diaspora* 更好,而ä¸æ˜¯é¸æ“‡é›¢é–‹ã€‚ä½†æ˜¯å¦‚æžœä½ çœŸçš„æƒ³é—œé–‰å¸³è™Ÿï¼Œé€™æ˜¯æŽ¥ä¸‹ä¾†çš„ç¨‹åºï¼š" - mr_wiggles: "Mr Wiggles çœ‹åˆ°ä½ èµ°æœƒå¾ˆé›£éŽ" + mr_wiggles: "æ–å°¾å·´å…ˆç”Ÿçœ‹åˆ°ä½ èµ°æœƒå¾ˆé›£éŽ" no_turning_back: "一旦確定刪除則無法復原。如果確定è¦åˆªé™¤å¸³è™Ÿï¼Œè«‹åœ¨ä¸‹æ–¹è¼¸å…¥ä½ 的密碼。" what_we_delete: "æˆ‘å€‘æœƒå„˜å¿«åˆªé™¤ä½ çš„è²¼æ–‡å’Œå€‹äººæª”æ¡ˆã€‚ä½ å°å…¶ä»–使用者貼文的留言ä»ç„¶ä¿ç•™ï¼Œä½†æœƒä»¥ diaspora* 帳號顯示,而éžä½ 的使用者å稱。" close_account_text: "關閉帳號" @@ -1268,16 +1095,14 @@ zh-TW: current_password_expl: "登入時那一個..." download_export: "下載個人檔案" download_export_photos: "下載相片" - download_photos: "下載我的相片" edit_account: "編輯帳號" - email_awaiting_confirmation: "我們已經將啟用連çµå¯„到 %{unconfirmed_email} çµ¦ä½ ã€‚åœ¨ä½ é»žè©²é€£çµå•Ÿç”¨æ–°çš„信箱之å‰ï¼Œæˆ‘å€‘é‚„æ˜¯æœƒç¹¼çºŒä½¿ç”¨ä½ åŽŸä¾†çš„ä¿¡ç®±ï¼Œä¹Ÿå°±æ˜¯ %{email}。" + email_awaiting_confirmation: "我們已經將開通連çµå¯„到 %{unconfirmed_email} çµ¦ä½ ã€‚åœ¨ä½ é»žè©²é€£çµé–‹é€šæ–°çš„é›»å信箱之å‰ï¼Œæˆ‘å€‘é‚„æ˜¯æœƒç¹¼çºŒä½¿ç”¨ä½ åŽŸä¾†çš„ä¿¡ç®±ï¼Œä¹Ÿå°±æ˜¯ %{email}。" export_data: "資料匯出" export_in_progress: "我們æ£åœ¨è™•ç†ä½ 的資料,請ç¨ç‰ä¸€ä¸‹å†ä¾†çœ‹çœ‹ã€‚" export_photos_in_progress: "æ£åœ¨è™•ç†ä½ 的相片ä¸ã€‚è«‹ç‰ä¸€ä¸‹å†å›žä¾†çœ‹çœ‹ã€‚" following: "分享è¨å®š" - getting_started: "新使用者å好è¨å®š" last_exported_at: "(最後一次是在 %{timestamp} æ›´æ–°)" - liked: "有人å°ä½ 的貼文說讚" + liked: "æœ‰äººç¨±è®šä½ çš„è²¼æ–‡" mentioned: "有貼文æåˆ°äº†ä½ " new_password: "新的密碼" private_message: "收到ç§äººè¨Šæ¯" @@ -1290,19 +1115,18 @@ zh-TW: show_community_spotlight: "在æµæ°´å¸³é¡¯ç¤ºç¤¾ç¾¤ç„¦é»ž" show_getting_started: "展示「入門指å—ã€" someone_reported: "有人寄了一å°å›žå ±" - started_sharing: "æœ‰äººé–‹å§‹å’Œä½ åˆ†äº«è²¼æ–‡" + started_sharing: "æœ‰äººé–‹å§‹è·Ÿä½ åˆ†äº«è²¼æ–‡" stream_preferences: "æµæ°´å¸³å好è¨å®š" - your_email: "ä½ çš„é›»å郵件" - your_email_private: "其他使用者看ä¸åˆ°ä½ çš„é›»å郵件信箱" + your_email: "ä½ çš„é›»åä¿¡ç®±" + your_email_private: "其他使用者看ä¸åˆ°ä½ çš„é›»åä¿¡ç®±" your_handle: "ä½ çš„ diaspora* è˜åˆ¥ç¢¼" getting_started: awesome_take_me_to_diaspora: "帥ï¼å¸¶æˆ‘去 diaspora* å§" community_welcome: "diaspora* 社群æ¡è¿Žä½ çš„åŠ å…¥ï¼" - connect_to_facebook: "diaspora* å¯ä»¥é€£çµè‡‰æ›¸å¸³è™Ÿ%{link} ,å–ç”¨ä½ çš„è‡‰æ›¸å§“åå’Œé åœ–ä¾†å¹«ä½ å¿«é€Ÿå®Œæˆè¨å®š ,åŒæ™‚開啟跨站貼文。" + connect_to_facebook: "diaspora* å¯ä»¥%{link} ,å–ç”¨ä½ åœ¨ Facebook 的姓åå’Œå€‹äººç…§ä¾†å¹«ä½ å¿«é€Ÿå®Œæˆè¨å®š ,åŒæ™‚開啟跨站貼文。" connect_to_facebook_link: "é€£çµ Facebook 帳號" hashtag_explanation: "æ¨™ç±¤è®“ä½ å¯ä»¥è¨Žè«–åŠè¿½è¹¤ä½ 有興趣的話題。也是在 diaspora* 找到新朋å‹çš„好方法。" hashtag_suggestions: "試試看追蹤åƒæ˜¯ #è—è¡“, #電影, #gif ç‰æ¨™ç±¤ã€‚" - saved: "å˜å¥½äº†ï¼" well_hello_there: "å—¨ï¼Œä½ å¥½ï¼" what_are_you_in_to: "ä½ å°ä»€éº¼æœ‰èˆˆè¶£ï¼Ÿ" who_are_you: "ä½ æ˜¯èª°ï¼Ÿ" @@ -1310,11 +1134,13 @@ zh-TW: ignored_users: "忽視的使用者" no_user_ignored_message: "ç›®å‰æ²’有忽視任何的其他人" stop_ignoring: "åœæ¢å¿½è¦–" - strip_exif: "上傳照片時移除裡é¢çš„æ述資料,åƒæ˜¯æ‹æ”地點,æ‹æ”人,相機型號ç‰ç‰(建è°é–‹å•Ÿ)" + strip_exif: "上傳圖片時移除裡é¢çš„æ述資料,åƒæ˜¯æ‹æ”地點,æ‹æ”人,相機型號ç‰ç‰(建è°é–‹å•Ÿ)" title: "éš±ç§è¨å®š" public: does_not_exist: "ä¸å˜åœ¨ %{username} 這個使用者ï¼" update: + color_theme_changed: "更改色彩主題æˆåŠŸã€‚" + color_theme_not_changed: "更改色彩主題時發生了錯誤。" email_notifications_changed: "電郵通知已經更改了" follow_settings_changed: "追蹤è¨å®šæ”¹è®Šäº†" follow_settings_not_changed: "追蹤è¨å®šæ”¹è®Šå¤±æ•—。" @@ -1324,15 +1150,8 @@ zh-TW: password_not_changed: "密碼更改失敗" settings_not_updated: "è¨å®šæ›´æ–°å¤±æ•—" settings_updated: "è¨å®šæ›´æ–°äº†" - unconfirmed_email_changed: "é›»åä¿¡ç®±å·²ç¶“è®Šæ›´äº†ã€‚å¿…é ˆè¦å•Ÿå‹•ä½¿ç”¨ã€‚" + unconfirmed_email_changed: "é›»åä¿¡ç®±å·²ç¶“è®Šæ›´äº†ã€‚å¿…é ˆè¦é‡æ–°é–‹é€šã€‚" unconfirmed_email_not_changed: "é›»å信箱更改失敗" - webfinger: - fetch_failed: "æ“·å– %{profile_url} çš„ webfinger 個人檔案失敗" - hcard_fetch_failed: "æ“·å– %{account} çš„ hcard 資料時發生錯誤" - no_person_constructed: "從這份 hcard 資料無法組出è¯çµ¡äººã€‚" - not_enabled: "帳號​ %{account} 的主機似乎沒有啟用 webfinger" - xrd_fetch_failed: "å–得帳號 %{account} çš„ xrd 資料時發生錯誤" - welcome: "æ¡è¿Žï¼" will_paginate: next_label: "å¾Œé¢ »" previous_label: "« å‰é¢" \ No newline at end of file diff --git a/config/locales/javascript/javascript.ar.yml b/config/locales/javascript/javascript.ar.yml index 7dd2b1cc35ff127a8ec14b5e35d48ef4f1981b0b..e332f0387f3cd41c63178994e76802afafa9f59f 100644 --- a/config/locales/javascript/javascript.ar.yml +++ b/config/locales/javascript/javascript.ar.yml @@ -55,20 +55,16 @@ ar: hide_post: "أأخÙ٠هذه التدوينة؟" hide_post_failed: "تعذّر إخÙاء هذه التدوينة" ignore: "تجاهل" - infinite_scroll: - no_more: "لا توجد مشاركات أخرى," my_activity: "نشاطى" my_stream: "ساØØ© المشاركات" photo_uploader: looking_good: "يا إلهى , تبدو رائعاً !" publisher: - at_least_one_aspect: "Øدد Ùئة واØدة على الأقل" limited: "Ù…Øدودة - مشاركتك ستكون متاØØ© لجهات إتصالك Ùقط" public: "عام - مشاركتك ستكون متاØØ© للجميع ومÙهرسة ÙÙŠ Ù…Øركات البØØ«" remove_post: "أأزيل هذه التدوينة؟" reshares: duplicate: "رائع، أليس كذلك؟ أعدت نشر هذه المشاركة مسبقا" - search_for: "إبØØ« عن <%= name %>" show_more: "المزيد" stream: comment: "تعليق" @@ -109,27 +105,22 @@ ar: wasnt_that_interesting: "OK, I suppose #<%= tagName %> wasn't all that interesting..." timeago: day: "يوم" - days: "%d أيام" + days: + other: "%d أيام" hour: "ساعة تقريباً" - hours: "منذ %d ساعات" + hours: + other: "منذ %d ساعات" minute: "دقيقة تقريباً" - minutes: "%d دقائق" + minutes: + other: "%d دقائق" month: "شهر تقريباً" - months: "%d شهور" + months: + other: "%d شهور" prefixAgo: "قبل" prefixFromNow: "من الآن" seconds: "أقل من دقيقة" suffixAgo: "مضت" suffixFromNow: "من اﻵن" year: "عام تقريباً" - years: "%d أعوام" - videos: - unknown: "نوع Ùيديو غير معروÙ" - watch: "شاهد هذا الÙيديو عبر <%= provider %>" - viewer: - comment: "تعليق" - follow_post: "اتبع المشاركة" - like: "أعجبنى" - reshare: "أعد المشاركة" - stop_following_post: "توق٠عن متابعة المشاركة" - unlike: "إلغاء إعجابى" \ No newline at end of file + years: + other: "%d أعوام" \ No newline at end of file diff --git a/config/locales/javascript/javascript.art-nvi.yml b/config/locales/javascript/javascript.art-nvi.yml index 14e5f5daaf4cf7f24027573ee20f48bf774ed549..cd7d4cfa321fbd401a3bcee35c8d13bea83b987b 100644 --- a/config/locales/javascript/javascript.art-nvi.yml +++ b/config/locales/javascript/javascript.art-nvi.yml @@ -22,11 +22,8 @@ art-nvi: recent_notifications: "Upxare asop" search: "fwew" view_all: "Tse'a nìwotx" - infinite_scroll: - no_more: "Kea nì'ul upxare" my_activity: "Oeyä Tìn" my_stream: "Payfya" - search_for: "fwew <%= name %>ìri" show_more: "wìntxu nì'ul" stream: comment: "plltxe" @@ -36,19 +33,15 @@ art-nvi: unlike: "Ke Sunu" timeago: day: "trr" - days: "%d srr" + days: + other: "%d srr" month: "vospxì" - months: "%d ayvospxì" + months: + other: "%d ayvospxì" prefixAgo: "" prefixFromNow: "" suffixAgo: "" suffixFromNow: "" year: "zìsìt" - years: "%d ayzìsìt" - videos: - unknown: "rusikxa rol fnel astxong" - watch: "Tse'a fìrusikxa rolit <%= provider %>mì" - viewer: - home: "KELUTRAL" - like: "Sunu" - unlike: "Ke Sunu" \ No newline at end of file + years: + other: "%d ayzìsìt" \ No newline at end of file diff --git a/config/locales/javascript/javascript.bg.yml b/config/locales/javascript/javascript.bg.yml index 997b67689ea33fc2d5543737019df70ca4dd07a1..53d1e1c8cc655ec4f3617b9e8997e36a359dec96 100644 --- a/config/locales/javascript/javascript.bg.yml +++ b/config/locales/javascript/javascript.bg.yml @@ -46,18 +46,14 @@ bg: settings: "ÐаÑтройки" view_all: "Покажи вÑички" ignore: "Игнориране" - infinite_scroll: - no_more: "ÐÑма други публикации." my_stream: "Поток" photo_uploader: looking_good: "Леле, изглеждате Ñтрахотно!" publisher: - at_least_one_aspect: "ТрÑбва да публикувате в поне един аÑпект" limited: "Ограничено - публикациÑта ще бъде видима Ñамо за хората, Ñ ÐºÐ¾Ð¸Ñ‚Ð¾ Ñ Ñподелите" public: "Публично - публикациÑта ще бъде видима за вÑеки, а Ñъдържанието Ñ Ñ‰Ðµ бъде налично за Ñ‚ÑŠÑ€Ñещите машини" reshares: duplicate: "Вече Ñте Ñподелили публикациÑта!" - search_for: "ТърÑене за <%= name %>" show_more: "покажи още" stream: comment: "Коментиране" @@ -87,20 +83,22 @@ bg: wasnt_that_interesting: "Е, вероÑтно марката #<%= tagName %> не е чак толкова интереÑна..." timeago: day: "ден" - days: "%d дни" + days: + other: "%d дни" hour: "около чаÑ" - hours: "около %d чаÑа" + hours: + other: "около %d чаÑа" minute: "около минута" - minutes: "%d минути" + minutes: + other: "%d минути" month: "около меÑец" - months: "%d меÑеца" + months: + other: "%d меÑеца" prefixAgo: "преди" prefixFromNow: "Ñлед" seconds: "по-малко от минута" suffixAgo: "преди" suffixFromNow: "от Ñега" year: "около година" - years: "%d години" - videos: - unknown: "ÐеизвеÑтен вид видео" - watch: "Гледайте видеото в <%= provider %>" \ No newline at end of file + years: + other: "%d години" \ No newline at end of file diff --git a/config/locales/javascript/javascript.br.yml b/config/locales/javascript/javascript.br.yml index f62f3098d387d4ab6a8253cc1e747a18210aded2..1cee930404b342756ad7a7e801279f9324a1f5b1 100644 --- a/config/locales/javascript/javascript.br.yml +++ b/config/locales/javascript/javascript.br.yml @@ -30,8 +30,6 @@ br: no_comments: "Evezhiadenn ebet evit ar mare" show: "Diskwel an holl evezhiadennoù" confirm_dialog: "Ha sur oc'h ?" - conversation: - participants: "Perzhidi" delete: "Diverkañ" edit: "Kemmañ" failed_to_like: "C'hwitet merkañ plijus !" @@ -59,9 +57,6 @@ br: view_all: "Gwelet pep tra" ignore: "Na ober van" ignore_user: "Na ober van ouzh an implijer-mañ ?" - infinite_scroll: - no_more: "Kemennadenn all ebet" - no_more_contacts: "Darempred ebet ken" my_activity: "Ma obererezh" my_aspects: "Ma strolladoù" my_stream: "Red darvoudoù" @@ -93,21 +88,18 @@ br: contacts: "Darempredoù" edit: "Embann" gender: "Jener" - ignoring: "Ne rit ket van eus an holl postoù gant <%= name %>" location: "Lec'hiadur" photos: "Skeudennoù" posts: "Postoù" you_have_no_tags: "N'ho peus tiked ebet !" publisher: add_option: "Ouzhpennañ un dibarzh" - at_least_one_aspect: "Dav eo deoc'h embann un arvez da'n nebeutañ" option: "Dibarzh <%= nr %>" question: "Goulenn" reshares: duplicate: "Kaset eo bet an destenn-mañ pelloc'h ganeoc'h c'hoazh !" post: "Rannañ pelloc'h embannadenn <%= name %> ?" successful: "Rannet pelloc'h eo bet an embannadenn ervat !" - search_for: "Klask war-lerc'h <%= name %>" show_more: "Gwelet muioc'h" stream: comment: "Ober un evezhiadenn" @@ -148,29 +140,24 @@ br: wasnt_that_interesting: "Mat eo, moarvat ne oa ket gwall zedennus #<%= tagName %>..." timeago: day: "un devezh" - days: "%d a zevezhioù" + days: + other: "%d a zevezhioù" hour: "war-dro un eurvezh" - hours: "war-dro %d eurvezh" + hours: + other: "war-dro %d eurvezh" minute: "war-dro ur vunutenn" - minutes: "%d a vunutennoù" + minutes: + other: "%d a vunutennoù" month: "war-dro miz" - months: "%d miz" + months: + other: "%d miz" prefixAgo: "" prefixFromNow: "" seconds: "dindan ur vunutenn" suffixAgo: "zo" suffixFromNow: "diwar-vremañ" year: "war-dro bloaz" - years: "%d bloaz" - videos: - unknown: "Dianav eo seurt ar video" - watch: "Sellet ouzh ar video gant <%= provider %>" + years: + other: "%d bloaz" viewer: - comment: "Evezhiadenn" - follow_post: "Heuliañ an embannadenn-mañ" - home: "Degemer" - like: "Plijus" - reshare: "Rannañ pelloc'h" - reshared: "Rannet pelloc'h" - stop_following_post: "Paouez da heuliañ an embannadenn-mañ" - unlike: "Displijus" \ No newline at end of file + reshared: "Rannet pelloc'h" \ No newline at end of file diff --git a/config/locales/javascript/javascript.bs.yml b/config/locales/javascript/javascript.bs.yml index 50f19f20e7ab4265d768559e5301b5eb254ec18a..543188d279d99038534bda053f9580545b07b2aa 100644 --- a/config/locales/javascript/javascript.bs.yml +++ b/config/locales/javascript/javascript.bs.yml @@ -32,8 +32,6 @@ bs: no_comments: "JoÅ¡ uvijek nema komentara." show: "pokaži sve komentare" confirm_dialog: "Jeste sigurni?" - conversation: - participants: "UÄesnici" delete: "IzbriÅ¡i" edit: "Uredi" failed_to_like: "NeuspjeÅ¡no sviÄ‘anje" @@ -58,9 +56,6 @@ bs: view_all: "Pogledaj sve" ignore: "IgnoriÅ¡i" ignore_user: "IgnoriÅ¡i ovog korisnika?" - infinite_scroll: - no_more: "Nema viÅ¡e objava." - no_more_contacts: "Nema viÅ¡e kontakata." my_activity: "Moja Aktivnost" my_aspects: "Moji Aspekti" my_stream: "Tok" @@ -73,7 +68,6 @@ bs: looking_good: "Bože, izgledate fenomenalno!" size_error: "{file} je prevelika, maksimalna veliÄina datoteke je {sizeLimit}." publisher: - at_least_one_aspect: "Morate objaviti za najmanje jedan aspekt" limited: "OgraniÄeno - vaÅ¡a objava će biti vidljiva od ljudi s kojima dijelite" near_from: "Objavljeno sa: <%= location %>" public: "Javno - vaÅ¡a objava će biti vidljiva svima i može biti pronaÄ‘ena od pretraživaÄa" @@ -81,7 +75,6 @@ bs: duplicate: "Tako dobro, ha? Već ste ponovo dijelili tu objavu!" post: "Ponovo dijeli objavu od <%= name %>?" successful: "Objava je uspjeÅ¡no ponovo dijeljenja!" - search_for: "Traži za <%= name %>" show_more: "pokaži viÅ¡e" stream: comment: "Komentar" @@ -127,29 +120,24 @@ bs: wasnt_that_interesting: "Uredu, pretpostavljam da #<%= tagName %> nije bilo tako interesantno..." timeago: day: "dan" - days: "%d dana" + days: + other: "%d dana" hour: "oko sat" - hours: "oko %d sati" + hours: + other: "oko %d sati" minute: "oko minute" - minutes: "%d minuta" + minutes: + other: "%d minuta" month: "oko mjesec" - months: "%d mjeseci" + months: + other: "%d mjeseci" prefixAgo: "prije" prefixFromNow: "u" seconds: "manje od minute" suffixAgo: "prije" suffixFromNow: "od sada" year: "oko godina" - years: "%d godina" - videos: - unknown: "Nepoznat video tip" - watch: "Pogledajte ovaj video na <%= provider %>" + years: + other: "%d godina" viewer: - comment: "Komentar" - follow_post: "Prati objavu" - home: "POÄŒETNA" - like: "SviÄ‘a mi se" - reshare: "Ponovo dijeli" - reshared: "Ponovo dijeljeno" - stop_following_post: "Zaustavi praćenje objave" - unlike: "Skini sviÄ‘anje" \ No newline at end of file + reshared: "Ponovo dijeljeno" \ No newline at end of file diff --git a/config/locales/javascript/javascript.cs.yml b/config/locales/javascript/javascript.cs.yml index bb0e4166d1a62817ba56c2f5f5262e77da217ffa..ad78ec1499fb4e06f3a55636f2b73f57913caaa9 100644 --- a/config/locales/javascript/javascript.cs.yml +++ b/config/locales/javascript/javascript.cs.yml @@ -6,6 +6,13 @@ cs: javascripts: + admin: + pods: + version_failed: + few: "<%= count %> pody nemajà verzi (staré pody, žádné NodeInfo)" + one: "Jeden pod nemá verzi (starý pod, žádné NodeInfo)." + other: "<%= count %> podů nemá verzi (staré pody, žádné NodeInfo)" + zero: "Nenà pod, který by nemÄ›l verzi." and: "a" aspect_dropdown: add_to_aspect: "PÅ™idat kontakt" @@ -58,7 +65,6 @@ cs: conversation: new: no_contacts: "MusÃte si pÅ™idat nÄ›jaké kontakty, než budete moci zaÄÃt konveraci." - participants: "ÚÄastnÃci" create: "VytvoÅ™it" delete: "Odstranit" edit: "Upravit" @@ -92,9 +98,6 @@ cs: ignore: "Ignorovat" ignore_failed: "Tohoto uživatele se nedařà ignorovat" ignore_user: "Ignorovat tohoto uživatele?" - infinite_scroll: - no_more: "Žádné dalÅ¡Ã pÅ™ÃspÄ›vky." - no_more_contacts: "Žádné dalÅ¡Ã kontakty." my_activity: "Moje aktivita" my_aspects: "Moje aspekty" my_stream: "Proud" @@ -136,14 +139,12 @@ cs: contacts: "Kontakty" edit: "upravit" gender: "PohlavÃ" - ignoring: "Ignorujete vÅ¡echny pÅ™ÃspÄ›vky od <%= name %>." location: "Pozice" photos: "Fotky" posts: "PÅ™ÃspÄ›vky" you_have_no_tags: "Nemáte žádné Å¡tÃtky" publisher: add_option: "PÅ™idejte odpovÄ›Ä" - at_least_one_aspect: "MusÃte publikovat alespoň do jednoho aspektu" limited: "Omezený — váš pÅ™ÃspÄ›vek bude pÅ™Ãstupný pouze lidem, se kterými sdÃlÃte" near_from: "Odesláno z: <%= location %>" option: "OdpovÄ›Ä" @@ -161,7 +162,6 @@ cs: duplicate: "Tento pÅ™ÃspÄ›vek už sdÃlÃte!" post: "SdÃlet pÅ™ÃspÄ›vek uživatele <%= name %>?" successful: "PÅ™ÃspÄ›vek je sdÃlen!" - search_for: "Hledat <%= name %>" show_more: "zobrazit vÃce" stream: comment: "Okomentovat" @@ -210,13 +210,17 @@ cs: wasnt_that_interesting: "DobÅ™e, pÅ™edpokládám, že #<%= tagName %> nebyl zase tak zajÃmavý…" timeago: day: "1 dnem" - days: "%d dny" + days: + other: "%d dny" hour: "hodinou" - hours: "%d hodinami" + hours: + other: "%d hodinami" minute: "minutou" - minutes: "%d minutami" + minutes: + other: "%d minutami" month: "1 mÄ›sÃcem" - months: "%d mÄ›sÃci" + months: + other: "%d mÄ›sÃci" prefixAgo: "pÅ™ed" prefixFromNow: "za" seconds: "ménÄ› než minutou" @@ -224,17 +228,8 @@ cs: suffixFromNow: "" wordSeparator: " " year: "1 rokem" - years: "%d roky" + years: + other: "%d roky" unblock_failed: "Odblokovánà tohoto uživatele selhalo" - videos: - unknown: "Neznámý typ videa" - watch: "PodÃvejte se na tohle video na <%= provider %>" viewer: - comment: "Komentovat" - follow_post: "Sledovat pÅ™ÃspÄ›vek" - home: "Domů" - like: "To se mi lÃbÃ" - reshare: "SdÃlet" - reshared: "SdÃleno" - stop_following_post: "PÅ™estat sledovat pÅ™ÃspÄ›vek" - unlike: "To se mi nelÃbÃ" \ No newline at end of file + reshared: "SdÃleno" \ No newline at end of file diff --git a/config/locales/javascript/javascript.cy.yml b/config/locales/javascript/javascript.cy.yml index 4594d8fb61d5c5c4900c572fcca74a0995fa312c..4481192ebd26e397604832c92c7081edd7a624b6 100644 --- a/config/locales/javascript/javascript.cy.yml +++ b/config/locales/javascript/javascript.cy.yml @@ -36,13 +36,10 @@ cy: preparing_your_stream: "Preparing your personalised stream..." header: search: "Find people or #tags" - infinite_scroll: - no_more: "Dim mwy o swyddi." photo_uploader: looking_good: "OMG, rydych chi'n ymddangos yn neis iawn!" reshares: duplicate: "Mae hynny'n dda, eh? Rydych chi wedi rhannu'r bost eisoes!" - search_for: "Chwilio am <%= name %>" show_more: "dangos mwy" stream: likes: @@ -70,20 +67,22 @@ cy: wasnt_that_interesting: "OK, mae'n debyg nid yw #<%= tagName %> yn ddiddorol iawn..." timeago: day: "diwrnod" - days: "%d diwrnod" + days: + other: "%d diwrnod" hour: "awr" - hours: "%d awr" + hours: + other: "%d awr" minute: "tua funud" - minutes: "%d munud" + minutes: + other: "%d munud" month: "mis" - months: "%d mis" + months: + other: "%d mis" prefixAgo: "" prefixFromNow: "" seconds: "rhai na munud" suffixAgo: "yn ôl" suffixFromNow: "o hÅ·d" year: "tua flwyddyn" - years: "%d blyddynoedd" - videos: - unknown: "Math o fideo anhysbys" - watch: "Gwyliwch y fideo ar <%= provider %>" \ No newline at end of file + years: + other: "%d blyddynoedd" \ No newline at end of file diff --git a/config/locales/javascript/javascript.da.yml b/config/locales/javascript/javascript.da.yml index 71ec60499350e431a7b3f60672c3444a98dda622..6dc090be8164a5c8b62234fc126b73b2b224fbe0 100644 --- a/config/locales/javascript/javascript.da.yml +++ b/config/locales/javascript/javascript.da.yml @@ -6,6 +6,55 @@ da: javascripts: + admin: + pods: + actions: "Handlinger" + added: "Tilføjet" + check: "lav en tilslutningstest" + errors: + one: "Forbindelses-testen viser fejl pÃ¥ en pod. " + other: "Forbindelses-testen viser fejl pÃ¥ <%= count %> pod-servere. " + follow_link: "Ã¥ben link i browser" + last_check: "seneste check:" + more_info: "vis mere information" + ms: + one: "<%= count %>ms" + other: "<%= count %>ms" + no_info: "Ingen yderligere information til rÃ¥dighed pÃ¥ dette tidspunkt" + not_available: "ikke tilgængelig" + offline_since: "offline siden:" + pod: "Pod" + recheck: + failure: "Checket blev ikke gennemført." + success: "Pod-serveren er blevet markeret igen." + response_time: "Svartid:" + server_software: "Server software:" + ssl: "SSL" + ssl_disabled: "SSL er slÃ¥et fra" + ssl_enabled: "SSL er slÃ¥et til" + states: + dns_failed: "Name resolution (DNS) fejlede" + http_failed: "HTTP tilslutning fejlede" + net_failed: "Tilslutningsforsøg fejlede" + no_errors: "OK" + ssl_failed: "Sikker forbindelse (SSL) fejlede" + unchecked: "Ikke markeret" + unknown_error: "Der er sket en uspecificeret fejl under checket" + version_failed: "Ude af stand til at hente software version" + status: "Status" + unchecked: + one: "Der er stadig en pod der slet ikke er blevet checket." + other: "Der er stadig <%= count %> pod-servere der slet ikke er blevet checket." + unknown: "ukendt" + version_failed: + one: "Der er en pod der ikke har versions-info (en gammel pod, eller en uden node-info)." + other: "Der er <%= count %> poder der ikke har versions-info (en gammel pod, eller en uden node-info)." + admins: + dashboard: + compare_versions: "Den seneste Diaspora udgave er <%= latestVersion %>, og din pod kører <%= podVersion %>." + error: "Ude af stand til at bestemme den seneste Diaspora-version." + outdated: "Din pod er ikke opdateret." + up_to_date: "Din pod er opdateret!" and: "og" aspect_dropdown: add_to_aspect: "Tilføj kontakt" @@ -18,12 +67,8 @@ da: started_sharing_with: "Du er begyndt at dele med <%= name %>!" stopped_sharing_with: "Du deler ikke længere med <%= name %>." toggle: - few: "I <%= count %> aspekter" - many: "I <%= count %> aspekter" one: "I <%= count %> aspekt" other: "I <%= count %> aspekter" - two: "I <%= count %> aspekter" - zero: "Vælg aspekter" updating: "opdaterer ..." aspect_navigation: add_an_aspect: "+ Tilføj et aspekt" @@ -51,6 +96,8 @@ da: confirm_unload: "Bekræft venligst at du ønsker at forlade denne side - data, du har indtastet, vil ikke blive gemt." contacts: add_contact: "Tilføj kontakt" + aspect_chat_is_enabled: "Kontakter i dette aspekt kan chatte med dig." + aspect_chat_is_not_enabled: "Kontakter i dette aspekt kan ikke chatte med dig." aspect_list_is_not_visible: "Kontakter i dette aspekt kan ikke se hinanden" aspect_list_is_visible: "Kontakter i dette aspekt kan se hinanden" error_add: "Kunne ikke tilføje <%= name %> til aspektet :(" @@ -60,11 +107,11 @@ da: conversation: new: no_contacts: "Du skal tilføje en eller flere kontakter før du kan starte en samtale." - participants: "Deltagere" create: "Opret" delete: "Slet" edit: "Rediger" - failed_to_like: "Kunne ikke synes om!" + failed_to_comment: "Din kommentar blev ikke lagt op. MÃ¥ske ignorerer indlæggets ophavsmand dig?" + failed_to_like: "Kunne ikke synes om! MÃ¥ske ignorere ophavsmanden dig?" failed_to_post_message: "Kunne ikke indsende besked!" failed_to_remove: "Det lykkedes ikke at fjerne indlægget!" failed_to_reshare: "Kunne ikke dele indlægget!" @@ -88,15 +135,14 @@ da: recent_notifications: "Seneste notifikationer" search: "Søg" settings: "Indstillinger" + toggle_mobile: "SlÃ¥ mobil til/fra" + toggle_navigation: "SlÃ¥ navigation til/fra" view_all: "Se alle" hide_post: "Skjul dette indlæg?" hide_post_failed: "Kan ikke skjule indlæg" ignore: "Ignorer" ignore_failed: "Kan ikke ignorere denne bruger" ignore_user: "Ignorer denne bruger?" - infinite_scroll: - no_more: "Ikke flere indlæg." - no_more_contacts: "Ikke flere kontakter." my_activity: "Min aktivitet" my_aspects: "Mine aspekter" my_stream: "Strøm" @@ -118,9 +164,13 @@ da: empty: "{file} er tom. Vælg venligst filer igen uden den." error: "Der er opstÃ¥et et problem med at lægge filen <%= file %> op." invalid_ext: "{file} har en ugyldig filtype. Kun {extensions} er tilladt." - looking_good: "OMG, du ser sej ud!" + looking_good: "Du ser virkelig pæn ud!" size_error: "{file} er for stor. Maksimal filstørrelse er {sizeLimit}." poll: + answer_count: + one: "1 stemme" + other: "<%=count%> stemmer" + zero: "0 stemmer" close_result: "Gem resultat" count: one: "<%=count%> stemme, indtil nu" @@ -137,15 +187,35 @@ da: contacts: "Kontakter" edit: "Rediger" gender: "Køn" - ignoring: "Du ignorerer alle indlæg fra <%= name %>" location: "Sted" photos: "Fotos" posts: "Indlæg" you_have_no_tags: "Du har ingen tags!" publisher: add_option: "Tilføj et svar" - at_least_one_aspect: "Du skal dele med mindst et aspekt" limited: "Begrænset - dit indlæg vil kun blive set af dem du deler med" + markdown_editor: + preview: "ForhÃ¥ndsvisning" + texts: + heading: "Overskriftstekst" + insert_link_description_text: "skriv link-beskrivelse her" + insert_link_help_text: "Indsæt link her" + italic: "tekst i kursiv" + strong: "fed tekst" + tooltips: + bold: "Fed" + cancel: "Annuller besked" + code: "Indsæt kode" + heading: "Overskrift" + insert_image: "Indsæt billede" + insert_link: "Indsæt link" + insert_ordered_list: "Indsæt ordnet liste" + insert_unordered_list: "Indsæt uordnet liste" + italic: "Kursiv" + preview: "ForhÃ¥ndsvisning af besked" + quote: "Indsæt citat" + write: "Rediger besked" + write: "Skriv" near_from: "Sendt fra: <%= location %>" option: "Svar" public: "Offentlig - dit indlæg vil være synligt for alle og kan findes af søgemaskiner" @@ -162,10 +232,9 @@ da: duplicate: "Du har allerede delt indlægget!" post: "Videredel <%= name %>s indlæg?" successful: "Indlægget er blevet videredelt!" - search_for: "Søg efter <%= name %>" show_more: "Vis mere" stream: - comment: "Kommentér" + comment: "Kommenter" disable_post_notifications: "SlÃ¥ notifikationer fra for dette indlæg" enable_post_notifications: "SlÃ¥ notifikationer til for dette indlæg" follow: "Følg" @@ -191,8 +260,14 @@ da: other: "Vis <%= count %> ekstra kommentarer" two: "Vis <%= count %> ekstra kommentarer" zero: "Vis <%= count %> ekstra kommentarer" + no_posts_yet: "Der er endnu ikke nogen indlæg at vise." original_post_deleted: "Oprindeligt indlæg er slettet af forfatteren" + permalink: "Permalink" public: "Offentlig" + reactions: + one: "<%= count%> reaktion" + other: "<%= count%> reaktioner" + zero: "<%= count%> reaktioner" reshare: "Videredel" reshares: few: "<%= count %> videredelinger" @@ -217,13 +292,22 @@ da: wasnt_that_interesting: "OK, #<%= tagName %> var ikke var sÃ¥ spændende alligevel ..." timeago: day: "en dag" - days: "%d dage" + days: + one: "1 dag" + other: "%d dage" hour: "ca. en time" - hours: "ca. %d timer" + hours: + one: "omkring en time" + other: "omkring %d timer" + inPast: "nÃ¥r som helst" minute: "ca. et minut" - minutes: "%d minutter" + minutes: + one: "1 minut" + other: "%d minutter" month: "ca. en mÃ¥ned" - months: "%d mÃ¥neder" + months: + one: "1 mÃ¥ned" + other: "%d mÃ¥neder" prefixAgo: "" prefixFromNow: "" seconds: "mindre end et minut" @@ -231,17 +315,9 @@ da: suffixFromNow: "fra nu" wordSeparator: " " year: "ca. et Ã¥r" - years: "%d Ã¥r" + years: + one: "1 Ã¥r" + other: "%d Ã¥r" unblock_failed: "Det lykkedes ikke at afblokere denne bruger" - videos: - unknown: "Ukendt videotype" - watch: "Se denne video pÃ¥ <%= provider %>" viewer: - comment: "Kommentér" - follow_post: "Følg indlæg" - home: "Hjem" - like: "Synes om" - reshare: "Videredel" - reshared: "Videredelt" - stop_following_post: "Ophør med at følge indlæg" - unlike: "Unlike" \ No newline at end of file + reshared: "Videredelt" \ No newline at end of file diff --git a/config/locales/javascript/javascript.de.yml b/config/locales/javascript/javascript.de.yml index bfbfb4244d2031084c22f0c5d635d7db8ee45240..f37afc57a5ca75e1def44260cdf688dde1cb9bc1 100644 --- a/config/locales/javascript/javascript.de.yml +++ b/config/locales/javascript/javascript.de.yml @@ -6,6 +6,55 @@ de: javascripts: + admin: + pods: + actions: "Aktionen" + added: "Hinzugefügt" + check: "Verbindungstest durchführen" + errors: + one: "Der Verbindungstest meldete für einen Pod einen Fehler." + other: "Der Verbindungstest meldete für <%= count %> Pods einen Fehler." + follow_link: "Link im Browser öffnen" + last_check: "letzte Ãœberprüfung:" + more_info: "zeige weitere Informationen" + ms: + one: "<%= count %>ms" + other: "<%= count %>ms" + no_info: "Zur Zeit keine weiteren Informationen verfügbar" + not_available: "nicht verfügbar" + offline_since: "offline seit:" + pod: "Pod" + recheck: + failure: "Die Ãœberprüfung wurde nicht durchgeführt." + success: "Der Pod wurde soeben erneut überprüft." + response_time: "Antwortzeit:" + server_software: "Server-Software:" + ssl: "SSL" + ssl_disabled: "SSL deaktiviert" + ssl_enabled: "SSL aktiviert" + states: + dns_failed: "Namensauflösung (DNS) fehlgeschlagen" + http_failed: "HTTP-Verbindung fehlgeschlagen" + net_failed: "Verbindungsversuch fehlgeschlagen" + no_errors: "OK" + ssl_failed: "Sichere Verbindung (SSL) fehlgeschlagen" + unchecked: "Nicht überprüft" + unknown_error: "Während der Ãœberprüfung ist ein nicht angegebener Fehler aufgetreten" + version_failed: "Konnte Software-Version nicht ermitteln" + status: "Status" + unchecked: + one: "Es gibt noch immer einen Pod, der gar nicht überprüft wurde." + other: "Es gibt noch immer <%= count %> Pods, die gar nicht überprüft wurden." + unknown: "unbekannt" + version_failed: + one: "Es gibt einen Pod, der keine Version hat (alter Pod, kein NodeInfo)." + other: "Es gibt <%= count %> Pods, die keine Version haben (alte Pods, kein NodeInfo)." + admins: + dashboard: + compare_versions: "Die neueste diaspora*-Version ist <%= latestVersion %>, dein Pod verwendet <%= podVersion %>." + error: "Konnte neueste diaspora*-Version nicht ermitteln." + outdated: "Dein Pod ist veraltet." + up_to_date: "Dein Pod ist auf dem neuesten Stand!" and: "und" aspect_dropdown: add_to_aspect: "Kontakt hinzufügen" @@ -18,12 +67,9 @@ de: started_sharing_with: "Du hast angefangen, mit <%= name %> zu teilen!" stopped_sharing_with: "Du hast aufgehört, mit <%= name %> zu teilen!" toggle: - few: "In <%= count %> Aspekten" - many: "In <%= count %> Aspekten" one: "In einem Aspekt" other: "In <%= count %> Aspekten" - two: "In <%= count %> Aspekten" - zero: "Aspekt auswählen" + zero: "In keinem Aspekt" updating: "aktualisiere..." aspect_navigation: add_an_aspect: "+ Aspekt hinzufügen" @@ -51,6 +97,8 @@ de: confirm_unload: "Bitte bestätige, dass du diese Seite verlassen willst - Daten, welche du eingegeben hast würden nicht gespeichert werden." contacts: add_contact: "Kontakt hinzufügen" + aspect_chat_is_enabled: "Kontakte in diesem Aspekt können mit dir chatten." + aspect_chat_is_not_enabled: "Kontakte in diesem Aspekt können nicht mit dir chatten." aspect_list_is_not_visible: "Kontakte in diesem Aspekt können einander nicht sehen." aspect_list_is_visible: "Kontakte in diesem Aspekt können einander sehen" error_add: "Konnte <%= name %> nicht zum Aspekt hinzufügen :(" @@ -60,11 +108,11 @@ de: conversation: new: no_contacts: "Du musst einige Kontakte hinzufügen, bevor du eine Konversation anfangen kannst." - participants: "Teilnehmer" create: "Erstellen" delete: "Löschen" edit: "Bearbeiten" - failed_to_like: "Gefällt mir fehlgeschlagen. Vielleicht ignoriert dich der Autor?" + failed_to_comment: "Konnte nicht kommentieren. Vielleicht ignoriert dich der Autor?" + failed_to_like: "Gefällt mir ist fehlgeschlagen. Vielleicht ignoriert dich der Autor?" failed_to_post_message: "Konnte Beitrag nicht senden!" failed_to_remove: "Fehler beim Entfernen des Beitrags!" failed_to_reshare: "Fehler beim Weitersagen!" @@ -88,15 +136,14 @@ de: recent_notifications: "Neuste Benachrichtigungen" search: "Suchen" settings: "Einstellungen" + toggle_mobile: "Mobile Ansicht umschalten" + toggle_navigation: "Navigation umschalten" view_all: "Alle anzeigen" hide_post: "Diesen Beitrag ausblenden?" hide_post_failed: "Ausblenden des Beitrags nicht möglich" ignore: "Ignorieren" ignore_failed: "Konnte Benutzer nicht ignorieren" ignore_user: "Benutzer ignorieren?" - infinite_scroll: - no_more: "Keine weiteren Beiträge." - no_more_contacts: "Keine weiteren Kontakte." my_activity: "Meine Aktivitäten" my_aspects: "Meine Aspekte" my_stream: "Stream" @@ -121,6 +168,10 @@ de: looking_good: "OMG, du siehst toll aus!" size_error: "{file} ist zu groß. Die maximale Dateigröße beträgt {sizeLimit}." poll: + answer_count: + one: "1 Stimme" + other: "<%=count%> Stimmen" + zero: "0 Stimmen" close_result: "Ergebnis ausblenden" count: one: "Bisher eine Stimme" @@ -137,15 +188,41 @@ de: contacts: "Kontakte" edit: "Bearbeiten" gender: "Geschlecht" - ignoring: "Du ignorierst sämtliche Beiträge von <%= name %>." location: "Ort" photos: "Fotos" posts: "Beiträge" you_have_no_tags: "Du hast keine Tags!" publisher: add_option: "Antwortmöglichkeit hinzufügen" - at_least_one_aspect: "Du musst zumindest zu einem Aspekt posten" limited: "Eingeschränkt - dein Beitrag wird nur Leuten sichtbar sein, mit denen du teilst" + markdown_editor: + preview: "Vorschau" + texts: + code: "Code hier" + heading: "Ãœberschrift" + insert_image_description_text: "Bildbeschreibung hier eingeben" + insert_image_help_text: "Bildlink hier einfügen" + insert_image_title: "Bildtitel hier eingeben" + insert_link_description_text: "Linkbeschreibung hier eingeben" + insert_link_help_text: "Link hier einfügen" + italic: "kursive Schrift" + list: "Listentext hier" + quote: "Zitattext hier" + strong: "wichtiger Text" + tooltips: + bold: "Fett" + cancel: "Nachricht verwerfen" + code: "Code einfügen" + heading: "Ãœberschrift" + insert_image: "Bild einfügen" + insert_link: "Link einfügen" + insert_ordered_list: "Geordnete Liste einfügen" + insert_unordered_list: "Ungeordnete Liste einfügen" + italic: "Kursiv" + preview: "Vorschau der Nachricht ansehen" + quote: "Zitat einfügen" + write: "Nachricht bearbeiten" + write: "Verfassen" near_from: "Gesendet aus <%= location %>" option: "Antwort" public: "Öffentlich - dein Beitrag ist für alle sichtbar und kann von Suchmaschinen gefunden werden" @@ -162,7 +239,6 @@ de: duplicate: "Du hast diesen Beitrag bereits weitergesagt!" post: "<%= name %>s Beitrag weitersagen?" successful: "Der Beitrag wurde erfolgreich weitergesagt!" - search_for: "Nach <%= name %> suchen" show_more: "Mehr zeigen" stream: comment: "Kommentar" @@ -188,8 +264,14 @@ de: one: "Zeige einen weiteren Kommentar" other: "Zeige <%= count %> weitere Kommentare" zero: "Keine weiteren Kommentare" + no_posts_yet: "Es gibt noch keine Beiträge, die hier angezeigt werden könnten." original_post_deleted: "Originalbeitrag wurde vom Autor entfernt." + permalink: "Permanentlink" public: "Öffentlich" + reactions: + one: "<%= count%> Reaktion" + other: "<%= count%> Reaktionen" + zero: "<%= count%> Reaktionen" reshare: "Weitersagen" reshares: few: "<%= count %> mal weitergesagt" @@ -214,13 +296,22 @@ de: wasnt_that_interesting: "OK, #<%= tagName %> war wohl doch nicht so interessant..." timeago: day: "einem Tag" - days: "%d Tagen" + days: + one: "einem Tag" + other: "%d Tagen" hour: "etwa einer Stunde" - hours: "etwa %d Stunden" + hours: + one: "etwa einer Stunde" + other: "etwa %d Stunden" + inPast: "jeden Moment" minute: "etwa einer Minute" - minutes: "%d Minuten" + minutes: + one: "einer Minute" + other: "%d Minuten" month: "etwa einem Monat" - months: "%d Monaten" + months: + one: "einem Monat" + other: "%d Monaten" prefixAgo: "vor" prefixFromNow: "in" seconds: "weniger als eine Minute" @@ -228,17 +319,9 @@ de: suffixFromNow: "ab jetzt" wordSeparator: " " year: "etwa einem Jahr" - years: "%d Jahren" + years: + one: "einem Jahr" + other: "%d Jahren" unblock_failed: "Den Benutzer zu entblocken ist fehlgeschlagen." - videos: - unknown: "Unbekanntes Videoformat" - watch: "Dieses Video auf <%= provider %> ansehen" viewer: - comment: "Kommentieren" - follow_post: "Diesen Beitrag verfolgen" - home: "Start" - like: "Gefällt mir" - reshare: "Weitersagen" - reshared: "Weitergesagt" - stop_following_post: "Diesen Beitrag nicht mehr verfolgen" - unlike: "Gefällt mir nicht mehr" \ No newline at end of file + reshared: "Weitergesagt" \ No newline at end of file diff --git a/config/locales/javascript/javascript.de_formal.yml b/config/locales/javascript/javascript.de_formal.yml index 303b9cc2da208468da5f1f6e9a1141d823435d09..ab64ce0f5e247ca3bafe5961a49740865a788fb9 100644 --- a/config/locales/javascript/javascript.de_formal.yml +++ b/config/locales/javascript/javascript.de_formal.yml @@ -6,19 +6,68 @@ de_formal: javascripts: + admin: + pods: + actions: "Aktionen" + added: "Hinzugefügt" + check: "Verbindungstest durchführen" + errors: + one: "Der Verbindungstest meldete für einen Pod einen Fehler." + other: "Der Verbindungstest meldete für <%= count %> Pods einen Fehler." + follow_link: "Link im Browser öffnen" + last_check: "letzte Ãœberprüfung:" + more_info: "zeige weitere Informationen" + ms: + one: "<%= count %>ms" + other: "<%= count %>ms" + no_info: "Zur Zeit sind keine weiteren Informationen verfügbar" + not_available: "Nicht verfügbar" + offline_since: "offline seit:" + pod: "Pod" + recheck: + failure: "Die Ãœberprüfung wurde nicht durchgeführt." + success: "Der Pod wurde soeben erneut überprüft." + response_time: "Antwortzeit:" + server_software: "Server-Software:" + ssl: "SSL" + ssl_disabled: "SSL deaktiviert" + ssl_enabled: "SSL aktiviert" + states: + dns_failed: "Namensauflösung (DNS) fehlgeschlagen" + http_failed: "HTTP-Verbindung fehlgeschlagen" + net_failed: "Verbindungsversuch fehlgeschlagen" + no_errors: "OK" + ssl_failed: "Sichere Verbindung (SSL) fehlgeschlagen" + unchecked: "Nicht überprüft" + unknown_error: "Während der Ãœberprüfung ist ein nicht angegebener Fehler aufgetreten" + version_failed: "Konnte Software-Version nicht ermitteln" + status: "Status" + unchecked: + one: "Es gibt noch immer einen Pod, der gar nicht überprüft wurde." + other: "Es gibt noch immer <%= count %> Pods, die gar nicht überprüft wurden." + unknown: "Unbekannt" + version_failed: + one: "Es gibt einen Pod, der keine Version hat (alter Pod, kein NodeInfo)." + other: "Es gibt <%= count %> Pods, die keine Version haben (alte Pods, kein NodeInfo)." + admins: + dashboard: + compare_versions: "Die neueste diaspora*-Version ist <%= latestVersion %>, Ihr Pod verwendet <%= podVersion %>." + error: "Konnte neueste diaspora*-Version nicht ermitteln." + outdated: "Ihr Pod ist veraltet." + up_to_date: "Ihr Pod ist auf dem neuesten Stand!" and: "und" aspect_dropdown: add_to_aspect: "Kontakt hinzufügen" all_aspects: "Alle Aspekte" error: "Konnte nicht anfangen, mit <%= name %> zu teilen. Ignorieren Sie ihn/sie?" - error_remove: "Konnte <%= name %> nicht vom Aspekt entfernen :(" + error_remove: "Konnte <%= name %> nicht aus dem Aspekt entfernen :(" mobile_row_checked: "<%= name %> (entfernen)" mobile_row_unchecked: "<%= name %> (hinzufügen)" select_aspects: "Wählen Sie Aspekte aus" started_sharing_with: "Sie haben angefangen, mit <%= name %> zu teilen!" stopped_sharing_with: "Sie haben aufgehört, mit <%= name %> zu teilen!" toggle: - one: "In einem Aspekt" + one: "In <%= count %> Aspekt" other: "In <%= count %> Aspekten" zero: "Aspekt auswählen" updating: "aktualisiere..." @@ -32,7 +81,7 @@ de_formal: add_a_new_aspect: "Einen neuen Aspekt hinzufügen" failure: "Fehler beim Erstellen des Aspekts." success: "Ihr neuer Aspekt <%= name %> wurde erstellt" - make_aspect_list_visible: "Kontakte aus diesem Aspekt gegenseitig sichtbar machen?" + make_aspect_list_visible: "Kontakte in diesem Aspekt gegenseitig sichtbar machen?" name: "Name" bookmarklet: post_something: "Erstellen Sie einen Beitrag in diaspora*" @@ -48,8 +97,10 @@ de_formal: confirm_unload: "Bitte bestätigen Sie, dass Sie diese Seite verlassen möchten. Die von Ihnen eingegebenen Daten werden nicht gespeichert werden." contacts: add_contact: "Kontakt hinzufügen" + aspect_chat_is_enabled: "Kontakte in diesem Askekt können mit Ihnen chatten." + aspect_chat_is_not_enabled: "Kontakte in diesem Aspekt können nicht mit Ihnen chatten." aspect_list_is_not_visible: "Kontakte in diesem Aspekt können einander nicht sehen." - aspect_list_is_visible: "Kontakte in diesem Aspekt können einander sehen" + aspect_list_is_visible: "Kontakte in diesem Aspekt können einander sehen." error_add: "Konnte <%= name %> nicht zum Aspekt hinzufügen :(" error_remove: "Konnte <%= name %> nicht aus dem Aspekt entfernen :(" remove_contact: "Kontakt entfernen" @@ -57,11 +108,11 @@ de_formal: conversation: new: no_contacts: "Sie müssen einige Kontakte hinzufügen, bevor Sie eine Konversation anfangen können." - participants: "Teilnehmer" create: "Erstellen" delete: "Löschen" edit: "Bearbeiten" - failed_to_like: "Gefällt mir fehlgeschlagen." + failed_to_comment: "Konnte nicht kommentieren. Vielleicht ignoriert Sie der Autor?" + failed_to_like: "Gefällt mir ist fehlgeschlagen. Vielleicht ignoriert Sie der Autor?" failed_to_post_message: "Konnte Beitrag nicht senden!" failed_to_remove: "Fehler beim Entfernen des Beitrags!" failed_to_reshare: "Fehler beim Weitersagen!" @@ -85,15 +136,14 @@ de_formal: recent_notifications: "Letzte Benachrichtigungen" search: "Find people or #tags" settings: "Einstellungen" + toggle_mobile: "Mobile Ansicht umschalten" + toggle_navigation: "Navigation umschalten" view_all: "Alle ansehen" hide_post: "Diesen Beitrag ausblenden?" hide_post_failed: "Konnte den Beitrag nicht ausblenden" ignore: "Ignorieren" ignore_failed: "Konnte Benutzer nicht ignorieren" ignore_user: "Benutzer ignorieren?" - infinite_scroll: - no_more: "Keine weiteren Beiträge." - no_more_contacts: "Keine weiteren Kontakte." my_activity: "Meine Aktivitäten" my_aspects: "Ihre Aspekte" my_stream: "Stream" @@ -118,6 +168,10 @@ de_formal: looking_good: "OMG, Sie sehen toll aus!" size_error: "{file} ist zu groß. Die maximale Dateigröße beträgt {sizeLimit}." poll: + answer_count: + one: "Eine Stimme" + other: "<%=count%> Stimmen" + zero: "Keine Stimmen" close_result: "Ergebnis ausblenden" count: one: "Bisher eine Stimme" @@ -134,15 +188,41 @@ de_formal: contacts: "Kontakte" edit: "Bearbeiten" gender: "Geschlecht" - ignoring: "Sie ignorieren sämtliche Beiträge von <%= name %>." location: "Ort" photos: "Fotos" posts: "Beiträge" you_have_no_tags: "Sie haben keine Tags!" publisher: add_option: "Antwortmöglichkeit hinzufügen" - at_least_one_aspect: "Sie müssen zumindest zu einem Aspekt posten" limited: "Eingeschränkt: Ihr Beitrag wird nur von Leuten gesehen werden können, mit denen Sie teilen" + markdown_editor: + preview: "Vorschau" + texts: + code: "Code hier" + heading: "Ãœberschrift" + insert_image_description_text: "Bildbeschreibung hier eingeben" + insert_image_help_text: "Bildlink hier einfügen" + insert_image_title: "Bildtitel hier eingeben" + insert_link_description_text: "Linkbeschreibung hier eingeben" + insert_link_help_text: "Link hier einfügen" + italic: "kursive Schrift" + list: "Listentext hier" + quote: "Zitattext hier" + strong: "wichtiger Text" + tooltips: + bold: "Fett" + cancel: "Nachricht verwerfen" + code: "Code einfügen" + heading: "Ãœberschrift" + insert_image: "Bild einfügen" + insert_link: "Link einfügen" + insert_ordered_list: "Geordnete Liste einfügen" + insert_unordered_list: "Ungeordnete Liste einfügen" + italic: "Kursiv" + preview: "Vorschau der Nachricht ansehen" + quote: "Zitat einfügen" + write: "Nachricht bearbeiten" + write: "Verfassen" near_from: "In der Nähe von <%= location %>" option: "Antwort" public: "Öffentlich: Ihr Beitrag wird von allen gesehen und von Suchmaschinen gefunden werden können" @@ -159,7 +239,6 @@ de_formal: duplicate: "Sie haben diesen Beitrag bereits weitergesagt!" post: "<%= name %>s Beitrag weitersagen?" successful: "Der Beitrag wurde erfolgreich weitergesagt!" - search_for: "Nach <%= name %> suchen" show_more: "Mehr zeigen" stream: comment: "Kommentieren" @@ -182,8 +261,14 @@ de_formal: one: "Zeige <%= count %> weiteren Kommentar" other: "Zeige <%= count %> weitere Kommentare" zero: "Keine weiteren Kommentare" - original_post_deleted: "Originalbeitrag wurde vom Autor entfernt" + no_posts_yet: "Es gibt noch keine Beiträge, die hier angezeigt werden könnten." + original_post_deleted: "Originalbeitrag wurde vom Autor gelöscht" + permalink: "Permalink" public: "Öffentlich" + reactions: + one: "Eine Reaktion" + other: "<%= count%> Reaktionen" + zero: "Keine Reaktionen" reshare: "Weitersagen" reshares: one: "<%= count %> mal weitergeteilt" @@ -205,13 +290,22 @@ de_formal: wasnt_that_interesting: "OK, ich nehme an, #<%= tagName %> war nicht so interessant..." timeago: day: "einem Tag" - days: "%d Tagen" + days: + one: "1 Tag" + other: "%d Tagen" hour: "etwa einer Stunde" - hours: "etwa %d Stunden" + hours: + one: "etwa 1 Stunde" + other: "etwa %d Stunden" + inPast: "jeden Moment" minute: "etwa einer Minute" - minutes: "%d Minuten" + minutes: + one: "1 Minute" + other: "%d Minuten" month: "etwa einem Monat" - months: "%d Monaten" + months: + one: "1 Monat" + other: "%d Monaten" prefixAgo: "vor" prefixFromNow: "in" seconds: "wenigen Sekunden" @@ -219,17 +313,9 @@ de_formal: suffixFromNow: "ab jetzt" wordSeparator: " " year: "etwa einem Jahr" - years: "%d Jahren" + years: + one: "1 Jahr" + other: "%d Jahren" unblock_failed: "Den Benutzer zu entblocken ist fehlgeschlagen." - videos: - unknown: "Unbekanntes Videoformat" - watch: "Dieses Video auf <%= provider %> ansehen" viewer: - comment: "Kommentar" - follow_post: "Diesem Beitrag folgen" - home: "Start" - like: "Gefällt mir" - reshare: "Weitersagen" - reshared: "Weitergesagt" - stop_following_post: "Diesem Beitrag nicht mehr folgen" - unlike: "Gefällt mir nicht mehr" \ No newline at end of file + reshared: "Weitergesagt" \ No newline at end of file diff --git a/config/locales/javascript/javascript.el.yml b/config/locales/javascript/javascript.el.yml index 58f02b5eb9669638d3eaf7830d9d3bb3658b8b32..36675af6833e78e744b09ea534e45ae393fd83bf 100644 --- a/config/locales/javascript/javascript.el.yml +++ b/config/locales/javascript/javascript.el.yml @@ -33,8 +33,6 @@ el: contacts: add_contact: "Î Ïοσθήκη επαφής" remove_contact: "ΔιαγÏαφή επαφής" - conversation: - participants: "ΣυμμετÎχοντες" delete: "ΔιαγÏαφή" edit: "ΕπεξεÏγασία" failed_to_like: "Αποτυχία!" @@ -61,8 +59,6 @@ el: view_all: "Î Ïοβολή όλων" ignore: "Αγνόησε" ignore_user: "Îα αγνοηθεί αυτός ο χÏήστης;" - infinite_scroll: - no_more: "Δεν υπάÏχουν άλλες δημοσιεÏσεις." my_activity: "Η δÏαστηÏιότητα μου" my_aspects: "Οι πτυχÎÏ‚ μου" my_stream: "Ροή" @@ -89,7 +85,6 @@ el: photos: "ΦωτογÏαφίες" publisher: add_option: "Î Ïόσθεσε μια απάντηση" - at_least_one_aspect: "Î ÏÎπει να κάνετε δημοσίευση σε τουλάχιστον μια πτυχή" limited: "ΠεÏιοÏισμÎνο - οι δημοσιεÏσεις σας θα είναι οÏατÎÏ‚ μόνο από τα άτομα με τα οποία διαμοιÏάζεστε" near_from: "ΑναÏτήθηκε από: <%= location %>" public: "Δημόσιο - οι δημοσιεÏσεις σας θα είναι οÏατÎÏ‚ στον καθÎνα και θα μποÏοÏν να βÏεθοÏν από τις μηχανÎÏ‚ αναζήτησης" @@ -100,7 +95,6 @@ el: duplicate: "Αυτό είναι τόσο καλό ε; Έχετε ήδη κοινοποιήσει αυτή τη δημοσίευση!" post: "Κοινοποίηση της ανάÏτησης του <%= name %>;" successful: "Η ανάÏτηση κοινοποιήθηκε επιτυχώς!" - search_for: "Αναζήτηση για <%= name %>" show_more: "Î Ïοβολή πεÏισσότεÏων" stream: comment: "Σχολιάστε" @@ -140,29 +134,24 @@ el: wasnt_that_interesting: "OK, φαντάζομαι πως το #<%= tagName %> δεν ήταν και τόσο ενδιαφÎÏον τελικά..." timeago: day: "μία μÎÏα" - days: "%d μÎÏες" + days: + other: "%d μÎÏες" hour: "πεÏίπου μία ÏŽÏα" - hours: "πεÏίπου %d ÏŽÏες" + hours: + other: "πεÏίπου %d ÏŽÏες" minute: "πεÏίπου Îνα λεπτό" - minutes: "%d λεπτά" + minutes: + other: "%d λεπτά" month: "πεÏίπου Îνα μήνα" - months: "%d μήνες" + months: + other: "%d μήνες" prefixAgo: "" prefixFromNow: "" seconds: "λιγότεÏο από Îνα λεπτό" suffixAgo: "Ï€Ïιν" suffixFromNow: "από Ï„ÏŽÏα" year: "πεÏίπου Îνα χÏόνο" - years: "%d χÏόνια" - videos: - unknown: "Άγνωστος Ï„Ïπος βίντεο" - watch: "Δείτε το βίντεο στο <%= provider %>" + years: + other: "%d χÏόνια" viewer: - comment: "Σχολιάστε" - follow_post: "ΠαÏακολοÏθησης δημοσιεÏσεων" - home: "ΑΡΧΙΚΗ" - like: "Μου αÏÎσει" - reshare: "Κοινοποιήστε" - reshared: "Κοινοποιήθηκε" - stop_following_post: "ΠαÏση παÏακολοÏθησης δημοσιεÏσεων" - unlike: "Δεν μου αÏÎσει" \ No newline at end of file + reshared: "Κοινοποιήθηκε" \ No newline at end of file diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml index 47d8404d10dd6f62821ceb48df39ef021e80bc4f..081057195f22a73d858cb0eb2b6935351e3db5a6 100644 --- a/config/locales/javascript/javascript.en.yml +++ b/config/locales/javascript/javascript.en.yml @@ -29,6 +29,56 @@ en: edit: "Edit" no_results: "No results found" + admins: + dashboard: + up_to_date: "Your pod is up to date!" + outdated: "Your pod is outdated." + compare_versions: "The latest diaspora* release is <%= latestVersion %>, your pod is running <%= podVersion %>." + error: "Unable to determine latest diaspora* version." + admin: + pods: + pod: "Pod" + ssl: "SSL" + ssl_enabled: "SSL enabled" + ssl_disabled: "SSL disabled" + added: "Added" + status: "Status" + states: + unchecked: "Unchecked" + no_errors: "OK" + dns_failed: "Name resolution (DNS) failed" + net_failed: "Connection attempt failed" + ssl_failed: "Secure connection (SSL) failed" + http_failed: "HTTP connection failed" + version_failed: "Unable to retrieve software version" + unknown_error: "An unspecified error has happened during the check" + actions: "Actions" + offline_since: "offline since:" + last_check: "last check:" + more_info: "show more information" + check: "perform connection test" + recheck: + success: "The pod was just checked again." + failure: "The check was not performed." + follow_link: "open link in browser" + no_info: "No additional information available at this point" + server_software: "Server software:" + response_time: "Response time:" + ms: + one: "<%= count %>ms" + other: "<%= count %>ms" + unknown: "unknown" + not_available: "not available" + unchecked: + one: "There is still one pod that hasn't been checked at all." + other: "There are still <%= count %> pods that haven't been checked at all." + version_failed: + one: "There is one pod that has no version (old pod, no NodeInfo)." + other: "There are <%= count %> pods that have no version (old pods, no NodeInfo)." + errors: + one: "The connection test returned an error for one pod." + other: "The connection test returned an error for <%= count %> pods." + aspects: make_aspect_list_visible: "Make contacts in this aspect visible to each other?" name: "Name" @@ -42,21 +92,34 @@ en: prefixFromNow: "" suffixAgo: "ago" suffixFromNow: "from now" + inPast: "any moment now" seconds: "less than a minute" minute: "about a minute" - minutes: "%d minutes" + minutes: + one: "1 minute" + other: "%d minutes" hour: "about an hour" - hours: "about %d hours" + hours: + one: "about 1 hour" + other: "about %d hours" day: "a day" - days: "%d days" + days: + one: "1 day" + other: "%d days" month: "about a month" - months: "%d months" + months: + one: "1 month" + other: "%d months" year: "about a year" - years: "%d years" + years: + one: "1 year" + other: "%d years" wordSeparator: " " contacts: add_contact: "Add contact" + aspect_chat_is_enabled: "Contacts in this aspect are able to chat with you." + aspect_chat_is_not_enabled: "Contacts in this aspect are not able to chat with you." aspect_list_is_visible: "Contacts in this aspect are able to see each other." aspect_list_is_not_visible: "Contacts in this aspect are not able to see each other." remove_contact: "Remove contact" @@ -68,25 +131,46 @@ en: my_stream: "Stream" my_aspects: "My aspects" - videos: - watch: "Watch this video on <%= provider %>" - unknown: "Unknown video type" - search_for: "Search for <%= name %>" publisher: - at_least_one_aspect: "You must publish to at least one aspect" limited: "Limited: your post will only be seen by people you are sharing with" public: "Public: your post will be visible to everyone and found by search engines" near_from: "Posted from: <%= location %>" option: "Answer" add_option: "Add an answer" question: "Question" + markdown_editor: + preview: "Preview" + write: "Write" + tooltips: + bold: "Bold" + italic: "Italic" + heading: "Heading" + insert_link: "Insert link" + insert_image: "Insert image" + insert_ordered_list: "Insert ordered list" + insert_unordered_list: "Insert unordered list" + preview: "Preview message" + write: "Edit message" + cancel: "Cancel message" + quote: "Insert quotation" + code: "Insert code" + texts: + strong: "strong text" + italic: "italic text" + heading: "heading text" + insert_link_description_text: "enter link description here" + insert_link_help_text: "Insert link here" + insert_image_description_text: "enter image description here" + insert_image_help_text: "Insert image link here" + insert_image_title: "enter image title here" + list: "list text here" + quote: "quotation text here" + code: "code here" + bookmarklet: post_something: "Post to diaspora*" post_submit: "Submitting post..." post_success: "Posted! Closing popup window..." - infinite_scroll: - no_more: "No more posts." - no_more_contacts: "No more contacts." aspect_dropdown: add_to_aspect: "Add contact" select_aspects: "Select aspects" @@ -99,12 +183,12 @@ en: error: "Couldn’t start sharing with <%= name %>. Are you ignoring them?" error_remove: "Couldn’t remove <%= name %> from the aspect :(" toggle: - zero: "Select aspects" one: "In <%= count %> aspect" other: "In <%= count %> aspects" show_more: "Show more" - failed_to_like: "Failed to like!" + failed_to_like: "Failed to like. Maybe the author is ignoring you?" failed_to_reshare: "Failed to reshare!" + failed_to_comment: "Failed to comment. Maybe the author is ignoring you?" failed_to_post_message: "Failed to post message!" failed_to_remove: "Failed to remove the entry!" comments: @@ -147,7 +231,6 @@ en: edit: "Edit" add_some: "Add some" you_have_no_tags: "You have no tags!" - ignoring: "You are ignoring all posts from <%= name %>." bio: "Bio" location: "Location" gender: "Gender" @@ -157,7 +240,6 @@ en: posts: "Posts" conversation: - participants: "Participants" new: no_contacts: "You need to add some contacts before you can start a conversation." @@ -181,7 +263,9 @@ en: unfollow: "Unfollow" enable_post_notifications: "Enable notifications for this post" disable_post_notifications: "Disable notifications for this post" + permalink: "Permalink" via: "via <%= provider %>" + no_posts_yet: "There are no posts to display here yet." likes: zero: "<%= count %> Likes" @@ -211,6 +295,11 @@ en: follow_error: "Couldn’t follow #<%= tag %> :(" stop_following_error: "Couldn’t stop following #<%= tag %> :(" + reactions: + zero: "<%= count%> reactions" + one: "<%= count%> reaction" + other: "<%= count%> reactions" + header: home: "Home" profile: "Profile" @@ -220,6 +309,8 @@ en: admin: "Admin" moderator: "Moderator" log_out: "Log out" + toggle_navigation: "Toggle navigation" + toggle_mobile: "Toggle mobile" notifications: "Notifications" conversations: "Conversations" @@ -232,14 +323,7 @@ en: close: "Close" viewer: - stop_following_post: "Stop following post" - follow_post: "Follow post" - like: "Like" - unlike: "Unlike" - reshare: "Reshare" reshared: "Reshared" - comment: "Comment" - home: "Home" poll: vote: "Vote" @@ -249,5 +333,9 @@ en: count: one: "1 vote so far" other: "<%=count%> votes so far" + answer_count: + zero: "0 votes" + one: "1 vote" + other: "<%=count%> votes" show_result: "Show result" close_result: "Hide result" diff --git a/config/locales/javascript/javascript.en_1337.yml b/config/locales/javascript/javascript.en_1337.yml index fd98ec9d3ec480cb4faf9507b8d847a894f751ee..8d3382c012976a83f9d856f18948a8935ea9aa06 100644 --- a/config/locales/javascript/javascript.en_1337.yml +++ b/config/locales/javascript/javascript.en_1337.yml @@ -31,15 +31,11 @@ en_1337: preparing_your_stream: "Preparing your personialized stream..." header: search: "F1ND N00B5 0R #74G5" - infinite_scroll: - no_more: "EOF" publisher: - at_least_one_aspect: "Y0U MU57 PUBL15H 70 47 L3457 1 4SP3C7" limited: "L1M173D - Y0UR 5P4M W1LL 0NLY B3 533N BY N00B5 U 4R3 5H4R1NG W17H!" public: "PUBL1C - Y0UR 5P4M W1LL B3 V151BL3 2 3V3RY0N3 4ND F0UND BY S34RCH 3NG1N35!" reshares: duplicate: "U H4V3 4LR34DY R35P4MM3D 7HI5!" - search_for: "S34RCH F0R <%= name %>" show_more: "5H0W M0R3!" stream: likes: @@ -67,20 +63,22 @@ en_1337: wasnt_that_interesting: "0K, 1 5UPP053 #<%= tagName %> W45N7 7H47 1N73R3571NG..." timeago: day: "4 D4Y" - days: "%d D4Y5" + days: + other: "%d D4Y5" hour: "4B0U7 4N H0UR" - hours: "4B0U7 %d H0UR5" + hours: + other: "4B0U7 %d H0UR5" minute: "4B0U7 4 M1NU73" - minutes: "%d M1NU735" + minutes: + other: "%d M1NU735" month: "4B0U7 4 M0N7H" - months: "%d M0N7H5" + months: + other: "%d M0N7H5" prefixAgo: "" prefixFromNow: "" seconds: "L355 7H3N 4 M1NU73" suffixAgo: "4G0" suffixFromNow: "FR0M N0W" year: "4B0U7 4 Y34R" - years: "%d Y34R5" - videos: - unknown: "UNK0WN V1D30 7YP3" - watch: "W47CH 7H15 V1D30 0N <%= provider %>" \ No newline at end of file + years: + other: "%d Y34R5" \ No newline at end of file diff --git a/config/locales/javascript/javascript.en_pirate.yml b/config/locales/javascript/javascript.en_pirate.yml index 85ee3353bf46955975e2253d72f6e6dd2138d3c3..c0573f0cdfb4a8658bba991d5cefdc6492b74720 100644 --- a/config/locales/javascript/javascript.en_pirate.yml +++ b/config/locales/javascript/javascript.en_pirate.yml @@ -22,7 +22,6 @@ en_pirate: search: "Find people or #tags" reshares: duplicate: "You've already reshared that post!" - search_for: "Search for <%= name %>" stream: likes: few: "<%= count %> Likes" @@ -51,6 +50,4 @@ en_pirate: prefixAgo: "" prefixFromNow: "" suffixAgo: "" - suffixFromNow: "" - videos: - watch: "Watch this video on <%= provider %>" \ No newline at end of file + suffixFromNow: "" \ No newline at end of file diff --git a/config/locales/javascript/javascript.en_shaw.yml b/config/locales/javascript/javascript.en_shaw.yml index 122592459ec67ce8abfb6ab392eecde08ed80895..27259dbc25ae246b288542d739d204e18d4b4b6d 100644 --- a/config/locales/javascript/javascript.en_shaw.yml +++ b/config/locales/javascript/javascript.en_shaw.yml @@ -26,13 +26,8 @@ en_shaw: preparing_your_stream: "Preparing your personialized stream..." header: search: "Find people or #tags" - infinite_scroll: - no_more: "ð‘¯ð‘´ ð‘¥ð‘¹ ð‘ð‘´ð‘•ð‘‘ð‘•." - publisher: - at_least_one_aspect: "ð‘¿ ð‘¥ð‘³ð‘•ð‘‘ ð‘ð‘³ð‘šð‘¤ð‘¦ð‘– ð‘‘ ð‘¨ð‘‘ ð‘¤ð‘°ð‘•ð‘‘ ð‘¢ð‘³ð‘¯ ð‘¨ð‘•ð‘ð‘§ð‘’ð‘‘" reshares: duplicate: "ð‘¿ð‘ ð‘·ð‘¤ð‘®ð‘§ð‘›ð‘¦ ð‘®ð‘¦ð‘–ð‘ºð‘› ð‘žð‘¨ð‘‘ ð‘ð‘´ð‘•ð‘‘!" - search_for: "ð‘•ð‘»ð‘— ð‘“𑹠<%= name %>" show_more: "ð‘–ð‘´ ð‘¥ð‘¹" stream: likes: @@ -60,20 +55,22 @@ en_shaw: wasnt_that_interesting: "OK, I suppose #<%= tagName %> wasn't all that interesting..." timeago: day: "ð‘© ð‘›ð‘±" - days: "%d ð‘›ð‘±ð‘Ÿ" + days: + other: "%d ð‘›ð‘±ð‘Ÿ" hour: "ð‘©ð‘šð‘¬ð‘‘ ð‘©ð‘¯ ð‘¬ð‘®" - hours: "ð‘©ð‘šð‘¬ð‘‘ %d ð‘¬ð‘®ð‘Ÿ" + hours: + other: "ð‘©ð‘šð‘¬ð‘‘ %d ð‘¬ð‘®ð‘Ÿ" minute: "ð‘©ð‘šð‘¬ð‘‘ ð‘© ð‘¥ð‘¦ð‘¯ð‘©ð‘‘" - minutes: "%d ð‘¥ð‘¦ð‘¯ð‘©ð‘‘ð‘•" + minutes: + other: "%d ð‘¥ð‘¦ð‘¯ð‘©ð‘‘ð‘•" month: "ð‘©ð‘šð‘¬ð‘‘ ð‘© ð‘¥ð‘³ð‘¯ð‘”" - months: "%d ð‘¥ð‘³ð‘¯ð‘”ð‘•" + months: + other: "%d ð‘¥ð‘³ð‘¯ð‘”ð‘•" prefixAgo: "ð‘©ð‘œð‘´" prefixFromNow: "ð‘“ð‘®ð‘ªð‘¥ ð‘¯ð‘¬" seconds: "ð‘¤ð‘§ð‘• ð‘žð‘¨ð‘¯ ð‘© ð‘¥ð‘¦ð‘¯ð‘©ð‘‘" suffixAgo: "ð‘©ð‘œð‘´" suffixFromNow: "ð‘“ð‘®ð‘ªð‘¥ ð‘¯ð‘¬" year: "ð‘©ð‘šð‘¬ð‘‘ ð‘© ð‘˜ð‘½" - years: "%d ð‘˜ð‘½ð‘Ÿ" - videos: - unknown: "ð‘©ð‘¯ð‘¯ð‘´ð‘¯ ð‘ð‘¦ð‘›ð‘¦ð‘´ ð‘‘ð‘²ð‘" - watch: "ð‘¢ð‘·ð‘— ð‘žð‘¦ð‘• ð‘ð‘¦ð‘›ð‘¦ð‘´ ð‘ªð‘¯ <%= provider %>" \ No newline at end of file + years: + other: "%d ð‘˜ð‘½ð‘Ÿ" \ No newline at end of file diff --git a/config/locales/javascript/javascript.en_valspeak.yml b/config/locales/javascript/javascript.en_valspeak.yml index 23f10fb259e20fa015fde81e5650ae1a23682c38..b8fc63771066db6a1d40b746d876471a6d810b35 100644 --- a/config/locales/javascript/javascript.en_valspeak.yml +++ b/config/locales/javascript/javascript.en_valspeak.yml @@ -49,7 +49,6 @@ en_valspeak: conversation: new: no_contacts: "So like, u got to add some ppl before u can start a convo..." - participants: "Ppl up in here" delete: "Trash" edit: "Edit!" failed_to_like: "Ur <3 didnt work :(" @@ -81,9 +80,6 @@ en_valspeak: ignore: "Block" ignore_failed: "Cant block this h8ter :\\" ignore_user: "Ignore this h8ter?" - infinite_scroll: - no_more: "No moar posties :(" - no_more_contacts: "No more besties :(" my_activity: "My Happenins" my_aspects: "My Aspectz" my_stream: "Wall" @@ -122,14 +118,12 @@ en_valspeak: contacts: "BFFs <33" edit: "edit!" gender: "So Im like..." - ignoring: "U r ignorin all posties from <%= name %>." location: "My crib" photos: "Pics and selfies <3" posts: "Posties!!" you_have_no_tags: "u like... have no tagz!" publisher: add_option: "Like, add an ansah!" - at_least_one_aspect: "U like... must add to at least 1 group" limited: "Limited - ur postie will only b seen by ppl u r sharin wit" near_from: "Postie from: <%= location %>" option: "Mah ansah<3" @@ -147,7 +141,6 @@ en_valspeak: duplicate: "OMG that gr8t eh? uve like, already reshared tht postie!! :P" post: "do u wanna like, reshare <%= name %>'s postie?" successful: "The postie was reshared!!! :D" - search_for: "Look for <%= name %>" show_more: "show moar" stream: comment: "Comment!!" @@ -188,13 +181,17 @@ en_valspeak: wasnt_that_interesting: "K, I guess #<%= tagName %> wasnt all that gr8. Whatev." timeago: day: "like... a day" - days: "like... %d dayz" + days: + other: "like... %d dayz" hour: "bout an hr" - hours: "bout %d hrs" + hours: + other: "bout %d hrs" minute: "bout a min" - minutes: "%d mins" + minutes: + other: "%d mins" month: "bout like... a month" - months: "like %d months" + months: + other: "like %d months" prefixAgo: "" prefixFromNow: "" seconds: "less than a min" @@ -202,17 +199,8 @@ en_valspeak: suffixFromNow: "from nao" wordSeparator: " " year: "bout like... a yr" - years: "like %d yrs" + years: + other: "like %d yrs" unblock_failed: "Unblockin this h8ter didnt work :(" - videos: - unknown: "i dunno what kinda vid this is :(" - watch: "Watch this vid on <%= provider %>" viewer: - comment: "Comment!!" - follow_post: "Follow postie" - home: "HOOOMMMMEEEE" - like: "<3" - reshare: "Reshare!!" - reshared: "Reshared<33" - stop_following_post: "Stop followin postie" - unlike: "</3" \ No newline at end of file + reshared: "Reshared<33" \ No newline at end of file diff --git a/config/locales/javascript/javascript.eo.yml b/config/locales/javascript/javascript.eo.yml index 9189f95bcd7a633b73309a47a9af259d70c8aa3b..439f2c33f6423f0079878a3a01a9909bf1c9bc57 100644 --- a/config/locales/javascript/javascript.eo.yml +++ b/config/locales/javascript/javascript.eo.yml @@ -6,6 +6,11 @@ eo: javascripts: + admin: + pods: + version_failed: + one: "Estas unu pod (Diaspora-servilo) kiu ne havas version (malnova pod, sen NodeInfo)." + other: "Estas <%= count %> pods (Diaspora-serviloj) kiuj ne havas version (malnova pod, sen NodeInfo)." and: "kaj" aspect_dropdown: add_to_aspect: "Aldoni kontakton" @@ -51,8 +56,6 @@ eo: settings: "Agordoj" view_all: "Vidi ĉiujn" ignore: "Ignori" - infinite_scroll: - no_more: "Neniu plua afiÅo." my_activity: "Mia aktiveco" my_aspects: "Viaj aspektoj" my_stream: "Torento" @@ -62,14 +65,12 @@ eo: completed: "<%= file %> kompletita" looking_good: "Diable, vi aspektas bonege!" publisher: - at_least_one_aspect: "Vi devas konigi al almenaÅ unu aspekton" limited: "Malpublika - via afiÅo nur videblos de homoj, al kiuj vi konigas aferojn" public: "Publika - via afiÅo videblos al ĉiuj kaj troveblos de retserĉprogramoj." reshares: duplicate: "Nu, ĉu tiel bone? Vi jam rekonigis tiun afiÅon!" post: "Ĉu vi deziras rekonigi la mesaÄon de <%= name %>?" successful: "La afiÅo estis sukcese rekonigita!" - search_for: "Serĉi por <%= name %>" show_more: "vidi plu" stream: comment: "Komenti" @@ -109,29 +110,24 @@ eo: wasnt_that_interesting: "Nu, mi supozas, ke #<%= tagName %> ne estis tiel interesa..." timeago: day: "unu tago" - days: "%d tagoj" + days: + other: "%d tagoj" hour: "ĉirkaÅ unu horo" - hours: "ĉirkaÅ %d horoj" + hours: + other: "ĉirkaÅ %d horoj" minute: "ĉirkaÅ unu minuto" - minutes: "%d minutoj" + minutes: + other: "%d minutoj" month: "ĉirkaÅ unu monato" - months: "%d monatoj" + months: + other: "%d monatoj" prefixAgo: "antaÅ " prefixFromNow: "post " seconds: "malpli ol unu minuto" suffixAgo: "" suffixFromNow: "ekde nun" year: "ĉirkaÅ unu jaro" - years: "%d jaroj" - videos: - unknown: "nekonata tipo de videaĵo" - watch: "Vidi tiun ĉi filmon ĉe <%= provider %>" + years: + other: "%d jaroj" viewer: - comment: "Komenti" - follow_post: "Sekvi mesaÄon" - home: "ĈefpaÄo" - like: "Åœati" - reshare: "Rekonigi" - reshared: "Rekonigita" - stop_following_post: "Ne plu sekvi mesaÄon" - unlike: "Ne plu Åati" \ No newline at end of file + reshared: "Rekonigita" \ No newline at end of file diff --git a/config/locales/javascript/javascript.es-AR.yml b/config/locales/javascript/javascript.es-AR.yml index 7288da7b3dfd4e0b8f445ebaba683b724387be26..1f9a13293f9020e246444a7b82c47f7867dc56dd 100644 --- a/config/locales/javascript/javascript.es-AR.yml +++ b/config/locales/javascript/javascript.es-AR.yml @@ -6,6 +6,55 @@ es-AR: javascripts: + admin: + pods: + actions: "Acciones" + added: "Agregado" + check: "ejectutar test de conexión" + errors: + one: "El test de conexión devolvió un error para un pod." + other: "El test de conexión devolvió un error para <%= count %> pods." + follow_link: "abrir enlace en el navegador" + last_check: "último chequeo:" + more_info: "mostrar más información" + ms: + one: "<%= count %>ms" + other: "<%= count %>ms" + no_info: "No hay información adicional en este momento" + not_available: "no disponible" + offline_since: "desconectado desde:" + pod: "Pod" + recheck: + failure: "No se ejecutó el chequeo." + success: "El pod se acaba de chequear." + response_time: "Tiempo de respuesta:" + server_software: "Software del servidor:" + ssl: "SSL" + ssl_disabled: "SSL desactivado" + ssl_enabled: "SSL activado" + states: + dns_failed: "Falló la resolución de nombres (DNS)" + http_failed: "Falló la conexión HTTP" + net_failed: "Falló el intento de conexión" + no_errors: "OK" + ssl_failed: "Falló la conexión segura (SSL)" + unchecked: "No verificado" + unknown_error: "Un error no identificado ha ocurrido durante el chequeo" + version_failed: "Imposible determinar la versión del software" + status: "Estado" + unchecked: + one: "TodavÃa hay un pod que no ha sido comprobado en absoluto." + other: "TodavÃa hay <%= count %> pods que no han sido comprobados en absoluto." + unknown: "desconocido" + version_failed: + one: "Hay un pod que no tiene versión (servidor antiguo, no hay información del nodo)." + other: "Hay <%= count %> pods que no tienen versión (servidores antiguos, no hay información de los nodos)." + admins: + dashboard: + compare_versions: "La última versión de diaspora* es la <%= latestVersion %>, tu pod está ejecutando la <%= podVersion %>." + error: "Imposible determinar la última versión de diaspora*." + outdated: "Tu pod está desactualizado." + up_to_date: "¡Tu pod está actualizado!" and: "y" aspect_dropdown: add_to_aspect: "Agregar contacto" @@ -20,7 +69,7 @@ es-AR: toggle: one: "En <%= count %> aspecto" other: "En <%= count %> aspectos" - zero: "Seleccionar aspectos" + zero: "En <%= count %> aspectos" updating: "actualizando…" aspect_navigation: add_an_aspect: "+ Agregar un aspecto" @@ -48,6 +97,8 @@ es-AR: confirm_unload: "Por favor, confirmá que deseás salir de esta página. Los datos que has ingresado no serán guardados." contacts: add_contact: "Agregar contacto" + aspect_chat_is_enabled: "Los contactos de este aspecto pueden chatear con vos." + aspect_chat_is_not_enabled: "Los contactos de este aspecto no pueden chatear con vos." aspect_list_is_not_visible: "La lista de contactos de este aspecto no es visible." aspect_list_is_visible: "La lista de contactos de este aspecto es visible." error_add: "No se puede agregar a <%= name %> a este aspecto :(" @@ -57,11 +108,11 @@ es-AR: conversation: new: no_contacts: "Necesitas agregar algunos contactos antes de iniciar una conversación." - participants: "Participantes" create: "Crear" delete: "Borrar" edit: "Editar" - failed_to_like: "¡No pudo marcarse como 'Me gusta'!" + failed_to_comment: "Error al comentar. ¿Puede ser que el autor te esté ignorando?" + failed_to_like: "¡No pudo marcarse como \"Me gusta\"! ¿Tal vez el autor de la publicación te está ignorando?" failed_to_post_message: "¡No pudo publicarse el mensaje!" failed_to_remove: "Fallo al eliminar la entrada!" failed_to_reshare: "Error al volver a compartir" @@ -85,15 +136,14 @@ es-AR: recent_notifications: "Notificaciones recientes" search: "Buscar" settings: "Opciones" + toggle_mobile: "Interfaz móvil" + toggle_navigation: "Cambiar navegación" view_all: "Ver todo" hide_post: "¿Ocultar esta publicación?" hide_post_failed: "No se puede ocultar esta publicación" ignore: "Ignorar" ignore_failed: "No es posible ignorar este usuario" ignore_user: "¿Ignorar a este usuario?" - infinite_scroll: - no_more: "No hay más publicaciones." - no_more_contacts: "No hay más contactos." my_activity: "Mi actividad" my_aspects: "Mis aspectos" my_stream: "Entrada" @@ -118,6 +168,10 @@ es-AR: looking_good: "¡Apa, te ves muy bien!" size_error: "El archivo {file} es demasiado grande, el tamaño máximo permitido es {sizeLimit}." poll: + answer_count: + one: "1 voto" + other: "<%=count%> votos" + zero: "0 votos" close_result: "Ocultar resultados" count: one: "<%=count%> voto hasta ahora" @@ -134,15 +188,41 @@ es-AR: contacts: "Contactos" edit: "Editar" gender: "Género" - ignoring: "Estás ignorando todas las publicaciones de <%= name %>." location: "Ubicación" photos: "Fotos" posts: "Publicaciones" you_have_no_tags: "¡No tenés etiquetas!" publisher: add_option: "Añadir respuesta" - at_least_one_aspect: "Tenés que publicarlo en, por lo menos, un aspecto" limited: "Limitada: tu publicación será vista solo por la gente con quien la compartes" + markdown_editor: + preview: "Vista previa" + texts: + code: "texto de código" + heading: "texto de encabezamiento" + insert_image_description_text: "ingresa aquà la descripción de la imagen" + insert_image_help_text: "Inserta aquà el enlace de la imagen" + insert_image_title: "ingresa aquà el tÃtulo de la imagen" + insert_link_description_text: "ingresa aquà la descripción del enlace" + insert_link_help_text: "Inserta aquà el enlace" + italic: "texto en cursiva" + list: "texto de la lista" + quote: "texto de la cita" + strong: "texto en negrita" + tooltips: + bold: "Negrita" + cancel: "Cancelar post" + code: "Insertar Código" + heading: "Encabezamiento" + insert_image: "Insertar imagen" + insert_link: "Insertar enlace" + insert_ordered_list: "Insertar lista ordenada" + insert_unordered_list: "Insertar lista sin ordenar" + italic: "Cursiva" + preview: "Vista previa del post" + quote: "Insertar cita" + write: "Editar post" + write: "Escribir" near_from: "Cerca de: <%= location %>" option: "Respuesta" public: "Publica: tu publicación será visible para cualquiera en Internet y los buscadores podrán encontrarla" @@ -159,7 +239,6 @@ es-AR: duplicate: "¿Te gustó eh? ¡Ya habÃas compartido esa publicación!" post: "¿Compartir la publicación de <%= name %>?" successful: "¡La publicación se compartió correctamente!" - search_for: "Buscar a <%= name %>" show_more: "Mostrar más" stream: comment: "Comentar" @@ -182,8 +261,14 @@ es-AR: one: "Mostrar <%= count %> comentario más" other: "Mostrar <%= count %> comentarios más" zero: "Mostrar <%= count %> comentarios más" + no_posts_yet: "No hay posts para mostrar aquà todavÃa." original_post_deleted: "La publicación original fue eliminada por el autor" + permalink: "Enlace permanente" public: "Pública" + reactions: + one: "<%= count%> reacción" + other: "<%= count%> reacciones" + zero: "<%= count%> reacciones" reshare: "Compartir" reshares: one: "Compartido <%= count %> vez" @@ -205,13 +290,22 @@ es-AR: wasnt_that_interesting: "Bueno, supongo que #<%= tagName %> no era tan interesante..." timeago: day: "un dÃa" - days: "%d dÃas" + days: + one: "1 dÃa" + other: "%d dÃas" hour: "cerca de una hora" - hours: "cerca de %d horas" + hours: + one: "1 hora" + other: "%d horas" + inPast: "cualquier momento" minute: "aproximadamente un minuto" - minutes: "%d minutos" + minutes: + one: "1 minuto" + other: "%d minutos" month: "cerca de un mes" - months: "%d meses" + months: + one: "1 mes" + other: "%d meses" prefixAgo: "" prefixFromNow: "" seconds: "menos de un minuto" @@ -219,17 +313,9 @@ es-AR: suffixFromNow: "desde ahora" wordSeparator: " " year: "cerca de un año" - years: "%d años" + years: + one: "1 año" + other: "%d años" unblock_failed: "Falló el desbloqueo del usuario" - videos: - unknown: "Tipo de video desconocido" - watch: "Ver este video en <%= provider %>" viewer: - comment: "Comentar" - follow_post: "Seguir esta publicación" - home: "Inicio" - like: "Me gusta" - reshare: "Compartir" - reshared: "Compartido" - stop_following_post: "Dejar de seguir esta publicación" - unlike: "No me gusta" \ No newline at end of file + reshared: "Compartido" \ No newline at end of file diff --git a/config/locales/javascript/javascript.es-CL.yml b/config/locales/javascript/javascript.es-CL.yml index ac6e21915a3cf8a93a1c885617eced4cc2123cd2..ab15420fa5be2cc67e7f446bb485c7c562300cde 100644 --- a/config/locales/javascript/javascript.es-CL.yml +++ b/config/locales/javascript/javascript.es-CL.yml @@ -47,8 +47,6 @@ es-CL: settings: "Ajustes" view_all: "Ver todo" ignore: "Ignorar" - infinite_scroll: - no_more: "No más publicaciones." my_activity: "Mi Actividad" my_stream: "Entrada" people: @@ -56,13 +54,11 @@ es-CL: photo_uploader: looking_good: "¡Guau, te ves genial!" publisher: - at_least_one_aspect: "Debes publicar para al menos un aspecto" limited: "Limitada - tu publicación sólo será visto por gente con la que compartes" public: "Público - tu post será visible para todos y encontrado por mecanismos de búsqueda" reshares: duplicate: "¿Es genial, cierto?  ¡Ya has compartido esa publicación!" successful: "¡La publicación se compartió correctamente!" - search_for: "Buscar <%= name%>" show_more: "mostrar más" stream: comment: "Comentar" @@ -86,28 +82,24 @@ es-CL: wasnt_that_interesting: "Bueno, supongo que #<%= tagName %> no era tan interesante..." timeago: day: "un dÃa" - days: "%d dÃas" + days: + other: "%d dÃas" hour: "alrededor de una hora" - hours: "cerca de %d horas" + hours: + other: "cerca de %d horas" minute: "alrededor de un minuto" - minutes: "%d minutos" + minutes: + other: "%d minutos" month: "alrededor de un mes" - months: "%d meses" + months: + other: "%d meses" prefixAgo: "" prefixFromNow: "" seconds: "hace menos de un minuto" suffixAgo: "hace" suffixFromNow: "desde ahora" year: "alrededor de un año" - years: "%d años" - videos: - unknown: "Tipo de video desconocido" - watch: "Mira este video en <%= provider %>" + years: + other: "%d años" viewer: - comment: "Comentar" - follow_post: "Seguir esta publicación" - like: "Me gusta" - reshare: "Compartir" - reshared: "Compartido" - stop_following_post: "Dejar de seguir esta publicación" - unlike: "No me gusta" \ No newline at end of file + reshared: "Compartido" \ No newline at end of file diff --git a/config/locales/javascript/javascript.es-MX.yml b/config/locales/javascript/javascript.es-MX.yml index a022c1b037846ccbfe8ba623f1aa4d4c8365ae90..a840ed04c560134e7cd5d8c2010225911caee378 100644 --- a/config/locales/javascript/javascript.es-MX.yml +++ b/config/locales/javascript/javascript.es-MX.yml @@ -30,8 +30,6 @@ es-MX: no_comments: "Aún no hay comentarios." show: "mostrar todos los comentarios" confirm_dialog: "¿Estás seguro?" - conversation: - participants: "Participantes" delete: "Borrar" edit: "Editar" failed_to_like: "¡No se pudo marcar como «Me gusta»!" @@ -58,9 +56,6 @@ es-MX: view_all: "Ver todo" ignore: "Ignorar" ignore_user: "¿Ignorar a este usuario?" - infinite_scroll: - no_more: "No hay más publicaciones." - no_more_contacts: "No hay más contactos." my_activity: "Mi actividad" my_aspects: "Mis aspectos" my_stream: "Entrada" @@ -74,7 +69,6 @@ es-MX: looking_good: "¡Ah, te ves increÃble!" size_error: "El archivo {file} es demasiado grande, el tamaño máximo de un archivo es {sizeLimit}." publisher: - at_least_one_aspect: "Debes publicar al menos en un aspecto" limited: "Limitado – tu publicación solo será vista por ia gente con quien compartes" near_from: "Publicado desde: <%= location %>" public: "Público – tu publicación será visible para todos, y encontrada por buscadores" @@ -82,7 +76,6 @@ es-MX: duplicate: "Qué bien, ¿eh? ¡Ya has compartido esa publicación!" post: "¿Compartir la publicación de <%= name %>?" successful: "¡La publicación se compartió exitosamente!" - search_for: "Buscar a <%= name %>" show_more: "mostrar más" stream: comment: "Comentar" @@ -122,29 +115,24 @@ es-MX: wasnt_that_interesting: "Muy bien, supongo que #<%= tagName %> no era tan interesante…" timeago: day: "un dÃa" - days: "%d dÃas" + days: + other: "%d dÃas" hour: "una hora aproximadamente" - hours: "%d horas aproximadamente" + hours: + other: "%d horas aproximadamente" minute: "un minuto aproximadamente" - minutes: "%d minutos" + minutes: + other: "%d minutos" month: "un mes aproximadamente" - months: "%d meses" + months: + other: "%d meses" prefixAgo: "hace" prefixFromNow: "dentro de" seconds: "menos de un minuto" suffixAgo: "" suffixFromNow: "desde ahora" year: "un año aproximadamente" - years: "%d años" - videos: - unknown: "Tipo de video desconocido" - watch: "Ver este video en <%= provider %>" + years: + other: "%d años" viewer: - comment: "Comentar" - follow_post: "Seguir esta publicación" - home: "INICIO" - like: "Me gusta" - reshare: "Compartir" - reshared: "Compartido" - stop_following_post: "Dejar de seguir esta publicación" - unlike: "No me gusta" \ No newline at end of file + reshared: "Compartido" \ No newline at end of file diff --git a/config/locales/javascript/javascript.es.yml b/config/locales/javascript/javascript.es.yml index 66a543162ea64124c4ce9f6f546f15633405e1bd..3e037b986b1df3bcdd9fdc17de45047ef2a93aa2 100644 --- a/config/locales/javascript/javascript.es.yml +++ b/config/locales/javascript/javascript.es.yml @@ -6,6 +6,55 @@ es: javascripts: + admin: + pods: + actions: "Acciones" + added: "Añadido" + check: "ejectutar test de conexión" + errors: + one: "El test de conexión ha devuelto un error en un pod." + other: "El test de conexión ha devuelto un error de <%= count %> pods." + follow_link: "abre enlace en el navegador" + last_check: "último chequeo:" + more_info: "muestra más información" + ms: + one: "<%= count %> ms" + other: "<%= count %> ms" + no_info: "No hay información adicional en este momento" + not_available: "no disponible" + offline_since: "Desconectado desde:" + pod: "Pod" + recheck: + failure: "No se ejecutó el chequeo." + success: "El pod se acaba de chequear." + response_time: "Tiempo de respuesta:" + server_software: "Software del servidor:" + ssl: "SSL" + ssl_disabled: "SSL desactivado" + ssl_enabled: "SSL activado" + states: + dns_failed: "Falló la resolución de nombres (DNS)" + http_failed: "Falló la conexión HTTP" + net_failed: "Falló el intento de conexión" + no_errors: "OK" + ssl_failed: "Falló la conexión segura (SSL)" + unchecked: "Desmarcado" + unknown_error: "Un error no identificado ha ocurrido durante el chequeo." + version_failed: "Imposible determinar la versión del software" + status: "Estado" + unchecked: + one: "TodavÃa hay un pod que no ha sido chequeado del todo." + other: "TodavÃa hay <%= count %> pods que no han sido chequeados del todo." + unknown: "desconocido" + version_failed: + one: "Hay un pod que no tiene versión (pod viejo, sin NodeInfo)." + other: "Hay <%= count %> pods que no tienen versión (pods viejos, sin NodeInfo)." + admins: + dashboard: + compare_versions: "La última versión de diaspora* es <%= latestVersion %>, tu pod está ejecutando <%= podVersion %>." + error: "Imposible determinar la última versión de diaspora*." + outdated: "Tu pod está obsoleto." + up_to_date: "¡Tu pod está actualizado!" and: "y" aspect_dropdown: add_to_aspect: "Añadir contacto" @@ -57,10 +106,10 @@ es: conversation: new: no_contacts: "Necesitas añadir algún contacto antes de empezar una conversación." - participants: "Participantes" create: "Crear" delete: "Eliminar" edit: "Editar" + failed_to_comment: "Error al comentar. ¿Puede ser que el autor te esté ignorando?" failed_to_like: "\"Me gusta\" no ha funcionado." failed_to_post_message: "¡Error al publicar el mensaje!" failed_to_remove: "¡Se produjo un error al eliminar la entrada!" @@ -85,15 +134,14 @@ es: recent_notifications: "Notificaciones recientes" search: "Buscar" settings: "Ajustes" + toggle_mobile: "Interfaz móvil" + toggle_navigation: "Cambiar navegación" view_all: "Ver todo" hide_post: "Ocultar esta publicación?" hide_post_failed: "Imposible ocultar esta publicación" ignore: "Ignorar" ignore_failed: "Imposible ignorar a este usuario" ignore_user: "¿Ignorar a este usuario?" - infinite_scroll: - no_more: "No hay más publicaciones." - no_more_contacts: "No hay más contactos." my_activity: "Mi Actividad" my_aspects: "Mis aspectos" my_stream: "Portada" @@ -118,6 +166,10 @@ es: looking_good: "¡Guau, estás increÃble!" size_error: "{file} es demasiado grande, el tamaño máximo es de {sizeLimit}." poll: + answer_count: + one: "1 voto" + other: "<%=count%> votos" + zero: "Sin votos" close_result: "Ocultar resultados" count: one: "<%=count%> voto por ahora" @@ -134,15 +186,41 @@ es: contacts: "Contactos" edit: "editar" gender: "Sexo" - ignoring: "Estás ignorando todas las publicaciones de <%= name %>." location: "Ubicación" photos: "Fotos" posts: "Mensajes" you_have_no_tags: "¡no tienes etiquetas!" publisher: add_option: "Añadir una respuesta" - at_least_one_aspect: "Debes publicarlo al menos en un aspecto" limited: "Limitado - tu publicación solo es visible para gente con quien compartes" + markdown_editor: + preview: "Previsualización" + texts: + code: "código aquÃ" + heading: "texto de encabezado" + insert_image_description_text: "introduce la descripción de la imagen aquÃ" + insert_image_help_text: "Inserta el enlace de la imagen aquÃ" + insert_image_title: "introduce el tÃtulo de la imagen aquÃ" + insert_link_description_text: "introduce la descripción del enlace aquÃ" + insert_link_help_text: "Insertar enlace aquÃ" + italic: "texto en cursiva" + list: "lista el texto aquÃ" + quote: "texto entrecomillado aquÃ" + strong: "texto en negrita" + tooltips: + bold: "Negritas" + cancel: "Cancelar mensaje" + code: "Insertar código" + heading: "Encabezando" + insert_image: "Insertar imagen" + insert_link: "Insertar enlace" + insert_ordered_list: "Insertar lista ordenada" + insert_unordered_list: "Insertar lista sin ordenar" + italic: "Cursiva" + preview: "Previsualizar mensaje" + quote: "Insertar comillas" + write: "Editar mensaje" + write: "Escribir" near_from: "Cerca de: <%= location %>" option: "Respuesta" public: "Público - tu publicación es visible para todos, incluyendo buscadores" @@ -159,7 +237,6 @@ es: duplicate: "¿Verdad que te ha gustado? Pero ya has esa publicación." post: "¿Compartir la publicación de <%= name %>?" successful: "¡Publicación compartida con éxito!" - search_for: "Buscar a <%= name %>" show_more: "mostrar más" stream: comment: "Comentar" @@ -182,8 +259,14 @@ es: one: "Mostrar <%= count %> comentario más" other: "Mostrar <%= count %> comentarios más" zero: "Mostrar <%= count %> comentarios más" + no_posts_yet: "TodavÃa no hay post para mostrar aquÃ." original_post_deleted: "Publicación original borrada por el autor." + permalink: "Enlace permanente" public: "Público" + reactions: + one: "<%= count%> reacción" + other: "<%= count%> reacciones" + zero: "<%= count%> reacciones" reshare: "Compartir" reshares: one: "Compartido <%= count %> vez" @@ -205,13 +288,17 @@ es: wasnt_that_interesting: "Muy bien, supongo que #<%= tagName %> no era tan interesante..." timeago: day: "1 dÃa" - days: "%d dÃas" + days: + other: "%d dÃas" hour: "1 hora aproximadamente" - hours: "%d horas aproximadamente" + hours: + other: "%d horas aproximadamente" minute: "1 minuto aproximadamente" - minutes: "%d minutos" + minutes: + other: "%d minutos" month: "1 mes aproximadamente" - months: "%d meses" + months: + other: "%d meses" prefixAgo: "Hace" prefixFromNow: "dentro de" seconds: "menos de 1 minuto" @@ -219,17 +306,8 @@ es: suffixFromNow: "" wordSeparator: " " year: "un año aproximadamente" - years: "%d años" + years: + other: "%d años" unblock_failed: "Falló el desbloqueo del usuario" - videos: - unknown: "Tipo de vÃdeo desconocido" - watch: "Ver este video con <%= provider %>" viewer: - comment: "Comentar" - follow_post: "Seguir" - home: "INICIO" - like: "Me gusta" - reshare: "Compartir" - reshared: "Compartido" - stop_following_post: "Dejar de seguir" - unlike: "No me gusta" \ No newline at end of file + reshared: "Compartido" \ No newline at end of file diff --git a/config/locales/javascript/javascript.et.yml b/config/locales/javascript/javascript.et.yml index 6aa4f322be1586e09b475719b845e643b61b46ad..efcd6dbd9cd4d988429ffd3c8118b5baa6112c44 100644 --- a/config/locales/javascript/javascript.et.yml +++ b/config/locales/javascript/javascript.et.yml @@ -36,17 +36,13 @@ et: settings: "Seaded" view_all: "Näita kõiki" ignore: "Eira" - infinite_scroll: - no_more: "Rohkem postitusi pole." my_activity: "Minu tegevused" my_stream: "Voog" photo_uploader: looking_good: "OMG, sa näed vinge välja!" publisher: - at_least_one_aspect: "Sa pead avaldama vähemalt ühe aspekti." limited: "Piiratud - sinu postitust näidatakse vaid neile inimestele kellega sa oled seda jaganud" public: "Avalik - sinu postitus on nähtav kõigile ja leitav otsingumootorite poolt" - search_for: "Otsi <%= name %>" show_more: "näita veel" stream: comment: "Kommenteeri" @@ -78,20 +74,22 @@ et: wasnt_that_interesting: "Oki, ma arvan, et <%= tagName %> polnud siiski nii huvitav..." timeago: day: "üks päev" - days: "%d päeva" + days: + other: "%d päeva" hour: "umbes üks tund" - hours: "umbes %d tundi" + hours: + other: "umbes %d tundi" minute: "umbes üks minut" - minutes: "%d minutit" + minutes: + other: "%d minutit" month: "umbes üks kuu" - months: "%d kuud" + months: + other: "%d kuud" prefixAgo: "" prefixFromNow: "" seconds: "vähem kui üks minut" suffixAgo: "tagasi" suffixFromNow: "hiljem" year: "umbes üks aasta" - years: "%d aastat" - videos: - unknown: "Tundmatu videoformaat" - watch: "Vaata seda videot <%= provider %>" \ No newline at end of file + years: + other: "%d aastat" \ No newline at end of file diff --git a/config/locales/javascript/javascript.eu.yml b/config/locales/javascript/javascript.eu.yml index f2a466d2e7b35ccab62553a5c7535df76d8cd286..bf98ebbd93146b9940521349657b9fc011effdfd 100644 --- a/config/locales/javascript/javascript.eu.yml +++ b/config/locales/javascript/javascript.eu.yml @@ -47,8 +47,6 @@ eu: settings: "Ezarpenak" view_all: "Guztiak ikusi" ignore: "Isildu" - infinite_scroll: - no_more: "Mezu gehiagorik ez dago." my_activity: "Nire Jarduera" my_stream: "Kronologia" people: @@ -56,14 +54,12 @@ eu: photo_uploader: looking_good: "Ene bada, oso jatorra dirudizu!" publisher: - at_least_one_aspect: "Gutxienez arlo batean partekatu behar duzu" limited: "Mugatua - zure mezua aukeratu duzun jendeak bakarrik ikusiko du" public: "Publikoa - zure mezua edonork ikusi ahalko du, bai eta bilaketa zerbitzuetan agertu ere" reshares: duplicate: "Oso ona, e? Dagoeneko birpartekatu duzu mezu hori!" post: "Birpartekatu nahi al duzu <%= name %>(r)en mezua?" successful: "Mezua arrakastaz birpartekatu da!" - search_for: "Bilatu <%= name %>" show_more: "erakutsi gehiago" stream: comment: "Iruzkindu" @@ -104,29 +100,24 @@ eu: wasnt_that_interesting: "Beno, suposatzen dut #<%= tagName %> ez zela oso interesgarria..." timeago: day: "egun bat" - days: "%d egun" + days: + other: "%d egun" hour: "ordu bat" - hours: "%d ordu" + hours: + other: "%d ordu" minute: "minutu bat" - minutes: "%d minutu" + minutes: + other: "%d minutu" month: "hilabete bat" - months: "%d hilabete" + months: + other: "%d hilabete" prefixAgo: "duela" prefixFromNow: "" seconds: "minutu bat baino gutxiago" suffixAgo: "" suffixFromNow: "barru" year: "urte bat" - years: "%d urte" - videos: - unknown: "Bideo mota ezezaguna" - watch: "Ikusi bideo hau <%= provider %>(e)n" + years: + other: "%d urte" viewer: - comment: "" - follow_post: "" - home: "HASIERA" - like: "" - reshare: "" - reshared: "" - stop_following_post: "" - unlike: "" \ No newline at end of file + reshared: "" \ No newline at end of file diff --git a/config/locales/javascript/javascript.fi.yml b/config/locales/javascript/javascript.fi.yml index 0a3e324429b8479304ee5b0d15b839147f7fbd89..3720953e39a177e68ffd164ce28c7a745ec67be9 100644 --- a/config/locales/javascript/javascript.fi.yml +++ b/config/locales/javascript/javascript.fi.yml @@ -60,7 +60,6 @@ fi: conversation: new: no_contacts: "Sinun pitää lisätä muutamia kontakteja ennen kuin voit aloittaa keskustelun." - participants: "Osallistujat" create: "Luo" delete: "Poista" edit: "Muokkaa" @@ -94,9 +93,6 @@ fi: ignore: "Sivuuta" ignore_failed: "Tämän käyttäjän sivuuttaminen ei onnistu" ignore_user: "Sivuuta tämä käyttäjä?" - infinite_scroll: - no_more: "Ei enempää viestejä." - no_more_contacts: "Ei enempää yhteystietoja." my_activity: "Oma toimintani" my_aspects: "Omat näkymäni" my_stream: "Virta" @@ -137,14 +133,12 @@ fi: contacts: "Kontaktit" edit: "Muokkaa" gender: "Sukupuoli" - ignoring: "Sivuutat nyt kaikki julkaisut, jotka <%= name %> lähettää." location: "Sijainti" photos: "Kuvat" posts: "Julkaisut" you_have_no_tags: "Sinulla ei ole tageja!" publisher: add_option: "Lisää vastaus" - at_least_one_aspect: "Sinun täytyy julkaista vähintään yhdelle näkymälle." limited: "Rajoitettu - julkaisusi näkyy vain ihmisille, joiden kanssa jaat" near_from: "Lähetetty sijainnista: <%= location %>" option: "Vastaus" @@ -162,7 +156,6 @@ fi: duplicate: "Olet jo uudelleenjakanut tämän julkaisun!" post: "Jaa käyttäjän <%= name %> julkaisu?" successful: "Julkaisu jaettiin onnistuneesti!" - search_for: "Etsi nimellä <%= name %>" show_more: "Näytä lisää" stream: comment: "Kommentoi" @@ -217,13 +210,17 @@ fi: wasnt_that_interesting: "OK, #<%= tagName %> ei tainnut ollakaan kovin kiinnostava aihe..." timeago: day: "päivä" - days: "%d päivää" + days: + other: "%d päivää" hour: "noin tunti" - hours: "noin %d tuntia" + hours: + other: "noin %d tuntia" minute: "noin minuutti" - minutes: "%d minuuttia" + minutes: + other: "%d minuuttia" month: "noin kuukausi" - months: "%d kuukautta" + months: + other: "%d kuukautta" prefixAgo: "" prefixFromNow: "tästä alkaen" seconds: "alle minuutti" @@ -231,17 +228,8 @@ fi: suffixFromNow: "tästä alkaen" wordSeparator: " " year: "noin vuosi" - years: "%d vuotta" + years: + other: "%d vuotta" unblock_failed: "Tämän käyttäjän torjumisen peruminen on epäonnistunut" - videos: - unknown: "Tuntematon videomuoto" - watch: "Katso video palvelussa <%= provider %>" viewer: - comment: "Kommentoi" - follow_post: "Seuraa julkaisua" - home: "KOTI" - like: "Tykkää" - reshare: "Jaa uudelleen" - reshared: "Jaettu uudelleen" - stop_following_post: "Lopeta julkaisun seuraaminen" - unlike: "Peru tykkäys" \ No newline at end of file + reshared: "Jaettu uudelleen" \ No newline at end of file diff --git a/config/locales/javascript/javascript.fil.yml b/config/locales/javascript/javascript.fil.yml index f9d803b613c5ddb2d2bb288ae8b06c7a4d68beca..ce11afe1a6ab2e9c2f0a0cb17070f8fe734fc369 100644 --- a/config/locales/javascript/javascript.fil.yml +++ b/config/locales/javascript/javascript.fil.yml @@ -9,12 +9,12 @@ fil: confirm_dialog: "Sigurado ka ba?" header: view_all: "Tingnan lahat" - search_for: "Hanapin si <%=name%>" stream: hide: "Itago" public: "Publiko" timeago: - minutes: "%d minuto" + minutes: + other: "%d minuto" prefixAgo: "" prefixFromNow: "" suffixAgo: "" diff --git a/config/locales/javascript/javascript.fr.yml b/config/locales/javascript/javascript.fr.yml index 29dc458bd23dcfff98744ab7428afbb428659430..a9aba75331b4400ba197eddbc5ae5c06d464be32 100644 --- a/config/locales/javascript/javascript.fr.yml +++ b/config/locales/javascript/javascript.fr.yml @@ -6,6 +6,55 @@ fr: javascripts: + admin: + pods: + actions: "Actions" + added: "Ajouté" + check: "exécuter un test de connexion" + errors: + one: "Le test de connexion rapporte une erreur pour un pod." + other: "Le test de connexion rapporte une erreur pour <%= count %> pods." + follow_link: "ouvrir le lien dans le navigateur" + last_check: "dernière vérification :" + more_info: "montrer plus d'information" + ms: + one: "<%= count %> ms" + other: "<%= count %> ms" + no_info: "Pas d'information supplémentaire disponible pour l'instant." + not_available: "non disponible" + offline_since: "hors ligne depuis :" + pod: "Pod" + recheck: + failure: "La vérification n'a pas été exécutée." + success: "Le pod vient d'être vérifié à nouveau." + response_time: "Temps de réponse :" + server_software: "Logiciel de serveur :" + ssl: "SSL" + ssl_disabled: "SSL désactivée" + ssl_enabled: "SSL activée" + states: + dns_failed: "La résolution du nom (DNS) a échoué" + http_failed: "La connexion HTTP a échoué" + net_failed: "La tentative de connexion a échoué" + no_errors: "OK" + ssl_failed: "La connexion sécurisée (SSL) a échoué" + unchecked: "Non vérifié" + unknown_error: "Une erreur inconnue s'est produite pendant la vérification" + version_failed: "Impossible de déterminer la version du programme" + status: "État" + unchecked: + one: "Il reste un pod qui n'a pas du tout été vérifié." + other: "Il reste <%= count %> pods qui n'ont pas du tout été vérifiés." + unknown: "inconnu" + version_failed: + one: "Il y a un pod dont la version est inconnue (un ancien pod, pas de NodeInfo)." + other: "Il y a un <%= count %> pods dont la version est inconnue (anciens pods, pas de NodeInfo)." + admins: + dashboard: + compare_versions: "La dernière version de diaspora* est <%= latestVersion %>, votre pod tourne sous la version <%= podVersion %>." + error: "Impossible de déterminer la dernière version de diaspora*." + outdated: "Votre pod n'est pas à jour." + up_to_date: "Votre pod est à jour !" and: "et" aspect_dropdown: add_to_aspect: "Ajouter le contact" @@ -48,6 +97,8 @@ fr: confirm_unload: "Merci de confirmer que vous voulez quitter cette page — les données saisies ne seront pas sauvegardées." contacts: add_contact: "Ajouter ce contact" + aspect_chat_is_enabled: "Les contacts de cet aspect peuvent discuter avec vous." + aspect_chat_is_not_enabled: "Les contacts de cet aspect ne peuvent pas discuter avec vous." aspect_list_is_not_visible: "Les contacts de cette facette ne peuvent pas se voir entre eux." aspect_list_is_visible: "Les contacts de cette facette peuvent se voir entre eux." error_add: "Impossible d'ajouter <%= name %> à cette facette :(" @@ -57,10 +108,10 @@ fr: conversation: new: no_contacts: "Vous devez ajouter des contacts avant de pouvoir démarrer une conversation." - participants: "Participants" create: "Créer" delete: "Effacer" edit: "Éditer" + failed_to_comment: "Impossible de commenter. Peut-être que l'auteur vous ignore ?" failed_to_like: "Impossible d'aimer !" failed_to_post_message: "Impossible de partager le message !" failed_to_remove: "L'entrée n'a pu être supprimée" @@ -85,15 +136,14 @@ fr: recent_notifications: "Notifications récentes" search: "Trouver des personnes ou #tags" settings: "Paramètres" + toggle_mobile: "Activer/désactiver la version mobile" + toggle_navigation: "Afficher/cacher le menu" view_all: "Tout afficher" hide_post: "Masquer ce message ?" hide_post_failed: "Impossible de masquer ce message" ignore: "Ignorer" ignore_failed: "Impossible d'ignorer cet utilisateur" ignore_user: "Ignorer cet utilisateur ?" - infinite_scroll: - no_more: "Pas d'autres messages." - no_more_contacts: "Pas d'autres contacts." my_activity: "Mon activité" my_aspects: "Mes aspects" my_stream: "Flux" @@ -118,10 +168,15 @@ fr: looking_good: "Impressionnant, vous avez un super look !" size_error: "{file} est trop gros, la taille maximum est de {sizeLimit}." poll: + answer_count: + one: "<%=count%> vote" + other: "<%=count%> votes" + zero: "Aucun vote" close_result: "Masquer les résultats" count: one: "<%=count%> vote pour le moment" other: "<%=count%> votes pour le moment" + zero: "Aucun vote pour le moment" go_to_original_post: "Vous pouvez participer à ce sondage sur le <%= original_post_link %>." original_post: "message initial" result: "Résultat" @@ -134,15 +189,41 @@ fr: contacts: "Contacts" edit: "modifier" gender: "Genre" - ignoring: "Vous ignorez tous les messages de <%= name %>." location: "Localisation" photos: "Photos" posts: "Messages" you_have_no_tags: "vous n'avez pas de tag !" publisher: add_option: "Ajouter un choix" - at_least_one_aspect: "Vous devez créer au moins un aspect" limited: "Limité - votre message ne sera vu que par des gens avec qui vous partagez" + markdown_editor: + preview: "Aperçu" + texts: + code: "langage de programmation ici" + heading: "Entête" + insert_image_description_text: "Entrer une description pour l'image ici" + insert_image_help_text: "Insérer un lien vers une image ici" + insert_image_title: "Entrer un intitulé d'image ici" + insert_link_description_text: "Entrer la description du lien ici" + insert_link_help_text: "Insérer un lien ici" + italic: "Texte italique" + list: "texte de liste ici" + quote: "texte de citation ici" + strong: "Emphase" + tooltips: + bold: "Gras" + cancel: "Annuler le message" + code: "Insérer du langage de programmation" + heading: "Titres" + insert_image: "Insérer une image" + insert_link: "Insérer un lien" + insert_ordered_list: "Insérer une liste ordonnée" + insert_unordered_list: "Insérer une liste à puces" + italic: "Italique" + preview: "Aperçu du message" + quote: "Insérer une citation" + write: "Modifier le message" + write: "Écrire" near_from: "Posté à : <%= location %>" option: "Choix" public: "Public - votre message sera visible de tous et trouvé par les moteurs de recherche" @@ -159,7 +240,6 @@ fr: duplicate: "C'est si bien que ça ? Vous avez déjà repartagé ce message !" post: "Repartager le message de <%= name %> ?" successful: "Le message a été repartagé !" - search_for: "Chercher <%= name %>" show_more: "Voir plus" stream: comment: "Commenter" @@ -185,8 +265,14 @@ fr: one: "Montrer <%= count %> commentaire supplémentaire" other: "Montrer <%= count %> commentaires supplémentaires" zero: "Montrer <%= count %> commentaires supplémentaires" + no_posts_yet: "Il n’y a aucun message à afficher pour le moment." original_post_deleted: "Le message original a été effacé par son auteur." + permalink: "Lien permanent" public: "Public" + reactions: + one: "<%= count%> réaction" + other: "<%= count%> réactions" + zero: "<%= count%> réactions" reshare: "Repartager" reshares: few: "<%= count %> repartages" @@ -211,13 +297,18 @@ fr: wasnt_that_interesting: "Ok, je suppose que #<%= tagName %> n'est pas la seule chose qui vous intéresse..." timeago: day: "environ un jour" - days: "environ %d jours" + days: + other: "environ %d jours" hour: "environ une heure" - hours: "environ %d heures" + hours: + other: "environ %d heures" + inPast: "très bientôt" minute: "environ une minute" - minutes: "environ %d minutes" + minutes: + other: "environ %d minutes" month: "environ un mois" - months: "environ %d mois" + months: + other: "environ %d mois" prefixAgo: "il y a" prefixFromNow: "d'ici" seconds: "moins d'une minute" @@ -225,17 +316,8 @@ fr: suffixFromNow: "maintenant" wordSeparator: " " year: "un an" - years: "%d ans" + years: + other: "%d ans" unblock_failed: "Impossible de débloquer cet utilisateur" - videos: - unknown: "Type de vidéo inconnu" - watch: "Voir cette vidéo sur <%= provider %>" viewer: - comment: "Commenter" - follow_post: "Suivre cette discussion" - home: "Accueil" - like: "J'aime" - reshare: "Repartager" - reshared: "Repartagé" - stop_following_post: "Ne plus suivre cette discussion" - unlike: "Je n'aime plus" \ No newline at end of file + reshared: "Repartagé" \ No newline at end of file diff --git a/config/locales/javascript/javascript.fy.yml b/config/locales/javascript/javascript.fy.yml index 84f0cf94269a5499e13bfccc5186a668d27aa0f6..b1e36f789823418a13e6e9f641f729f9010c7c49 100644 --- a/config/locales/javascript/javascript.fy.yml +++ b/config/locales/javascript/javascript.fy.yml @@ -35,7 +35,6 @@ fy: my_activity: "Myn Aktiviteit" photo_uploader: looking_good: "Heare GOD noch oan ta, do sjochst der fantastysk út!" - search_for: "Sykje nei <%= name %>" show_more: "toan mear" stream: comment: "Reaksje" @@ -62,17 +61,20 @@ fy: unlike: "Net mear Leuk" timeago: day: "in dei" - days: "%d dagen" + days: + other: "%d dagen" hour: "likernôch in oere" - hours: "likernôch %d oeren" - minutes: "%d minuten" + hours: + other: "likernôch %d oeren" + minutes: + other: "%d minuten" month: "likernôch in moanne" - months: "%d moannen" + months: + other: "%d moannen" prefixAgo: "" prefixFromNow: "" suffixAgo: "lyn" suffixFromNow: "" year: "likernôch in jier" - years: "%d jierren" - videos: - watch: "Dizze fideo op <%= provider %> besjen" \ No newline at end of file + years: + other: "%d jierren" \ No newline at end of file diff --git a/config/locales/javascript/javascript.ga.yml b/config/locales/javascript/javascript.ga.yml index 8ba3b936870e8b62153ed11281308e8e1c7ecbd0..c39fee2a9ae2c5e0fd0cd055cbac8f06665c4bf5 100644 --- a/config/locales/javascript/javascript.ga.yml +++ b/config/locales/javascript/javascript.ga.yml @@ -16,6 +16,4 @@ ga: prefixAgo: "" prefixFromNow: "" suffixAgo: "" - suffixFromNow: "" - viewer: - home: "BAILE" \ No newline at end of file + suffixFromNow: "" \ No newline at end of file diff --git a/config/locales/javascript/javascript.he.yml b/config/locales/javascript/javascript.he.yml index 83b0009068468135004e7c9fd4686fb1624ebe14..5f5a8d4d57f5f8cc496b920a1dc413b2dc9b1594 100644 --- a/config/locales/javascript/javascript.he.yml +++ b/config/locales/javascript/javascript.he.yml @@ -30,8 +30,6 @@ he: no_comments: "×ין תגובות כרגע." show: "הצגת כל התגובות" confirm_dialog: "×”×× ××ª× ×‘×˜×•×—×™×?" - conversation: - participants: "משתתפי×" delete: "מחיקה" edit: "עריכה" failed_to_like: "הסימון ב'×הבתי' × ×›×©×œ!" @@ -59,9 +57,6 @@ he: view_all: "הצגת הכל" ignore: "התעלמות" ignore_user: "×œ×”×ª×¢×œ× ×ž×ž×©×ž×© ×–×”?" - infinite_scroll: - no_more: "×ין הודעות × ×•×¡×¤×•×ª." - no_more_contacts: "×ין ×× ×©×™ קשר × ×•×¡×¤×™×." my_activity: "הפעילות שלי" my_aspects: "×”×”×™×‘×˜×™× ×©×œ×™" my_stream: "חדשות" @@ -87,7 +82,6 @@ he: vote: "הצבעה" publisher: add_option: "הוספת ×פשרות" - at_least_one_aspect: "יש ×œ×¤×¨×¡× ×œ×”×™×‘×˜ ×חד לפחות" limited: "מוגבל - הודעתך תהיה גלויה רק ל×× ×©×™× ×©××™×ª× ×‘×—×¨×ª לשתף" near_from: "×¤×•×¨×¡× ×ž<%= location %>" option: "×פשרות <%= nr %>" @@ -97,7 +91,6 @@ he: duplicate: "כבר שיתפת מחדש ×ת ההודעה הזו." post: "×”×× ×œ×©×ª×£ מחדש ×ת ההודעה של <%= name %>?" successful: "ההודעה שותפה מחדש בהצלחה!" - search_for: "חיפוש ×חר <%= name %>" show_more: "הצגת עוד" stream: comment: "תגובה" @@ -138,29 +131,24 @@ he: wasnt_that_interesting: "בסדר, ×›× ×¨××” שהתגית #<%= tagName %> ×œ× ×”×™×™×ª×” ×ž×¢× ×™×™× ×ª במיוחד..." timeago: day: "יו×" - days: "%d ימי×" + days: + other: "%d ימי×" hour: "כשעה" - hours: "×›-%d שעות" + hours: + other: "×›-%d שעות" minute: "כדקה" - minutes: "%d דקות" + minutes: + other: "%d דקות" month: "כחודש" - months: "%d חודשי×" + months: + other: "%d חודשי×" prefixAgo: "×œ×¤× ×™" prefixFromNow: "מעכשיו" seconds: "פחות מדקה" suffixAgo: "" suffixFromNow: "מעכשיו" year: "×›×©× ×”" - years: "%d ×©× ×™×" - videos: - unknown: "סוג הסרטון ××™× ×• מוכר" - watch: "צפייה בסרטון ×–×” ב×תר <%= provider %>" + years: + other: "%d ×©× ×™×" viewer: - comment: "תגובה" - follow_post: "עקיבה ×חר ההודעה" - home: "בית" - like: "×הבתי" - reshare: "שיתוף מחדש" - reshared: "בוצע שיתוף מחדש" - stop_following_post: "הפסקת עקיבה ×חר ההודעה" - unlike: "×œ× ×הבתי" \ No newline at end of file + reshared: "בוצע שיתוף מחדש" \ No newline at end of file diff --git a/config/locales/javascript/javascript.hu.yml b/config/locales/javascript/javascript.hu.yml index 4afa3a01a17c9254f6fd770b8441c51d8172093d..d868bc85818c38d1efd57423d342d26647037540 100644 --- a/config/locales/javascript/javascript.hu.yml +++ b/config/locales/javascript/javascript.hu.yml @@ -42,8 +42,6 @@ hu: aspect_list_is_not_visible: "A csoport tagjai nem láthatják egymást." aspect_list_is_visible: "A csoport tagjai láthatják egymást." remove_contact: "IsmerÅ‘s eltávolÃtása" - conversation: - participants: "RésztvevÅ‘k" delete: "Töröl" edit: "Szerkesztés" failed_to_like: "Hiba" @@ -72,9 +70,6 @@ hu: ignore: "MellÅ‘zés" ignore_failed: "Nem sikerült mellÅ‘zni ezt a felhasználót" ignore_user: "Felhasználó mellÅ‘zése?" - infinite_scroll: - no_more: "Nincs több bejegyzés." - no_more_contacts: "Nincs több ismerÅ‘s." my_activity: "Tevékenységeim" my_aspects: "Csoportjaim" my_stream: "HÃrfolyam" @@ -109,14 +104,12 @@ hu: contacts: "ismerÅ‘sök" edit: "szerkesztés" gender: "nem" - ignoring: "<%= name %> minden hozzászólását mellÅ‘zöd" location: "lakóhely" photos: "képek" posts: "bejegyzések" you_have_no_tags: "nincsenek cÃmkéid!" publisher: add_option: "Válasz hozzáadása" - at_least_one_aspect: "Legalább egy csoporttal meg kell osztanod!" limited: "Korlátozott - csak az ismerÅ‘seid láthatják ezt a bejegyzést" near_from: "<%= location %> közelében" option: "Válasz" @@ -133,7 +126,6 @@ hu: duplicate: "Jó mi? De már egyszer megosztottad ezt a bejegyzést!" post: "Szeretnéd újra megosztani <%= name %> bejegyzését?" successful: "A bejegyzés újraosztása sikeres!" - search_for: "<%= name %> keresése." show_more: "tovább" stream: comment: "Hozzászólás" @@ -179,13 +171,17 @@ hu: wasnt_that_interesting: "Oké, azt hiszem a #<%= tagName %> nem volt annyira érdekes." timeago: day: "egy nappal" - days: "%d nappal" + days: + other: "%d nappal" hour: "körülbelül egy órával" - hours: "körülbelül %d órával" + hours: + other: "körülbelül %d órával" minute: "körülbelül egy perccel" - minutes: "%d perccel" + minutes: + other: "%d perccel" month: "körülbelül egy hónappal" - months: "%d hónappal" + months: + other: "%d hónappal" prefixAgo: "" prefixFromNow: "" seconds: "kevesebb mint egy perccel" @@ -193,16 +189,7 @@ hu: suffixFromNow: "mostantól" wordSeparator: " " year: "körülbelül egy évvel" - years: "%d évvel" - videos: - unknown: "Ismeretlen videó tipus" - watch: "Videó megtekintése itt: <%= provider %>" + years: + other: "%d évvel" viewer: - comment: "Hozzászólás" - follow_post: "Követem" - home: "KEZDÅLAP" - like: "Tetszik" - reshare: "Megosztás" - reshared: "Megosztva" - stop_following_post: "Nem követem többé" - unlike: "Nem tetszik" \ No newline at end of file + reshared: "Megosztva" \ No newline at end of file diff --git a/config/locales/javascript/javascript.hy.yml b/config/locales/javascript/javascript.hy.yml index d461b69b340493a79a1abd0ab872fea10534ce8c..47b217e428dbbd0817c3b64da622a930b0a84b09 100644 --- a/config/locales/javascript/javascript.hy.yml +++ b/config/locales/javascript/javascript.hy.yml @@ -6,6 +6,51 @@ hy: javascripts: + admin: + pods: + actions: "Ô³Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€" + added: "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¾Õ¡Õ®" + check: "Õ¯Õ¡Õ¿Õ¡Ö€Õ¥Õ¬ Õ¯Õ¡ÕºÕ« ÖƒÕ¸Ö€Õ±Õ¡Ö€Õ¯Õ¸Ö‚Õ´" + errors: + one: "Ô¿Õ¡ÕºÕ« ÖƒÕ¸Ö€Õ±Õ¡Ö€Õ¯Õ¸Ö‚Õ´Õ¨ Õ½ÕÕ¡Õ¬Õ¡Õ¶Ö„ Õ¿Õ¾Õ¥Ö Õ´Õ¥Õ¯ ÖƒÕ¸Õ¤Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰" + other: "Ô¿Õ¡ÕºÕ« ÖƒÕ¸Ö€Õ±Õ¡Ö€Õ¯Õ¸Ö‚Õ´Õ¨ Õ½ÕÕ¡Õ¬Õ¡Õ¶Ö„ Õ¿Õ¾Õ¥Ö <%= count %> ÖƒÕ¸Õ¤Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰" + follow_link: "Õ¢Õ¡ÖÕ¥Õ¬ Õ°Õ²Õ¸Ö‚Õ´Õ¨ Õ¦Õ¶Õ¶Õ«Õ¹Õ¸Ö‚Õ´" + last_check: "Õ¾Õ¥Ö€Õ»Õ«Õ¶ Õ½Õ¿Õ¸Ö‚Õ£Õ¸Ö‚Õ´Õ¨Õ" + ms: + one: "<%= count %>Õ´Õ¾" + other: "<%= count %>Õ´Õ¾" + no_info: "Ô±ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ Õ¬Ö€Õ¡ÖÕ¸Ö‚ÖÕ«Õ¹ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ§" + not_available: "Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ§" + offline_since: "Õ¡Õ¶ÖÕ¡Õ¶Ö Õ§ Õ½Õ¯Õ½Õ¡Õ®Õ" + pod: "Õ“Õ¸Õ¤" + recheck: + failure: "ÕÕ¿Õ¸Ö‚Õ£Õ¸Ö‚Õ´Õ¨ Õ¹Õ¯Õ¡Õ¿Õ¡Ö€Õ¾Õ¥ÖÖ‰" + success: "Õ“Õ¸Õ¤Õ¨ Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Õ¶Õ¸Ö€Õ«Ö Õ½Õ¿Õ¸Ö‚Õ£Õ¾Õ¥ÖÖ‰" + response_time: "Ô±Ö€Õ±Õ¡Õ£Õ¡Õ¶Ö„Õ´Õ¡Õ¶ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¨Õ" + server_software: "ÕÕ¥Ö€Õ¾Õ¥Ö€Õ« Õ®Ö€Õ¡Õ£Ö€Õ¡Õ¯Õ¡Õ¦Õ´Õ¨Õ" + ssl: "Ô·Õ½Ô·Õ½Ô·Õ¬" + ssl_disabled: "Ô·Õ½Ô·Õ½Ô·Õ¬-Õ¶ Õ¡Õ¶Õ»Õ¡Õ¿Õ¾Õ¡Õ® Õ§" + ssl_enabled: "Ô·Õ½Ô·Õ½Ô·Õ¬-Õ¶ Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§" + states: + http_failed: "Ô·ÕµÕ¹Ô¹Õ«Ô¹Õ«Õ“Õ« Õ¯Õ¡ÕºÕ¨ Õ±Õ¡ÕÕ¸Õ²Õ¾Õ¥Ö" + no_errors: "Ô¿Õ¡Ö€Õ£Õ«Õ¶" + ssl_failed: "Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£ Õ¯Õ¡ÕºÕ¨ (Ô·Õ½Ô·Õ½Ô·Õ¬) Õ±Õ¡ÕÕ¸Õ²Õ¾Õ¥Ö" + unchecked: "Õ‰Õ½Õ¿Õ¸Ö‚Õ£Õ¾Õ¡Õ®" + version_failed: "Ô±Õ¶Õ°Õ¶Õ¡Ö€ Õ§ Õ¡Õ¼Õ¢Õ¥Ö€Õ¥Õ¬ Õ®Õ¡-ÕµÕ« Õ¾Õ¡Ö€Õ¯Õ¡Õ®Õ¨" + status: "ÕŽÕ«Õ³Õ¡Õ¯" + unchecked: + one: "Ô´Õ¥Õ¼ Õ¥Ö‚Õ½ Õ´Õ¥Õ¯ ÖƒÕ¸Õ¤ Õ¯Õ¡, Õ¸Ö€ Õ¨Õ¶Õ¤Õ°Õ¡Õ¶Ö€Õ¡ÕºÕ¥Õ½ Õ¹Õ« Õ½Õ¿Õ¸Ö‚Õ£Õ¾Õ¥Õ¬Ö‰" + other: "Ô´Õ¥Õ¼ Õ¥Ö‚Õ½ <%= count %> ÖƒÕ¸Õ¤ Õ¯Õ¡, Õ¸Ö€ Õ¨Õ¶Õ¤Õ°Õ¡Õ¶Ö€Õ¡ÕºÕ¥Õ½ Õ¹Õ¥Õ¶ Õ½Õ¿Õ¸Ö‚Õ£Õ¾Õ¥Õ¬Ö‰" + unknown: "Õ°Õ¡ÕµÕ¿Õ¶Õ« Õ¹Õ§" + version_failed: + one: "Ô·Õ½Õ¿Õ¥Õ² Õ´Õ¥Õ¯ ÖƒÕ¸Õ¤ Õ¯Õ¡, Õ¸Ö€ Õ¹Õ¸Ö‚Õ¶Õ« Õ¾Õ¡Ö€Õ¯Õ¡Õ® (Õ°Õ«Õ¶ ÖƒÕ¸Õ¤ Õ§, Õ†Õ¸Õ¸Ö‚Õ¤Ô»Õ¶Ö†Õ¸ Õ¹Õ¸Ö‚Õ¶Õ«)Ö‰" + other: "Ô·Õ½Õ¿Õ¥Õ² <%= count %> ÖƒÕ¸Õ¤ Õ¯Õ¡, Õ¸Ö€ Õ¹Õ¸Ö‚Õ¶Õ¥Õ¶ Õ¾Õ¡Ö€Õ¯Õ¡Õ® (Õ°Õ«Õ¶ ÖƒÕ¸Õ¤Õ¥Ö€ Õ¥Õ¶, Õ†Õ¸Õ¸Ö‚Õ¤Ô»Õ¶Ö†Õ¸ Õ¹Õ¸Ö‚Õ¶Õ¥Õ¶)Ö‰" + admins: + dashboard: + compare_versions: "Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ¡Õ´Õ¥Õ¶Õ¡Õ©Õ¡Ö€Õ´ Õ©Õ¸Õ²Õ¡Ö€Õ¯Õ¸Ö‚Õ´Õ¨ <%= latestVersion %>-Õ¶ Õ§, Ö„Õ¸ ÖƒÕ¸Õ¤Õ¶ Õ¡Õ·ÕÕ¡Õ¿Õ¸Ö‚Õ´ Õ§ <%= podVersion %>-Õ¸Õ¾Ö‰" + error: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ¸Ö€Õ¸Õ·Õ¥Õ¬ Õ¤Õ«Õ¡Õ½ÕºÕ¸Ö€Õ¡*ÕµÕ« Õ¡Õ´Õ¥Õ¶Õ¡Õ©Õ¡Ö€Õ´ Õ¾Õ¡Ö€Õ¯Õ¡Õ®Õ¨Ö‰" + outdated: "Õ”Õ¸ ÖƒÕ¸Õ¤Õ« ÕªÕ¡Õ´Õ¯Õ¥Õ¿Õ¶ Õ¡Õ¶Ö Õ§Ö‰" + up_to_date: "Õ”Õ¸ ÖƒÕ¸Õ¤Õ¶ Õ¸Ö‚ÕªÕ« Õ´Õ¥Õ» Õ§Ö‰" and: "Ö‡" aspect_dropdown: add_to_aspect: "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬" @@ -48,6 +93,8 @@ hy: confirm_unload: "Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ«Ö€, Õ¸Ö€ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ¥Õ½ Õ¬Ö„Õ¥Õ¬ Õ¡ÕµÕ½ էջը․ Ö„Õ¸ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¹Õ¥Õ¶ ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ¾Õ«Ö‰" contacts: add_contact: "Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬" + aspect_chat_is_enabled: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¹Õ¡Õ©Õ¾Õ¥Õ¬ Ö„Õ¸ Õ°Õ¥Õ¿Ö‰" + aspect_chat_is_not_enabled: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¹Õ¥Õ¶ Õ¯Õ¡Ö€Õ¸Õ² Õ¹Õ¡Õ©Õ¾Õ¥Õ¬ Ö„Õ¸ Õ°Õ¥Õ¿Ö‰" aspect_list_is_not_visible: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¹Õ¥Õ¶ Õ¯Õ¡Ö€Õ¸Õ² Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ´Õ«Õ´ÕµÕ¡Õ¶ÖÖ‰" aspect_list_is_visible: "Ô±ÕµÕ½ ÕÕ´Õ¢Õ« Õ´Õ¡Ö€Õ¤Õ«Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ´Õ«Õ´ÕµÕ¡Õ¶ÖÖ‰" error_add: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö <%= name %>Õ«Õ¶ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ ÕÕ´Õ¢Õ¸Ö‚Õ´Ö‰ Ափսո՜ս։" @@ -57,11 +104,11 @@ hy: conversation: new: no_contacts: "Õ†Õ¡ÕÖ„Õ¡Õ¶ Õ¦Ö€Õ¸Ö‚ÕµÖ Õ½Õ¯Õ½Õ¥Õ¬Õ¨ ÕºÕ¥Õ¿Ö„ Õ§ Õ£Õ¸Õ¶Õ¥ Õ´Õ¥Õ¯Õ«Õ¶ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ½Ö‰" - participants: "Õ„Õ¡Õ½Õ¶Õ¡Õ¯Õ«ÖÕ¶Õ¥Ö€" create: "ÕÕ¿Õ¥Õ²Õ®Õ¥Õ¬" delete: "Õ‹Õ¶Õ»Õ¥Õ¬" edit: "Õ“Õ¸ÖƒÕ¸ÕÕ¥Õ¬" - failed_to_like: "Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬Ö‰" + failed_to_comment: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¥Õ¬Ö‰ Ô³Õ¸Ö‚ÖÕ¥ Õ°Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ¶ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¸ÕžÖ‚Õ´ Õ§ Ö„Õ¥Õ¦Ö‰" + failed_to_like: "Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬Ö‰ Ô³Õ¸Ö‚ÖÕ¥ Õ°Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ¶ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¸ÕžÖ‚Õ´ Õ§ Ö„Õ¥Õ¦Ö‰" failed_to_post_message: "Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´ Õ¯Õ¡Õ¿Õ¡Ö€Õ¥Õ¬Ö‰" failed_to_remove: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ»Õ¶Õ»Õ¥Õ¬ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¡Õ®Õ¨Ö‰" failed_to_reshare: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ¿Õ¡Ö€Õ¡Õ®Õ¥Õ¬Ö‰" @@ -91,9 +138,6 @@ hy: ignore: "Ô±Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬" ignore_failed: "Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ¥Õ²Õ¡Õ¾ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬ Õ¡ÕµÕ½ Õ´Õ¡Ö€Õ¤Õ¸Ö‚Õ¶" ignore_user: "Ô±Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥ÕžÕ¬ Õ¡ÕµÕ½ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨Ö‰" - infinite_scroll: - no_more: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ§Õ¬ Õ¹Õ¯Õ¡Õ¶Ö‰" - no_more_contacts: "Ô·Õ¬ Õ´Õ¡Ö€Õ¤ Õ¹Õ¯Õ¡Ö‰" my_activity: "Ô»Õ´ Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ¶Õ¥Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨" my_aspects: "Ô»Õ´ ÕÕ´Õ¢Õ¥Ö€Õ¨" my_stream: "Ô¼Ö€Õ¡Õ°Õ¸Õ½" @@ -107,7 +151,7 @@ hy: is_not_sharing: "<%= name %> Õ¹Õ« Õ¯Õ«Õ½Õ¾Õ¸Ö‚Õ´ Ö„Õ¸ Õ°Õ¥Õ¿" is_sharing: "<%= name %> Õ¯Õ«Õ½Õ¾Õ¸Ö‚Õ´ Õ§ Ö„Õ¸ Õ°Õ¥Õ¿" mention: "Õ†Õ·Õ¥Õ¬" - message: "Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" + message: "Õ†Õ¡Õ´Õ¡Õ¯Õ¥Õ¬" not_found: "... Ö‡ Õ¸Õ¹ Õ¸Ö„ Õ¹Õ£Õ¿Õ¶Õ¾Õ¥Ö" stop_ignoring: "Ô´Õ¡Õ¤Õ¡Ö€Õ¥Õ¬ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¥Õ¬" photo_uploader: @@ -118,12 +162,16 @@ hy: looking_good: "Õ•Õœ, Õ¡Õ½Õ¿Õ¾Õ¡Õ®Õ¶Õ¥Ö€, Õ°Õ«Õ¡Õ¶Õ¡Õ¬Õ« Õ¿Õ¥Õ½Ö„ Õ¸Ö‚Õ¶Õ¥Õ½Ö‰" size_error: "{file}-Õ¨ Õ¹Õ¡ÖƒÕ«Ö Õ¤Õ¸Ö‚Ö€Õ½ Õ´Õ¥Õ® Õ§, Õ¡Õ¼Õ¡Õ¾Õ¥Õ¬Õ¡Õ£Õ¸Ö‚ÕµÕ¶ Õ¹Õ¡ÖƒÕ¶ Õ§Õ {sizeLimit}Ö‰" poll: + answer_count: + one: "1 Õ±Õ¡ÕµÕ¶" + other: "<%=count%> Õ±Õ¡ÕµÕ¶" + zero: "Ö„Õ¾Õ¥Õ¡Ö€Õ¯Õ¸Õ² Õ¹Õ« Õ¥Õ²Õ¥Õ¬" close_result: "Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¡Ö€Õ¤ÕµÕ¸Ö‚Õ¶Ö„Õ¨" count: one: "Õ¡Õ¼Õ¡ÕµÕªÕ´ 1 Õ±Õ¡ÕµÕ¶" other: "Õ¡Õ¼Õ¡ÕµÕªÕ´ <%=count%> Õ±Õ¡ÕµÕ¶" - go_to_original_post: "Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ´Õ¡Õ½Õ¶Õ¡Õ¯ÖÕ¥Õ¬ Õ¡ÕµÕ½ Õ°Õ¡Ö€ÖÕ´Õ¡Õ¶Õ¨ Õ¡ÕµÕ½Õ¿Õ¥Õ²` <%= original_post_link %>Ö‰" - original_post: "Õ¢Õ¶Ö…Ö€Õ«Õ¶Õ¡Õ¯ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´" + go_to_original_post: "Ô¿Õ¡Ö€Õ¸Õ² Õ¥Õ½ Õ´Õ¡Õ½Õ¶Õ¡Õ¯ÖÕ¥Õ¬ Õ¡ÕµÕ½ Õ°Õ¡Ö€ÖÕ´Õ¡Õ¶Õ¨ <%= original_post_link %>Ö‰" + original_post: "Õ¢Õ¶Ö…Ö€Õ«Õ¶Õ¡Õ¯ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¸Ö‚Õ´" result: "Ô±Ö€Õ¤ÕµÕ¸Ö‚Õ¶Ö„Õ¶Õ¥Ö€Õ¨" show_result: "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¡Ö€Õ¤ÕµÕ¸Ö‚Õ¶Ö„Õ¨" vote: "Õ”Õ¾Õ¥Õ¡Ö€Õ¯Õ¥Õ¬" @@ -134,16 +182,14 @@ hy: contacts: "Ô¿Õ¡ÕºÕ¥Ö€" edit: "Õ“Õ¸ÖƒÕ¸ÕÕ¥Õ¬" gender: "ÕÕ¥Õ¼" - ignoring: "Ô´Õ¸Ö‚ Õ¡Ö€Õ°Õ¡Õ´Õ¡Ö€Õ°Õ¸Ö‚Õ´ Õ¥Õ½ <%= name %>-Õ« Õ¢Õ¸Õ¬Õ¸Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰" location: "ÕÕ¥Õ²Õ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" photos: "Õ†Õ¯Õ¡Ö€Õ¶Õ¥Ö€" posts: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€" you_have_no_tags: "ÕˆÖ€Ö‡Õ§ ÕºÕ«Õ¿Õ¡Õ¯Õ¸Õ¾ Õ¹Õ¥Õ½ Õ¶Õ·Õ¥Õ¬ Ö„Õ¥Õ¦Ö‰" publisher: add_option: "ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬" - at_least_one_aspect: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¤ ÕºÕ¥Õ¿Ö„ Õ§ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¬Õ«Õ¶Õ« Õ¡Õ¼Õ¶Õ¾Õ¡Õ¦Õ¶ Õ´Õ¥Õ¯ ÕÕ´Õ¢Õ«Ö‰" limited: "Õ“Õ¡Õ¯. Õ½Õ¡ Õ¶Õ·Õ¡Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§, Õ¸Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¤ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§ Õ¬Õ«Õ¶Õ¥Õ¬Õ¸Ö‚ Õ´Õ«Õ¡ÕµÕ¶ Õ¡ÕµÕ¶ Õ´Õ¡Ö€Õ¤Õ¯Õ¡Õ¶Ö, Õ¸Ö‚Õ´ Õ°Õ¥Õ¿ Õ¯Õ«Õ½Õ¾Õ¸Ö‚Õ´ Õ¥Õ½Ö‰" - near_from: "Ô³Ö€Õ¡Õ¼Õ¾Õ¡Õ® Õ§ <%= location %>ÖŠÕ«ÖÖ‰" + near_from: "Ô³Ö€Õ¡Õ¼Õ¾Õ¡Õ® Õ§ <%= location %>Õ«Ö" option: "ÕŠÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶" public: "Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶. Õ½Õ¡ Õ¶Õ·Õ¡Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§, Õ¸Ö€ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¤ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§ Õ¬Õ«Õ¶Õ¥Õ¬Õ¸Ö‚ Õ¢Õ¸Õ¬Õ¸Ö€Õ«Õ¶ Ö‡ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¯Õ¬Õ«Õ¶Õ« ÖƒÕ¶Õ¿Ö€Õ¸Õ² Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€" question: "Õ€Õ¡Ö€Ö" @@ -159,7 +205,6 @@ hy: duplicate: "Ô·Õ¤Ö„Õ¡Õ¶ Õ¬Õ¡ÕžÕ¾Õ¶ Õ¡Ö‰ Ô±Ö€Õ¤Õ¥Õ¶ Õ¿Õ¡Ö€Õ¡Õ®Õ¥Õ¬ Õ¥Õ½ Õ¡ÕµÕ½ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨Ö‰" post: "ÕÕ¡Ö€Õ¡Õ®Õ¥ÕžÕ¬ <%= name %>-Õ« Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨Ö‰" successful: "Ô³Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢ Õ¿Õ¡Ö€Õ¡Õ®Õ¾Õ¥ÖÖ‰" - search_for: "Õ“Õ¶Õ¿Ö€Õ¥Õ¬ <%= name %>" show_more: "Õ‘Õ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬ Õ¡Õ¾Õ¥Õ¬Õ«Õ¶" stream: comment: "Õ„Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¥Õ¬" @@ -182,8 +227,14 @@ hy: one: "Õ‘Õ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬ Ö‡Õ½ <%= count %> Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" other: "Õ‘Õ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬ Ö‡Õ½ <%= count %> Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" zero: "Õ‘Õ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬ Ö‡Õ½ <%= count %> Õ´Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶" + no_posts_yet: "Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬Õ¸Ö‚ Õ£Ö€Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ¤Õ¥Õ¼ Õ¹Õ¯Õ¡Õ¶Ö‰" original_post_deleted: "Õ€Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ¨ Õ»Õ¶Õ»Õ¥Õ¬ Õ§ Õ¢Õ¶Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ¨" + permalink: "ÕÕ¯Õ¦Õ¢Õ¶Õ¡Õ²Õ¢ÕµÕ¸Ö‚Ö€" public: "Õ€Ö€Õ¡ÕºÕ¡Ö€Õ¡Õ¯Õ¡ÕµÕ«Õ¶" + reactions: + one: "<%= count%> Õ¡Ö€Õ±Õ¡Õ£Õ¡Õ¶Ö„" + other: "<%= count%> Õ¡Ö€Õ±Õ¡Õ£Õ¡Õ¶Ö„" + zero: "Õ¡Ö€Õ±Õ¡Õ£Õ¡Õ¶Ö„ Õ¹Õ¯Õ¡" reshare: "ÕÕ¡Ö€Õ¡Õ®Õ¥Õ¬" reshares: one: "<%= count %> Õ°Õ¸Õ£Õ« Õ¿Õ¡Ö€Õ¡Õ®Õ¥Õ¬ Õ§" @@ -205,13 +256,21 @@ hy: wasnt_that_interesting: "Ô¼Õ¡Õ¾, Õ¥Õ¶Õ©Õ¡Õ¤Ö€Õ¸Ö‚Õ´ Õ¥Õ´, Õ¸Ö€ #<%= tagName %> ÕºÕ«Õ¿Õ¡Õ¯Õ¨ Õ§Õ¤Ö„Õ¡Õ¶ Õ§Õ¬ Õ°Õ¥Õ¿Ö„Ö€Ö„Õ«Ö€ Õ¹Õ§Ö€..." timeago: day: "Õ´Õ¥Õ¯ Ö…Ö€" - days: "%d Ö…Ö€" + days: + one: "1 Ö…Ö€" + other: "%d Ö…Ö€" hour: "Õ´Õ¸Õ¿ Õ´Õ¥Õ¯ ÕªÕ¡Õ´" - hours: "Õ´Õ¸Õ¿ %d ÕªÕ¡Õ´" + hours: + one: "Õ´Õ¸Õ¿ 1 ÕªÕ¡Õ´" + other: "Õ´Õ¸Õ¿ %d ÕªÕ¡Õ´" minute: "Õ´Õ¸Õ¿ Õ´Õ¥Õ¯ Ö€Õ¸ÕºÕ¥" - minutes: "%d Ö€Õ¸ÕºÕ¥" + minutes: + one: "1 Ö€Õ¸ÕºÕ¥" + other: "%d Ö€Õ¸ÕºÕ¥" month: "Õ´Õ¸Õ¿ Õ´Õ¥Õ¯ Õ¡Õ´Õ«Õ½" - months: "%d Õ¡Õ´Õ«Õ½" + months: + one: "1 Õ¡Õ´Õ«Õ½" + other: "%d Õ¡Õ´Õ«Õ½" prefixAgo: "" prefixFromNow: "" seconds: "Õ¾Õ¡ÕµÖ€Õ¯ÕµÕ¡Õ¶Õ¶Õ¥Ö€" @@ -219,17 +278,9 @@ hy: suffixFromNow: "Õ°Õ«Õ´Õ«Õ¯Õ¾Õ¡Õ¶Õ«Ö Õ½Õ¯Õ½Õ¡Õ®" wordSeparator: " " year: "Õ´Õ¸Õ¿ Õ´Õ¥Õ¯ Õ¿Õ¡Ö€Õ«" - years: "%d Õ¿Õ¡Ö€Õ«" + years: + one: "1 Õ¿Õ¡Ö€Õ«" + other: "%d Õ¿Õ¡Ö€Õ«" unblock_failed: "Õ‰Õ½Õ¿Õ¡ÖÕ¾Õ¥Ö Õ¡ÕºÕ¡Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ¡ÕµÕ½ Ö…Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨Ö‰" - videos: - unknown: "ÕÕ¥Õ½Õ¡Õ°Õ¸Õ¬Õ¸Õ¾Õ¡Õ¯Õ« Õ¡Õ¶Õ°Õ¡ÕµÕ¿ Õ¿Õ¥Õ½Õ¡Õ¯Ö‰" - watch: "Ô´Õ«Õ¿Õ¥Õ¬ Õ¡ÕµÕ½ Õ¿Õ¥Õ½Õ¡Õ°Õ¸Õ¬Õ¸Õ¾Õ¡Õ¯Õ¨ <%= provider %> Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´" viewer: - comment: "Õ„Õ¥Õ¯Õ¶Õ¡Õ¢Õ¡Õ¶Õ¥Õ¬" - follow_post: "Õ€Õ¥Õ¿Ö‡Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶Õ¨" - home: "Ô³Õ¬ÕÕ¡Õ¾Õ¸Ö€ Õ§Õ»" - like: "Õ€Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬" - reshare: "ÕÕ¡Ö€Õ¡Õ®Õ¥Õ¬" - reshared: "ÕÕ¡Ö€Õ¡Õ®Õ¾Õ¥Õ¬ Õ§" - stop_following_post: "Ô´Õ¡Õ¤Õ¡Ö€Õ¥ÖÕ¶Õ¥Õ¬ Õ°Õ¥Õ¿Ö‡Õ¥Õ¬ Õ£Ö€Õ¡Õ¼Õ´Õ¡Õ¶Õ¨" - unlike: "Ô±ÕºÕ¡Õ°Õ¡Õ¾Õ¡Õ¶Õ¥Õ¬" \ No newline at end of file + reshared: "ÕÕ¡Ö€Õ¡Õ®Õ¾Õ¥Õ¬ Õ§" \ No newline at end of file diff --git a/config/locales/javascript/javascript.ia.yml b/config/locales/javascript/javascript.ia.yml index 408244f0f14722f388418fdebc692eebb7e7895e..c59ff47896a2d1f61f2995b7f36aff9719b273b0 100644 --- a/config/locales/javascript/javascript.ia.yml +++ b/config/locales/javascript/javascript.ia.yml @@ -6,6 +6,52 @@ ia: javascripts: + admin: + pods: + actions: "Actiones" + added: "Addite" + check: "exequer test de connexion" + errors: + one: "Le test de connexion ha producite un error pro un pod." + other: "Le test de connexion ha producite un error pro <%= count %> pods." + follow_link: "aperir ligamine in navigator" + last_check: "ultime verification:" + more_info: "monstrar plus information" + ms: + one: "<%= count %>ms" + other: "<%= count %>ms" + no_info: "Nulle information additional es disponibile in iste momento" + not_available: "indisponibile" + offline_since: "foras de linea depost:" + pod: "Pod" + recheck: + failure: "Le verification non ha essite exequite." + success: "Le pod ha justo essite verificate de novo." + response_time: "Duration de responsa:" + server_software: "Software de servitor:" + ssl: "SSL" + ssl_disabled: "SSL non active" + ssl_enabled: "SSL active" + states: + dns_failed: "Le resolution de nomines (DNS) ha fallite" + http_failed: "Le connexion HTTP ha fallite" + net_failed: "Le tentativa de connexion ha fallite" + no_errors: "OK" + ssl_failed: "Le connexion secur (SSL) ha fallite" + unchecked: "Non verificate" + unknown_error: "Un error non specificate ha occurrite durante le verification" + version_failed: "Impossibile obtener le version del software" + status: "Stato" + unchecked: + one: "Il ha ancora un pod non verificate." + other: "Il ha ancora <%= count %> pods non verificate." + unknown: "incognite" + admins: + dashboard: + compare_versions: "Le ultime version de diaspora* es <%= latestVersion %>; iste pod executa <%= podVersion %>." + error: "Impossibile determinar le ultime version de diaspora*." + outdated: "Tu pod non es actual." + up_to_date: "Tu pod es actual!" and: "e" aspect_dropdown: add_to_aspect: "Adder contacto" @@ -53,10 +99,10 @@ ia: conversation: new: no_contacts: "Es necessari adder alcun contactos ante de poter initiar un conversation." - participants: "Participantes" create: "Crear" delete: "Deler" edit: "Modificar" + failed_to_comment: "Commento fallite. Es possibile que le autor te ignora." failed_to_like: "Appreciation fallite!" failed_to_post_message: "Publication del entrata fallite!" failed_to_remove: "Le remotion del entrata ha fallite." @@ -81,15 +127,14 @@ ia: recent_notifications: "Notificationes recente" search: "Cercar" settings: "Configuration" + toggle_mobile: "Alternar mobile" + toggle_navigation: "Alternar navigation" view_all: "Vider totes" hide_post: "Celar iste entrata?" hide_post_failed: "Impossibile celar ite entrata" ignore: "Ignorar" ignore_failed: "Impossibile ignorar iste usator" ignore_user: "Ignorar iste usator?" - infinite_scroll: - no_more: "Nulle messages restante." - no_more_contacts: "Nulle altere contactos." my_activity: "Mi activitate" my_aspects: "Mi aspectos" my_stream: "Fluxo" @@ -114,6 +159,10 @@ ia: looking_good: "Oh, tu pare splendide!" size_error: "{file} es troppo grande. Le dimension maxime es {sizeLimit}." poll: + answer_count: + one: "1 voto" + other: "<%=count%> votos" + zero: "0 votos" close_result: "Celar resultato" count: one: "1 voto usque ora" @@ -130,14 +179,12 @@ ia: contacts: "Contactos" edit: "modificar" gender: "Sexo" - ignoring: "Tu ignora tote le entratas de <%= name %>." location: "Loco" photos: "Photos" posts: "Entratas" you_have_no_tags: "tu non ha etiquettas!" publisher: add_option: "Adder un responsa" - at_least_one_aspect: "Le publication debe esser includite in al minus un aspecto" limited: "Limitate: le message es visibile solmente pro le personas con qui tu lo divide" near_from: "Inviate ab: <%= location %>" option: "Responsa" @@ -155,7 +202,6 @@ ia: duplicate: "Tu ha jam repetite iste entrata." post: "Repeter le entrata de <%= name %>?" successful: "Le entrata ha essite repetite con successo." - search_for: "Cercar <%= name %>" show_more: "monstrar plus" stream: comment: "Commentar" @@ -171,7 +217,12 @@ ia: like: "Appreciar" limited: "Limitate" original_post_deleted: "Le entrata original ha essite delite per le autor." + permalink: "Permaligamine" public: "Public" + reactions: + one: "<%= count%> reaction" + other: "<%= count%> reactiones" + zero: "<%= count%> reactiones" reshare: "Repeter" show_nsfw_post: "Monstrar entrata" show_nsfw_posts: "Monstrar totes" @@ -189,13 +240,17 @@ ia: wasnt_that_interesting: "OK, io suppone que #<%= tagName %> non es si interessante..." timeago: day: "un die" - days: "%d dies" + days: + other: "%d dies" hour: "circa un hora" - hours: "circa %d horas" + hours: + other: "circa %d horas" minute: "circa un minuta" - minutes: "%d minutas" + minutes: + other: "%d minutas" month: "circa un mense" - months: "%d menses" + months: + other: "%d menses" prefixAgo: "" prefixFromNow: "" seconds: "minus de un minuta" @@ -203,17 +258,8 @@ ia: suffixFromNow: "ab ora" wordSeparator: " " year: "circa un anno" - years: "%d annos" + years: + other: "%d annos" unblock_failed: "Le action de disblocar iste usator ha fallite" - videos: - unknown: "Typo de video incognite" - watch: "Spectar iste video sur <%= provider %>" viewer: - comment: "Commento" - follow_post: "Sequer iste entrata" - home: "INITIO" - like: "Appreciar" - reshare: "Repeter" - reshared: "Repetite" - stop_following_post: "Non plus sequer iste entrata" - unlike: "Non plus appreciar" \ No newline at end of file + reshared: "Repetite" \ No newline at end of file diff --git a/config/locales/javascript/javascript.id.yml b/config/locales/javascript/javascript.id.yml index 2d031b1e4bc781523545d1d2ec6bfcc6b640f507..73326f6da64946dab2fb1966ee5a5d1d5b687a08 100644 --- a/config/locales/javascript/javascript.id.yml +++ b/config/locales/javascript/javascript.id.yml @@ -35,19 +35,15 @@ id: header: search: "Temukan nama orang atau #tags" ignore: "Abaikan" - infinite_scroll: - no_more: "Tidak ada post lagi" my_activity: "Aktifitas Saya" my_stream: "Stream" photo_uploader: looking_good: "Puji Tuhan, anda terlihat luar biasa!" publisher: - at_least_one_aspect: "Anda harus mempublikasi, setidaknya satu hal" limited: "Di Limitasi - Apa yang anda publikasi hanya dapat di lihat oleh orang-orang yang berbagi dengan anda." public: "Publik - Apa yang anda publikasi dapat di lihat oleh siapa saja dan dapat di temukan oleh mesin pencari." reshares: duplicate: "Menarik ? Anda telah membagikan ulang posting tersebut!" - search_for: "Mencari <%= name %>" show_more: "Tampilkan lebih banyak lagi" stream: comment: "Komentar" @@ -84,20 +80,22 @@ id: wasnt_that_interesting: "OK, sepertinya #<%= tagName %> tidak terlalu menarik..." timeago: day: "sehari" - days: "%d hari" + days: + other: "%d hari" hour: "sekitar sejam" - hours: "sekitar %d jam" + hours: + other: "sekitar %d jam" minute: "sekitar satu menit" - minutes: "%d menit" + minutes: + other: "%d menit" month: "sekitar sebulan" - months: "%d tahun" + months: + other: "%d tahun" prefixAgo: "" prefixFromNow: "" seconds: "kurang dari semenit" suffixAgo: "yang lalu" suffixFromNow: "dari sekarang" year: "sekitar setahun" - years: "%d tahun" - videos: - unknown: "Tipe video tidak di kenal" - watch: "Lihat video ini di <%= provider %>" \ No newline at end of file + years: + other: "%d tahun" \ No newline at end of file diff --git a/config/locales/javascript/javascript.is.yml b/config/locales/javascript/javascript.is.yml index 723ba71ca990a82de64d15a86b5bfa48d8f86ff3..74f2419492ed7d3e1a4aebfd6801cd969df3f618 100644 --- a/config/locales/javascript/javascript.is.yml +++ b/config/locales/javascript/javascript.is.yml @@ -10,15 +10,15 @@ is: aspect_dropdown: add_to_aspect: "Add to aspect" all_aspects: "Allar sýnir" - error: "Couldn't start sharing with <%= name %>. Are you ignoring them?" - error_remove: "Gat ekki eytt <%= name %> úr þessari sýn :(" + error: "Gat ekki byrjað deilingu með <%= name %>. Ertu að hunsa þá?" + error_remove: "Gat ekki fjarlægt <%= name %> úr þessari ásýnd :(" select_aspects: "Veldu sýn" started_sharing_with: "You have started sharing with <%= name %>!" stopped_sharing_with: "You have stopped sharing with <%= name %>." toggle: - one: "In <%= count %> aspect" - other: "In <%= count %> aspects" - zero: "Add to aspect" + one: "à <%= count %> ásýnd" + other: "à <%= count %> ásýndum" + zero: "Velja ásýndir" aspect_navigation: add_an_aspect: "+ Bæta við sýn" deselect_all: "Velja ekkert" @@ -26,24 +26,22 @@ is: select_all: "Velja allt" comma: "," comments: - hide: "fela athugasemdir" + hide: "Fela athugasemdir" no_comments: "Það eru engar athugasemdir komnar." - show: "sýna allar athugasemdir" + show: "Birta allar athugasemdir" confirm_dialog: "Ertu viss?" - conversation: - participants: "Þátttakendur" delete: "Eyða" edit: "Breyta" - failed_to_like: "Tókst ekki að lÃka við!" + failed_to_like: "Tókst ekki að lÃka við. Ætli höfundurinn sé að hunsa þig?" failed_to_post_message: "Tókst ekki að senda skeytið!" getting_started: alright_ill_wait: "Ekkert mál, ég get beðið." hey: "Hey, <%= name %>!" - no_tags: "Hey, þú hefur ekki valið að fylgjast með neinum tögum! Halda samt áfram?" + no_tags: "Hey, þú hefur ekki valið að fylgjast með neinum merkjum! Halda samt áfram?" preparing_your_stream: "Preparing your personialized stream..." header: admin: "Kerfisstjórn" - close: "loka" + close: "Loka" contacts: "Tengiliðir" help: "Hjálp" home: "Heim" @@ -56,42 +54,37 @@ is: settings: "Stillingar" view_all: "Skoða allt" ignore_user: "Horfa framhjá þessum notanda?" - infinite_scroll: - no_more: "Engin fleirri skeyti." - no_more_contacts: "Engir fleirri tengiliðir" - my_aspects: "MÃnar sýnir" + my_aspects: "MÃnar ásýndir" notifications: mark_read: "Merkja sem lesið" mark_unread: "Merkja sem ólesið" people: - not_found: "og enginn fannst..." + not_found: "og engin fannst..." photo_uploader: completed: "<%= file %> móttekin" - empty: "{file} skráin er tóm, veldu vinsamlegast skrárnar aftur en slepptu henni." - invalid_ext: "{file} hefur ógilt viðskeyti. Aðeins {extensions} eru leyfð." + empty: "{file} skráin er tóm, veldu skrárnar aftur en slepptu þessari skrá." + invalid_ext: "{file} er með ógilda skráarendingu. Aðeins {extensions} eru leyfðar." looking_good: "Vá, þú lÃtur vel út!" - size_error: "{file} skráin er of stór, mesta stærð er {sizeLimit}." + size_error: "{file} skráin er of stór, hámarksstærð er {sizeLimit}." poll: close_result: "Fela niðurstöður" result: "Niðurstaða" show_result: "Birta niðurstöður" publisher: - at_least_one_aspect: "Þú verður að opna á að minnsta kosti eina sýn" limited: "Takmarkað - skeytið verður eingögnu sýnilegt þeim sem þú veitir leyfi" near_from: "Sennt inn nálægt: <%= location %>" - public: "Aðgengilegt - skeytið verður sýnilegt öllum, leitarvélar geta einnig fundið póstinn" + public: "Opinbert - skeytið verður sýnilegt öllum, leitarvélar geta einnig fundið póstinn" reshares: - duplicate: "You've already reshared that post!" - post: "Deila áfram skeyti frá <%= name %>?" + duplicate: "Þetta gott, ha? Þú ert þegar búinn að endurdeila þessari færslu!" + post: "Deila áfram færslu frá <%= name %>?" successful: "Tókst að deila þessu skeyti áfram!" - search_for: "Search for <%= name %>" - show_more: "sýna meira" + show_more: "Sýna meira" stream: comment: "Athugasemd" follow: "Fyljgast með" followed_tag: add_a_tag: "Bæta við merki" - title: "#Merkisem fylgst er með" + title: "#Merki sem fylgst er með" hide: "Fela" hide_nsfw_posts: "Fela skeyti sem hennta ekki vinnu" like: "LÃka við" @@ -104,16 +97,13 @@ is: one: "Birta <%= count %> athugasemd til viðbótar" other: "Birta <%= count %> athugasemdir til viðbótar" zero: "Birta <%= count %> athugasemd til viðbótar" - original_post_deleted: "Upphaflegi höfundurinn hefur eytt skeytinu." + original_post_deleted: "Upphaflegri færslu var eytt af höfundinum" public: "Aðengilegt" reshare: "Deila áfram" reshares: - few: "<%= count %> Reshares" - many: "<%= count %> Reshares" - one: "<%= count %> Reshare" - other: "<%= count %> Reshares" - two: "<%= count %> Reshares" - zero: "<%= count %> Reshares" + one: "<%= count %> endurdeiling" + other: "<%= count %> endurdeilingar" + zero: "<%= count %> endurdeilingar" show_nsfw_post: "Sýna skeyti" show_nsfw_posts: "Sýna öll skeyti" tags: @@ -123,32 +113,27 @@ is: unfollow: "Hætta að fylgjast með" unlike: "Hætta við að lÃka við" tags: - wasnt_that_interesting: "OK, I suppose #<%= tagName %> wasn't all that interesting..." + wasnt_that_interesting: "Gott og vel, ætli #<%= tagName %> sé nokkuð svo áhugavert..." timeago: day: "á dag" - days: "%d dagar" + days: + other: "%d dagar" hour: "um klukkustund" - hours: "um það bil %d klukkutÃmar" + hours: + other: "um það bil %d klukkutÃmar" minute: "um eina mÃnútu" - minutes: "%d mÃnútur" + minutes: + other: "%d mÃnútur" month: "um það bil mánuð" - months: "%d mánuðir" + months: + other: "%d mánuðir" prefixAgo: "fyrir" prefixFromNow: "eftir" seconds: "minna en mÃnútu" suffixAgo: "sÃðan" suffixFromNow: "" year: "um það bil ár" - years: "%d ára" - videos: - unknown: "Óþekkt vÃdeó tegund" - watch: "Horfa á þetta vÃdeó á <%= provider %>" + years: + other: "%d ára" viewer: - comment: "Athugasemd" - follow_post: "Fylgjast með skeyti" - home: "HEIM" - like: "LÃka við" - reshare: "Deila áfram" - reshared: "Deilt áfram" - stop_following_post: "Hætta að fylgjast með skeyti" - unlike: "Hætta við að lÃka við" \ No newline at end of file + reshared: "Deilt áfram" \ No newline at end of file diff --git a/config/locales/javascript/javascript.it.yml b/config/locales/javascript/javascript.it.yml index 310768974b3db8c7b8add5daafd685b1744700ad..8fdec11a9327f3a9a7f138060b033942bba218a9 100644 --- a/config/locales/javascript/javascript.it.yml +++ b/config/locales/javascript/javascript.it.yml @@ -33,8 +33,6 @@ it: no_comments: "Non ci sono commenti al momento." show: "mostra tutti i commenti" confirm_dialog: "Sei sicuro?" - conversation: - participants: "Partecipanti" delete: "Elimina" edit: "Modifica" failed_to_like: "Errore, il \"mi piace\" non è stato inviato!" @@ -61,9 +59,6 @@ it: view_all: "Vedi tutti" ignore: "Ignora" ignore_user: "Ignora utente?" - infinite_scroll: - no_more: "Non ci sono altri post." - no_more_contacts: "Non ci sono altri contatti." my_activity: "Attività " my_aspects: "I miei aspetti" my_stream: "Stream" @@ -76,7 +71,6 @@ it: looking_good: "Accidenti, sei in splendida forma!" size_error: "{file} è troppo grande, la dimensione massima è {sizeLimit}." publisher: - at_least_one_aspect: "Devi scegliere almeno un aspetto" limited: "Non pubblico - il tuo post sarà visibile solamente a coloro con cui lo condividi" near_from: "Vicino a: <%= location %>" public: "Pubblico - il tuo post sarà visibile a tutti, inclusi i motori di ricerca" @@ -84,7 +78,6 @@ it: duplicate: "Bello eh? Ma hai già condiviso quel post!" post: "Vuoi condividere il post di <%= name %>?" successful: "Il post è stato condiviso!" - search_for: "Cerca su <%= name %>" show_more: "continua..." stream: comment: "Commenta" @@ -130,29 +123,24 @@ it: wasnt_that_interesting: "OK, immagino che #<%= tagName %> non fosse così interessante..." timeago: day: "un giorno" - days: "%d giorni" + days: + other: "%d giorni" hour: "circa un'ora" - hours: "circa %d ore" + hours: + other: "circa %d ore" minute: "circa un minuto" - minutes: "%d minuti" + minutes: + other: "%d minuti" month: "circa un mese" - months: "%d mesi" + months: + other: "%d mesi" prefixAgo: "" prefixFromNow: "fra" seconds: "meno di un minuto" suffixAgo: "fa" suffixFromNow: "da ora" year: "circa un anno" - years: "%d anni" - videos: - unknown: "Tipo di video sconosciuto" - watch: "Guarda questo video su <%= provider %>" + years: + other: "%d anni" viewer: - comment: "Commenta" - follow_post: "Segui il post" - home: "HOME" - like: "Mi piace" - reshare: "Condividi" - reshared: "Condiviso" - stop_following_post: "Smetti di seguire il post" - unlike: "Non mi piace più" \ No newline at end of file + reshared: "Condiviso" \ No newline at end of file diff --git a/config/locales/javascript/javascript.ja.yml b/config/locales/javascript/javascript.ja.yml index 550135bbf208135174c46b6bb3f5f7dbb4502084..e7897d2ea0d1c144280b8606e9885c0fd4e0377a 100644 --- a/config/locales/javascript/javascript.ja.yml +++ b/config/locales/javascript/javascript.ja.yml @@ -6,81 +6,236 @@ ja: javascripts: + admin: + pods: + actions: "æ“作" + added: "è¿½åŠ " + check: "接続テストを実行" + errors: + other: "<%= count %> ã®ãƒãƒƒãƒ‰ã§ã€æŽ¥ç¶šãƒ†ã‚¹ãƒˆã®ã‚¨ãƒ©ãƒ¼ãŒè¿”ã•ã‚Œã¾ã—ãŸ" + follow_link: "ブラウザーã§ãƒªãƒ³ã‚¯ã‚’é–‹ã" + last_check: "å‰å›žã®ç¢ºèª:" + more_info: "ã•ã‚‰ã«æƒ…å ±ã‚’è¡¨ç¤º" + ms: + other: "<%= count %>ms" + no_info: "ã“ã®æ™‚点ã§å…¥æ‰‹å¯èƒ½ãªè¿½åŠ æƒ…å ±ã¯ã‚ã‚Šã¾ã›ã‚“" + not_available: "使用ä¸å¯" + offline_since: "オフライン開始:" + pod: "ãƒãƒƒãƒ‰" + recheck: + failure: "ãƒã‚§ãƒƒã‚¯ã¯å®Ÿè¡Œã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚" + success: "ãƒãƒƒãƒ‰ã‚’ã‚‚ã†ä¸€åº¦ç¢ºèªã—ã¾ã—ãŸã€‚" + response_time: "レスãƒãƒ³ã‚¹ã‚¿ã‚¤ãƒ :" + server_software: "サーãƒãƒ¼ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢:" + ssl: "SSL" + ssl_disabled: "SSL ãŒç„¡åŠ¹ã§ã™" + ssl_enabled: "SSL ãŒæœ‰åŠ¹ã§ã™" + states: + dns_failed: "åå‰è§£æ±º (DNS) ã«å¤±æ•—ã—ã¾ã—ãŸ" + http_failed: "HTTP 接続ã«å¤±æ•—ã—ã¾ã—ãŸ" + net_failed: "接続ã«å¤±æ•—ã—ã¾ã—ãŸ" + no_errors: "OK" + ssl_failed: "安全ãªæŽ¥ç¶š (SSL) ã«å¤±æ•—ã—ã¾ã—ãŸ" + unchecked: "é¸æŠžè§£é™¤" + unknown_error: "確èªä¸ã«ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" + version_failed: "ソフトウェアãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’å–å¾—ã§ãã¾ã›ã‚“" + status: "ステータス" + unchecked: + other: "ã¾ã 確èªã—ã¦ã„ãªã„ãƒãƒƒãƒ‰ãŒ <%= count %> ã‚ã‚Šã¾ã™ã€‚" + unknown: "ä¸æ˜Ž" + version_failed: + other: "<%= count %> ãƒãƒƒãƒ‰ã§ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚ã‚Šã¾ã›ã‚“ (å¤ã„ãƒãƒƒãƒ‰ã€ãƒŽãƒ¼ãƒ‰æƒ…å ±ãªã—)" + admins: + dashboard: + compare_versions: "最新ã®ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©* リリース㯠<%= latestVersion %> ã§ã™ã€ãŠä½¿ã„ã®ãƒãƒƒãƒ‰ã¯ <%= podVersion %> を実行ä¸ã§ã™ã€‚" + error: "最新ã®ãƒ€ã‚¤ã‚¢ã‚¹ãƒãƒ©* ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’確èªã§ãã¾ã›ã‚“。" + outdated: "ãƒãƒƒãƒ‰ãŒå¤ããªã£ã¦ã„ã¾ã™ã€‚" + up_to_date: "ãƒãƒƒãƒ‰ã¯æœ€æ–°ã§ã™ï¼" + and: "ãŠã‚ˆã³" aspect_dropdown: add_to_aspect: "Add to aspect" all_aspects: "å…¨ã¦ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆ" - error: "Couldn't start sharing with <%= name %>. Are you ignoring them?" + error: "<%= name %>ã•ã‚“ã¨å…±æœ‰ã‚’始ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。 無視ã—ã¾ã™ã‹?" error_remove: "アスペクトã‹ã‚‰<%= name %>ã•ã‚“を削除ã§ãã¾ã›ã‚“ã§ã—㟠:(" + mobile_row_checked: "<%= name %> (削除)" + mobile_row_unchecked: "<%= name %> (è¿½åŠ )" select_aspects: "アスペクトをé¸æŠžã™ã‚‹" started_sharing_with: "You have started sharing with <%= name %>!" stopped_sharing_with: "You have stopped sharing with <%= name %>." toggle: - other: "In <%= count %> aspects" - zero: "Add to aspect" + other: "<%= count %> アスペクトã«" + zero: "<%= count %> アスペクトã«" + updating: "æ›´æ–°ä¸..." aspect_navigation: add_an_aspect: "+ ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’è¿½åŠ ã™ã‚‹" deselect_all: "å…¨ã¦é¸æŠžè§£é™¤" no_aspects: "ã©ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚‚é¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“" select_all: "å…¨ã¦é¸æŠž" + aspects: + create: + add_a_new_aspect: "æ–°ã—ã„ã‚¢ã‚¹ãƒšã‚¯ãƒˆã‚’è¿½åŠ ã™ã‚‹" + failure: "アスペクトã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚" + success: "æ–°ã—ã„アスペクト<%= name %>を作æˆã—ã¾ã—ãŸ" + make_aspect_list_visible: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ãƒ¡ãƒ³ãƒãƒ¼ä¸€è¦§ã‚’メンãƒãƒ¼ã¸å…¬é–‹ã—ã¾ã™ã‹ï¼Ÿ" + name: "åå‰" bookmarklet: post_something: "ダイアスãƒãƒ©ã«æŠ•ç¨¿" + post_submit: "投稿ã®é€ä¿¡ä¸..." post_success: "投稿ã—ã¾ã—ãŸ! ウインドウを閉ã˜ã¦ã„ã¾ã™..." + cancel: "å–消" comma: "," comments: hide: "ã‚³ãƒ¡ãƒ³ãƒˆã‚’éš ã™" + no_comments: "ã¾ã コメントã¯ã‚ã‚Šã¾ã›ã‚“。" show: "å…¨ã¦ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’表示ã™ã‚‹" confirm_dialog: "本当ã«ã„ã„ã§ã™ã‹ã€‚" + confirm_unload: "ã“ã®ãƒšãƒ¼ã‚¸ã‚’離れるã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。入力ã—ãŸãƒ‡ãƒ¼ã‚¿ã¯ä¿å˜ã•ã‚Œã¾ã›ã‚“。" + contacts: + add_contact: "é€£çµ¡å…ˆã‚’è¿½åŠ " + aspect_chat_is_enabled: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®é€£çµ¡å…ˆã¯ã€ã‚ãªãŸã¨ãƒãƒ£ãƒƒãƒˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + aspect_chat_is_not_enabled: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®é€£çµ¡å…ˆã¯ã€ã‚ãªãŸã¨ãƒãƒ£ãƒƒãƒˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。" + aspect_list_is_not_visible: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ãƒ¡ãƒ³ãƒãƒ¼ä¸€è¦§ã¯ãƒ¡ãƒ³ãƒãƒ¼ã¸å…¬é–‹ã•ã‚Œã¦ã„ã¾ã›ã‚“。" + aspect_list_is_visible: "ã“ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆã®ãƒ¡ãƒ³ãƒãƒ¼ä¸€è¦§ã¯ãƒ¡ãƒ³ãƒãƒ¼ã«å…¬é–‹ã•ã‚Œã¦ã„ã¾ã™ã€‚" + error_add: "アスペクトã«<%= name %>ã•ã‚“ã‚’è¿½åŠ ã§ãã¾ã›ã‚“ã§ã—㟠:(\n" + error_remove: "アスペクトã‹ã‚‰<%= name %>ã•ã‚“を削除ã§ãã¾ã›ã‚“ã§ã—㟠:(" + remove_contact: "連絡先を削除" + search_no_results: "連絡先ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" + conversation: + new: + no_contacts: "会話を開始ã™ã‚‹å‰ã«ã€é€£çµ¡å…ˆã‚’è¿½åŠ ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚" + create: "作æˆ" delete: "削除" edit: "編集" + failed_to_comment: "コメントã«å¤±æ•—ã—ã¾ã—ãŸã€‚ãŠãらã作者ãŒã‚ãªãŸã‚’無視ã—ã¦ã„ã¾ã›ã‚“ã‹ï¼Ÿ" + failed_to_like: "ã„ã„ãï¼ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ãŠãらã作者ãŒã‚ãªãŸã‚’無視ã—ã¦ã„ã¾ã›ã‚“ã‹ï¼Ÿ" failed_to_post_message: "メッセージã®æŠ•ç¨¿ã«å¤±æ•—ã—ã¾ã—ãŸ!" + failed_to_remove: "エントリーã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸï¼" + failed_to_reshare: "å†å…±æœ‰ã«å¤±æ•—ã—ã¾ã—ãŸï¼" getting_started: + alright_ill_wait: "OKã€ç§ã¯å¾…ã¡ã¾ã™ã€‚" hey: "Hey, <%= name %>!" - preparing_your_stream: "Preparing your personialized stream..." + no_tags: "タグを何もフォãƒãƒ¼ã—ã¦ã„ã¾ã›ã‚“ï¼ç¶šè¡Œã—ã¾ã™ã‹ï¼Ÿ" + preparing_your_stream: "パーソナライズ ストリームを準備ã—ã¦ã„ã¾ã™..." header: + admin: "管ç†" close: "é–‰ã˜ã‚‹" contacts: "連絡先" + conversations: "会話" help: "ヘルプ" home: "ホーム" log_out: "ãƒã‚°ã‚¢ã‚¦ãƒˆ" mark_all_as_read: "å…¨ã¦æ—¢èªã«ã™ã‚‹" + moderator: "モデレーター" notifications: "通知" profile: "プãƒãƒ•ã‚£ãƒ¼ãƒ«" recent_notifications: "最近ã®é€šçŸ¥" search: "Find people or #tags" settings: "è¨å®š" + toggle_mobile: "æºå¸¯ã‚µã‚¤ãƒˆã®åˆ‡ã‚Šæ›¿ãˆ" + toggle_navigation: "ナビゲーションã®åˆ‡ã‚Šæ›¿ãˆ" view_all: "å…¨ã¦è¦‹ã‚‹" + hide_post: "ã“ã®æŠ•ç¨¿ã‚’éžè¡¨ç¤ºã«ã—ã¾ã™ã‹ï¼Ÿ" + hide_post_failed: "ã“ã®æŠ•ç¨¿ã‚’éžè¡¨ç¤ºã«ã§ãã¾ã›ã‚“" ignore: "無視" + ignore_failed: "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’無視ã§ãã¾ã›ã‚“" ignore_user: "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’無視ã—ã¾ã™ã‹?" - infinite_scroll: - no_more: "投稿ã¯ã“れ以上ã‚ã‚Šã¾ã›ã‚“。" - no_more_contacts: "ã“れ以上連絡先ã¯ã‚ã‚Šã¾ã›ã‚“。" + my_activity: "マイ アクティビティ" my_aspects: "ç§ã®ã‚¢ã‚¹ãƒšã‚¯ãƒˆ" + my_stream: "ストリーム" + no_results: "çµæžœãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" notifications: mark_read: "æ—¢èªã«ã™ã‚‹" mark_unread: "未èªã«ã™ã‚‹" + people: + edit_my_profile: "マイ プãƒãƒ•ã‚£ãƒ¼ãƒ«ã‚’編集ã™ã‚‹" + helper: + is_not_sharing: "<%= name %>ã•ã‚“ã¯ã‚ãªãŸã¨å…±æœ‰ã—ã¦ã„ã¾ã›ã‚“" + is_sharing: "<%= name %>ã•ã‚“ã¯ã‚ãªãŸã¨å…±æœ‰ã—ã¦ã„ã¾ã™" + mention: "メンション" + message: "メッセージ" + not_found: "…1人も見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ" + stop_ignoring: "無視を解除ã™ã‚‹" photo_uploader: + completed: "<%= file %> 完了" empty: "{file}ã¯ç©ºã®ãƒ•ã‚¡ã‚¤ãƒ«ã§ã™ã€‚ä»–ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„。" + error: "ファイル <%= file %> ã®ã‚¢ãƒƒãƒ—ãƒãƒ¼ãƒ‰ä¸ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ" + invalid_ext: "{file}ã®æ‹¡å¼µåã¯æ£ã—ãã‚ã‚Šã¾ã›ã‚“。{extensions}以外ã®æ‹¡å¼µåã¯ä½¿ãˆã¾ã›ã‚“。" + looking_good: "ãªã‚“ã¦ã“ã£ãŸãƒ¼ï¼ã‚ãªãŸã¯ç´ 晴らã—ã„ã§ã™ãï¼" size_error: "{file}ã¯å¤§ãã™ãŽã¾ã™ã€‚ファイルサイズã®ä¸Šé™ã¯{sizeLimit}ã§ã™ã€‚" poll: + answer_count: + other: "<%=count%> 投票" close_result: "çµæžœã‚’éžè¡¨ç¤ºã«ã™ã‚‹" + count: + other: "ã“ã‚Œã¾ã§ <%=count%> 投票" + go_to_original_post: "<%= original_post_link %> ã‹ã‚‰ã€ã“ã®æŠ•ç¥¨ã«å‚åŠ ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" + original_post: "å…ƒã®æŠ•ç¨¿" + result: "çµæžœ" show_result: "çµæžœã‚’表示ã™ã‚‹" + vote: "投票" + profile: + add_some: "何ã‹ã‚’è¿½åŠ " + bio: "ç•¥æ´" + born: "誕生日" + contacts: "連絡先" + edit: "編集" + gender: "性別" + location: "å ´æ‰€" + photos: "写真" + posts: "投稿" + you_have_no_tags: "ã‚¿ã‚°ãŒã‚ã‚Šã¾ã›ã‚“ï¼" publisher: - at_least_one_aspect: "アスペクトをé¸æŠžã—ã¦ã‹ã‚‰æŠ•ç¨¿ã—ã¦ãã ã•ã„。" + add_option: "回ç”ã‚’è¿½åŠ " limited: "é™å®šå…¬é–‹ - 投稿ã¯ã‚ãªãŸãŒå…±æœ‰ã—ã¦ã„る人ã ã‘ãŒè¦‹ã‚‰ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™" + markdown_editor: + preview: "プレビュー" + texts: + code: "ã“ã“ã«ã‚³ãƒ¼ãƒ‰" + heading: "見出ã—テã‚スト" + insert_image_description_text: "ã“ã“ã«ç”»åƒã®èª¬æ˜Žã‚’入力" + insert_image_help_text: "ã“ã“ã«ç”»åƒã®ãƒªãƒ³ã‚¯ã‚’挿入" + insert_image_title: "ã“ã“ã«ç”»åƒã®ã‚¿ã‚¤ãƒˆãƒ«ã‚’入力" + insert_link_description_text: "ã“ã“ã«ãƒªãƒ³ã‚¯ã®èª¬æ˜Žã‚’入力" + insert_link_help_text: "ã“ã“ã«ãƒªãƒ³ã‚¯ã‚’挿入" + italic: "斜体テã‚スト" + list: "ã“ã“ã«ãƒªã‚¹ãƒˆãƒ†ã‚スト" + quote: "ã“ã“ã«å¼•ç”¨ãƒ†ã‚スト" + strong: "強調テã‚スト" + tooltips: + bold: "太å—" + cancel: "メッセージã®å–消" + code: "コードã®æŒ¿å…¥" + heading: "見出ã—" + insert_image: "ç”»åƒã®æŒ¿å…¥" + insert_link: "リンクã®æŒ¿å…¥" + insert_ordered_list: "番å·ä»˜ãリストã®æŒ¿å…¥" + insert_unordered_list: "箇æ¡æ›¸ãリストã®æŒ¿å…¥" + italic: "斜体" + preview: "メッセージã®ãƒ—レビュー" + quote: "引用ã®æŒ¿å…¥" + write: "メッセージを編集" + write: "書ã" near_from: "<%= location %>ã‹ã‚‰ã®æŠ•ç¨¿" + option: "回ç”" public: "公開 - 投稿ã¯å…¨ã¦ã®äººã‹ã‚‰è¦‹ã‚‹ã“ã¨ãŒã§ãã€æ¤œç´¢ã‚¨ãƒ³ã‚¸ãƒ³ã§è¦‹ã¤ã‹ã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™" + question: "質å•" + remove_post: "ã“ã®æŠ•ç¨¿ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ" report: name: "å ±å‘Š" prompt: "ç†ç”±ã‚’入力ã—ã¦ãã ã•ã„:" prompt_default: "攻撃的ãªã‚³ãƒ³ãƒ†ãƒ³ãƒ„" + status: + created: "å ±å‘Šã‚’æ£å¸¸ã«ä½œæˆã—ã¾ã—ãŸ" + exists: "å ±å‘Šã¯ã™ã§ã«å˜åœ¨ã—ã¾ã™" reshares: - duplicate: "You've already reshared that post!" + duplicate: "ãˆã£ï¼Ÿã™ã§ã«ã“ã®æŠ•ç¨¿ã‚’共有ã—ã¦ã„ã¾ã™ï¼" post: "<%= name %>ã•ã‚“ã®æŠ•ç¨¿ã‚’å†å…±æœ‰ã—ã¾ã™ã‹?" successful: "投稿ã¯æ£å¸¸ã«å†å…±æœ‰ã•ã‚Œã¾ã—ãŸ!" - search_for: "<%= name %>を検索ã™ã‚‹" show_more: "ã•ã‚‰ã«è¡¨ç¤ºã™ã‚‹" stream: comment: "コメント" + disable_post_notifications: "ã“ã®æŠ•ç¨¿ã«å¯¾ã™ã‚‹é€šçŸ¥ã‚’無効ã«ã™ã‚‹" + enable_post_notifications: "ã“ã®æŠ•ç¨¿ã«å¯¾ã™ã‚‹é€šçŸ¥ã‚’有効ã«ã™ã‚‹" follow: "フォãƒãƒ¼" followed_tag: add_a_tag: "ã‚¿ã‚°ã‚’è¿½åŠ ã™ã‚‹" @@ -88,61 +243,74 @@ ja: title: "#フォãƒãƒ¼ã—ãŸã‚¿ã‚°" hide: "éš ã™" hide_nsfw_posts: "#nsfwã®æŠ•ç¨¿ã‚’éš ã™" + like: "ã„ã„ãï¼" likes: few: "<%= count %> Likes" many: "<%= count %> Likes" one: "<%= count %> Like" - other: "<%= count %> Likes" + other: "<%= count %> ã„ã„ãï¼" two: "<%= count %> Likes" - zero: "<%= count %> Likes" + zero: "<%= count %> ã„ã„ãï¼" limited: "é™å®šå…¬é–‹" more_comments: few: "Show <%= count %> more comments" many: "Show <%= count %> more comments" one: "Show <%= count %> more comment" - other: "Show <%= count %> more comments" + other: "ã•ã‚‰ã« <%= count %> ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’表示" two: "Show <%= count %> more comments" - zero: "Show <%= count %> more comments" + zero: "ã•ã‚‰ã« <%= count %> ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’表示" + no_posts_yet: "ã¾ã ã“ã“ã«è¡¨ç¤ºã™ã‚‹æŠ•ç¨¿ã¯ã‚ã‚Šã¾ã›ã‚“。" + original_post_deleted: "å…ƒã®æŠ•ç¨¿ã¯ä½œè€…ã«ã‚ˆã£ã¦å‰Šé™¤ã•ã‚Œã¾ã—ãŸ" + permalink: "パーマリンク" public: "公開" + reactions: + other: "<%= count%> リアクション" + zero: "<%= count%> リアクション" reshare: "å†å…±æœ‰" reshares: few: "<%= count %> Reshares" many: "<%= count %> Reshares" one: "<%= count %> Reshare" - other: "<%= count %> Reshares" + other: "<%= count %> å†å…±æœ‰" two: "<%= count %> Reshares" - zero: "<%= count %> Reshares" + zero: "<%= count %> å†å…±æœ‰" show_nsfw_post: "投稿を表示ã™ã‚‹" show_nsfw_posts: "å…¨ã¦è¡¨ç¤º" tags: follow: "#<%= tag %>をフォãƒãƒ¼ã™ã‚‹" + follow_error: "#<%= tag %> をフォãƒãƒ¼ã§ãã¾ã›ã‚“ã§ã—㟠:(" following: "#<%= tag %>をフォãƒãƒ¼ä¸" stop_following: "#<%= tag %>ã®ãƒ•ã‚©ãƒãƒ¼ã‚’ä¸æ¢ã™ã‚‹" + stop_following_confirm: "#<%= tag %>ã®ãƒ•ã‚©ãƒãƒ¼ã‚’ä¸æ¢ã™ã‚‹" + stop_following_error: "#<%= tag %> ã®ãƒ•ã‚©ãƒãƒ¼ã‚’åœæ¢ã§ãã¾ã›ã‚“ã§ã—㟠:(" unfollow: "フォãƒãƒ¼è§£é™¤" + unlike: "ã„ã„ãï¼ã‚’å–消" + via: "<%= provider %> ã§" tags: - wasnt_that_interesting: "OK, I suppose #<%= tagName %> wasn't all that interesting..." + wasnt_that_interesting: "OKã€#<%= tagName %> ã¯èˆˆå‘³ãŒã‚ã‚Šã¾ã›ã‚“ã§ã—ãŸ..." timeago: day: "1æ—¥" - days: "%dæ—¥" + days: + other: "%dæ—¥" hour: "大体1時間" - hours: "大体%d時間" + hours: + other: "大体%d時間" + inPast: "今ã•ã£ã" minute: "ç´„1分" - minutes: "%d分" + minutes: + other: "%d分" month: "大体1ヶ月" - months: "%dヶ月" + months: + other: "%dヶ月" prefixAgo: "" prefixFromNow: "今ã‹ã‚‰" seconds: "1分未満" suffixAgo: "å‰" suffixFromNow: "後" + wordSeparator: " " year: "大体1å¹´" - years: "%då¹´" - videos: - unknown: "å‹•ç”»ã®ç¨®é¡žãŒä¸æ˜Žã§ã™" - watch: "<%= provider %>ã§å‹•ç”»ã‚’視è´ã™ã‚‹" + years: + other: "%då¹´" + unblock_failed: "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ–ãƒãƒƒã‚¯è§£é™¤ã«å¤±æ•—ã—ã¾ã—ãŸ" viewer: - comment: "コメント" - follow_post: "投稿をフォãƒãƒ¼ã™ã‚‹" - home: "ホーム" - reshare: "å†å…±æœ‰" - stop_following_post: "投稿ã®ãƒ•ã‚©ãƒãƒ¼ã‚’解除ã™ã‚‹" \ No newline at end of file + reshared: "å†å…±æœ‰ã—ã¾ã—ãŸ" \ No newline at end of file diff --git a/config/locales/javascript/javascript.ka.yml b/config/locales/javascript/javascript.ka.yml index 17c966000ea8bc6977e2ac409aed737c79190400..79e4f018d06074cb6a93f0b829f38b04c495aa9c 100644 --- a/config/locales/javascript/javascript.ka.yml +++ b/config/locales/javascript/javascript.ka.yml @@ -45,19 +45,15 @@ ka: settings: "პáƒáƒ áƒáƒ›áƒ”ტრები" view_all: "ყველáƒáƒ¡ ჩვენებáƒ" ignore: "იგნáƒáƒ ირებáƒ" - infinite_scroll: - no_more: "მეტი პáƒáƒ¡áƒ¢áƒ˜ áƒáƒ áƒáƒ ის." my_activity: "ჩემი áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒ‘áƒ" my_stream: "ნáƒáƒ™áƒáƒ“ი" photo_uploader: looking_good: "OMG, ძáƒáƒšáƒ˜áƒáƒœ კáƒáƒ გáƒáƒ“ გáƒáƒ›áƒáƒ˜áƒ§áƒ£áƒ ები!" publisher: - at_least_one_aspect: "თქვენ უნდრგáƒáƒ›áƒáƒáƒ¥áƒ•áƒ”ყნáƒáƒ— მინიმუმ ერთ áƒáƒ¡áƒžáƒ”ქტში" limited: "შეზღუდული - თქვენს პáƒáƒ¡áƒ¢áƒ¡ დáƒáƒ˜áƒœáƒáƒ®áƒáƒ•áƒ¡ მხáƒáƒšáƒáƒ“ ის ხáƒáƒšáƒ®áƒ˜ რáƒáƒ›áƒ”ლთáƒáƒª გáƒáƒ£áƒ–იáƒáƒ ებთ" public: "სáƒáƒ¯áƒáƒ რ- თქვენს პáƒáƒ¡áƒ¢áƒ¡ დáƒáƒ˜áƒœáƒáƒ®áƒáƒ•áƒ¡ ყველრდრის გáƒáƒ›áƒáƒ©áƒœáƒ“ებრსáƒáƒ«áƒ˜áƒ”ბრსისტემáƒáƒ¨áƒ˜" reshares: duplicate: "áƒáƒ¡áƒ”თი მáƒáƒ’áƒáƒ იáƒ? თქვენ უკვე გáƒáƒáƒ–იáƒáƒ ეთ ეს პáƒáƒ¡áƒ¢áƒ˜!" - search_for: "<%= name %>-ს მáƒáƒ«áƒ”ბნáƒ" show_more: "მეტის ჩვენებáƒ" stream: comment: "კáƒáƒ›áƒ”ნტáƒáƒ ი" @@ -94,20 +90,22 @@ ka: wasnt_that_interesting: "კáƒáƒ გი, მე ვფიქრáƒáƒ‘ რáƒáƒ› #<%= tagName %> áƒáƒ ც ისე სáƒáƒ˜áƒœáƒ¢áƒ”რესრიყáƒ..." timeago: day: "დღე" - days: "%d დღე" + days: + other: "%d დღე" hour: "დáƒáƒáƒ®áƒšáƒáƒ”ბით ერთი სáƒáƒáƒ—ი" - hours: "დáƒáƒáƒ®áƒšáƒáƒ”ბით %d სáƒáƒáƒ—ი" + hours: + other: "დáƒáƒáƒ®áƒšáƒáƒ”ბით %d სáƒáƒáƒ—ი" minute: "დáƒáƒáƒ®áƒšáƒáƒ”ბით წუთი" - minutes: "%d წუთი" + minutes: + other: "%d წუთი" month: "დáƒáƒáƒ®áƒšáƒáƒ”ბით ერთი თვე" - months: "%d თვე" + months: + other: "%d თვე" prefixAgo: "" prefixFromNow: "" seconds: "წუთზე ნáƒáƒ™áƒšáƒ”ბი" suffixAgo: "áƒáƒ“რე" suffixFromNow: "áƒáƒ›áƒ˜áƒ”რიდáƒáƒœ" year: "დáƒáƒáƒ®áƒšáƒáƒ”ბით ერთი წელი" - years: "%d წელი" - videos: - unknown: "ვიდეáƒáƒ¡ ტიპი უცნáƒáƒ‘იáƒ" - watch: "ვიდეáƒáƒ¡ ნáƒáƒ®áƒ•áƒ სáƒáƒ˜áƒ¢áƒ–ე <%= provider %>" \ No newline at end of file + years: + other: "%d წელი" \ No newline at end of file diff --git a/config/locales/javascript/javascript.ko.yml b/config/locales/javascript/javascript.ko.yml index 4767a72bec27a4ce2028c8f5ec89cb0e1b1d26e8..8f9378a592f6ef1718a7f7c1efc3878adb9163aa 100644 --- a/config/locales/javascript/javascript.ko.yml +++ b/config/locales/javascript/javascript.ko.yml @@ -31,8 +31,6 @@ ko: hide: "댓글 숨기기" show: "ëª¨ë“ ëŒ“ê¸€ 보기" confirm_dialog: "확실합니까?" - conversation: - participants: "참여ìž" delete: "지우기" edit: "ê³ ì¹˜ê¸°" failed_to_like: "좋아요를 실패했습니다!" @@ -59,9 +57,6 @@ ko: view_all: "ëª¨ë‘ ë³´ê¸°" ignore: "무시하기" ignore_user: "ì´ ì‚¬ìš©ìžë¥¼ ë¬´ì‹œí• ê¹Œìš”?" - infinite_scroll: - no_more: "ê²Œì‹œë¬¼ì´ ë” ì—†ìŠµë‹ˆë‹¤." - no_more_contacts: "ì»¨íƒ ë." my_activity: "ë‚´ 활ë™" my_aspects: "ë‚´ ì• ìŠ¤íŽ™" my_stream: "스트림" @@ -78,7 +73,6 @@ ko: result: "ê²°ê³¼" publisher: add_option: "ì„ íƒ ì‚¬í• ì¶”ê°€" - at_least_one_aspect: "ê³µìœ í•˜ë ¤ë©´ ì ì–´ë„ í•œ ì• ìŠ¤íŽ™ì„ ê³¨ë¼ì•¼ 합니다." limited: "ì œí•œë¨ - ë‚´ ê²Œì‹œë¬¼ì„ ë‚˜ì™€ ê³µìœ í•˜ê³ ìžˆëŠ” 사람들만 ë³¼ 수 있습니다" near_from: "<%= location %> 근처" public: "공개 - ë‚´ ê²Œì‹œë¬¼ì„ ëˆ„êµ¬ë‚˜ ë³¼ 수 ìžˆê³ ê²€ìƒ‰ 엔진으로 ì°¾ì„ ìˆ˜ 있습니다" @@ -87,7 +81,6 @@ ko: duplicate: "ì´ë¯¸ ìž¬ê³µìœ ëœ ê²Œì‹œë¬¼ìž…ë‹ˆë‹¤!" post: "<%= name %>ë‹˜ì˜ ê²Œì‹œë¬¼ì„ ìž¬ê³µìœ í• ê¹Œìš”?" successful: "해당 ê²Œì‹œë¬¼ì´ ì„±ê³µì 으로 ìž¬ê³µìœ ë˜ì—ˆìŠµë‹ˆë‹¤!" - search_for: "<%= name %> 검색" show_more: "ë” ë³´ê¸°" stream: comment: "댓글" @@ -128,29 +121,24 @@ ko: wasnt_that_interesting: "ì•Œê² ìŠµë‹ˆë‹¤. #<%= tagName %> 태그는 í¥ë¯¸ë¡ì§€ 않았군요?" timeago: day: "하루" - days: "%dì¼" + days: + other: "%dì¼" hour: "약 í•œ 시간" - hours: "약 %d시간" + hours: + other: "약 %d시간" minute: "몇 분" - minutes: "%d분" + minutes: + other: "%d분" month: "약 í•œ 달" - months: "%d개월" + months: + other: "%d개월" prefixAgo: "" prefixFromNow: "지금부터" seconds: "방금" suffixAgo: "ì „" suffixFromNow: "" year: "í•œ í•´" - years: "%dë…„" - videos: - unknown: "ì•Œ 수 없는 ë™ì˜ìƒ 형ì‹" - watch: "ë™ì˜ìƒì„ <%= provider %>ì—ì„œ 보기" + years: + other: "%dë…„" viewer: - comment: "댓글" - follow_post: "게시물 팔로우하기" - home: "처ìŒ" - like: "좋아요" - reshare: "ìž¬ê³µìœ " - reshared: "ìž¬ê³µìœ " - stop_following_post: "게시물 팔로우 멈추기" - unlike: "좋아요 취소" \ No newline at end of file + reshared: "ìž¬ê³µìœ " \ No newline at end of file diff --git a/config/locales/javascript/javascript.lt.yml b/config/locales/javascript/javascript.lt.yml index dfc4c4a7935062f51d2ead2d53a8e8bfdeae4bbf..33a7d03666b36eefb71795c1ff9891e3addd8a4a 100644 --- a/config/locales/javascript/javascript.lt.yml +++ b/config/locales/javascript/javascript.lt.yml @@ -47,19 +47,15 @@ lt: settings: "Nustatymai" view_all: "Rodyti viskÄ…" ignore: "Ignoruoti" - infinite_scroll: - no_more: "Ä®rašų nÄ—ra." my_activity: "Mano veikla" my_stream: "Srautas" photo_uploader: looking_good: "Wow, JÅ«s atrodote nuostabiai!" publisher: - at_least_one_aspect: "Jums reikia pavieÅ¡inti bent vienÄ… kategorijÄ…" limited: "Ribotas - JÅ«sų įraÅ¡Ä… galÄ—s peržiÅ«rÄ—ti tik žmonÄ—s, su kuriais JÅ«s dalijatÄ—s" public: "VieÅ¡as - JÅ«sų įraÅ¡us galÄ—s peržiÅ«rÄ—ti visi, taip pat jie bus randami paieÅ¡kos sistemose." reshares: duplicate: "Å itas geras, ne? JÅ«s jau dalijotÄ—s Å¡iuo įraÅ¡u!" - search_for: "IeÅ¡koti <%= name %>" show_more: "Rodyti daugiau" stream: comment: "Komentuoti" @@ -94,20 +90,22 @@ lt: wasnt_that_interesting: "Na gerai, greiÄiausiai #<%= tagName%> tai nebuvo taip įdomu..." timeago: day: "1 d." - days: "%d d." + days: + other: "%d d." hour: "maždaug1 val." - hours: "maždaug %d val." + hours: + other: "maždaug %d val." minute: "maždaug 1 min." - minutes: "%d min." + minutes: + other: "%d min." month: "maždaug 1 mÄ—n." - months: "%d mÄ—n." + months: + other: "%d mÄ—n." prefixAgo: "" prefixFromNow: "" seconds: "mažiau nei 1 min." suffixAgo: "prieÅ¡" suffixFromNow: "nuo dabar" year: "maždaug 1 m." - years: "%d m." - videos: - unknown: "Netinkamas video įraÅ¡o tipas." - watch: "ŽiÅ«rÄ—kite video įraÅ¡Ä… Äia <%=provider %>" \ No newline at end of file + years: + other: "%d m." \ No newline at end of file diff --git a/config/locales/javascript/javascript.ml.yml b/config/locales/javascript/javascript.ml.yml index 98227605893ff60a148400d6ada33f49d420ce79..4110513dd161ab741072dead4a23c33bcefa413b 100644 --- a/config/locales/javascript/javascript.ml.yml +++ b/config/locales/javascript/javascript.ml.yml @@ -30,8 +30,6 @@ ml: no_comments: "ഇതàµà´µà´°àµ† à´…à´à´¿à´ªàµà´°à´¾à´¯à´™àµà´™à´³àµŠà´¨àµà´¨àµà´‚ à´•à´¿à´Ÿàµà´Ÿà´¿à´¯à´¿à´Ÿàµà´Ÿà´¿à´²àµà´²" show: "à´Žà´²àµà´²à´¾ à´…à´à´¿à´ªàµà´°à´¾à´¯à´™àµà´™à´³àµà´‚ കാണികàµà´•àµà´•" confirm_dialog: "താങàµà´•à´³àµâ€à´•àµà´•àµ ഉറപàµà´ªà´¾à´£àµ‹?" - conversation: - participants: "പങàµà´•à´¾à´³à´¿à´•à´³àµâ€" delete: "മായàµà´•àµà´•àµà´•" edit: "തിരàµà´¤àµà´¤àµà´•" failed_to_like: "ഇഷàµà´Ÿà´ªàµ†à´Ÿà´¾àµ» സാധിചàµà´šà´¿à´²àµà´²" @@ -57,9 +55,6 @@ ml: view_all: "à´Žà´²àµà´²à´¾à´‚ കാണàµà´•" ignore: "അവഗണികàµà´•àµà´•" ignore_user: "à´ˆ ഉപയോകàµà´¤à´¾à´µà´¿à´¨àµ† അവഗണികàµà´•à´£àµ‹?" - infinite_scroll: - no_more: "കൂടàµà´¤à´²àµâ€ പോസàµà´±àµà´±àµà´•à´³àµŠà´¨àµà´¨àµà´®à´¿à´²àµà´²." - no_more_contacts: "മറàµà´±àµ സമàµà´ªàµ¼à´•àµà´•à´™àµà´™à´³àµŠà´¨àµà´¨àµà´®à´¿à´²àµà´²" my_activity: "à´Žà´¨àµà´±àµ† à´ªàµà´°à´µàµƒà´¤àµà´¤à´¿" my_aspects: "à´Žà´¨àµà´±àµ† à´à´¾à´µà´™àµà´™àµ¾" my_stream: "à´¸àµà´Ÿàµà´°àµ€à´‚" @@ -72,7 +67,6 @@ ml: looking_good: "താങàµà´•à´³àµ† കാണാൻ വളരെ നനàµà´¨à´¾à´¯à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ!" size_error: "{file} വളരെ വലàµà´¤à´¾à´£àµ, കൂടിയ ഫയലàµâ€ വലിപàµà´ªà´‚ {sizeLimit} ആകàµà´¨àµà´¨àµ." publisher: - at_least_one_aspect: "താങàµà´•à´³àµâ€ ഒരൠപരിചയതàµà´¤à´¿à´®àµ†à´™àµà´•à´¿à´²àµà´‚ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµ‡à´£àµà´Ÿà´¤à´¾à´£àµ." limited: "പരിമിതം - താങàµà´•à´³àµà´Ÿàµ† à´•àµà´±à´¿à´ªàµà´ªàµ താങàµà´•àµ¾ പങàµà´•à´¿à´Ÿàµà´¨àµà´¨ ആൾകàµà´•à´¾àµ¼ മാതàµà´°à´®àµ‡ കാണൂ" near_from: "<%= location %>à´²àµâ€ നിനàµà´¨àµà´‚ അയചàµà´šà´¤àµ" public: "പൊതàµà´µà´¾à´¯à´¤àµ - താങàµà´•à´³àµà´Ÿàµ† à´•àµà´±à´¿à´ªàµà´ªàµ à´Žà´²àµà´²à´¾à´µàµ¼à´•àµà´•àµà´‚ കാണാൻ സാധികàµà´•àµà´‚. കൂടാതെ തിരചàµà´šà´¿àµ½ യനàµà´¤àµà´°à´™àµà´™à´³à´¾àµ½ à´•à´£àµà´Ÿàµà´ªà´¿à´Ÿà´¿à´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´•à´¯àµà´‚ ചെയàµà´¯àµà´‚" @@ -80,7 +74,6 @@ ml: duplicate: "à´…à´¤àµà´° നലàµà´²à´¤à´¾à´£àµ‹? താങàµà´•àµ¾ à´† à´•àµà´±à´¿à´ªàµà´ªàµ à´®àµàµ»à´ªàµ‡ തനàµà´¨àµ† വീണàµà´Ÿàµà´‚ പങàµà´•à´¿à´Ÿàµà´Ÿà´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ" post: "<%= name %>à´¨àµà´±àµ† à´•àµà´±à´¿à´ªàµà´ªàµ വീണàµà´Ÿàµà´‚ പങàµà´•à´¿à´Ÿà´£àµ‹?" successful: "à´ˆ à´•àµà´±à´¿à´ªàµà´ªàµ വിജയകരമായി വീണàµà´Ÿàµà´‚ പങàµà´•àµà´µàµ†à´¯àµà´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿàµ!" - search_for: "<%= name %>നായി തിരയàµà´•" show_more: "കൂടàµà´¤à´²àµâ€ കാണികàµà´•àµà´•" stream: comment: "à´…à´à´¿à´ªàµà´°à´¾à´¯à´‚" @@ -120,29 +113,24 @@ ml: wasnt_that_interesting: "ശരി, ഞാൻ à´•à´°àµà´¤àµà´¨àµà´¨àµ #<%= tagName %> à´…à´¤àµà´° രസമàµà´³àµà´³à´¤à´¾à´¯à´¿à´°àµà´¨àµà´¨à´¿à´²àµà´²àµ†à´¨àµà´¨àµ." timeago: day: "ഒരൠദിവസം" - days: "%d ദിവസങàµà´™à´³àµâ€" + days: + other: "%d ദിവസങàµà´™à´³àµâ€" hour: "ഉദàµà´¦àµ‡à´¶à´‚ ഒരൠമണീകàµà´•àµ‚à´°àµâ€" - hours: "ഉദàµà´¦àµ‡à´¶à´‚ %d മണികàµà´•àµ‚à´±àµà´•à´³àµâ€" + hours: + other: "ഉദàµà´¦àµ‡à´¶à´‚ %d മണികàµà´•àµ‚à´±àµà´•à´³àµâ€" minute: "ഉദàµà´¦àµ‡à´¶à´‚ ഒരൠമിനിടàµà´Ÿàµ" - minutes: "%d മിനിടàµà´Ÿàµà´•à´³àµâ€" + minutes: + other: "%d മിനിടàµà´Ÿàµà´•à´³àµâ€" month: "ഉദàµà´¦àµ‡à´¶à´‚ ഒരൠമാസം" - months: "%d മാസങàµà´™à´³àµâ€" + months: + other: "%d മാസങàµà´™à´³àµâ€" prefixAgo: "" prefixFromNow: "ഇപàµà´ªàµ‹à´³àµâ€ à´®àµà´¤à´²àµâ€" seconds: "à´à´¤à´¾à´¨àµà´‚ നിമിഷങàµà´™à´³àµâ€" suffixAgo: "à´®àµà´¨àµâ€à´ªàµ" suffixFromNow: "വരെ" year: "ഉദàµà´¦àµ‡à´¶à´‚ ഒരൠവരàµâ€à´·à´‚" - years: "%d വരàµâ€à´·à´™àµà´™à´³àµâ€à´•àµà´•àµ" - videos: - unknown: "à´…à´œàµà´žà´¾à´¤à´®à´¾à´¯ തരം വീഡിയോ" - watch: "à´ˆ വീഡിയോ <%= provider %>à´²àµâ€ കാണàµà´•" + years: + other: "%d വരàµâ€à´·à´™àµà´™à´³àµâ€à´•àµà´•àµ" viewer: - comment: "à´…à´à´¿à´ªàµà´°à´¾à´¯à´‚" - follow_post: "à´•àµà´±à´¿à´ªàµà´ªà´¿à´¨àµ† പിനàµà´¤àµà´Ÿà´°àµà´•" - home: "പൂമàµà´–à´‚" - like: "ഇഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´•" - reshare: "വീണàµà´Ÿàµà´‚ പങàµà´•àµà´µàµ†à´¯àµà´•àµà´•àµà´•" - reshared: "വീണàµà´Ÿàµà´‚ പങàµà´•àµà´µàµ†à´¯àµà´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´¤àµ" - stop_following_post: "à´•àµà´±à´¿à´ªàµà´ªà´¿à´¨àµ† പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨à´¤àµ നിർതàµà´¤àµà´•" - unlike: "നീരസപàµà´ªàµ†à´Ÿàµà´•" \ No newline at end of file + reshared: "വീണàµà´Ÿàµà´‚ പങàµà´•àµà´µàµ†à´¯àµà´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´¤àµ" \ No newline at end of file diff --git a/config/locales/javascript/javascript.ms.yml b/config/locales/javascript/javascript.ms.yml index 5ee8feae48b6399bd49c730c5f0feb0c60774291..08538a490ca7d9779a81291a06aa9a7a9b4abaa4 100644 --- a/config/locales/javascript/javascript.ms.yml +++ b/config/locales/javascript/javascript.ms.yml @@ -41,8 +41,6 @@ ms: error_add: "Tidak dapat menambah <%= name %> kepada aspek :(" error_remove: "Tidak dapat membuang <%= name %> dari aspek :(" remove_contact: "Buang kenalan" - conversation: - participants: "Peserta" edit: "Edit" failed_to_like: "Gagal untuk suka!" failed_to_post_message: "Gagal untuk pos mesej!" @@ -59,9 +57,6 @@ ms: search: "Find people or #tags" ignore_failed: "Tidak boleh mengabaikan pengguna ini" ignore_user: "Abaikan pengguna ini?" - infinite_scroll: - no_more: "Tiada lagi pos." - no_more_contacts: "Tiada lagi kenalan." my_aspects: "Aspek-aspek saya" no_results: "Tiada Hasil Dijumpai" notifications: @@ -98,14 +93,12 @@ ms: contacts: "Kenalan-kenalan" edit: "edit" gender: "Jantina" - ignoring: "Anda mengabaikan semua siaran daripada <%= name %>." location: "Lokasi" photos: "Gambar" posts: "Catatan" you_have_no_tags: "anda tidak mempunyai tag!" publisher: add_option: "Tambah jawapan" - at_least_one_aspect: "Anda perlu menerbitkan sekurang-kurangnya satu aspek" limited: "Terhad - catatan anda hanya akan dilihat oleh orang-orang yang berkongsi dengan anda" near_from: "Dicatatkan dari: <%= location %>" option: "Jawapan" @@ -122,7 +115,6 @@ ms: duplicate: "Yang baik, kan? Anda telah berkongsi semula pos itu!" post: "Kongsi semula catatan <%= name %>?" successful: "Catatan berjaya dikongsi semula!" - search_for: "Mencari <%= name %>" show_more: "tunjuk lagi" stream: followed_tag: @@ -159,21 +151,23 @@ ms: wasnt_that_interesting: "OK, saya mengandaikan #<%= tagName %> tidak semua yang menarik..." timeago: day: "sehari" - days: "%d hari" + days: + other: "%d hari" hour: "kira-kira sejam" - hours: "kira-kira %d jam" + hours: + other: "kira-kira %d jam" minute: "kira-kira satu minit" - minutes: "%d minit" + minutes: + other: "%d minit" month: "kira-kira sebulan" - months: "%d bulan" + months: + other: "%d bulan" prefixAgo: "javascripts:timeago:prefixAgo" prefixFromNow: "javascripts:timeago:prefixFromNow" seconds: "kurang daripada satu minit" suffixAgo: "lalu" suffixFromNow: "dari sekarang" year: "kira-kira setahun" - years: "%d tahun" - unblock_failed: "Membuang sekatan pada pengguna ini telah gagal" - videos: - unknown: "Jenis video tidak diketahui" - watch: "Tonton video ini di <%= provider %>" \ No newline at end of file + years: + other: "%d tahun" + unblock_failed: "Membuang sekatan pada pengguna ini telah gagal" \ No newline at end of file diff --git a/config/locales/javascript/javascript.nb.yml b/config/locales/javascript/javascript.nb.yml index 689aec1e6da9489a419a1443662008959138597f..6367edcd93876f3af769476f64c34cb0b92d01c1 100644 --- a/config/locales/javascript/javascript.nb.yml +++ b/config/locales/javascript/javascript.nb.yml @@ -57,7 +57,6 @@ nb: conversation: new: no_contacts: "Du mÃ¥ legge til noen kontakter før du kan starte en samtale." - participants: "Deltakere" create: "Lag" delete: "Slett" edit: "Rediger" @@ -91,9 +90,6 @@ nb: ignore: "Ignorer" ignore_failed: "Ikke mulig Ã¥ ignorere brukeren" ignore_user: "Overse denne brukeren?" - infinite_scroll: - no_more: "Ingen flere innlegg." - no_more_contacts: "Ingen flere kontakter." my_activity: "Min aktivitet" my_aspects: "Mine aspekter" my_stream: "Strøm" @@ -135,14 +131,12 @@ nb: contacts: "Kontakter" edit: "Endre" gender: "Kjønn" - ignoring: "Du vil ignorere alle innlegg fra <%= name %>." location: "Lokasjon" photos: "Bilder" posts: "Innlegg" you_have_no_tags: "Du har ingen tagger!" publisher: add_option: "Legg til valg" - at_least_one_aspect: "Du mÃ¥ poste til minst ett aspekt" limited: "Begrenset - posten din vil bare være synlig for de du deler med" near_from: "Publisert fra: <%= location %>" option: "Valg <%= nr %>" @@ -160,7 +154,6 @@ nb: duplicate: "du har allerede delt denne posten!" post: "Videredel <%= name %> sitt innhold?" successful: "Dette innholdet ble videredelt" - search_for: "Søk etter <%= name %>" show_more: "vis mer" stream: comment: "Kommenter" @@ -206,13 +199,17 @@ nb: wasnt_that_interesting: "OK, jeg skjønner at #<%= tagName %> ikke var sÃ¥ spennende likevel ..." timeago: day: "en dag" - days: "%d dager" + days: + other: "%d dager" hour: "ca. en time" - hours: "ca. %d timer" + hours: + other: "ca. %d timer" minute: "ca. et minutt" - minutes: "%d minutter" + minutes: + other: "%d minutter" month: "ca. en mÃ¥ned" - months: "%d mÃ¥neder" + months: + other: "%d mÃ¥neder" prefixAgo: "for" prefixFromNow: "om" seconds: "under ett minutt" @@ -220,17 +217,8 @@ nb: suffixFromNow: "fra nÃ¥" wordSeparator: " " year: "ca. et Ã¥r" - years: "%d Ã¥r" + years: + other: "%d Ã¥r" unblock_failed: "Feilet i Ã¥ stoppe blokkering" - videos: - unknown: "Ukjent videotype" - watch: "Se denne videoen pÃ¥ <%= provider %>" viewer: - comment: "Kommenter" - follow_post: "Følg post" - home: "HJEM" - like: "Liker" - reshare: "Del" - reshared: "Delt med andre" - stop_following_post: "Slutt Ã¥ følge post" - unlike: "Fjern liker" \ No newline at end of file + reshared: "Delt med andre" \ No newline at end of file diff --git a/config/locales/javascript/javascript.nds.yml b/config/locales/javascript/javascript.nds.yml index e4ae0d2120579396f6b6b6419970a64a247abdde..ac9f2fc5fc8acda157039a7480068d299cee795a 100644 --- a/config/locales/javascript/javascript.nds.yml +++ b/config/locales/javascript/javascript.nds.yml @@ -40,8 +40,6 @@ nds: error_remove: "Kun <%= name %> nich ut den Aspekt rutdaun :(" remove_contact: "Kontakt löschen" search_no_results: "Keene Kontakte funnen" - conversation: - participants: "Bedeeligte" delete: "Löschen" edit: "Ännern" failed_to_remove: "Kun den Indrag nich löschen!" @@ -68,9 +66,6 @@ nds: ignore: "Ignorieren" ignore_failed: "Kun dissen Bruker nich ignorieren" ignore_user: "Dissen Bruker ignorieren?" - infinite_scroll: - no_more: "Keene Bidräg mehr." - no_more_contacts: "Keene annern Kontakte." my_activity: "Mien Rümröören" my_aspects: "Miene Aspekte" my_stream: "Stream" @@ -105,7 +100,6 @@ nds: contacts: "Kontakte" edit: "Ännern" gender: "Geschlecht" - ignoring: "Du ignorierst alle Bidräg von <%= name %>." location: "Ort" photos: "Bilder" posts: "Bidräg" @@ -161,22 +155,19 @@ nds: via: "öber <%= provider %>" timeago: day: "een Dag" - days: "%d Doog" - minutes: "%d Minuten" - months: "%d Monate" + days: + other: "%d Doog" + minutes: + other: "%d Minuten" + months: + other: "%d Monate" prefixAgo: "" prefixFromNow: "" seconds: "weniger as eene Minute" suffixAgo: "her" suffixFromNow: "" wordSeparator: " " - years: "%d Johre" + years: + other: "%d Johre" viewer: - comment: "Kommentieren" - follow_post: "Den Bidrag folgen" - home: "Startsiet" - like: "Mag ik" - reshare: "Widerseggen" - reshared: "Widerseggt" - stop_following_post: "Den Bidrag nich mehr folgen" - unlike: "Mag ik nich mehr" \ No newline at end of file + reshared: "Widerseggt" \ No newline at end of file diff --git a/config/locales/javascript/javascript.ne.yml b/config/locales/javascript/javascript.ne.yml index 002aa43fe44ea9ed7313e6beed0ba5ec01d6e1bf..9034c8d82bd9486ccda2adb9ad4f226fe7512a13 100644 --- a/config/locales/javascript/javascript.ne.yml +++ b/config/locales/javascript/javascript.ne.yml @@ -23,15 +23,19 @@ ne: unlike: "मनपरेन" timeago: day: "à¤à¤• दिन" - days: "%d दिन" + days: + other: "%d दिन" hour: "लगà¤à¤— à¤à¤• घणà¥à¤Ÿà¤¾" - hours: "लगà¤à¤— %d घणà¥à¤Ÿà¤¾" + hours: + other: "लगà¤à¤— %d घणà¥à¤Ÿà¤¾" minute: "लगà¤à¤— à¤à¤• मिनेट" month: "लगà¤à¤— à¤à¤• महिना" - months: "%d महिना" + months: + other: "%d महिना" prefixAgo: "" prefixFromNow: "" suffixAgo: "अघि" suffixFromNow: "अहिले देखी" year: "लगà¤à¤— à¤à¤• वरà¥à¤·" - years: "%d वरà¥à¤·" \ No newline at end of file + years: + other: "%d वरà¥à¤·" \ No newline at end of file diff --git a/config/locales/javascript/javascript.nl.yml b/config/locales/javascript/javascript.nl.yml index 49c873791933351f834bb53c8cd8d58b871062d0..b0c9296697d7b54c41590a0b7491458659b70298 100644 --- a/config/locales/javascript/javascript.nl.yml +++ b/config/locales/javascript/javascript.nl.yml @@ -6,6 +6,55 @@ nl: javascripts: + admin: + pods: + actions: "Acties" + added: "Toegevoegd" + check: "voer verbindingstest uit" + errors: + one: "De verbindingstest gaf een foutmelding voor een pod." + other: "De verbindingstest gaf een foutmelding voor <%= count %> pods." + follow_link: "open link in browser" + last_check: "laatst gecontroleerd:" + more_info: "toon meer informatie" + ms: + one: "<%= count %>ms" + other: "<%= count %>ms" + no_info: "Op dit punt is geen extra informatie beschikbaar" + not_available: "niet beschikbaar" + offline_since: "offline sinds:" + pod: "Pod" + recheck: + failure: "De controle is niet uitgevoerd." + success: "De pod is net weer gecontroleerd." + response_time: "Responsetijd" + server_software: "Serversoftware:" + ssl: "SSL" + ssl_disabled: "SSL gedeactiveerd" + ssl_enabled: "SSL geactiveerd" + states: + dns_failed: "Naam resolutie (DNS) mislukt" + http_failed: "HTTP verbinding mislukt" + net_failed: "Verbindingspoging mislukt" + no_errors: "OK" + ssl_failed: "Beveiligde verbinding (SSL) mislukt" + unchecked: "Uitgevinkt" + unknown_error: "Er trad een niet-gedefnieerde fout op tijdens de controle" + version_failed: "Kan de softwareversie niet ophalen" + status: "Status" + unchecked: + one: "Er nog steeds een pod die niet is gecontroleerd." + other: "Er nog steeds <%= count %> pods die niet zijn gecontroleerd." + unknown: "onbekend" + version_failed: + one: "Er is een pod zonder versie (oude pod, geen NodeInfo)." + other: "Er zijn <%= count %> pods zonder versie (oude pods, geen NodeInfo)." + admins: + dashboard: + compare_versions: "De laatste diaspora* release is <%= latestVersion %>, jouw pod draait nog <%= podVersion %>." + error: "Kan de laatste diaspora* versie niet bepalen." + outdated: "Je pod is verouderd." + up_to_date: "Je pod is bijgewerkt!" and: "en" aspect_dropdown: add_to_aspect: "Voeg contact toe" @@ -51,6 +100,8 @@ nl: confirm_unload: "Bevestig dat je deze pagina wilt verlaten - gegevens die je hebt ingevoerd, worden niet bewaard." contacts: add_contact: "Toevoegen contact" + aspect_chat_is_enabled: "Contactpersonen in dit aspect kunnen met jou chatten." + aspect_chat_is_not_enabled: "Contactpersonen in dit aspect kunnen niet met jou chatten." aspect_list_is_not_visible: "Contactpersonen in dit aspect kunnen elkaar niet zien." aspect_list_is_visible: "Contactpersonen in dit aspect kunnen elkaar zien." error_add: "Kon <%= name %> niet toevoegen aan het aspect :(" @@ -60,11 +111,11 @@ nl: conversation: new: no_contacts: "Je moet een paar contactpersonen opgeven om een conversatie te kunnen starten." - participants: "Deelnemers" create: "Creëren" delete: "Verwijder" edit: "Bewerken" - failed_to_like: "Leuk vinden mislukt!" + failed_to_comment: "Reageren mislukt. Misschien negeert de schrijver jou?" + failed_to_like: "Leuk vinden mislukt. Misschien negeert de auteur jou?" failed_to_post_message: "Bericht plaatsen mislukt!" failed_to_remove: "Kon het bericht niet verwijderen!" failed_to_reshare: "Doorgeven mislukt!" @@ -88,15 +139,14 @@ nl: recent_notifications: "Recente meldingen" search: "Zoek" settings: "Instellingen" + toggle_mobile: "Omschakelen mobiel" + toggle_navigation: "Omschakelen navigatie" view_all: "Bekijk alle" hide_post: "Dit bericht verbergen?" hide_post_failed: "Kon bericht niet verbergen" ignore: "Negeer" ignore_failed: "Kan deze gebruiker niet negeren" ignore_user: "Wilt u deze gebruiker negeren?" - infinite_scroll: - no_more: "Geen berichten meer." - no_more_contacts: "Geen contacten meer." my_activity: "Mijn activiteit" my_aspects: "Mijn aspecten" my_stream: "Stream" @@ -121,6 +171,10 @@ nl: looking_good: "Wow, wat ben je knap!" size_error: "{file} is te groot, maximum omvang is {sizeLimit}." poll: + answer_count: + one: "1 stem" + other: "<%=count%> stemmen" + zero: "0 stemmen" close_result: "Verberg resultaat" count: one: "1 stem tot dit moment" @@ -137,14 +191,12 @@ nl: contacts: "Contacten" edit: "Bewerken" gender: "Geslacht" - ignoring: "Je negeert alle berichten van <%= name %>" location: "Locatie" photos: "Foto's" posts: "Berichten" you_have_no_tags: "Je hebt geen tags!" publisher: add_option: "Keuzemogelijkheid toevoegen" - at_least_one_aspect: "Je moet op zijn minst één aspect publiceren" limited: "Gelimiteerd - je bericht is alleen zichtbaar voor de mensen waarmee je hem deelt" near_from: "Geplaatst vanaf: <%= location %>" option: "Keuze <%= nr %>" @@ -162,7 +214,6 @@ nl: duplicate: "Je hebt dit bericht al doorgegeven! Is het echt zo goed?" post: "Doorgeven <%= name %>'s bericht?" successful: "Het bericht is gedeeld!" - search_for: "Zoek naar <%= name %>" show_more: "Laat meer zien" stream: comment: "Reageren" @@ -186,7 +237,12 @@ nl: other: "Toon nog <%= count %> reacties" zero: "Toon nog <%= count %> reacties" original_post_deleted: "Originele bericht verwijderd door de auteur." + permalink: "Permalink" public: "Openbaar" + reactions: + one: "<%= count%> reactie" + other: "<%= count%> reacties" + zero: "<%= count%> reacties" reshare: "Doorgeven" reshares: one: "<%= count %>keer opnieuw gedeeld" @@ -208,13 +264,18 @@ nl: wasnt_that_interesting: "#<%= tagName %> zal dan toch niet zo interessant geweest zijn..." timeago: day: "een dag" - days: "%d dagen" + days: + other: "%d dagen" hour: "ongeveer een uur" - hours: "ongeveer %d uur" + hours: + other: "ongeveer %d uur" + inPast: "op elk moment nu" minute: "ongeveer een minuut" - minutes: "%d minuten" + minutes: + other: "%d minuten" month: "ongeveer een maand" - months: "%d maanden" + months: + other: "%d maanden" prefixAgo: "" prefixFromNow: "" seconds: "iets minder dan een minuut" @@ -222,17 +283,8 @@ nl: suffixFromNow: "vanaf nu" wordSeparator: " " year: "ongeveer een jaar" - years: "%d jaar" + years: + other: "%d jaar" unblock_failed: "Deblokkeren van deze gebruiker is mislukt" - videos: - unknown: "Onbekend video type" - watch: "Bekijk deze video op <%= provider %>" viewer: - comment: "Reageren" - follow_post: "Volgen" - home: "Home" - like: "Vind ik leuk" - reshare: "Doorgeven" - reshared: "Doorgegeven" - stop_following_post: "Niet meer volgen" - unlike: "Niet meer leuk" \ No newline at end of file + reshared: "Doorgegeven" \ No newline at end of file diff --git a/config/locales/javascript/javascript.nn.yml b/config/locales/javascript/javascript.nn.yml index ae606fb10a33f36f175c47284a84f9394f62035a..708e558b0068c96515d8d460bdc1e06dd25848fc 100644 --- a/config/locales/javascript/javascript.nn.yml +++ b/config/locales/javascript/javascript.nn.yml @@ -53,8 +53,6 @@ nn: view_all: "Syn alle" ignore: "OversjÃ¥" ignore_user: "OversjÃ¥ denne brukaren?" - infinite_scroll: - no_more: "Ingen fleire meldingar." my_activity: "Min aktivitet" my_aspects: "Aspekta mine" my_stream: "Straum" @@ -64,14 +62,12 @@ nn: completed: "<%= file %> ferdig" looking_good: "Du verda, du ser flott ut!" publisher: - at_least_one_aspect: "Du mÃ¥ offentleggjera til minst eitt aspekt" limited: "Avgrensa - berre personar du deler med vil kunna sjÃ¥ meldinga" public: "Offentleg - alle kan sjÃ¥ meldinga di og ho kan bli funnen av søkjemotorar" reshares: duplicate: "SÃ¥ bra, altsÃ¥? Men du har allereie delt meldinga :-)" post: "Vil du dele <%= name %> sin post?" successful: "Hurra, posten vart delt!" - search_for: "Leit etter <%= name %>" show_more: "syn meir" stream: comment: "Kommenter" @@ -111,29 +107,24 @@ nn: wasnt_that_interesting: "Greitt, #<%= tagName %> var vel kanskje ikkje sÃ¥ interessant …" timeago: day: "i gÃ¥r" - days: "%d dagar" + days: + other: "%d dagar" hour: "om lag ein time" - hours: "om lag %d timar" + hours: + other: "om lag %d timar" minute: "om lag eit minutt" - minutes: "%d minutt" + minutes: + other: "%d minutt" month: "om lag ein mÃ¥nad" - months: "%d mÃ¥nader" + months: + other: "%d mÃ¥nader" prefixAgo: "" prefixFromNow: "" seconds: "mindre enn eit minutt" suffixAgo: "sidan" suffixFromNow: "frÃ¥ no" year: "om lag eit Ã¥r" - years: "%d Ã¥r" - videos: - unknown: "Ukjend videotype" - watch: "SjÃ¥ denne videoen hos <%= provider %>" + years: + other: "%d Ã¥r" viewer: - comment: "Kommenter" - follow_post: "Følg innlegg" - home: "HEIM" - like: "Lik" - reshare: "Del" - reshared: "Delt" - stop_following_post: "Ikkje følg innlegg meir" - unlike: "Lik ikkje lenger" \ No newline at end of file + reshared: "Delt" \ No newline at end of file diff --git a/config/locales/javascript/javascript.pl.yml b/config/locales/javascript/javascript.pl.yml index 9988b6a42de8f3213675c1d4a7d3b84bb89f4406..1f746a9395e99e479720cf8740b509c19714cde1 100644 --- a/config/locales/javascript/javascript.pl.yml +++ b/config/locales/javascript/javascript.pl.yml @@ -60,7 +60,6 @@ pl: conversation: new: no_contacts: "Przed rozpoczÄ™ciem rozmowy musisz dodać kontakty" - participants: "Uczestnicy" create: "Utwórz" delete: "UsuÅ„" edit: "Edycja" @@ -93,9 +92,6 @@ pl: ignore: "Ignoruj" ignore_failed: "Nie można zignorować tego użytkownika" ignore_user: "Zignorować tego użytkownika?" - infinite_scroll: - no_more: "Nie ma wiÄ™cej wpisów." - no_more_contacts: "Brak kontaktów." my_activity: "Moja aktywność" my_aspects: "Moje aspekty" my_stream: "StrumieÅ„" @@ -139,14 +135,12 @@ pl: contacts: "Kontakty" edit: "zmieÅ„" gender: "PÅ‚eć" - ignoring: "Ignorujesz wszystkie wpisy od <%= name %>." location: "Miejsce" photos: "ZdjÄ™cia" posts: "Wpisy" you_have_no_tags: "nie masz tagów!" publisher: add_option: "Dodaj odpowiedź" - at_least_one_aspect: "Musisz udostÄ™pnić dla co najmniej jednego aspektu" limited: "Ograniczony - wpis bÄ™dzie widoczny tylko dla wybranej grupy osób" near_from: "Blisko <%= location %>" option: "Odpowiedź" @@ -164,7 +158,6 @@ pl: duplicate: "Już przekaza@{m:Å‚eÅ›|f:Å‚aÅ›|n:no} dalej ten wpis!" post: "PrzesÅ‚ać dalej wpis użytkownika <%= name %>?" successful: "Wpis zostaÅ‚ pomyÅ›lnie przesÅ‚any dalej!" - search_for: "Znajdź: <%= name %>" show_more: "wyÅ›wietl wiÄ™cej" stream: comment: "Skomentuj" @@ -216,13 +209,17 @@ pl: wasnt_that_interesting: "OK, przypuszczam, że #<%= tagName %> nie byÅ‚, aż tak interesujÄ…cy..." timeago: day: "dzieÅ„" - days: "%d dni" + days: + other: "%d dni" hour: "okoÅ‚o godziny" - hours: "okoÅ‚o %d godzin" + hours: + other: "okoÅ‚o %d godzin" minute: "okoÅ‚o minuty" - minutes: "%d minut" + minutes: + other: "%d minut" month: "okoÅ‚o miesiÄ…ca" - months: "%d miesiÄ™cy" + months: + other: "%d miesiÄ™cy" prefixAgo: "" prefixFromNow: "" seconds: "mniej niż minutÄ™" @@ -230,17 +227,8 @@ pl: suffixFromNow: "od teraz" wordSeparator: " " year: "okoÅ‚o roku" - years: "%d lat" + years: + other: "%d lat" unblock_failed: "Nie udaÅ‚o siÄ™ odblokować tego użytkownika" - videos: - unknown: "Nieznany typ wideo" - watch: "Zobacz ten film na <%= provider %>" viewer: - comment: "Skomentuj" - follow_post: "Obserwuj wpis" - home: "GÅÓWNA" - like: "LubiÄ™ to!" - reshare: "Przekaż dalej" - reshared: "Przekazano dalej" - stop_following_post: "PrzestaÅ„ obserwować wpis" - unlike: "Nie lubiÄ™" \ No newline at end of file + reshared: "Przekazano dalej" \ No newline at end of file diff --git a/config/locales/javascript/javascript.pt-BR.yml b/config/locales/javascript/javascript.pt-BR.yml index f43a6a3fdd2abfe7e40ab6fb6d60d3333dd3b621..824bfd3040ba53700b1da1b4e6aaa5d75f56d332 100644 --- a/config/locales/javascript/javascript.pt-BR.yml +++ b/config/locales/javascript/javascript.pt-BR.yml @@ -6,11 +6,62 @@ pt-BR: javascripts: + admin: + pods: + actions: "Operações" + added: "Adicionados" + check: "testar conexão" + errors: + one: "O teste de conexão acusou erro para <%= count %> servidor." + other: "O teste de conexão acusou erro para <%= count %> servidores." + zero: "O teste de conexão não acusou erro para nenhum servidor." + follow_link: "abrir link no navegador" + last_check: "última verificação:" + more_info: "mostrar mais informações" + ms: + one: "<%= count %> ms" + other: "<%= count %> ms" + no_info: "Não há mais informações disponÃveis neste momento" + not_available: "indisponÃvel" + offline_since: "desconectado desde:" + pod: "Servidor" + recheck: + failure: "A reverificação não foi efetuada." + success: "O servidor acabou de ser reverificado." + response_time: "Tempo de resposta:" + server_software: "Software do servidor:" + ssl: "SSL" + ssl_disabled: "SSL desabilitado" + ssl_enabled: "SSL habilitado" + states: + dns_failed: "Falha na tradução de nomes (DNS)" + http_failed: "Falha na conexão HTTP" + net_failed: "Falha ao tentar conectar-se" + no_errors: "Em ordem" + ssl_failed: "Falha na conexão segura (SSL)" + unchecked: "A verificar" + unknown_error: "Um erro indefinido ocorreu durante a verificação" + version_failed: "Não foi possÃvel obter versão do software" + status: "Estado" + unchecked: + one: "Resta <%= count %> servidor a ser verificado." + other: "Restam <%= count %> servidores a serem verificados." + zero: "Não restam servidores a serem verificados." + unknown: "desconhecido" + version_failed: + one: "Há um servidor sem versão (servidor antigo, sem NodeInfo)." + other: "Há <%= count %> servidores sem versão (servidores antigos, sem NodeInfo)." + admins: + dashboard: + compare_versions: "A versão mais recente de diaspora* é <%= latestVersion %>; a versão instalada no seu servidor é <%= podVersion %>." + error: "Não foi possÃvel encontrar a versão mais recente de diaspora*." + outdated: "Seu servidor está desatualizado." + up_to_date: "Seu servidor está atualizado!" and: "e" aspect_dropdown: add_to_aspect: "Adicionar contato" all_aspects: "Todos aspectos" - error: "Não foi possÃvel compartilhar com<%= name %>. Deseja ignorar isto?" + error: "Não foi possÃvel compartilhar com <%= name %>. Você está ignorando essa pessoa?" error_remove: "Não foi possÃvel remover <%= name %> do aspecto :(" mobile_row_checked: "<%= name %> (remover)" mobile_row_unchecked: "<%= name %> (adicionar)" @@ -20,7 +71,6 @@ pt-BR: toggle: one: "Em <%= count %> aspecto" other: "Em <%= count %> aspectos" - zero: "Selecione aspectos" updating: "atualizando..." aspect_navigation: add_an_aspect: "+ Adicionar um aspecto" @@ -48,6 +98,8 @@ pt-BR: confirm_unload: "Por favor, confirme se deseja sair desta página. Os dados que você informou não serão salvos." contacts: add_contact: "Adicionar contato" + aspect_chat_is_enabled: "Contatos neste aspecto podem bater papo com você." + aspect_chat_is_not_enabled: "Contatos neste aspecto não podem bater papo com você." aspect_list_is_not_visible: "Contatos neste aspecto não podem ver uns aos outros." aspect_list_is_visible: "Contatos neste aspecto podem ver uns aos outros." error_add: "Não foi possÃvel adicionar <%= name %> ao aspecto. :(" @@ -57,11 +109,11 @@ pt-BR: conversation: new: no_contacts: "Você precisa adicionar contatos antes de começar uma conversa." - participants: "Participantes" create: "Criar" delete: "Apagar" edit: "Editar" - failed_to_like: "Falhou ao curtir!" + failed_to_comment: "Falha ao comentar. Será que estão ignorando você?" + failed_to_like: "Falha ao curtir. Será que o autor está ignorando você?" failed_to_post_message: "Falha na publicação da mensagem!" failed_to_remove: "Falha ao remover a entrada!" failed_to_reshare: "Falha ao recompartilhar!" @@ -85,15 +137,14 @@ pt-BR: recent_notifications: "Notificações recentes" search: "Encontrar pessoas ou #tags" settings: "Configurações" + toggle_mobile: "Versão para celular" + toggle_navigation: "Alternar navegação" view_all: "Ver todas" hide_post: "Esconder esta publicação?" hide_post_failed: "Não foi possÃvel esconder esta publicação" ignore: "Ignorar" ignore_failed: "Não foi possÃvel ignorar este usuário" ignore_user: "Ignorar este usuário?" - infinite_scroll: - no_more: "Não há mais publicações." - no_more_contacts: "Sem mais contatos." my_activity: "Minha atividade" my_aspects: "Meus aspectos" my_stream: "Fluxo" @@ -108,7 +159,7 @@ pt-BR: is_sharing: "<%= name %> está compartilhando com você" mention: "Menção" message: "Mensagem" - not_found: "e ninguém foi encontrado..." + not_found: "... e ninguém foi encontrado" stop_ignoring: "Parar de ignorar" photo_uploader: completed: "<%= file %> completo" @@ -118,6 +169,10 @@ pt-BR: looking_good: "OMG, veja você é incrÃvel!" size_error: "{file} é muito grande, o tamanho máximo do arquivo é {sizeLimit}." poll: + answer_count: + one: "Um voto" + other: "<%=count%> votos" + zero: "Nenhum voto" close_result: "Ocultar resultado" count: one: "<%=count%> voto até agora" @@ -134,15 +189,41 @@ pt-BR: contacts: "Contatos" edit: "Editar" gender: "Sexo" - ignoring: "Você está ignorando todas as publicações de <%= name %>." location: "Localização" photos: "Fotos" posts: "Publicações" you_have_no_tags: "Você não tem tags!" publisher: add_option: "Adicionar uma resposta" - at_least_one_aspect: "Você deve publicar em pelo menos um aspecto" limited: "Limitada: a sua publicação será visÃvel apenas para as pessoas com quem você compartilha." + markdown_editor: + preview: "Pré-visualizar" + texts: + code: "código aqui" + heading: "texto do tÃtulo" + insert_image_description_text: "digitar descrição da imagem aqui" + insert_image_help_text: "Inserir link da imagem aqui" + insert_image_title: "digitar tÃtulo da imagem aqui" + insert_link_description_text: "digitar descrição do link aqui" + insert_link_help_text: "Inserir link aqui" + italic: "texto itálico" + list: "texto da lista aqui" + quote: "texto da citação aqui" + strong: "texto negrito" + tooltips: + bold: "Negrito" + cancel: "Cancelar mensagem" + code: "Inserir código" + heading: "TÃtulo" + insert_image: "Inserir imagem" + insert_link: "Inserir link" + insert_ordered_list: "Inserir lista ordenada" + insert_unordered_list: "Inserir lista não ordenada" + italic: "Itálico" + preview: "Pré-visualizar mensagem" + quote: "Inserir citação" + write: "Editar mensagem" + write: "Escrever" near_from: "Publicado de: <%= location %>" option: "Resposta" public: "Pública: a sua publicação será totalmente visÃvel na Web e poderá ser encontrada por meio de mecanismos de buscas" @@ -156,10 +237,9 @@ pt-BR: created: "O relato foi criado com sucesso" exists: "O relato já existe" reshares: - duplicate: "Que bom, hein? Você já recompartilhou essa publicação." + duplicate: "Que bom, hein? Você já recompartilhou essa publicação!" post: "Recompartilhar a publicação de <%= name %>?" successful: "A publicação foi recompartilhada com sucesso!" - search_for: "Procurar por <%= name %>" show_more: "Mostrar mais" stream: comment: "Comentar" @@ -182,8 +262,14 @@ pt-BR: one: "Mostre mais <%= count %> comentário" other: "Mostre mais <%= count %> comentários" zero: "Mostre mais <%= count %> comentário" + no_posts_yet: "Ainda não há publicações para exibir aqui." original_post_deleted: "A publicação original foi apagada pelo autor." + permalink: "Link permanente" public: "Público" + reactions: + one: "Uma reação" + other: "<%= count%> reações" + zero: "Nenhuma reação" reshare: "Recompartilhar" reshares: one: "<%= count %> recompartilhamento" @@ -205,13 +291,22 @@ pt-BR: wasnt_that_interesting: "Ok, eu acho que #<%= tagName %> não era tão interessante..." timeago: day: "um dia" - days: "%d dias" + days: + one: "1 dia" + other: "%d dias" hour: "cerca de uma hora" - hours: "cerca de %d horas" + hours: + one: "cerca de 1 hora" + other: "cerca de %d horas" + inPast: "a qualquer instante" minute: "cerca de um minuto" - minutes: "%d minutos" + minutes: + one: "1 minuto" + other: "%d minutos" month: "cerca de um mês" - months: "%d meses" + months: + one: "1 mês" + other: "%d meses" prefixAgo: "" prefixFromNow: "" seconds: "menos de um minuto" @@ -219,17 +314,9 @@ pt-BR: suffixFromNow: "a partir de agora" wordSeparator: " " year: "cerca de um ano" - years: "%d anos" + years: + one: "1 ano" + other: "%d anos" unblock_failed: "O desbloqueio deste usuário falhou" - videos: - unknown: "Tipo de vÃdeo desconhecido" - watch: "Assista este vÃdeo no <%= provider %>" viewer: - comment: "Comentário" - follow_post: "Seguir publicação" - home: "Página inicial" - like: "Curtir" - reshare: "Recompartilhar" - reshared: "Recompartilhado" - stop_following_post: "Parar de seguir publicação" - unlike: "Descurtir" \ No newline at end of file + reshared: "Recompartilhado" \ No newline at end of file diff --git a/config/locales/javascript/javascript.pt-PT.yml b/config/locales/javascript/javascript.pt-PT.yml index f198cb48d2e2ed168e1b8f36b1965a6bb867f8bb..cf25549dcee0ce4bafb6b999b106ea0d8f395b9d 100644 --- a/config/locales/javascript/javascript.pt-PT.yml +++ b/config/locales/javascript/javascript.pt-PT.yml @@ -29,8 +29,6 @@ pt-PT: hide: "ocultar comentários" show: "mostrar todos os comentários" confirm_dialog: "Tem a certeza?" - conversation: - participants: "Participantes" delete: "Eliminar" edit: "Editar" failed_to_like: "Falhou em gostar!" @@ -55,9 +53,6 @@ pt-PT: view_all: "Ver tudo" ignore: "Ignorar" ignore_user: "Ignorar este utilizador?" - infinite_scroll: - no_more: "Não há mais publicações." - no_more_contacts: "Sem mais contatos." my_activity: "Minha atividade" my_aspects: "Os meus grupos" my_stream: "Fluxo" @@ -70,7 +65,6 @@ pt-PT: looking_good: "OMD, tu estás fantástico(a)!" size_error: "O {file} é muito grande, o tamanho máximo do ficheiro é {sizeLimit}." publisher: - at_least_one_aspect: "Tem de publicar em pelo menos um grupo" limited: "Limitado - a sua publicação só será vista pelas pessoas com as quais está a partilhar" near_from: "Publicado em: <%= location %>" public: "Público - A sua publicação será visÃvel para todos e encontrada por motores de busca" @@ -78,7 +72,6 @@ pt-PT: duplicate: "Que bom, hein? Você já republicou essa mensagem!" post: "Repartilhar a publicação de <%= name %>?" successful: "A publicação foi repartilhada com sucesso!" - search_for: "Procurar por <%= name %>" show_more: "mostrar mais" stream: comment: "Comentar" @@ -124,29 +117,24 @@ pt-PT: wasnt_that_interesting: "OK, suponho que #<%= tagName %> não era assim tão interessante..." timeago: day: "um dia" - days: "%d dias" + days: + other: "%d dias" hour: "cerca de uma hora" - hours: "cerca de %d horas" + hours: + other: "cerca de %d horas" minute: "cerca de um minuto" - minutes: "%d minutos" + minutes: + other: "%d minutos" month: "cerca de um mês" - months: "%d meses" + months: + other: "%d meses" prefixAgo: "" prefixFromNow: "" seconds: "menos de um minuto" suffixAgo: "" suffixFromNow: "a partir de agora" year: "cerca de um ano" - years: "%d anos" - videos: - unknown: "Formato de vÃdeo desconhecido" - watch: "Veja este vÃdeo no <%= provider %>" + years: + other: "%d anos" viewer: - comment: "Comentário" - follow_post: "Seguir a publicação" - home: "INÃCIO" - like: "Gostar" - reshare: "Repartilhar" - reshared: "Repartilhado" - stop_following_post: "Parar de seguir a publicação" - unlike: "Não gostar" \ No newline at end of file + reshared: "Repartilhado" \ No newline at end of file diff --git a/config/locales/javascript/javascript.ro.yml b/config/locales/javascript/javascript.ro.yml index 1b0d4ccd5acc894a878a2f4364f71559f474fc44..5737916c45eb22eb08659a7c835b24eff3fb3f9e 100644 --- a/config/locales/javascript/javascript.ro.yml +++ b/config/locales/javascript/javascript.ro.yml @@ -53,9 +53,6 @@ ro: settings: "Setări" view_all: "Vizualizează-le pe Toate" ignore: "Ignoră" - infinite_scroll: - no_more: "Nu mai sunt posturi." - no_more_contacts: "Niciun contact" my_activity: "Activitatea proprie" my_stream: "Flux" photo_uploader: @@ -65,13 +62,11 @@ ro: profile: posts: "Postări" publisher: - at_least_one_aspect: "Trebuie sa publici pe cel puÅ£in un aspect" limited: "Limitat - publicatia va fi vazuta doar de catre persoanele cu care imparti publicatii" near_from: "Publicat din <%= location %>" public: "Public - articolul tău va fi vizibil tuturor ÅŸi va fi accesibilă prin motoarele de căutare" reshares: duplicate: "E chiar asa de tare, hmm? Ati mai raspandit o data aceasta publicatie!" - search_for: "Caută <%= name %>" show_more: "arată mai mult" stream: comment: "Comentariu" @@ -118,22 +113,22 @@ ro: wasnt_that_interesting: "Bine, presupun ca #<%= tagName %> nu a fost chiar atat de interesant..." timeago: day: "o zi" - days: "%d zile" + days: + other: "%d zile" hour: "o ora" - hours: "%d ore" + hours: + other: "%d ore" minute: "un minut" - minutes: "%d minute" + minutes: + other: "%d minute" month: "o luna" - months: "%d luni" + months: + other: "%d luni" prefixAgo: "acum" prefixFromNow: "in timp de" seconds: "mai putin de un minut" suffixAgo: "în urmă" suffixFromNow: "in urma" year: "un an" - years: "%d ani" - videos: - unknown: "Format de video necunoscut" - watch: "Vizualizează acest video pe <%= provider %>" - viewer: - home: "Pagina de start" \ No newline at end of file + years: + other: "%d ani" \ No newline at end of file diff --git a/config/locales/javascript/javascript.ru.yml b/config/locales/javascript/javascript.ru.yml index 863e5099af70441d8f9235f8a5cfb0e49cf1c75b..2fd45487a53ffd4a7f88eabcfa4f811ea210b8db 100644 --- a/config/locales/javascript/javascript.ru.yml +++ b/config/locales/javascript/javascript.ru.yml @@ -6,6 +6,16 @@ ru: javascripts: + admin: + pods: + states: + no_errors: "Хорошо" + status: "СтатуÑ" + version_failed: + few: "<%= count %> пода не имеют информации о верÑии (Ñтарые поды, нет NodeInfo)" + many: "<%= count %> подов не имеют информации о верÑии (Ñтарые поды, нет NodeInfo)" + one: "<%= count %> под не имеет информации о верÑии (Ñтарые поды, нет NodeInfo)" + other: "<%= count %> подов не имеют информации о верÑии (Ñтарые поды, нет NodeInfo)" and: "и" aspect_dropdown: add_to_aspect: "Добавить контакт" @@ -60,7 +70,6 @@ ru: conversation: new: no_contacts: "Ðужно добавить кого-нибудь в ÑпиÑок контактов, перед тем, как заводить разговор." - participants: "УчаÑтники" create: "Создать" delete: "Удалить" edit: "Изменить" @@ -94,9 +103,6 @@ ru: ignore: "Блокировать" ignore_failed: "Ðевозможно игнорировать Ñтого пользователÑ" ignore_user: "Игнорировать Ñтого пользователÑ?" - infinite_scroll: - no_more: "Больше запиÑей нет." - no_more_contacts: "Контактов больше нет." my_activity: "ÐœÐ¾Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚ÑŒ" my_aspects: "Мои аÑпекты" my_stream: "Поток" @@ -140,15 +146,40 @@ ru: contacts: "Контакты" edit: "Редактировать" gender: "Пол" - ignoring: "Ð’Ñ‹ игнорируете вÑе запиÑи Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ <%= name %>." location: "МеÑтоположение" photos: "Фотографии" posts: "ЗапиÑи" you_have_no_tags: "у Ð²Ð°Ñ Ð½ÐµÑ‚ меток!" publisher: add_option: "Добавить вариант" - at_least_one_aspect: "Вам надо Ñоздать как минимум один аÑпект" limited: "ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð½Ð°Ñ - ваша запиÑÑŒ будет видна только указанным вами людÑм" + markdown_editor: + preview: "ПредпроÑмотр" + texts: + code: "код" + heading: "заголовок" + insert_image_description_text: "введите Ñюда опиÑание изображениÑ" + insert_image_help_text: "Ð’Ñтавьте ÑÑылку на изображение Ñюда" + insert_image_title: "введите Ñюда заголовок изображениÑ" + insert_link_description_text: "введите Ñюда опиÑание ÑÑылки" + insert_link_help_text: "Ð’Ñтавьте ÑÑылку Ñюда" + italic: "текÑÑ‚ курÑивом" + list: "текÑÑ‚ ÑпиÑка" + quote: "текÑÑ‚ цитаты" + strong: "жирный текÑÑ‚" + tooltips: + bold: "Жирный" + cancel: "Отменить Ñообщение" + code: "Ð’Ñтавить код" + heading: "Заголовок" + insert_image: "Ð’Ñтавить изображение" + insert_link: "Ð’Ñтавить ÑÑылку" + insert_ordered_list: "Ð’Ñтавить нумерованный ÑпиÑок" + insert_unordered_list: "Ð’Ñтавить маркированный ÑпиÑок" + italic: "КурÑив" + preview: "ПредпроÑмотр ÑообщениÑ" + quote: "Ð’Ñтавить цитату" + write: "Редактировать Ñообщение" near_from: "Отправлено из: <%= location %>" option: "Вариант <%= nr %>" public: "ÐŸÑƒÐ±Ð»Ð¸Ñ‡Ð½Ð°Ñ - ваша запиÑÑŒ будет видна вÑем, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¿Ð¾Ð¸Ñковые ÑиÑтемы" @@ -165,7 +196,6 @@ ru: duplicate: "Здорово, да? Ð’Ñ‹ уже поделилиÑÑŒ Ñтой запиÑью!" post: "ПоделитьÑÑ Ð·Ð°Ð¿Ð¸Ñью Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ <%= name %>?" successful: "Ð’Ñ‹ уÑпешно поделилиÑÑŒ запиÑью!" - search_for: "ИÑкать <%= name %>" show_more: "показать больше" stream: comment: "Комментировать" @@ -193,6 +223,7 @@ ru: one: "Ещё <%= count %> комментарий" other: "Ещё <%= count %> комментариев" zero: "Ещё <%= count %> комментариев" + no_posts_yet: "ЗдеÑÑŒ пока не видно запиÑей." original_post_deleted: "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ удалена автором." public: "ПубличнаÑ" reshare: "ПоделитьÑÑ" @@ -218,13 +249,17 @@ ru: wasnt_that_interesting: "Что ж, видимо, метка #<%= tagName %> была не такой уж интереÑной..." timeago: day: "день" - days: "%d дней[-Ñ]" + days: + other: "%d дней[-Ñ]" hour: "около чаÑа" - hours: "около %d чаÑов" + hours: + other: "около %d чаÑов" minute: "около минуты" - minutes: "%d минут[-Ñ‹]" + minutes: + other: "%d минут[-Ñ‹]" month: "около меÑÑца" - months: "%d меÑÑца[-ев]" + months: + other: "%d меÑÑца[-ев]" prefixAgo: "" prefixFromNow: "" seconds: "меньше минуты" @@ -232,17 +267,8 @@ ru: suffixFromNow: "Ñ Ñтого момента" wordSeparator: " " year: "около года" - years: "%d лет" + years: + other: "%d лет" unblock_failed: "Разблокировка Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ удалаÑÑŒ" - videos: - unknown: "ÐеизвеÑтный тип видео" - watch: "Смотреть Ñтот ролик на <%= provider %>" viewer: - comment: "Комментировать" - follow_post: "Следить за запиÑью" - home: "ДОМОЙ" - like: "ÐравитÑÑ" - reshare: "ПоделитьÑÑ" - reshared: "ПоделилиÑÑŒ" - stop_following_post: "Ðе Ñледить за запиÑью" - unlike: "Ðе нравитÑÑ" \ No newline at end of file + reshared: "ПоделилиÑÑŒ" \ No newline at end of file diff --git a/config/locales/javascript/javascript.si.yml b/config/locales/javascript/javascript.si.yml index 37f357a1b42843367cddb73806a8260e979dfb0d..2cb67c795130faf256ed50a13eea13d4e29490dc 100644 --- a/config/locales/javascript/javascript.si.yml +++ b/config/locales/javascript/javascript.si.yml @@ -25,7 +25,6 @@ si: my_activity: "මගේ ක්â€à¶»à·’යà·à·€" photo_uploader: looking_good: "මà·à¶»à¶ºà·’, ඔය෠නියමයි!" - search_for: "<%= name %> සදහ෠සොය෠බලන්න" show_more: "à¶à·€à¶à·Š පෙන්නන්න" stream: hide: "සගවන්න" @@ -45,24 +44,22 @@ si: unlike: "අකà·à¶¸à¶à·’යි" timeago: day: "දවසක්" - days: "දවස් %d" + days: + other: "දවස් %d" hour: "පà·à¶ºà¶šà·’න් පමණ" - hours: "පà·à¶º %d පමණ" + hours: + other: "පà·à¶º %d පමණ" minute: "විනà·à¶©à·’යකින් පමණ" - minutes: "විනà·à¶©à·’ %d" + minutes: + other: "විනà·à¶©à·’ %d" month: "මà·à·ƒà¶ºà¶šà·’න් පමණ" - months: "මà·à·ƒ %d" + months: + other: "මà·à·ƒ %d" prefixAgo: "" prefixFromNow: "" seconds: "විනà·à¶©à·’යකට අඩු කà·à¶½à¶ºà¶šà·’න්" suffixAgo: "පෙර" suffixFromNow: "මෙà¶à·à¶±à·Š සිට" year: "අවුරුද්දකින් පමණ" - years: "අවුරුදු %d" - videos: - unknown: "දන්නේ නà·à¶à·’ විඩිය෠type එකක්" - watch: "මෙම විඩිය෠එක <%= provider %> එකෙන් බලන්න" - viewer: - home: "නිවස" - like: "කà·à¶¸à¶à·’යි" - unlike: "අකà·à¶¸à¶à·’යි" \ No newline at end of file + years: + other: "අවුරුදු %d" \ No newline at end of file diff --git a/config/locales/javascript/javascript.sk.yml b/config/locales/javascript/javascript.sk.yml index df8c71c898a030bee3b4453e9f500c9a554ad26e..1bf7feea83fc35a17cfa8c30d40ea8bed38158a1 100644 --- a/config/locales/javascript/javascript.sk.yml +++ b/config/locales/javascript/javascript.sk.yml @@ -35,8 +35,6 @@ sk: no_comments: "EÅ¡te tu nie sú žiadne prÃspevky." show: "ZobraziÅ¥ vÅ¡etky komentáre" confirm_dialog: "UrÄite?" - conversation: - participants: "ÚÄastnÃci" delete: "OdstrániÅ¥" edit: "UpraviÅ¥" failed_to_like: "Nepodarilo sa oznaÄiÅ¥, že sa ti to páÄi!" @@ -63,9 +61,6 @@ sk: view_all: "ZobraziÅ¥ vÅ¡etko" ignore: "IgnorovaÅ¥" ignore_user: "IgnorovaÅ¥ tohto použÃvateľa?" - infinite_scroll: - no_more: "Žiadne ÄalÅ¡ie prÃspevky." - no_more_contacts: "Žiadne ÄalÅ¡ie kontakty." my_activity: "Moja aktivita" my_aspects: "Moje kategórie" my_stream: "Nástenka" @@ -91,7 +86,6 @@ sk: vote: "HlasovaÅ¥" publisher: add_option: "PridaÅ¥ možnosÅ¥" - at_least_one_aspect: "MusÃÅ¡ publikovaÅ¥ aspoň jednu kategóriu" limited: "Vyhradený – tvoj prÃspevok uvidia len ľudia, s ktorými sa oň podelÃÅ¡" near_from: "Odoslané z obce:<%= location %>" option: "MožnosÅ¥ <%= nr %>" @@ -108,7 +102,6 @@ sk: duplicate: "Je to dobré, Äo? O tento prÃspevok si sa už raz znova podelil(a)!" post: "Znova ukázaÅ¥ priateľom prÃspevok, ktorý napÃsal(a) <%= name %>?" successful: "Tento prÃspevok si úspeÅ¡ne znova ukázal(a) priateľom!" - search_for: "HľadaÅ¥ <%= name %>" show_more: "ZobraziÅ¥ viac" stream: comment: "OkomentovaÅ¥" @@ -153,29 +146,24 @@ sk: wasnt_that_interesting: "OK, znaÄka #<%= tagName %> asi vôbec nebola zaujÃmavá." timeago: day: "vÄera" - days: "pred %d dňami" + days: + other: "pred %d dňami" hour: "asi pred hodinou" - hours: "asi pred %d hodinami" + hours: + other: "asi pred %d hodinami" minute: "asi pred minútou" - minutes: "pred %d minútami" + minutes: + other: "pred %d minútami" month: "asi pred mesiacom" - months: "pred %d mesiacmi" + months: + other: "pred %d mesiacmi" prefixAgo: "" prefixFromNow: "" seconds: "pred menej ako minútou" suffixAgo: "" suffixFromNow: "" year: "asi pred rokom" - years: "pred %d rokmi" - videos: - unknown: "Neznámy typ videa" - watch: "Sleduj toto video na <%= provider %>" + years: + other: "pred %d rokmi" viewer: - comment: "Komentár" - follow_post: "SledovaÅ¥ prÃspevok" - home: "ÚVODNà STRÃNKA" - like: "PáÄi sa mi to" - reshare: "UkázaÅ¥ prÃspevok priateľom" - reshared: "Znova ukázané" - stop_following_post: "PrestaÅ¥ sledovaÅ¥ prÃspevok" - unlike: "Už sa mi to nepáÄi" \ No newline at end of file + reshared: "Znova ukázané" \ No newline at end of file diff --git a/config/locales/javascript/javascript.sl.yml b/config/locales/javascript/javascript.sl.yml index e80607852db2f8fd501e9480a585b19dd40a85fe..00e7831565b94ef4856aa6a0f851f953acea799f 100644 --- a/config/locales/javascript/javascript.sl.yml +++ b/config/locales/javascript/javascript.sl.yml @@ -49,8 +49,6 @@ sl: settings: "Nastavitve" view_all: "Prikaži vse" ignore: "Ne meni se" - infinite_scroll: - no_more: "Konec objav." my_activity: "Moja dejavnost" my_stream: "Tok" people: @@ -58,14 +56,12 @@ sl: photo_uploader: looking_good: "OMG, izgledaÅ¡ super!" publisher: - at_least_one_aspect: "Objaviti morate v vsaj en vidik" limited: "Omejeno - VaÅ¡a objava bo vidna le ljudem, s katerimi delite" public: "Javno - VaÅ¡a objava bo vidna vsem, prikazana bo tudi v spletnih iskalnikih" reshares: duplicate: "To objavo ste že ponovno delili" post: "Ponovno deli objavo osebe <%= name %>?" successful: "Objavo ste uspeÅ¡no ponovno delili!" - search_for: "IÅ¡Äi <%= name %>" show_more: "pokaži veÄ" stream: comment: "Mnenje" @@ -103,29 +99,24 @@ sl: wasnt_that_interesting: "V redu, mislim, da zaznamek #<%= tagName %> ni bil tako zanimiv ..." timeago: day: "vÄeraj" - days: "pred %d dnem" + days: + other: "pred %d dnem" hour: "pred približno uro" - hours: "pred približno %d urami" + hours: + other: "pred približno %d urami" minute: "pred približno minuto" - minutes: "pred %d minutami" + minutes: + other: "pred %d minutami" month: "pred približno mesecem" - months: "pred %d meseci" + months: + other: "pred %d meseci" prefixAgo: "" prefixFromNow: "" seconds: "pred manj kot minuto" suffixAgo: "nazaj" suffixFromNow: "od zdaj" year: "pred približno letom dni" - years: "pred %d leti" - videos: - unknown: "Neznan tip videa" - watch: "Glej ta video na <%= provider %>" + years: + other: "pred %d leti" viewer: - comment: "Mnenje" - follow_post: "Sledi objavi" - home: "DOMOV" - like: "VÅ¡eÄ mi je" - reshare: "Ponovno deli" - reshared: "Ponovno deljeno" - stop_following_post: "Ne sledi veÄ objavi" - unlike: "Ni mi vÅ¡eÄ" \ No newline at end of file + reshared: "Ponovno deljeno" \ No newline at end of file diff --git a/config/locales/javascript/javascript.sr.yml b/config/locales/javascript/javascript.sr.yml index c07eca062bc5e0e44f1f84f19f041eb5a6a8cec4..d4ff3fb71cba21561df7e6cd04957478d80f1fc5 100644 --- a/config/locales/javascript/javascript.sr.yml +++ b/config/locales/javascript/javascript.sr.yml @@ -48,19 +48,15 @@ sr: settings: "Подешавања" view_all: "Погледај Ñве" ignore: "Игнориши" - infinite_scroll: - no_more: "Ðема више објава." my_activity: "Моје активноÑти" my_stream: "ВеÑти" photo_uploader: looking_good: "Човече, изгледаш одлично!" publisher: - at_least_one_aspect: "Мораш објавити бар једном погледу" limited: "Ограничено - твоју објаву ће видети Ñамо људи Ñа којима је делиш" public: "Јавно - твоју објаву ће видети Ñви и биће је могуће тражити путем претраживача" reshares: duplicate: "Добро је, а? Већ Ñте објавили ово!" - search_for: "Тражи <%= name %>" show_more: "прикажи још" stream: comment: "Коментариши" @@ -98,20 +94,22 @@ sr: wasnt_that_interesting: "Добро, изгледа да те #<%= tagName %> не занима толико..." timeago: day: "један дан" - days: "%d дана" + days: + other: "%d дана" hour: "око један чаÑ" - hours: "око %d чаÑова" + hours: + other: "око %d чаÑова" minute: "око минут" - minutes: "%d минута" + minutes: + other: "%d минута" month: "око један меÑец" - months: "%d меÑеци" + months: + other: "%d меÑеци" prefixAgo: "Пре" prefixFromNow: "" seconds: "мање од минута" suffixAgo: "" suffixFromNow: "од овог тренутка" year: "око једну годину" - years: "%d година" - videos: - unknown: "Ðепозната врÑта видеа" - watch: "Погледај овај видео на" \ No newline at end of file + years: + other: "%d година" \ No newline at end of file diff --git a/config/locales/javascript/javascript.sv.yml b/config/locales/javascript/javascript.sv.yml index f1f1493e3ff31200bc2d3eb1f8d99744ff0f22bc..47aa80569e49d8a74cc5387e2790502d871c3f4e 100644 --- a/config/locales/javascript/javascript.sv.yml +++ b/config/locales/javascript/javascript.sv.yml @@ -6,6 +6,56 @@ sv: javascripts: + admin: + pods: + actions: "Handlingar" + added: "Tillagd" + check: "utför anslutningstest" + errors: + one: "Anslutningstestet misslyckades för en pod." + other: "Anslutningstestet misslyckades för <%= count %> poddar." + follow_link: "öppna länk i webbläsare" + last_check: "senaste besiktningen:" + more_info: "visa mer information" + ms: + one: "<%= count %> ms" + other: "<%= count %> ms" + no_info: "Ingen ytterligare information finns tillgänglig nu." + not_available: "ej tillgänglig" + offline_since: "nedkopplad sedan:" + pod: "Pod" + recheck: + failure: "NÃ¥gon besiktning utfördes icke." + success: "Podden besiktigades just igen." + response_time: "Svarstid:" + server_software: "Servermjukvara:" + ssl: "SSL" + ssl_disabled: "SSL är inte i stÃ¥nd" + ssl_enabled: "SSL är i stÃ¥nd" + states: + dns_failed: "DNS-namnupplösningen misslyckades." + http_failed: "Förbindelseupprättelse med HTTP misslyckades." + net_failed: "Förbindelseupprättelsen misslyckades." + no_errors: "I sin ordning" + ssl_failed: "SSL-förbindelseupprättelse misslyckades" + unchecked: "Okontrollerad" + unknown_error: "Ett oförutsett fel uppstod under besiktningen." + version_failed: "Oförmögen att hämta mjukvaruversion." + status: "TillstÃ¥nd" + unchecked: + one: "En pod kvar att besiktiga." + other: "<%= count %> poddar kvar att besiktiga." + unknown: "okänd" + version_failed: + one: "Det finns en pod utan version (gammal pod, ingen NodeInfo)." + other: "Det finns <%= count %> poddar utan version (gamla poddar, ingen NodeInfo)." + zero: "Det finns inga poddar utan version." + admins: + dashboard: + compare_versions: "Senaste utgÃ¥van av Diaspora* är <%= latestVersion %> och din pod är av <%= podVersion %>." + error: "Oförmögen att bestämma vilken version av Diaspora* som är den senaste." + outdated: "Din pod Ã¥r förÃ¥ldrad." + up_to_date: "Din pod är av senaste utgÃ¥va." and: "och" aspect_dropdown: add_to_aspect: "Lägg till kontakt" @@ -51,6 +101,8 @@ sv: confirm_unload: "Bekräfta att du vill gÃ¥ frÃ¥n sidan. Du har osparad information här." contacts: add_contact: "Lägg till kontakt" + aspect_chat_is_enabled: "Kontakter i den här aspekten fÃ¥r chatta med dig" + aspect_chat_is_not_enabled: "Kontakter i den här aspekten fÃ¥r inte chatta med dig" aspect_list_is_not_visible: "Aspektens kontakter kan inte se vilka andra som tillhör aspekten." aspect_list_is_visible: "Aspektens kontakter kan se varandra." error_add: "Kunde inte lägga till <%= name %> till aspekten. :-(" @@ -60,11 +112,11 @@ sv: conversation: new: no_contacts: "Du behöver nÃ¥gra kontakter innan du kan pÃ¥börja konversationer." - participants: "Deltagare" create: "Skapa" delete: "Radera" edit: "Ändra" - failed_to_like: "Misslyckades att gilla." + failed_to_comment: "Lyckades inte kommentera. Författaren kanske ignorerar dig." + failed_to_like: "Misslyckades att gilla. Kanske är du inte önskvärd av författaren." failed_to_post_message: "Misslyckades att posta meddelande!" failed_to_remove: "Misslyckades med att borttaga inlägget!" failed_to_reshare: "Kunde inte dela vidare!" @@ -88,15 +140,14 @@ sv: recent_notifications: "Tidigare notiser" search: "Sök" settings: "Inställningar" + toggle_mobile: "Växla mobiltelefonanpassning" + toggle_navigation: "Växla navigation" view_all: "Visa alla" hide_post: "Vill du dölja inlägget?" hide_post_failed: "Misslyckades med att dölja inlägget" ignore: "Ignorera" ignore_failed: "Lyckades inte ignorera denna användare" ignore_user: "Vill du ignorera den här användaren?" - infinite_scroll: - no_more: "Inga fler inlägg." - no_more_contacts: "Inga fler kontakter." my_activity: "Min aktivitet" my_aspects: "Mina aspekter" my_stream: "Ström" @@ -121,6 +172,10 @@ sv: looking_good: "OMG, du ser grym ut!" size_error: "{file} är för stor, den största tillÃ¥tna filstorleken är {sizeLimit}." poll: + answer_count: + one: "En röst" + other: "<%=count%> röster" + zero: "Inga röster" close_result: "Göm resultat" count: one: "<%=count%> röst lagd" @@ -137,14 +192,12 @@ sv: contacts: "Kontakter" edit: "Ändra" gender: "Kön" - ignoring: "Du ignorerar alla inlägg frÃ¥n <%= name %>." location: "Plats" photos: "Foton" posts: "Inlägg" you_have_no_tags: "Du har inga taggar!" publisher: add_option: "Lägg till alternativ" - at_least_one_aspect: "Du mÃ¥ste publicera till minst en aspekt." limited: "Begränsat: ditt inlägg visas endast för personer som du delar med" near_from: "Sänt frÃ¥n: <%= location %>" option: "Alternativ" @@ -162,7 +215,6 @@ sv: duplicate: "Du gillar detta va? Du har nämligen redan delat vidare detta inlägg!" post: "Vill du dela vidare inlägget av <%= name %>?" successful: "Lyckades med att dela vidare inlägget." - search_for: "Sök efter <%= name %>" show_more: "Visa mer" stream: comment: "Kommentera" @@ -186,7 +238,12 @@ sv: other: "Visa <%= count %> kommentarer till" zero: "Visa inga fler kommentarer" original_post_deleted: "Det ursprungliga inlägget har blivit borttaget av författaren." + permalink: "Permanent länk" public: "Publik" + reactions: + one: "<%= count%> reaktion" + other: "<%= count%> reaktioner" + zero: "<%= count%> reaktioner" reshare: "Dela vidare" reshares: one: "En delar vidare" @@ -208,13 +265,18 @@ sv: wasnt_that_interesting: "Ok, jag antar att #<%= tagName %> inte var sÃ¥ intressant..." timeago: day: "en dag" - days: "%d dagar" + days: + other: "%d dagar" hour: "ungefär en timme" - hours: "ungefär %d timmar" + hours: + other: "ungefär %d timmar" + inPast: "när som helst nu" minute: "ungefär en minut" - minutes: "%d minuter" + minutes: + other: "%d minuter" month: "ungefär en mÃ¥nad" - months: "%d mÃ¥nader" + months: + other: "%d mÃ¥nader" prefixAgo: "för" prefixFromNow: "om" seconds: "mindre än en minut" @@ -222,17 +284,8 @@ sv: suffixFromNow: "frÃ¥n nu" wordSeparator: " " year: "ungefär ett Ã¥r" - years: "%d Ã¥r" + years: + other: "%d Ã¥r" unblock_failed: "Misslyckades med att häva blockeringen" - videos: - unknown: "Okänd videotyp" - watch: "Se den här videon pÃ¥ <%= provider %>" viewer: - comment: "Kommentera" - follow_post: "Följ inlägg" - home: "Hem" - like: "Gilla" - reshare: "Dela vidare" - reshared: "Ã…terdelad" - stop_following_post: "Sluta att följa inlägg" - unlike: "Sluta gilla" \ No newline at end of file + reshared: "Ã…terdelad" \ No newline at end of file diff --git a/config/locales/javascript/javascript.te.yml b/config/locales/javascript/javascript.te.yml index 9e803cd3a33df72dc2d87e22a91300799035a11c..5c38cdfce21efbaf78e97f2c6de0702162b6276d 100644 --- a/config/locales/javascript/javascript.te.yml +++ b/config/locales/javascript/javascript.te.yml @@ -47,8 +47,6 @@ te: add_contact: "పరిచయానà±à°¨à°¿ జతచేయి" remove_contact: "పరిచయానà±à°¨à°¿ తీసివేయి" search_no_results: "ఠపరిచయాలౠకనపడలేదà±" - conversation: - participants: "పాలà±à°—ొనà±à°µà°¾à°°à±" create: "సృషà±à°Ÿà°¿à°‚à°šà±" delete: "తొలగించà±" edit: "సవరించà±" @@ -79,9 +77,6 @@ te: hide_post_failed: "à°ˆ టపానౠదాయలేకపోయాం" ignore: "విసà±à°®à°°à°¿à°‚à°šà±" ignore_user: "à°ˆ వాడà±à°•à°°à°¿à°¨à°¿ విసà±à°®à°°à°¿à°‚చాలా?" - infinite_scroll: - no_more: "ఇంక టపాలౠలేవà±." - no_more_contacts: "ఇంకే పరిచయాలౠలేవà±." my_activity: "నా à°•à±à°°à°¿à°¯à°¾à°¶à±€à°²à°¤" my_aspects: "నా కోణాలà±" my_stream: "à°ªà±à°°à°µà°¾à°¹à°‚" @@ -122,7 +117,6 @@ te: you_have_no_tags: "మీరౠఠకొసలౠజతచేయలేదà±!" publisher: add_option: "à°’à°• సమాధానానà±à°¨à°¿ జతచేయి" - at_least_one_aspect: "మీరౠకనీసం à°’à°•à±à°• కోణానికైనా à°ªà±à°°à°šà±à°°à°¿à°‚చాలి" limited: "పరిమితం: మీరౠఎవరితోనైతే పంచà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à±‹ వారౠమాతà±à°°à°®à±‡ మీ టపానౠచూడగలరà±" near_from: "ఇకà±à°•à°¡à°¿ à°¨à±à°‚à°¡à°¿ టపా వేసారà±: <%= location %>" option: "సమాధానం" @@ -138,7 +132,6 @@ te: exists: "à°«à°¿à°°à±à°¯à°¾à°¦à± ఇదివరకే ఉంది" reshares: duplicate: "à°…à°‚à°¤ బాగà±à°‚దా? à°† టపాని మీరౠఇపà±à°ªà°Ÿà°¿à°•à±‡ పంచà±à°•à±à°¨à±à°¨à°¾à°°à±!" - search_for: "<%= name %> కోసం వెతకండి" show_more: "ఇంకా చూపించà±" stream: comment: "à°µà±à°¯à°¾à°–à±à°¯" @@ -175,25 +168,22 @@ te: wasnt_that_interesting: "సరే, #<%= tagName %> మొతà±à°¤à°‚ à°…à°‚à°¤ ఆసకà±à°¤à°¿à°•à°°à°‚à°—à°¾ లేదని నేనౠఅనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°¨à±..." timeago: day: "à°’à°• రోజà±" - days: "%d రోజà±à°²" + days: + other: "%d రోజà±à°²" hour: "దాదాపౠగంట" - hours: "దాదాపౠ%d à°—à°‚à°Ÿà°²" + hours: + other: "దాదాపౠ%d à°—à°‚à°Ÿà°²" minute: "దాదాపౠనిమిషం" - minutes: "%d నిమిషాల" + minutes: + other: "%d నిమిషాల" month: "దాదాపౠనెల" - months: "%d నెలల" + months: + other: "%d నెలల" prefixAgo: " " prefixFromNow: "" seconds: "కొనà±à°¨à°¿ à°•à±à°·à°£à°¾à°²" suffixAgo: "à°•à±à°°à°¿à°¤à°‚" suffixFromNow: "ఇపà±à°ªà°Ÿà°¿ à°¨à±à°‚à°¡à°¿" year: "దాదాపౠసంవతà±à°¸à°°à°‚" - years: "%d సంవతà±à°¸à°°à°¾à°²" - videos: - unknown: "తెలియని వీడియో à°°à°•à°‚" - watch: "à°ˆ వీడియోనౠ<%= provider %>లో చూడండి" - viewer: - comment: "à°µà±à°¯à°¾à°–à±à°¯" - home: "నివాసం" - like: "ఇషà±à°Ÿà°‚" - unlike: "అయిషà±à°Ÿà°‚" \ No newline at end of file + years: + other: "%d సంవతà±à°¸à°°à°¾à°²" \ No newline at end of file diff --git a/config/locales/javascript/javascript.tr.yml b/config/locales/javascript/javascript.tr.yml index 3f929a5ff94b25e03be5a92587591010853ae091..a0756bd6889729a6512064cc65f9d524a629236f 100644 --- a/config/locales/javascript/javascript.tr.yml +++ b/config/locales/javascript/javascript.tr.yml @@ -47,8 +47,6 @@ tr: view_all: "Tümünü gör" ignore: "Yoksay" ignore_failed: "Bu kullanıcı ihmal edilemiyor" - infinite_scroll: - no_more: "Daha fazla gönderi yok." my_activity: "Etkinliklerim" my_stream: "Akış" people: @@ -56,14 +54,40 @@ tr: photo_uploader: looking_good: "OMG, harika görünüyorsun!" publisher: - at_least_one_aspect: "En az bir yönünün yayınlanması zorunludur" limited: "Sınırlı - gönderi sadece paylaşılan kiÅŸiler tarafından görünür" + markdown_editor: + preview: "Önizle" + texts: + code: "buraya kodu" + heading: "baÅŸlığı metni" + insert_image_description_text: "buraya imaj açıklama girin" + insert_image_help_text: "buraya imaj baÄŸlantısını sokun" + insert_image_title: "buraya imaj baÅŸlığı girin" + insert_link_description_text: "Burada link açıklama girin" + insert_link_help_text: "buraya linki sokun" + italic: "eÄŸik metin" + list: "buraya listesinde metni" + quote: "buraya alıntı metni" + strong: "gçlü metin" + tooltips: + bold: "Kalın" + cancel: "iletiyi iptal" + code: "kesici uç kodu" + heading: "baÅŸlığı" + insert_image: "Resim ekle" + insert_link: "BaÄŸlantı ekle" + insert_ordered_list: "Ekle sıralı listesi" + insert_unordered_list: "Sırasız liste ekleme" + italic: "EÄŸik" + preview: "Önizleme mesajı" + quote: "Ekle tırnak" + write: "düzenle mesajı" + write: "yazma" public: "Genel - gönderi herkes tarafından görünür ve arama motorları tarafından bulunur olacak" reshares: duplicate: "Bu iyi, deÄŸil mi? Zaten bu gönderiyi tekrar paylaÅŸtın!" post: "<%= name %> kiÅŸisinin gönderisini yeniden paylaÅŸamak istiyor musun?" successful: "Gönderi baÅŸarıyla yeniden paylaşıldı!" - search_for: "<%= name %> Ara" show_more: "daha fazlasını göster" stream: comment: "Yorum" @@ -78,6 +102,7 @@ tr: more_comments: other: "DiÄŸer <%= count %> yorumu gör" zero: "DiÄŸer <%= count %> yorumu gör" + no_posts_yet: "burada henüz görüntülemek hiç mesaj yok." original_post_deleted: "Ä°leti yazarı tarafından silindi." public: "Genel" reshare: "Yeniden paylaÅŸ" @@ -92,29 +117,24 @@ tr: wasnt_that_interesting: "Tamam, benim #<%= tagName %> o kadar da ilginç deÄŸil..." timeago: day: "1 gün" - days: "%d gün" + days: + other: "%d gün" hour: "yaklaşık 1 saat" - hours: "yaklaşık %d saat" + hours: + other: "yaklaşık %d saat" minute: "yaklaşık 1 dakika" - minutes: "%d dakika" + minutes: + other: "%d dakika" month: "yaklaşık 1 ay" - months: "%d ay" + months: + other: "%d ay" prefixAgo: "önce" prefixFromNow: "önce" seconds: "1 dakikadan az" suffixAgo: "önce" suffixFromNow: "ÅŸimdi" year: "yaklaşık 1 yıl" - years: "%d yıl" - videos: - unknown: "Bilinmeyen video tipi" - watch: "Bu videoyu <%= provider %>'da izle" + years: + other: "%d yıl" viewer: - comment: "Yorum" - follow_post: "Ä°letiyi izle" - home: "ANA SAYFA" - like: "BeÄŸen" - reshare: "Yeniden paylaÅŸ" - reshared: "Yeniden paylaÅŸtı" - stop_following_post: "Ä°letiyi izlemeyi durdur" - unlike: "BeÄŸenme" \ No newline at end of file + reshared: "Yeniden paylaÅŸtı" \ No newline at end of file diff --git a/config/locales/javascript/javascript.uk.yml b/config/locales/javascript/javascript.uk.yml index 44e344d12366694c8f4d539575aedccb0ecb566a..93ddca011dbf230791ac4d5c94137936b019427c 100644 --- a/config/locales/javascript/javascript.uk.yml +++ b/config/locales/javascript/javascript.uk.yml @@ -51,7 +51,6 @@ uk: conversation: new: no_contacts: "Перш ніж розпочати розмову, треба мати хоча б один контакт." - participants: "УчаÑники" delete: "Вилучити" edit: "Змінити" failed_to_like: "Ðе вдалоÑÑ!" @@ -83,9 +82,6 @@ uk: ignore: "Iгнорувати" ignore_failed: "Ðеможливо ігнорувати цього кориÑтувача" ignore_user: "Ігнорувати цього кориÑтувача?" - infinite_scroll: - no_more: "Повідомлень більше немає." - no_more_contacts: "Контактів більше немає." my_activity: "ÐœÐ¾Ñ Ð´Ñ–ÑльніÑÑ‚ÑŒ" my_aspects: "Мої аÑпекти" my_stream: "Мій потік" @@ -127,14 +123,12 @@ uk: contacts: "Контакти" edit: "редагувати" gender: "Стать" - ignoring: "Ви блокуєте уÑÑ– запиÑи кориÑтувача <%= name %>." location: "ÐдреÑа" photos: "Фотогорафії" posts: "ЗапиÑи" you_have_no_tags: "у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” міток!" publisher: add_option: "Додати відповідь" - at_least_one_aspect: "Вам потрібно Ñтворити мінімум один аÑпект" limited: "Обмежена - ваш Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ´Ðµ видимий тільки вказаним вами людÑм" near_from: "Відправлено з: <%= location %>" option: "Відповідь" @@ -152,7 +146,6 @@ uk: duplicate: "ÐаÑтільки круто, так? Ви вже поділилиÑÑ Ñ†Ð¸Ð¼ запиÑом!" post: "Поширити Ð´Ð¾Ð¿Ð¸Ñ <%= name %>?" successful: "Ви уÑпішно поділилиÑÑ Ð·Ð°Ð¿Ð¸Ñом!" - search_for: "Шукати <%= name %>" show_more: "показати більше" stream: comment: "Коментувати" @@ -199,30 +192,25 @@ uk: wasnt_that_interesting: "Гаразд, мабуть, Ñтежити за міткою #<%= tagName %> було не так вже цікаво..." timeago: day: "день" - days: "%d днів[-Ñ]" + days: + other: "%d днів[-i]" hour: "близько години" - hours: "близько %d годин" + hours: + other: "близько %d годин" minute: "близько хвилини" - minutes: "%d хвилин[-и]" + minutes: + other: "%d хвилин[-и]" month: "близько міÑÑцÑ" - months: "%d міÑÑцÑ[-ів]" + months: + other: "%d міÑÑцÑ[-ів]" prefixAgo: "" prefixFromNow: "через" seconds: "декілька Ñекунд" suffixAgo: "тому" suffixFromNow: "з цієї миті" year: "близько року" - years: "%d років" + years: + other: "%d років" unblock_failed: "Ðе вдалоÑÑŒ розблокувати цього кориÑтувача" - videos: - unknown: "Ðевідомий відеоформат" - watch: "ДивитиÑÑ Ñ†Ðµ відео на <%= provider %>" viewer: - comment: "Коментувати" - follow_post: "Слідкувати за запиÑом" - home: "Домівка" - like: "ПодобаєтьÑÑ" - reshare: "ПоділитиÑÑ" - reshared: "ПоділилиÑÑ" - stop_following_post: "Ðе Ñлідкувати за запиÑом" - unlike: "Ðе подобаєтьÑÑ" \ No newline at end of file + reshared: "ПоділилиÑÑ" \ No newline at end of file diff --git a/config/locales/javascript/javascript.vi.yml b/config/locales/javascript/javascript.vi.yml index b9e5e3044ae7515e54dddc425254312923063946..3ce23e0619a7824eb7457fed6433339015e6b874 100644 --- a/config/locales/javascript/javascript.vi.yml +++ b/config/locales/javascript/javascript.vi.yml @@ -28,8 +28,6 @@ vi: hide: "ẩn các bình luáºn" show: "hiện tất cả bình luáºn" confirm_dialog: "Bạn có chắc không?" - conversation: - participants: "NgÆ°á»i tham gia" delete: "Xoá" edit: "Chỉnh sá»a" failed_to_like: "Không thÃch được!" @@ -54,9 +52,6 @@ vi: view_all: "Xem tất cả" ignore: "Bá» qua" ignore_user: "Bá» qua ngÆ°á»i nà y?" - infinite_scroll: - no_more: "Không còn bà i đăng nà o nữa." - no_more_contacts: "Không có liên lạc." my_activity: "Hoạt Ä‘á»™ng của tôi" my_aspects: "Các mối quan hệ của tôi" my_stream: "Luồng" @@ -69,7 +64,6 @@ vi: looking_good: "Ôi, trông bạn tháºt tuyệt!" size_error: "Táºp tin {file} quá lá»›n, dung lượng tối Ä‘a là {sizeLimit}." publisher: - at_least_one_aspect: "Bạn phải công khai Ãt nhất má»™t mối quan hệ" limited: "Giá»›i hạn - bà i đăng của bạn được những ngÆ°á»i chỉ định nhìn thấy" near_from: "Gá»i từ: <%= location %>" public: "Công khai - baÌ€i đăng của bạn được má»i ngÆ°á»i và máy tìm kiếm nhìn thấy" @@ -77,7 +71,6 @@ vi: duplicate: "Bạn đã chia sẻ lại tin đó!" post: "Chia sẻ lại bà i đăng của <%= name %>?" successful: "Äã chia sẻ lại bà i đăng!" - search_for: "Tìm <%= name %>" show_more: "hiện thêm" stream: comment: "Bình luáºn" @@ -113,28 +106,24 @@ vi: wasnt_that_interesting: "Tôi cho rằng #<%= tagName %> không thú vị..." timeago: day: "má»™t ngà y" - days: "%d ngà y" + days: + other: "%d ngà y" hour: "khoảng má»™t giá»" - hours: "khoảng %d giá»" + hours: + other: "khoảng %d giá»" minute: "khoảng má»™t phút" - minutes: "%d phút" + minutes: + other: "%d phút" month: "khoảng má»™t tháng" - months: "%d tháng" + months: + other: "%d tháng" prefixAgo: "" prefixFromNow: "" seconds: "Ãt hÆ¡n má»™t phút" suffixAgo: "trÆ°á»›c" suffixFromNow: "kể từ đây" year: "khoảng má»™t năm" - years: "%d năm" - videos: - unknown: "ChÆ°a biết kiểu video" - watch: "Xem video nà y trên <%= provider %>" + years: + other: "%d năm" viewer: - comment: "Bình luáºn" - follow_post: "Theo dõi bà i đăng" - like: "ThÃch" - reshare: "Chia sẻ lại" - reshared: "Äã chia sẻ lại" - stop_following_post: "Dừng theo dõi bà i đăng" - unlike: "Bá» thÃch" \ No newline at end of file + reshared: "Äã chia sẻ lại" \ No newline at end of file diff --git a/config/locales/javascript/javascript.wo.yml b/config/locales/javascript/javascript.wo.yml index 471589be1ef0d63d1a6fb9081c54a75d30457cbf..10a02a1236ada1acf24d4d2b05a080ca0940f255 100644 --- a/config/locales/javascript/javascript.wo.yml +++ b/config/locales/javascript/javascript.wo.yml @@ -40,14 +40,13 @@ wo: unlike: "Du bëgg" timeago: day: "bés" - days: "%di bés" - months: "%di weer" + days: + other: "%di bés" + months: + other: "%di weer" prefixAgo: "" prefixFromNow: "" suffixAgo: "" suffixFromNow: "" - years: "%di at" - viewer: - home: "KËR GI" - like: "Bëgg" - unlike: "Du bëgg" \ No newline at end of file + years: + other: "%di at" \ No newline at end of file diff --git a/config/locales/javascript/javascript.zh-CN.yml b/config/locales/javascript/javascript.zh-CN.yml index ea944015bbfb937c44f7e2ce07e57ec0d12ac40d..46bca1ae5269a6a4900feb2465f4242ec252991a 100644 --- a/config/locales/javascript/javascript.zh-CN.yml +++ b/config/locales/javascript/javascript.zh-CN.yml @@ -47,8 +47,6 @@ zh-CN: view_all: "查看所有" ignore: "忽略" ignore_user: "忽略æ¤ç”¨æˆ·ï¼Ÿ" - infinite_scroll: - no_more: "æš‚æ— æ›´å¤šçš„å†…å®¹ã€‚" my_activity: "我的活动" my_stream: "动æ€" people: @@ -56,14 +54,12 @@ zh-CN: photo_uploader: looking_good: "天啊,您太棒了ï¼" publisher: - at_least_one_aspect: "å‘布时请选择至少一个情景" limited: "é™åˆ¶ - åªæœ‰æ‚¨æƒ³åˆ†äº«çš„人æ‰çœ‹å¾—到您的内容" public: "公开 - 所有人都能看到您的内容,包括æœç´¢å¼•æ“Ž" reshares: duplicate: "您已ç»è½¬å‘过了。" post: "è¦è½¬å‘ <%= name %> 的内容å—?" successful: "转å‘æˆåŠŸ" - search_for: "æœç´¢ <%= name %>" show_more: "查看更多" stream: comment: "评论" @@ -92,29 +88,24 @@ zh-CN: wasnt_that_interesting: "我想 #<%= tagName %> 并ä¸å…¨é‚£ä¹ˆæœ‰è¶£ã€‚" timeago: day: "1 天" - days: "%d 天" + days: + other: "%d 天" hour: "约 1 å°æ—¶" - hours: "约 %d å°æ—¶" + hours: + other: "约 %d å°æ—¶" minute: "约 1 分钟" - minutes: "%d 分钟" + minutes: + other: "%d 分钟" month: "约 1 个月" - months: "%d 个月" + months: + other: "%d 个月" prefixAgo: "在" prefixFromNow: "è·ä»Š" seconds: "少于 1 分钟" suffixAgo: "å‰" suffixFromNow: "åŽ" year: "约 1 å¹´" - years: "%d å¹´" - videos: - unknown: "æœªçŸ¥è§†é¢‘æ ¼å¼" - watch: "在 <%= provider %> 上看观看视频" + years: + other: "%d å¹´" viewer: - comment: "评论" - follow_post: "关注内容" - home: "主页" - like: "赞" - reshare: "转å‘" - reshared: "转å‘çš„" - stop_following_post: "åœæ¢å…³æ³¨å†…容" - unlike: "å–消赞" \ No newline at end of file + reshared: "转å‘çš„" \ No newline at end of file diff --git a/config/locales/javascript/javascript.zh-TW.yml b/config/locales/javascript/javascript.zh-TW.yml index 0daef01b36303b083a171bab24637922b6fd60ec..a5665a620c97e0bcd99adbb8a7b4019c26caa874 100644 --- a/config/locales/javascript/javascript.zh-TW.yml +++ b/config/locales/javascript/javascript.zh-TW.yml @@ -6,17 +6,62 @@ zh-TW: javascripts: + admin: + pods: + actions: "動作" + added: "åŠ å…¥æ™‚é–“" + check: "執行連線測試" + errors: + other: "有<%= count %>個豆莢連線檢查ä¸æˆåŠŸã€‚" + follow_link: "在ç€è¦½å™¨ä¸é–‹å•Ÿé€£çµ" + last_check: "最近檢查時間:" + more_info: "顯示更多資訊" + ms: + other: "<%= count %>毫秒(ms)" + no_info: "ç›®å‰é‚„沒有進一æ¥çš„資訊" + not_available: "沒資料" + offline_since: "離線時間:" + pod: "豆莢" + recheck: + failure: "沒有åšæª¢æŸ¥ã€‚" + success: "剛剛æ‰åˆä¸€æ¬¡æª¢æŸ¥é€™å€‹è±†èŽ¢ã€‚" + response_time: "回應時間:" + server_software: "伺æœå™¨è»Ÿé«”:" + ssl: "安全通訊å”定(SSL)" + ssl_disabled: "沒用 SSL" + ssl_enabled: "有用 SSL" + states: + dns_failed: "解æžåŸŸå(DNS)失敗" + http_failed: "HTTP 連線失敗" + net_failed: "連線失敗" + no_errors: "æ£å¸¸" + ssl_failed: "安全連線(SSL)失敗" + unchecked: "沒檢查" + unknown_error: "檢查éŽç¨‹ä¸ç™¼ç”Ÿä¸æ˜ŽéŒ¯èª¤" + version_failed: "沒辦法å–得軟體版本" + status: "狀態" + unchecked: + other: "還有<%= count %>個沒有被檢查éŽçš„豆莢。" + unknown: "ä¸æ˜Ž" + version_failed: + other: "有 <%= count %> 個豆莢沒有版本資訊(舊版的豆莢會沒有 NodeInfo)。" + admins: + dashboard: + compare_versions: "diaspora* 最新的釋出版本是 <%= latestVersion %> ç‰ˆï¼Œä½ çš„è±†èŽ¢æ£åœ¨è·‘的版本是 <%= podVersion %> 版。" + error: "沒辦法判斷 diaspora* 的最新版本。" + outdated: "ä½ çš„è±†èŽ¢æ˜¯èˆŠç‰ˆçš„ã€‚" + up_to_date: "ä½ çš„è±†èŽ¢æ˜¯æœ€æ–°ç‰ˆæœ¬ï¼" and: "åŠ" aspect_dropdown: add_to_aspect: "åŠ è¯çµ¡äºº" all_aspects: "所有社交é¢" - error: "無法開始和 <%= name %> åˆ†äº«ã€‚ä½ é‚„åœ¨å¿½è¦–ä»–å€‘å—Žï¼Ÿ" + error: "無法開始跟 <%= name %> åˆ†äº«ã€‚ä½ é‚„åœ¨å¿½è¦–ä»–å€‘å—Žï¼Ÿ" error_remove: "無法把 <%= name %> 從社交é¢ä¸ç§»é™¤ :(" mobile_row_checked: "<%= name %> (移除)" mobile_row_unchecked: "<%= name %> (新增)" select_aspects: "é¸ç¤¾äº¤é¢" - started_sharing_with: "ä½ é–‹å§‹å’Œ <%= name %> 分享了ï¼" - stopped_sharing_with: "åœæ¢å’Œ <%= name %> 分享了。" + started_sharing_with: "ä½ é–‹å§‹è·Ÿ <%= name %> 分享了ï¼" + stopped_sharing_with: "åœæ¢è·Ÿ <%= name %> 分享了。" toggle: other: "在<%= count %>個社交é¢ä¸" zero: "é¸ç¤¾äº¤é¢" @@ -47,6 +92,8 @@ zh-TW: confirm_unload: "請確èªè¦é›¢é–‹é€™å€‹é é¢ã€‚ä½ ç›®å‰è¼¸å…¥çš„資料將ä¸æœƒä¿ç•™ã€‚" contacts: add_contact: "åŠ è¯çµ¡äºº" + aspect_chat_is_enabled: "這一é¢çš„è¯çµ¡äººå¯ä»¥è·Ÿä½ èŠå¤©ã€‚" + aspect_chat_is_not_enabled: "這一é¢çš„è¯çµ¡äººä¸èƒ½è·Ÿä½ èŠå¤©ã€‚" aspect_list_is_not_visible: "這一é¢ä¸çš„連絡人無法互相看見。" aspect_list_is_visible: "這一é¢ä¸çš„連絡人å¯ä»¥äº’相看見。" error_add: "沒辦法把 <%= name %> åŠ é€²é€™ä¸€é¢ :(" @@ -56,11 +103,11 @@ zh-TW: conversation: new: no_contacts: "\x1f開始å°è©±å‰ä½ å¿…é ˆå…ˆåŠ ä¸€äº›è¯çµ¡äºº" - participants: "åƒåŠ 人員" create: "建立" delete: "刪除" edit: "編輯" - failed_to_like: "說讚失敗ï¼" + failed_to_comment: "發表æ„見失敗。作者å¯èƒ½æ£åœ¨å¿½è¦–ä½ ã€‚" + failed_to_like: "èªªè®šå¤±æ•—ã€‚ä¹Ÿè¨±æ˜¯å› ç‚ºä½œè€…æ£åœ¨å¿½è¦–ä½ ã€‚" failed_to_post_message: "貼文失敗ï¼" failed_to_remove: "åˆªæŽ‰é€™å€‹é …ç›®çš„å‹•ä½œå¤±æ•—äº†ï¼" failed_to_reshare: "轉貼失敗ï¼" @@ -73,7 +120,7 @@ zh-TW: admin: "管ç†" close: "關閉" contacts: "連絡人" - conversations: "交談" + conversations: "å°è©±" help: "說明" home: "我家" log_out: "登出" @@ -84,15 +131,14 @@ zh-TW: recent_notifications: "最新消æ¯" search: "æœå°‹" settings: "è¨å®š" + toggle_mobile: "行動檢視切æ›" + toggle_navigation: "ç€è¦½æ¨¡å¼åˆ‡æ›" view_all: "看全部" hide_post: "è¦éš±è—貼文嗎?" hide_post_failed: "沒辦法隱è—貼文" ignore: "忽視" ignore_failed: "沒辦法忽視這個使用者" ignore_user: "è¦å¿½è¦–這個使用者嗎?" - infinite_scroll: - no_more: "沒有貼文了。" - no_more_contacts: "沒有è¯çµ¡äººäº†ã€‚" my_activity: "我的活動" my_aspects: "我的社交é¢" my_stream: "æµæ°´å¸³" @@ -117,6 +163,9 @@ zh-TW: looking_good: "å¤©å•Šï¼Œä½ çœ‹èµ·ä¾†çœŸå¸¥ï¼" size_error: "檔案 {file} 太大了,上é™æ˜¯{sizeLimit}。" poll: + answer_count: + other: "有<%=count%>個人投票" + zero: "沒人投票" close_result: "éš±è—çµæžœ" count: other: "到目å‰æœ‰ <%=count%> 張票" @@ -129,18 +178,44 @@ zh-TW: add_some: "åŠ å…¥ä¸€äº›" bio: "自我介紹" born: "生日" - contacts: "è¯çµ¡è³‡è¨Š" + contacts: "連絡人" edit: "編輯" gender: "性別" - ignoring: "ä½ ç›®å‰æœƒå¿½è¦– <%= name %> 的所有貼文。" location: "地點" photos: "相片" posts: "貼文" you_have_no_tags: "ä½ æ²’æœ‰ä»»ä½•æ¨™ç±¤ï¼" publisher: add_option: "å¢žåŠ ç”案" - at_least_one_aspect: "發表時請至少é¸æ“‡ä¸€å€‹ç¤¾äº¤é¢" limited: "è¨é™ - åªæœ‰ä½ 想分享的人æ‰çœ‹å¾—åˆ°ä½ çš„è²¼æ–‡" + markdown_editor: + preview: "é 覽" + texts: + code: "在這裡打程å¼ç¢¼" + heading: "將文å—變標題" + insert_image_description_text: "在這裡輸入圖片的說明" + insert_image_help_text: "åœ¨é€™è£¡åŠ å…¥åœ–ç‰‡" + insert_image_title: "在這裡輸入圖片的標題" + insert_link_description_text: "在這裡輸入連çµçš„說明" + insert_link_help_text: "åœ¨é€™è£¡åŠ å…¥é€£çµ" + italic: "傾斜文å—" + list: "在這裡æ¢åˆ—æ–‡å—" + quote: "在這裡引用文å—" + strong: "強調文å—" + tooltips: + bold: "ç²—é«”" + cancel: "å–消訊æ¯" + code: "åŠ å…¥ç¨‹å¼ç¢¼" + heading: "標題" + insert_image: "åŠ å…¥åœ–ç‰‡" + insert_link: "åŠ å…¥é€£çµ" + insert_ordered_list: "åŠ å…¥ç·¨è™Ÿæ¸…å–®" + insert_unordered_list: "åŠ å…¥é …ç›®æ¸…å–®" + italic: "斜體" + preview: "é 覽訊æ¯" + quote: "åŠ å…¥å¼•ç”¨æ–‡å—" + write: "編輯訊æ¯" + write: "編寫" near_from: "貼文地點:<%= location %>" option: "ç”案" public: "å…¬é–‹ï¼šæ‰€æœ‰äººéƒ½èƒ½çœ‹åˆ°ä½ çš„è²¼æ–‡ï¼ŒåŒ…æ‹¬æœå°‹å¼•æ“Ž" @@ -157,7 +232,6 @@ zh-TW: duplicate: "很棒å°å§ï¼Ÿä½ 已經轉貼éŽè©²ç¯‡è²¼æ–‡äº†ï¼" post: "è¦è½‰è²¼ <%= name %> 的貼文嗎?" successful: "貼文轉貼æˆåŠŸï¼" - search_for: "æœå°‹ <%= name %>" show_more: "顯示更多" stream: comment: "留言" @@ -178,8 +252,13 @@ zh-TW: more_comments: other: "顯示å¦å¤–<%= count %>則留言" zero: "顯示å¦å¤–<%= count %>則留言" + no_posts_yet: "ç›®å‰é€™è£¡é‚„沒有貼文å¯ä»¥é¡¯ç¤ºã€‚" original_post_deleted: "原貼文已經被作者刪除了" + permalink: "永久連çµ" public: "公開" + reactions: + other: "有<%= count%>個回應" + zero: "沒有回應" reshare: "轉貼" reshares: other: "被轉貼<%= count %>次" @@ -200,13 +279,18 @@ zh-TW: wasnt_that_interesting: "OK,我想 #<%= tagName %> 大概沒那麼有趣..." timeago: day: "一天" - days: "%d天" + days: + other: "%d天" hour: "約一å°æ™‚" - hours: "ç´„%då°æ™‚" + hours: + other: "ç´„%då°æ™‚" + inPast: "å†ç‰ä¸€ä¸‹" minute: "約一分é˜" - minutes: "%d分é˜" + minutes: + other: "%d分é˜" month: "約一個月" - months: "%d個月" + months: + other: "%d個月" prefixAgo: "在" prefixFromNow: "è·ä»Š" seconds: "少於一分é˜" @@ -214,17 +298,8 @@ zh-TW: suffixFromNow: "å‰" wordSeparator: "" year: "約一年" - years: "%då¹´" + years: + other: "%då¹´" unblock_failed: "å–消å°éŽ–這個使用者失敗了" - videos: - unknown: "ä¸æ˜Žçš„影片類別" - watch: "從 <%= provider %> 看這部影片" viewer: - comment: "留言" - follow_post: "追蹤貼文" - home: "我家" - like: "讚" - reshare: "轉貼" - reshared: "轉貼的" - stop_following_post: "åœæ¢è¿½è¹¤è²¼æ–‡" - unlike: "收回讚" \ No newline at end of file + reshared: "已轉貼" \ No newline at end of file diff --git a/config/logging.rb b/config/logging.rb index b29130f67044c5fcca95a5b0eafcbb8cd8f04a32..57cf39b0aaa724d61ab6b02557b413d2a0a3f748 100644 --- a/config/logging.rb +++ b/config/logging.rb @@ -86,7 +86,8 @@ Logging::Rails.configure do |config| # log-levels from the diaspora.yml for SQL and federation debug-logging Logging.logger[ActiveRecord::Base].level = AppConfig.environment.logging.debug.sql? ? :debug : :info - Logging.logger["XMLLogger"].level = AppConfig.environment.logging.debug.federation? ? :debug : :info + Logging.logger[DiasporaFederation::Salmon::MagicEnvelope].level = + AppConfig.environment.logging.debug.federation? ? :debug : :info # Under Phusion Passenger smart spawning, we need to reopen all IO streams # after workers have forked. diff --git a/config/routes.rb b/config/routes.rb index 2daa85525d05ecc7dcac400e6db5086237554bb6..4fc376e2de31aae2c33d09e1ff0be9a7bb96c43c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,11 +3,11 @@ # the COPYRIGHT file. require 'sidekiq/web' -require 'sidetiq/web' +require "sidekiq/cron/web" Diaspora::Application.routes.draw do - resources :report, :except => [:edit, :new] + resources :report, except: %i(edit new show) if Rails.env.production? mount RailsAdmin::Engine => '/admin_panel', :as => 'rails_admin' @@ -25,11 +25,11 @@ Diaspora::Application.routes.draw do get 'oembed' => 'posts#oembed', :as => 'oembed' # Posting and Reading - resources :reshares + resources :reshares, only: %i(create) resources :status_messages, :only => [:new, :create] - resources :posts do + resources :posts, only: %i(show destroy) do member do get :interactions end @@ -40,10 +40,7 @@ Diaspora::Application.routes.draw do resources :comments, only: %i(new create destroy index) end - - get 'p/:id' => 'posts#show', :as => 'short_post' - get 'posts/:id/iframe' => 'posts#iframe', :as => 'iframe' # roll up likes into a nested resource above resources :comments, :only => [:create, :destroy] do @@ -60,7 +57,7 @@ Diaspora::Application.routes.draw do get "commented" => "streams#commented", :as => "commented_stream" get "aspects" => "streams#aspects", :as => "aspects_stream" - resources :aspects do + resources :aspects, except: %i(index new edit) do put :toggle_contact_visibility put :toggle_chat_privilege collection do @@ -70,15 +67,15 @@ Diaspora::Application.routes.draw do get 'bookmarklet' => 'status_messages#bookmarklet' - resources :photos, :except => [:index, :show] do + resources :photos, only: %i(destroy create) do put :make_profile_photo end #Search get 'search' => "search#search" - resources :conversations do - resources :messages, :only => [:create, :show] + resources :conversations, except: %i(edit update destroy) do + resources :messages, only: %i(create) delete 'visibility' => 'conversation_visibilities#destroy' end @@ -99,11 +96,10 @@ Diaspora::Application.routes.draw do get 'tags/:name' => 'tags#show', :as => 'tag' - resources :apps, :only => [:show] - # Users and people - resource :user, :only => [:edit, :update, :destroy], :shallow => true do + resource :user, only: %i(edit destroy), shallow: true do + put :edit, action: :update get :getting_started_completed post :export_profile get :download_profile @@ -112,39 +108,41 @@ Diaspora::Application.routes.draw do end controller :users do - get 'public/:username' => :public, :as => 'users_public' - get 'getting_started' => :getting_started, :as => 'getting_started' - get 'privacy' => :privacy_settings, :as => 'privacy_settings' - get 'getting_started_completed' => :getting_started_completed - get 'confirm_email/:token' => :confirm_email, :as => 'confirm_email' + get "public/:username" => :public, :as => :users_public + get "getting_started" => :getting_started, :as => :getting_started + get "confirm_email/:token" => :confirm_email, :as => :confirm_email + get "privacy" => :privacy_settings, :as => :privacy_settings + put "privacy" => :update_privacy_settings, :as => :update_privacy_settings + get "getting_started_completed" => :getting_started_completed end - # This is a hack to overide a route created by devise. - # I couldn't find anything in devise to skip that route, see Bug #961 - get 'users/edit' => redirect('/user/edit') - - devise_for :users, :controllers => {:registrations => "registrations", - :sessions => "sessions"} + devise_for :users, controllers: {sessions: :sessions}, skip: :registration + devise_scope :user do + get "/users/sign_up" => "registrations#new", :as => :new_user_registration + post "/users" => "registrations#create", :as => :user_registration + end - #legacy routes to support old invite routes - get 'users/invitation/accept' => 'invitations#edit' - get 'invitations/email' => 'invitations#email', :as => 'invite_email' - get 'users/invitations' => 'invitations#new', :as => 'new_user_invitation' - post 'users/invitations' => 'invitations#create', :as => 'user_invitation' + get "users/invitations" => "invitations#new", :as => "new_user_invitation" + post "users/invitations" => "invitations#create", :as => "user_invitation" get 'login' => redirect('/users/sign_in') # Admin backend routes - scope 'admins', :controller => :admins do + scope "admins", controller: :admins do match :user_search, via: [:get, :post] - get :admin_inviter - get :weekly_user_stats - get :stats, :as => 'pod_stats' - get "add_invites/:invite_code_id" => 'admins#add_invites', :as => 'add_invites' + get :admin_inviter + get :weekly_user_stats + get :stats, as: "pod_stats" + get :dashboard, as: "admin_dashboard" + get "add_invites/:invite_code_id" => "admins#add_invites", :as => "add_invites" end namespace :admin do + resources :pods, only: :index do + post :recheck + end + post 'users/:id/close_account' => 'users#close_account', :as => 'close_account' post 'users/:id/lock_account' => 'users#lock_account', :as => 'lock_account' post 'users/:id/unlock_account' => 'users#unlock_account', :as => 'unlock_account' @@ -154,8 +152,7 @@ Diaspora::Application.routes.draw do resources :profiles, :only => [:show] - resources :contacts, :except => [:update, :create] do - end + resources :contacts, only: %i(index) resources :aspect_memberships, :only => [:destroy, :create] resources :share_visibilities, :only => [:update] resources :blocks, :only => [:create, :destroy] @@ -163,21 +160,15 @@ Diaspora::Application.routes.draw do get 'i/:id' => 'invitation_codes#show', :as => 'invite_code' get 'people/refresh_search' => "people#refresh_search" - resources :people, :except => [:edit, :update] do - resources :status_messages - resources :photos + resources :people, only: %i(show index) do + resources :status_messages, only: %i(new create) + resources :photos, except: %i(new update) get :contacts - get "aspect_membership_button" => :aspect_membership_dropdown, :as => "aspect_membership_button" get :stream get :hovercard - member do - get :last_post - end - collection do post 'by_handle' => :retrieve_remote, :as => 'person_by_handle' - get :tag_index end end get '/u/:username' => 'people#show', :as => 'user_profile', :constraints => { :username => /[^\/]+/ } @@ -193,15 +184,7 @@ Diaspora::Application.routes.draw do end end - scope 'api/v0', :controller => :apis do - get :me - end - namespace :api do - namespace :v0 do - get "/users/:username" => 'users#show', :as => 'user' - get "/tags/:name" => 'tags#show', :as => 'tag' - end namespace :v1 do resources :tokens, :only => [:create, :destroy] end @@ -226,10 +209,34 @@ Diaspora::Application.routes.draw do get "statistics", to: "node_info#statistics" # Terms - if AppConfig.settings.terms.enable? + if AppConfig.settings.terms.enable? || Rails.env.test? get 'terms' => 'terms#index' end + # Relay + get ".well-known/x-social-relay" => "social_relay#well_known" + # Startpage root :to => 'home#show' + get "podmin", to: "home#podmin" + + namespace :api do + namespace :openid_connect do + resources :clients, only: :create + get "clients/find", to: "clients#find" + + post "access_tokens", to: "token_endpoint#create" + + # Authorization Servers MUST support the use of the HTTP GET and POST methods at the Authorization Endpoint + # See http://openid.net/specs/openid-connect-core-1_0.html#AuthResponseValidation + resources :authorizations, only: %i(new create destroy) + post "authorizations/new", to: "authorizations#new" + get "user_applications", to: "user_applications#index" + get "jwks.json", to: "id_tokens#jwks" + match "user_info", to: "user_info#show", via: %i(get post) + end + end + + get ".well-known/webfinger", to: "api/openid_connect/discovery#webfinger" + get ".well-known/openid-configuration", to: "api/openid_connect/discovery#configuration" end diff --git a/config/schedule.yml b/config/schedule.yml new file mode 100644 index 0000000000000000000000000000000000000000..5ba7e5cd67cc310ae226e27cfcc32cce0641139b --- /dev/null +++ b/config/schedule.yml @@ -0,0 +1,11 @@ +clean_cached_files: + cron: "0 0 * * *" + class: "Workers::CleanCachedFiles" + +queue_users_for_removal: + cron: "0 0 * * *" + class: "Workers::QueueUsersForRemoval" + +recurring_pod_check: + cron: "0 0 * * *" + class: "Workers::RecurringPodCheck" diff --git a/config/selenium.yml b/config/selenium.yml deleted file mode 100644 index b53a7e946c33756955ad6be782984fcf45092cdc..0000000000000000000000000000000000000000 --- a/config/selenium.yml +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -common: &common - # Try to kill mongrel after suite if tmp/pids/mongrel_selenium.pid exists - # kill_mongrel_after_suite: true - -local: &local - <<: *common - test_framework: webrat - selenium_server_address: "127.0.0.1" - selenium_server_port: "4444" - selenium_browser_key: "*chrome /usr/bin/firefox" - application_address: "127.0.0.1" - application_port: "4000" - -local_jsunit: - <<: *local - application_port: "8080" - -# Possible Sauce Labs configurations as of 2009/11/19 -# From: http://saucelabs.com/products/docs/sauce-ondemand/browsers -# -# saucelabs_browser_os saucelabs_browser saucelabs_browser_version (pick one) -# -# "Windows 2003" "iexplore" "6.", "7.", "8." -# "firefox" "2.", "3.0", "3.5" -# "safari" "3.", "4." -# "opera" "9." -# "googlechrome" "" -# "Linux" "firefox" "3." -saucelabs: &saucelabs - <<: *common - test_framework: webrat - # URL of Selenium RC server: - selenium_server_address: "saucelabs.com" - selenium_server_port: "4444" - # Saucelabs credentials / Browser to drive - saucelabs_username: "YOUR-SAUCELABS-USERNAME" - saucelabs_access_key: "YOUR-SAUCELABS-ACCESS-KEY" - saucelabs_browser_os: "Linux" - saucelabs_browser: "firefox" - saucelabs_browser_version: "3." - saucelabs_max_duration_seconds: 1800 - # Selenium RC browser connects to and tests the app at this URL: - application_address: "testhost.com" # this will be ovewritten if tunnel_method == :saucetunnel - application_port: 80 - # App host can actually be a tunnel that tunnels from <application_address>:<application_port> to localhost:<tunnel_to_localhost_port> - # There are 3 kinds of tunnels: - # - # tunnel_method: :saucetunnel - # tunnel_to_localhost_port: 4000 # Warning: application_port and tunnel_to_localhost_port must be identical if you are using Webrat - # tunnel_startup_timeout: 240 - # - # tunnel_method: :sshtunnel - # application_address: proxy.mycompany.com - # application_port: 12345 # or can be a range XXXX-YYYY - # tunnel_to_localhost_port: 4000 # Warning: application_port and tunnel_to_localhost_port must be identical if you are using Webrat - # tunnel_username: fred - # tunnel_keyfile: "/Users/<%= ENV['USER'] %>/.ssh/id_rsa" # or tunnel_password: "password" - # - # tunnel_method: :othertunnel You're managing your tunnel independently - -saucelabs_jsunit: &saucelabs_jsunit - <<: *saucelabs - # We are using the Jetty server for Saucelabs JsUnit selenium testing. - localhost_app_server_port: "8080" - -saucelabs_jsunit_firefox: - <<: *saucelabs_jsunit - -saucelabs_jsunit_ie: - <<: *saucelabs_jsunit - saucelabs_browser_os: "Windows 2003" - saucelabs_browser: "iexplore" - saucelabs_browser_version: "7." - jsunit_polling_interval_seconds: 300 - -saucelabs_jsunit_safari: - <<: *saucelabs_jsunit - saucelabs_browser_os: "Windows 2003" - saucelabs_browser: "safari" - saucelabs_browser_version: "4." - -saucelabs_jsunit_chrome: - <<: *saucelabs_jsunit - saucelabs_browser_os: "Windows 2003" - saucelabs_browser: "googlechrome" - saucelabs_browser_version: "" diff --git a/config/sidekiq.yml b/config/sidekiq.yml index 50d7a8b5cf2e345e0d7fca253a42b1775599db40..a99dd69c98deae6a472db4f1619d2452cd0ee119 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -5,17 +5,11 @@ :logfile: "<%= AppConfig.sidekiq_log %>" <% end %> :concurrency: <%= AppConfig.environment.sidekiq.concurrency.to_i %> +:dead_max_jobs: <%= AppConfig.environment.sidekiq.dead_jobs_limit.to_i %> +:dead_timeout_in_seconds: <%= AppConfig.environment.sidekiq.dead_jobs_timeout.to_i %> :queues: - - socket_webfinger - - photos - - http_service - - dispatch - - mail - - delete_account - - receive_local - - receive - - receive_salmon - - http - - export - - maintenance + - urgent + - high + - medium + - low - default diff --git a/config/vines/README b/config/vines/README deleted file mode 100644 index 819906dc718e336f931bc64acf4a5bd6b52d831f..0000000000000000000000000000000000000000 --- a/config/vines/README +++ /dev/null @@ -1,7 +0,0 @@ -If you want to encrypt your chat streams with vines. -Add to `config/vines` your server certificate and key. - -The domain name should be included in the file name e.g.: - -* example.com.crt -* example.com.key diff --git a/db/migrate/20150523004437_enable_color_themes.rb b/db/migrate/20150523004437_enable_color_themes.rb new file mode 100644 index 0000000000000000000000000000000000000000..d9cea868d765e0dca61bdc5db1da9c2685c0a4a8 --- /dev/null +++ b/db/migrate/20150523004437_enable_color_themes.rb @@ -0,0 +1,9 @@ +class EnableColorThemes < ActiveRecord::Migration + def up + add_column(:users, :color_theme, :string) + end + + def down + remove_column(:users, :color_theme) + end +end diff --git a/db/migrate/20150613202109_create_o_auth_applications.rb b/db/migrate/20150613202109_create_o_auth_applications.rb new file mode 100644 index 0000000000000000000000000000000000000000..1170b5c9e294b8158c2e5cb2b14e9e3361fc3e4f --- /dev/null +++ b/db/migrate/20150613202109_create_o_auth_applications.rb @@ -0,0 +1,30 @@ +# Inspired by https://github.com/nov/openid_connect_sample/blob/master/db/migrate/20110829023826_create_clients.rb + +class CreateOAuthApplications < ActiveRecord::Migration + def change + create_table :o_auth_applications do |t| + t.belongs_to :user, index: true + t.string :client_id, index: {unique: true, length: 191} + t.string :client_secret + t.string :client_name + + t.text :redirect_uris + t.string :response_types + t.string :grant_types + t.string :application_type, default: "web" + t.string :contacts + t.string :logo_uri + t.string :client_uri + t.string :policy_uri + t.string :tos_uri + t.string :sector_identifier_uri + t.string :token_endpoint_auth_method + t.text :jwks + t.string :jwks_uri + t.boolean :ppid, default: false + + t.timestamps null: false + end + add_foreign_key :o_auth_applications, :users + end +end diff --git a/db/migrate/20150630221004_add_public_to_profiles.rb b/db/migrate/20150630221004_add_public_to_profiles.rb new file mode 100644 index 0000000000000000000000000000000000000000..06973e02742367e274f77ec2d5dad76a9a85da83 --- /dev/null +++ b/db/migrate/20150630221004_add_public_to_profiles.rb @@ -0,0 +1,5 @@ +class AddPublicToProfiles < ActiveRecord::Migration + def change + add_column :profiles, :public_details, :boolean, default: false + end +end diff --git a/db/migrate/20150708153926_create_authorizations.rb b/db/migrate/20150708153926_create_authorizations.rb new file mode 100644 index 0000000000000000000000000000000000000000..ee88ab01750bae38f70073f69ebda3cbe9adb770 --- /dev/null +++ b/db/migrate/20150708153926_create_authorizations.rb @@ -0,0 +1,18 @@ +class CreateAuthorizations < ActiveRecord::Migration + def change + create_table :authorizations do |t| + t.belongs_to :user, index: true + t.belongs_to :o_auth_application, index: true + t.string :refresh_token + t.string :code + t.string :redirect_uri + t.string :nonce + t.string :scopes + t.boolean :code_used, default: false + + t.timestamps null: false + end + add_foreign_key :authorizations, :users + add_foreign_key :authorizations, :o_auth_applications + end +end diff --git a/db/migrate/20150708153928_create_o_auth_access_tokens.rb b/db/migrate/20150708153928_create_o_auth_access_tokens.rb new file mode 100644 index 0000000000000000000000000000000000000000..d833011c5e38b560b4c5167c4d779b11dbb858bf --- /dev/null +++ b/db/migrate/20150708153928_create_o_auth_access_tokens.rb @@ -0,0 +1,14 @@ +# Inspired by https://github.com/nov/openid_connect_sample/blob/master/db/migrate/20110829023837_create_access_tokens.rb + +class CreateOAuthAccessTokens < ActiveRecord::Migration + def change + create_table :o_auth_access_tokens do |t| + t.belongs_to :authorization, index: true + t.string :token, index: {unique: true, length: 191} + t.datetime :expires_at + + t.timestamps null: false + end + add_foreign_key :o_auth_access_tokens, :authorizations + end +end diff --git a/db/migrate/20150714055110_create_id_tokens.rb b/db/migrate/20150714055110_create_id_tokens.rb new file mode 100644 index 0000000000000000000000000000000000000000..b1e3abdfa0b31bba4a16e05e3dd7a5fdfaf7cbef --- /dev/null +++ b/db/migrate/20150714055110_create_id_tokens.rb @@ -0,0 +1,14 @@ +# Inspired by https://github.com/nov/openid_connect_sample/blob/master/db/migrate/20110829024010_create_id_tokens.rb + +class CreateIdTokens < ActiveRecord::Migration + def change + create_table :id_tokens do |t| + t.belongs_to :authorization, index: true + t.datetime :expires_at + t.string :nonce + + t.timestamps null: false + end + add_foreign_key :id_tokens, :authorizations + end +end diff --git a/db/migrate/20150731123113_create_pairwise_pseudonymous_identifiers.rb b/db/migrate/20150731123113_create_pairwise_pseudonymous_identifiers.rb new file mode 100644 index 0000000000000000000000000000000000000000..0c86908488b0242000d8e2b249c39a211667163a --- /dev/null +++ b/db/migrate/20150731123113_create_pairwise_pseudonymous_identifiers.rb @@ -0,0 +1,15 @@ +# Inspired by https://github.com/nov/openid_connect_sample/blob/master/db/migrate/20110829024140_create_pairwise_pseudonymous_identifiers.rb + +class CreatePairwisePseudonymousIdentifiers < ActiveRecord::Migration + def change + create_table :ppid do |t| + t.belongs_to :o_auth_application, index: true + t.belongs_to :user, index: true + + t.string :guid, :string, limit: 32 + t.string :identifier + end + add_foreign_key :ppid, :o_auth_applications + add_foreign_key :ppid, :users + end +end diff --git a/db/migrate/20150731123114_add_status_to_pods.rb b/db/migrate/20150731123114_add_status_to_pods.rb new file mode 100644 index 0000000000000000000000000000000000000000..b53051f06a9e65a9d3baa69279de90c6513d8c7d --- /dev/null +++ b/db/migrate/20150731123114_add_status_to_pods.rb @@ -0,0 +1,14 @@ +class AddStatusToPods < ActiveRecord::Migration + def change + add_column :pods, :status, :integer, default: 0 + add_column :pods, :checked_at, :datetime, default: Time.zone.at(0) + add_column :pods, :offline_since, :datetime, default: nil + add_column :pods, :response_time, :integer, default: -1 + add_column :pods, :software, :string, limit: 255 + add_column :pods, :error, :string, limit: 255 + + add_index :pods, :status + add_index :pods, :checked_at + add_index :pods, :offline_since + end +end diff --git a/db/migrate/20150828132451_remove_duplicate_and_empty_pods.rb b/db/migrate/20150828132451_remove_duplicate_and_empty_pods.rb new file mode 100644 index 0000000000000000000000000000000000000000..e93acf722d085a5d909cfcc419cd482bc319485e --- /dev/null +++ b/db/migrate/20150828132451_remove_duplicate_and_empty_pods.rb @@ -0,0 +1,24 @@ +class RemoveDuplicateAndEmptyPods < ActiveRecord::Migration + def up + remove_dupes + remove_empty_or_nil + + add_index :pods, :host, unique: true, length: 190 # =190*4 for utf8mb4 + end + + def down + remove_index :pods, :host + end + + private + + def remove_dupes + duplicates = Pod.group(:host).count.select {|_, v| v > 1 }.keys + ids = duplicates.flat_map {|pod| Pod.where(host: pod).order(created_at: :asc).pluck(:id).tap(&:shift) } + Pod.where(id: ids).destroy_all + end + + def remove_empty_or_nil + Pod.where(host: [nil, ""]).destroy_all + end +end diff --git a/db/migrate/20151003142048_update_report_item_types.rb b/db/migrate/20151003142048_update_report_item_types.rb new file mode 100644 index 0000000000000000000000000000000000000000..9a318edff0adec3a808d8156e1a436f4ad291299 --- /dev/null +++ b/db/migrate/20151003142048_update_report_item_types.rb @@ -0,0 +1,7 @@ +class UpdateReportItemTypes < ActiveRecord::Migration + def change + Report.all.each do |report| + report.update_attribute :item_type, report[:item_type].capitalize + end + end +end diff --git a/db/migrate/20151210213023_remove_signatures_from_relayables.rb b/db/migrate/20151210213023_remove_signatures_from_relayables.rb new file mode 100644 index 0000000000000000000000000000000000000000..1d2cb485cb6b574be3174c6f572f2cdd6dd9b5fd --- /dev/null +++ b/db/migrate/20151210213023_remove_signatures_from_relayables.rb @@ -0,0 +1,9 @@ +class RemoveSignaturesFromRelayables < ActiveRecord::Migration + def change + remove_column :comments, :parent_author_signature, :text + remove_column :poll_participations, :parent_author_signature, :text + remove_column :messages, :parent_author_signature, :text + remove_column :participations, :parent_author_signature, :text + remove_column :likes, :parent_author_signature, :text + end +end diff --git a/db/migrate/20160124234712_extend_pods.rb b/db/migrate/20160124234712_extend_pods.rb new file mode 100644 index 0000000000000000000000000000000000000000..17fb6c2151df9df1e4db2fcc3a6ebcb93adb2283 --- /dev/null +++ b/db/migrate/20160124234712_extend_pods.rb @@ -0,0 +1,77 @@ +class ExtendPods < ActiveRecord::Migration + class Pod < ActiveRecord::Base + has_many :people + + DEFAULT_PORTS = [URI::HTTP::DEFAULT_PORT, URI::HTTPS::DEFAULT_PORT] + + def self.find_or_create_by(opts) + uri = URI.parse(opts.fetch(:url)) + port = DEFAULT_PORTS.include?(uri.port) ? nil : uri.port + find_or_initialize_by(host: uri.host, port: port).tap do |pod| + pod.ssl ||= (uri.scheme == "https") + pod.save + end + end + + def url + (ssl ? URI::HTTPS : URI::HTTP).build(host: host, port: port, path: "/") + end + end + + class Person < ActiveRecord::Base + belongs_to :owner, class_name: "User" + belongs_to :pod + + def url + owner_id.nil? ? pod.url.to_s : AppConfig.url_to("/") + end + end + + class User < ActiveRecord::Base + has_one :person, inverse_of: :owner, foreign_key: :owner_id + end + + def up + remove_index :pods, :host + + # add port + add_column :pods, :port, :integer + add_index :pods, %i(host port), unique: true, length: {host: 190, port: nil}, using: :btree + + add_column :pods, :blocked, :boolean, default: false + + Pod.reset_column_information + + # link people with pod + add_column :people, :pod_id, :integer + add_index :people, :url, length: 190 + add_foreign_key :people, :pods, name: :people_pod_id_fk, on_delete: :cascade + Person.where(owner: nil).distinct(:url).pluck(:url).each do |url| + pod = Pod.find_or_create_by(url: url) + Person.where(url: url, owner_id: nil).update_all(pod_id: pod.id) if pod.persisted? + end + + # cleanup unused pods + Pod.joins("LEFT OUTER JOIN people ON pods.id = people.pod_id").delete_all("people.id is NULL") + + remove_column :people, :url + end + + def down + # restore url + add_column :people, :url, :text + Person.all.group_by(&:pod_id).each do |pod_id, persons| + Person.where(pod_id: pod_id).update_all(url: persons.first.url) + end + change_column :people, :url, :text, null: false + remove_foreign_key :people, :pods + remove_column :people, :pod_id + + # remove pods with port + Pod.where.not(port: nil).delete_all + + remove_index :pods, column: %i(host port) + remove_columns :pods, :port, :blocked + add_index :pods, :host, unique: true, length: 190 + end +end diff --git a/db/migrate/20160225232049_link_share_visibilities_with_user.rb b/db/migrate/20160225232049_link_share_visibilities_with_user.rb new file mode 100644 index 0000000000000000000000000000000000000000..f7db77306f4e0c7f4384d534fe943e10caa69e99 --- /dev/null +++ b/db/migrate/20160225232049_link_share_visibilities_with_user.rb @@ -0,0 +1,79 @@ +class LinkShareVisibilitiesWithUser < ActiveRecord::Migration + class ShareVisibility < ActiveRecord::Base + end + + def up + cleanup_deleted_share_visibilities + + remove_columns :share_visibilities, :created_at, :updated_at + add_column :share_visibilities, :user_id, :integer + + # update_all from AR doesn't work with postgres, see: https://github.com/rails/rails/issues/13496 + if AppConfig.postgres? + execute "UPDATE share_visibilities SET user_id = contacts.user_id " \ + "FROM contacts WHERE contacts.id = share_visibilities.contact_id" + else + ShareVisibility.joins("INNER JOIN contacts ON share_visibilities.contact_id = contacts.id") + .update_all("share_visibilities.user_id = contacts.user_id") + end + + remove_foreign_key :share_visibilities, name: :post_visibilities_contact_id_fk + + remove_index :share_visibilities, name: :index_post_visibilities_on_contact_id + remove_index :share_visibilities, name: :shareable_and_contact_id + remove_index :share_visibilities, name: :shareable_and_hidden_and_contact_id + + remove_column :share_visibilities, :contact_id + change_column :share_visibilities, :user_id, :integer, null: false + + ShareVisibility.joins("LEFT OUTER JOIN users ON users.id = share_visibilities.user_id") + .delete_all("users.id is NULL") + + add_index :share_visibilities, :user_id + add_index :share_visibilities, %i(shareable_id shareable_type user_id), name: :shareable_and_user_id + add_index :share_visibilities, %i(shareable_id shareable_type hidden user_id), + name: :shareable_and_hidden_and_user_id + + add_foreign_key :share_visibilities, :users, name: :share_visibilities_user_id_fk, on_delete: :cascade + end + + def down + add_column :share_visibilities, :contact_id, :integer + + if AppConfig.postgres? + execute "UPDATE share_visibilities SET contact_id = contacts.id " \ + "FROM contacts WHERE contacts.user_id = share_visibilities.user_id" + else + ShareVisibility.joins("INNER JOIN contacts ON share_visibilities.user_id = contacts.user_id") + .update_all("share_visibilities.contact_id = contacts.id") + end + + remove_foreign_key :share_visibilities, name: :share_visibilities_user_id_fk + + remove_index :share_visibilities, :user_id + remove_index :share_visibilities, name: :shareable_and_user_id + remove_index :share_visibilities, name: :shareable_and_hidden_and_user_id + + remove_column :share_visibilities, :user_id + change_column :share_visibilities, :contact_id, :integer, null: false + + add_index :share_visibilities, :contact_id, name: :index_post_visibilities_on_contact_id + add_index :share_visibilities, %i(shareable_id shareable_type contact_id), name: :shareable_and_contact_id + add_index :share_visibilities, %i(shareable_id shareable_type hidden contact_id), + name: :shareable_and_hidden_and_contact_id + + add_foreign_key :share_visibilities, :contacts, name: :post_visibilities_contact_id_fk, on_delete: :cascade + + add_column :share_visibilities, :created_at, :datetime + add_column :share_visibilities, :updated_at, :datetime + end + + private + + def cleanup_deleted_share_visibilities + ShareVisibility.joins("LEFT OUTER JOIN posts ON posts.id = share_visibilities.shareable_id") + .where(shareable_type: "Post").delete_all("posts.id is NULL") + ShareVisibility.joins("LEFT OUTER JOIN photos ON photos.id = share_visibilities.shareable_id") + .where(shareable_type: "Photo").delete_all("photos.id is NULL") + end +end diff --git a/db/migrate/20160302025129_cleanup_aspect_visibility.rb b/db/migrate/20160302025129_cleanup_aspect_visibility.rb new file mode 100644 index 0000000000000000000000000000000000000000..c937ac4df0ee4cdff85a889fd28bec9354ecb565 --- /dev/null +++ b/db/migrate/20160302025129_cleanup_aspect_visibility.rb @@ -0,0 +1,27 @@ +class CleanupAspectVisibility < ActiveRecord::Migration + class AspectVisibility < ActiveRecord::Base + end + + def up + AspectVisibility.joins("LEFT OUTER JOIN posts ON posts.id = aspect_visibilities.shareable_id") + .where(shareable_type: "Post").delete_all("posts.id is NULL") + AspectVisibility.joins("LEFT OUTER JOIN photos ON photos.id = aspect_visibilities.shareable_id") + .where(shareable_type: "Photo").delete_all("photos.id is NULL") + AspectVisibility.joins("INNER JOIN posts ON posts.id = aspect_visibilities.shareable_id") + .where(shareable_type: "Post").delete_all(posts: {public: true}) + AspectVisibility.joins("INNER JOIN photos ON photos.id = aspect_visibilities.shareable_id") + .where(shareable_type: "Photo").delete_all(photos: {public: true}) + + remove_columns :aspect_visibilities, :created_at, :updated_at + end + + def down + add_column :aspect_visibilities, :created_at, :datetime + add_column :aspect_visibilities, :updated_at, :datetime + + User.all.each do |user| + user.posts.where(public: true).each {|post| user.add_to_streams(post, user.aspects) } + user.photos.where(public: true).each {|photo| user.add_to_streams(photo, user.aspects) } + end + end +end diff --git a/db/migrate/20160307142216_cleanup_handles.rb b/db/migrate/20160307142216_cleanup_handles.rb new file mode 100644 index 0000000000000000000000000000000000000000..b2ed8fc8ac9eed264e25b9098cf86966f3035041 --- /dev/null +++ b/db/migrate/20160307142216_cleanup_handles.rb @@ -0,0 +1,7 @@ +class CleanupHandles < ActiveRecord::Migration + def change + remove_column :photos, :tmp_old_id, :integer + remove_column :photos, :diaspora_handle, :string + remove_column :posts, :diaspora_handle, :string + end +end diff --git a/db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb b/db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb new file mode 100644 index 0000000000000000000000000000000000000000..4f5750a3e2dd49390013307fbad2fef942993359 --- /dev/null +++ b/db/migrate/20160509232726_cleanup_duplicates_and_add_unique_indexes.rb @@ -0,0 +1,66 @@ +class CleanupDuplicatesAndAddUniqueIndexes < ActiveRecord::Migration + class Post < ActiveRecord::Base + end + + class StatusMessage < Post + end + + class Photo < ActiveRecord::Base + belongs_to :status_message, foreign_key: :status_message_guid, primary_key: :guid + end + + class ShareVisibility < ActiveRecord::Base + end + + def up + # temporary index to speed up the migration + add_index :photos, :guid, length: 191 + + # fix share visibilities for private photos + if AppConfig.postgres? + execute "UPDATE share_visibilities" \ + " SET shareable_id = (SELECT MIN(p3.id) FROM photos as p3 WHERE p3.guid = p1.guid)" \ + " FROM photos as p1, photos as p2" \ + " WHERE p1.id = share_visibilities.shareable_id AND (p1.guid = p2.guid AND p1.id > p2.id)" \ + " AND share_visibilities.shareable_type = 'Photo'" + else + execute "UPDATE share_visibilities" \ + " INNER JOIN photos as p1 ON p1.id = share_visibilities.shareable_id" \ + " INNER JOIN photos as p2 ON p1.guid = p2.guid AND p1.id > p2.id" \ + " SET share_visibilities.shareable_id = (SELECT MIN(p3.id) FROM photos as p3 WHERE p3.guid = p1.guid)" \ + " WHERE share_visibilities.shareable_type = 'Photo'" + end + + %i(conversations messages photos polls poll_answers poll_participations).each do |table| + delete_duplicates_and_create_unique_index(table) + end + + # fix photo public flag again ... + Photo.joins(:status_message).where(posts: {public: true}).update_all(public: true) + + ShareVisibility.joins("INNER JOIN photos ON photos.id = share_visibilities.shareable_id") + .where(shareable_type: "Photo", photos: {public: true}).delete_all + end + + def down + raise ActiveRecord::IrreversibleMigration + end + + private + + def delete_duplicates_and_create_unique_index(table) + # temporary index to speed up the migration + add_index table, :guid, length: 191 unless table == :photos + + if AppConfig.postgres? + execute "DELETE FROM #{table} AS t1 USING #{table} AS t2 WHERE t1.guid = t2.guid AND t1.id > t2.id" + else + execute "DELETE t1 FROM #{table} t1, #{table} t2 WHERE t1.guid = t2.guid AND t1.id > t2.id" + end + + remove_index table, column: :guid + + # now create unique index \o/ + add_index table, :guid, length: 191, unique: true + end +end diff --git a/db/migrate/20160531170531_remove_duplicate_aspect_visibilities.rb b/db/migrate/20160531170531_remove_duplicate_aspect_visibilities.rb new file mode 100644 index 0000000000000000000000000000000000000000..8269606be988a08971467b73136efaa58124bfe7 --- /dev/null +++ b/db/migrate/20160531170531_remove_duplicate_aspect_visibilities.rb @@ -0,0 +1,11 @@ +class RemoveDuplicateAspectVisibilities < ActiveRecord::Migration + def up + where = "WHERE a1.aspect_id = a2.aspect_id AND a1.shareable_id = a2.shareable_id AND "\ + "a1.shareable_type = a2.shareable_type AND a1.id > a2.id" + if AppConfig.postgres? + execute("DELETE FROM aspect_visibilities AS a1 USING aspect_visibilities AS a2 #{where}") + else + execute("DELETE a1 FROM aspect_visibilities a1, aspect_visibilities a2 #{where}") + end + end +end diff --git a/db/migrate/20160618033455_cleanup_participations.rb b/db/migrate/20160618033455_cleanup_participations.rb new file mode 100644 index 0000000000000000000000000000000000000000..ffe857885ff50f27d1d356294eddf3b09d668c19 --- /dev/null +++ b/db/migrate/20160618033455_cleanup_participations.rb @@ -0,0 +1,44 @@ +class CleanupParticipations < ActiveRecord::Migration + class Participation < ActiveRecord::Base + end + + def up + remove_column :participations, :author_signature + + cleanup + + remove_index :participations, name: :index_participations_on_target_id_and_target_type_and_author_id + add_index :participations, %i(target_id target_type author_id), unique: true + end + + def down + remove_index :participations, name: :index_participations_on_target_id_and_target_type_and_author_id + add_index :participations, %i(target_id target_type author_id) + add_column :participations, :author_signature, :text + end + + private + + def cleanup + self_where = "WHERE participations.target_type = 'Post' AND participations.target_id = posts.id AND " \ + "posts.author_id = participations.author_id" + remote_where = "WHERE participations.target_type = 'Post' AND participations.target_id = posts.id AND " \ + "posts.author_id = post_author.id AND participations.author_id = author.id AND " \ + "author.owner_id is NULL AND post_author.owner_id is NULL" + duplicate_where = "WHERE p1.author_id = p2.author_id AND p1.target_id = p2.target_id " \ + "AND p1.target_type = p2.target_type AND p1.id > p2.id" + + if AppConfig.postgres? + execute "DELETE FROM participations USING posts #{self_where}" + execute "DELETE FROM participations USING posts, people AS author, people AS post_author #{remote_where}" + execute "DELETE FROM participations AS p1 USING participations AS p2 #{duplicate_where}" + else + execute "DELETE participations FROM participations, posts #{self_where}" + execute "DELETE participations FROM participations, posts, people author, people post_author #{remote_where}" + execute "DELETE p1 FROM participations p1, participations p2 #{duplicate_where}" + end + + Participation.joins("LEFT OUTER JOIN posts ON posts.id = participations.target_id") + .where(target_type: "Post").delete_all("posts.id is NULL") + end +end diff --git a/db/migrate/20160720212620_create_signature_tables.rb b/db/migrate/20160720212620_create_signature_tables.rb new file mode 100644 index 0000000000000000000000000000000000000000..f9e2d6c05d1fbeb8ec1e89806042f557eab1c26d --- /dev/null +++ b/db/migrate/20160720212620_create_signature_tables.rb @@ -0,0 +1,87 @@ +class CreateSignatureTables < ActiveRecord::Migration + class SignatureOrder < ActiveRecord::Base + end + + RELAYABLES = %i(comment like poll_participation).freeze + + def self.up + create_table :signature_orders do |t| + t.string :order, null: false + end + add_index :signature_orders, :order, length: 191, unique: true + + RELAYABLES.each {|relayable_type| create_signature_table(relayable_type) } + + migrate_signatures + + RELAYABLES.each {|relayable_type| remove_column "#{relayable_type}s", :author_signature } + end + + def self.down + RELAYABLES.each {|relayable_type| add_column "#{relayable_type}s", :author_signature, :text } + + RELAYABLES.each {|relayable_type| restore_signatures(relayable_type) } + + drop_table :comment_signatures + drop_table :like_signatures + drop_table :poll_participation_signatures + drop_table :signature_orders + end + + private + + def create_signature_table(relayable_type) + create_table "#{relayable_type}_signatures", id: false do |t| + t.integer "#{relayable_type}_id", null: false + t.text :author_signature, null: false + t.integer :signature_order_id, null: false + t.text :additional_data + end + + add_index "#{relayable_type}_signatures", "#{relayable_type}_id", unique: true + + add_foreign_key "#{relayable_type}_signatures", :signature_orders, + name: "#{relayable_type}_signatures_signature_orders_id_fk" + add_foreign_key "#{relayable_type}_signatures", "#{relayable_type}s", + name: "#{relayable_type}_signatures_#{relayable_type}_id_fk", on_delete: :cascade + end + + def migrate_signatures + comment_order_id = SignatureOrder.create!(order: "guid parent_guid text author").id + comment_parent_join = "INNER JOIN posts AS parent ON relayable.commentable_id = parent.id" + migrate_signatures_for(:comment, comment_order_id, comment_parent_join) + + like_order_id = SignatureOrder.create!(order: "positive guid parent_type parent_guid author").id + post_like_join = "INNER JOIN posts AS parent ON relayable.target_id = parent.id AND relayable.target_type = 'Post'" + comment_like_join = "INNER JOIN comments ON relayable.target_id = comments.id " \ + "AND relayable.target_type = 'Comment' " \ + "INNER JOIN posts AS parent ON comments.commentable_id = parent.id" + migrate_signatures_for(:like, like_order_id, post_like_join) + migrate_signatures_for(:like, like_order_id, comment_like_join) + + poll_participation_order_id = SignatureOrder.create!(order: "guid parent_guid author poll_answer_guid").id + poll_participation_parent_join = "INNER JOIN polls ON relayable.poll_id = polls.id " \ + "INNER JOIN posts AS parent ON polls.status_message_id = parent.id" + migrate_signatures_for(:poll_participation, poll_participation_order_id, poll_participation_parent_join) + end + + def migrate_signatures_for(relayable_type, order_id, parent_join) + execute "INSERT INTO #{relayable_type}_signatures (#{relayable_type}_id, signature_order_id, author_signature) " \ + "SELECT relayable.id, #{order_id}, relayable.author_signature FROM #{relayable_type}s AS relayable " \ + "INNER JOIN people AS author ON relayable.author_id = author.id " \ + "#{parent_join} INNER JOIN people AS parent_author ON parent.author_id = parent_author.id " \ + "WHERE author.owner_id IS NULL AND parent_author.owner_id IS NOT NULL AND relayable.author_signature IS NOT NULL" + end + + def restore_signatures(relayable_type) + if AppConfig.postgres? + execute "UPDATE #{relayable_type}s SET author_signature = #{relayable_type}_signatures.author_signature " \ + "FROM #{relayable_type}_signatures " \ + "WHERE #{relayable_type}s.id = #{relayable_type}_signatures.#{relayable_type}_id " + else + execute "UPDATE #{relayable_type}s INNER JOIN #{relayable_type}_signatures " \ + "ON #{relayable_type}s.id = #{relayable_type}_signatures.#{relayable_type}_id " \ + "SET #{relayable_type}s.author_signature = #{relayable_type}_signatures.author_signature" + end + end +end diff --git a/db/migrate/20160802212635_cleanup_posts_table.rb b/db/migrate/20160802212635_cleanup_posts_table.rb new file mode 100644 index 0000000000000000000000000000000000000000..79e473e8e44895ff67b143dc76cffade49e46f8a --- /dev/null +++ b/db/migrate/20160802212635_cleanup_posts_table.rb @@ -0,0 +1,30 @@ +class CleanupPostsTable < ActiveRecord::Migration + def change + remove_index :posts, column: %i(status_message_guid pending), + name: :index_posts_on_status_message_guid_and_pending, length: {status_message_guid: 190} + remove_index :posts, column: :status_message_guid, name: :index_posts_on_status_message_guid, length: 191 + remove_index :posts, column: %i(type pending id), name: :index_posts_on_type_and_pending_and_id + + # from photos? + remove_column :posts, :pending, :boolean, default: false, null: false + remove_column :posts, :remote_photo_path, :text + remove_column :posts, :remote_photo_name, :string + remove_column :posts, :random_string, :string + remove_column :posts, :processed_image, :string + remove_column :posts, :unprocessed_image, :string + remove_column :posts, :status_message_guid, :string + + # old cubbi.es stuff + remove_column :posts, :object_url, :string + remove_column :posts, :image_url, :string + remove_column :posts, :image_height, :integer + remove_column :posts, :image_width, :integer + remove_column :posts, :actor_url, :string + remove_column :posts, :objectId, :string + + # old single post view templates + remove_column :posts, :frame_name, :string + + add_index :posts, %i(id type), name: :index_posts_on_id_and_type + end +end diff --git a/db/migrate/20160807212443_participation_counter.rb b/db/migrate/20160807212443_participation_counter.rb new file mode 100644 index 0000000000000000000000000000000000000000..871a1197fb0313441db77d0287139e285e755f15 --- /dev/null +++ b/db/migrate/20160807212443_participation_counter.rb @@ -0,0 +1,47 @@ +class ParticipationCounter < ActiveRecord::Migration + class Comment < ActiveRecord::Base + end + + class Like < ActiveRecord::Base + end + + class Participation < ActiveRecord::Base + belongs_to :author, class_name: "Person" + end + + class Poll < ActiveRecord::Base + end + + class PollParticipation < ActiveRecord::Base + belongs_to :poll + end + + def up + return if ActiveRecord::SchemaMigration.where(version: "20150404193023").exists? + + add_column :participations, :count, :integer, null: false, default: 1 + + likes_count = Like.select("COUNT(likes.id)") + .where("likes.target_id = participations.target_id") + .where("likes.author_id = participations.author_id") + .to_sql + comments_count = Comment.select("COUNT(comments.id)") + .where("comments.commentable_id = participations.target_id") + .where("comments.author_id = participations.author_id") + .to_sql + polls_count = PollParticipation.select("COUNT(*)") + .where("poll_participations.author_id = participations.author_id") + .joins(:poll) + .where("polls.status_message_id = participations.target_id") + .to_sql + Participation.joins(:author).where.not(people: {owner_id: nil}) + .update_all("count = (#{likes_count}) + (#{comments_count}) + (#{polls_count})") + Participation.where(count: 0).update_all(count: 1) + end + + def down + remove_column :participations, :count + + ActiveRecord::SchemaMigration.where(version: "20150404193023").delete_all + end +end diff --git a/db/migrate/20160810230114_cleanup_invitation_columns_from_users.rb b/db/migrate/20160810230114_cleanup_invitation_columns_from_users.rb new file mode 100644 index 0000000000000000000000000000000000000000..f51312b2f4bcb6c6ae261dfb60b354c29f071e6b --- /dev/null +++ b/db/migrate/20160810230114_cleanup_invitation_columns_from_users.rb @@ -0,0 +1,72 @@ +class CleanupInvitationColumnsFromUsers < ActiveRecord::Migration + class InvitationCode < ActiveRecord::Base + end + + class User < ActiveRecord::Base + end + + def change + remove_index :users, column: %i(invitation_service invitation_identifier), + name: :index_users_on_invitation_service_and_invitation_identifier, + unique: true, length: {invitation_service: 64} + remove_index :users, column: :invitation_token, name: :index_users_on_invitation_token + remove_index :users, column: :email, name: :index_users_on_email, length: 191 + + cleanup_invitations + + remove_column :users, :invitation_token, :string, limit: 60 + remove_column :users, :invitation_sent_at, :datetime + remove_column :users, :invitation_service, :string, limit: 127 + remove_column :users, :invitation_identifier, :string, limit: 127 + remove_column :users, :invitation_limit, :integer + remove_column :users, :invited_by_type, :string + + add_index :users, :email, name: :index_users_on_email, unique: true, length: 191 + end + + def cleanup_invitations + reversible do |dir| + dir.up do + drop_table :invitations + + # reset negative invitation counters + new_counter = AppConfig.settings.enable_registrations? ? AppConfig["settings.invitations.count"] : 0 + InvitationCode.where("count < 0").update_all(count: new_counter) + + # remove old invitation-users + User.delete_all(username: nil) + change_column :users, :username, :string, null: false + end + + dir.down do + change_column :users, :username, :string, null: true + + create_invitations_table + end + end + end + + def create_invitations_table + # rubocop:disable Style/ExtraSpacing + create_table :invitations, force: :cascade do |t| + t.text :message, limit: 65_535 + t.integer :sender_id, limit: 4 + t.integer :recipient_id, limit: 4 + t.integer :aspect_id, limit: 4 + t.datetime :created_at, null: false + t.datetime :updated_at, null: false + t.string :service, limit: 255 + t.string :identifier, limit: 255 + t.boolean :admin, default: false + t.string :language, limit: 255, default: "en" + end + # rubocop:enable Style/ExtraSpacing + + add_index :invitations, :aspect_id, name: :index_invitations_on_aspect_id, using: :btree + add_index :invitations, :recipient_id, name: :index_invitations_on_recipient_id, using: :btree + add_index :invitations, :sender_id, name: :index_invitations_on_sender_id, using: :btree + + add_foreign_key :invitations, :users, column: :recipient_id, name: :invitations_recipient_id_fk, on_delete: :cascade + add_foreign_key :invitations, :users, column: :sender_id, name: :invitations_sender_id_fk, on_delete: :cascade + end +end diff --git a/db/migrate/20160813115514_remove_id_tokens.rb b/db/migrate/20160813115514_remove_id_tokens.rb new file mode 100644 index 0000000000000000000000000000000000000000..36689d6889b313cae2e8613f23e2168b9cbc6bde --- /dev/null +++ b/db/migrate/20160813115514_remove_id_tokens.rb @@ -0,0 +1,7 @@ +require_relative "20150714055110_create_id_tokens" + +class RemoveIdTokens < ActiveRecord::Migration + def change + revert CreateIdTokens + end +end diff --git a/db/migrate/20160822212739_remove_started_sharing_notifications_without_contact.rb b/db/migrate/20160822212739_remove_started_sharing_notifications_without_contact.rb new file mode 100644 index 0000000000000000000000000000000000000000..70a62f68fcf97a0650e0a152deef7cab4bb78eea --- /dev/null +++ b/db/migrate/20160822212739_remove_started_sharing_notifications_without_contact.rb @@ -0,0 +1,12 @@ +class RemoveStartedSharingNotificationsWithoutContact < ActiveRecord::Migration + class Notification < ActiveRecord::Base + end + + def up + Notification.where(type: "Notifications::StartedSharing", target_type: "Person") + .joins("INNER JOIN people ON people.id = notifications.target_id") + .joins("LEFT OUTER JOIN contacts ON contacts.person_id = people.id " \ + "AND contacts.user_id = notifications.recipient_id") + .delete_all("contacts.id IS NULL") + end +end diff --git a/db/schema.rb b/db/schema.rb index f0002b483b0e1fd776102770765aa31c65e113ee..593703cb4acf66182ee3d3f810741a2ac6ecf5b3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160327103605) do +ActiveRecord::Schema.define(version: 20160822212739) do create_table "account_deletions", force: :cascade do |t| t.string "diaspora_handle", limit: 255 @@ -31,11 +31,9 @@ ActiveRecord::Schema.define(version: 20160327103605) do add_index "aspect_memberships", ["contact_id"], name: "index_aspect_memberships_on_contact_id", using: :btree create_table "aspect_visibilities", force: :cascade do |t| - t.integer "shareable_id", limit: 4, null: false - t.integer "aspect_id", limit: 4, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "shareable_type", limit: 255, default: "Post", null: false + t.integer "shareable_id", limit: 4, null: false + t.integer "aspect_id", limit: 4, null: false + t.string "shareable_type", limit: 255, default: "Post", null: false end add_index "aspect_visibilities", ["aspect_id"], name: "index_aspect_visibilities_on_aspect_id", using: :btree @@ -55,6 +53,22 @@ ActiveRecord::Schema.define(version: 20160327103605) do add_index "aspects", ["user_id", "contacts_visible"], name: "index_aspects_on_user_id_and_contacts_visible", using: :btree add_index "aspects", ["user_id"], name: "index_aspects_on_user_id", using: :btree + create_table "authorizations", force: :cascade do |t| + t.integer "user_id", limit: 4 + t.integer "o_auth_application_id", limit: 4 + t.string "refresh_token", limit: 255 + t.string "code", limit: 255 + t.string "redirect_uri", limit: 255 + t.string "nonce", limit: 255 + t.string "scopes", limit: 255 + t.boolean "code_used", default: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "authorizations", ["o_auth_application_id"], name: "index_authorizations_on_o_auth_application_id", using: :btree + add_index "authorizations", ["user_id"], name: "index_authorizations_on_user_id", using: :btree + create_table "blocks", force: :cascade do |t| t.integer "user_id", limit: 4 t.integer "person_id", limit: 4 @@ -86,17 +100,25 @@ ActiveRecord::Schema.define(version: 20160327103605) do t.datetime "created_at", null: false end + create_table "comment_signatures", id: false, force: :cascade do |t| + t.integer "comment_id", limit: 4, null: false + t.text "author_signature", limit: 65535, null: false + t.integer "signature_order_id", limit: 4, null: false + t.text "additional_data", limit: 65535 + end + + add_index "comment_signatures", ["comment_id"], name: "index_comment_signatures_on_comment_id", unique: true, using: :btree + add_index "comment_signatures", ["signature_order_id"], name: "comment_signatures_signature_orders_id_fk", using: :btree + create_table "comments", force: :cascade do |t| - t.text "text", limit: 65535, null: false - t.integer "commentable_id", limit: 4, null: false - t.integer "author_id", limit: 4, null: false - t.string "guid", limit: 255, null: false - t.text "author_signature", limit: 65535 - t.text "parent_author_signature", limit: 65535 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "likes_count", limit: 4, default: 0, null: false - t.string "commentable_type", limit: 60, default: "Post", null: false + t.text "text", limit: 65535, null: false + t.integer "commentable_id", limit: 4, null: false + t.integer "author_id", limit: 4, null: false + t.string "guid", limit: 255, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "likes_count", limit: 4, default: 0, null: false + t.string "commentable_type", limit: 60, default: "Post", null: false end add_index "comments", ["author_id"], name: "index_comments_on_person_id", using: :btree @@ -136,6 +158,7 @@ ActiveRecord::Schema.define(version: 20160327103605) do end add_index "conversations", ["author_id"], name: "conversations_author_id_fk", using: :btree + add_index "conversations", ["guid"], name: "index_conversations_on_guid", unique: true, length: {"guid"=>191}, using: :btree create_table "invitation_codes", force: :cascade do |t| t.string "token", limit: 255 @@ -145,33 +168,24 @@ ActiveRecord::Schema.define(version: 20160327103605) do t.datetime "updated_at", null: false end - create_table "invitations", force: :cascade do |t| - t.text "message", limit: 65535 - t.integer "sender_id", limit: 4 - t.integer "recipient_id", limit: 4 - t.integer "aspect_id", limit: 4 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "service", limit: 255 - t.string "identifier", limit: 255 - t.boolean "admin", default: false - t.string "language", limit: 255, default: "en" + create_table "like_signatures", id: false, force: :cascade do |t| + t.integer "like_id", limit: 4, null: false + t.text "author_signature", limit: 65535, null: false + t.integer "signature_order_id", limit: 4, null: false + t.text "additional_data", limit: 65535 end - add_index "invitations", ["aspect_id"], name: "index_invitations_on_aspect_id", using: :btree - add_index "invitations", ["recipient_id"], name: "index_invitations_on_recipient_id", using: :btree - add_index "invitations", ["sender_id"], name: "index_invitations_on_sender_id", using: :btree + add_index "like_signatures", ["like_id"], name: "index_like_signatures_on_like_id", unique: true, using: :btree + add_index "like_signatures", ["signature_order_id"], name: "like_signatures_signature_orders_id_fk", using: :btree create_table "likes", force: :cascade do |t| - t.boolean "positive", default: true - t.integer "target_id", limit: 4 - t.integer "author_id", limit: 4 - t.string "guid", limit: 255 - t.text "author_signature", limit: 65535 - t.text "parent_author_signature", limit: 65535 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "target_type", limit: 60, null: false + t.boolean "positive", default: true + t.integer "target_id", limit: 4 + t.integer "author_id", limit: 4 + t.string "guid", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "target_type", limit: 60, null: false end add_index "likes", ["author_id"], name: "likes_author_id_fk", using: :btree @@ -198,18 +212,18 @@ ActiveRecord::Schema.define(version: 20160327103605) do add_index "mentions", ["post_id"], name: "index_mentions_on_post_id", using: :btree create_table "messages", force: :cascade do |t| - t.integer "conversation_id", limit: 4, null: false - t.integer "author_id", limit: 4, null: false - t.string "guid", limit: 255, null: false - t.text "text", limit: 65535, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.text "author_signature", limit: 65535 - t.text "parent_author_signature", limit: 65535 + t.integer "conversation_id", limit: 4, null: false + t.integer "author_id", limit: 4, null: false + t.string "guid", limit: 255, null: false + t.text "text", limit: 65535, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.text "author_signature", limit: 65535 end add_index "messages", ["author_id"], name: "index_messages_on_author_id", using: :btree add_index "messages", ["conversation_id"], name: "messages_conversation_id_fk", using: :btree + add_index "messages", ["guid"], name: "index_messages_on_guid", unique: true, length: {"guid"=>191}, using: :btree create_table "notification_actors", force: :cascade do |t| t.integer "notification_id", limit: 4 @@ -236,6 +250,43 @@ ActiveRecord::Schema.define(version: 20160327103605) do add_index "notifications", ["target_id"], name: "index_notifications_on_target_id", using: :btree add_index "notifications", ["target_type", "target_id"], name: "index_notifications_on_target_type_and_target_id", length: {"target_type"=>190, "target_id"=>nil}, using: :btree + create_table "o_auth_access_tokens", force: :cascade do |t| + t.integer "authorization_id", limit: 4 + t.string "token", limit: 255 + t.datetime "expires_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "o_auth_access_tokens", ["authorization_id"], name: "index_o_auth_access_tokens_on_authorization_id", using: :btree + add_index "o_auth_access_tokens", ["token"], name: "index_o_auth_access_tokens_on_token", unique: true, length: {"token"=>191}, using: :btree + + create_table "o_auth_applications", force: :cascade do |t| + t.integer "user_id", limit: 4 + t.string "client_id", limit: 255 + t.string "client_secret", limit: 255 + t.string "client_name", limit: 255 + t.text "redirect_uris", limit: 65535 + t.string "response_types", limit: 255 + t.string "grant_types", limit: 255 + t.string "application_type", limit: 255, default: "web" + t.string "contacts", limit: 255 + t.string "logo_uri", limit: 255 + t.string "client_uri", limit: 255 + t.string "policy_uri", limit: 255 + t.string "tos_uri", limit: 255 + t.string "sector_identifier_uri", limit: 255 + t.string "token_endpoint_auth_method", limit: 255 + t.text "jwks", limit: 65535 + t.string "jwks_uri", limit: 255 + t.boolean "ppid", default: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "o_auth_applications", ["client_id"], name: "index_o_auth_applications_on_client_id", unique: true, length: {"client_id"=>191}, using: :btree + add_index "o_auth_applications", ["user_id"], name: "index_o_auth_applications_on_user_id", using: :btree + create_table "o_embed_caches", force: :cascade do |t| t.string "url", limit: 1024, null: false t.text "data", limit: 65535, null: false @@ -252,23 +303,21 @@ ActiveRecord::Schema.define(version: 20160327103605) do end create_table "participations", force: :cascade do |t| - t.string "guid", limit: 255 - t.integer "target_id", limit: 4 - t.string "target_type", limit: 60, null: false - t.integer "author_id", limit: 4 - t.text "author_signature", limit: 65535 - t.text "parent_author_signature", limit: 65535 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "guid", limit: 255 + t.integer "target_id", limit: 4 + t.string "target_type", limit: 60, null: false + t.integer "author_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "count", limit: 4, default: 1, null: false end add_index "participations", ["author_id"], name: "index_participations_on_author_id", using: :btree add_index "participations", ["guid"], name: "index_participations_on_guid", length: {"guid"=>191}, using: :btree - add_index "participations", ["target_id", "target_type", "author_id"], name: "index_participations_on_target_id_and_target_type_and_author_id", using: :btree + add_index "participations", ["target_id", "target_type", "author_id"], name: "index_participations_on_target_id_and_target_type_and_author_id", unique: true, using: :btree create_table "people", force: :cascade do |t| t.string "guid", limit: 255, null: false - t.text "url", limit: 65535, null: false t.string "diaspora_handle", limit: 255, null: false t.text "serialized_public_key", limit: 65535, null: false t.integer "owner_id", limit: 4 @@ -276,17 +325,17 @@ ActiveRecord::Schema.define(version: 20160327103605) do t.datetime "updated_at", null: false t.boolean "closed_account", default: false t.integer "fetch_status", limit: 4, default: 0 + t.integer "pod_id", limit: 4 end add_index "people", ["diaspora_handle"], name: "index_people_on_diaspora_handle", unique: true, length: {"diaspora_handle"=>191}, using: :btree add_index "people", ["guid"], name: "index_people_on_guid", unique: true, length: {"guid"=>191}, using: :btree add_index "people", ["owner_id"], name: "index_people_on_owner_id", unique: true, using: :btree + add_index "people", ["pod_id"], name: "people_pod_id_fk", using: :btree create_table "photos", force: :cascade do |t| - t.integer "tmp_old_id", limit: 4 t.integer "author_id", limit: 4, null: false t.boolean "public", default: false, null: false - t.string "diaspora_handle", limit: 255 t.string "guid", limit: 255, null: false t.boolean "pending", default: false, null: false t.text "text", limit: 65535 @@ -303,14 +352,28 @@ ActiveRecord::Schema.define(version: 20160327103605) do t.integer "width", limit: 4 end + add_index "photos", ["guid"], name: "index_photos_on_guid", unique: true, length: {"guid"=>191}, using: :btree add_index "photos", ["status_message_guid"], name: "index_photos_on_status_message_guid", length: {"status_message_guid"=>191}, using: :btree create_table "pods", force: :cascade do |t| - t.string "host", limit: 255 + t.string "host", limit: 255 t.boolean "ssl" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "status", limit: 4, default: 0 + t.datetime "checked_at", default: '1970-01-01 00:00:00' + t.datetime "offline_since" + t.integer "response_time", limit: 4, default: -1 + t.string "software", limit: 255 + t.string "error", limit: 255 + t.integer "port", limit: 4 + t.boolean "blocked", default: false + end + + add_index "pods", ["checked_at"], name: "index_pods_on_checked_at", using: :btree + add_index "pods", ["host", "port"], name: "index_pods_on_host_and_port", unique: true, length: {"host"=>190, "port"=>nil}, using: :btree + add_index "pods", ["offline_since"], name: "index_pods_on_offline_since", using: :btree + add_index "pods", ["status"], name: "index_pods_on_status", using: :btree create_table "poll_answers", force: :cascade do |t| t.string "answer", limit: 255, null: false @@ -319,19 +382,29 @@ ActiveRecord::Schema.define(version: 20160327103605) do t.integer "vote_count", limit: 4, default: 0 end + add_index "poll_answers", ["guid"], name: "index_poll_answers_on_guid", unique: true, length: {"guid"=>191}, using: :btree add_index "poll_answers", ["poll_id"], name: "index_poll_answers_on_poll_id", using: :btree + create_table "poll_participation_signatures", id: false, force: :cascade do |t| + t.integer "poll_participation_id", limit: 4, null: false + t.text "author_signature", limit: 65535, null: false + t.integer "signature_order_id", limit: 4, null: false + t.text "additional_data", limit: 65535 + end + + add_index "poll_participation_signatures", ["poll_participation_id"], name: "index_poll_participation_signatures_on_poll_participation_id", unique: true, using: :btree + add_index "poll_participation_signatures", ["signature_order_id"], name: "poll_participation_signatures_signature_orders_id_fk", using: :btree + create_table "poll_participations", force: :cascade do |t| - t.integer "poll_answer_id", limit: 4, null: false - t.integer "author_id", limit: 4, null: false - t.integer "poll_id", limit: 4, null: false - t.string "guid", limit: 255 - t.text "author_signature", limit: 65535 - t.text "parent_author_signature", limit: 65535 + t.integer "poll_answer_id", limit: 4, null: false + t.integer "author_id", limit: 4, null: false + t.integer "poll_id", limit: 4, null: false + t.string "guid", limit: 255 t.datetime "created_at" t.datetime "updated_at" end + add_index "poll_participations", ["guid"], name: "index_poll_participations_on_guid", unique: true, length: {"guid"=>191}, using: :btree add_index "poll_participations", ["poll_id"], name: "index_poll_participations_on_poll_id", using: :btree create_table "polls", force: :cascade do |t| @@ -343,38 +416,24 @@ ActiveRecord::Schema.define(version: 20160327103605) do t.datetime "updated_at" end + add_index "polls", ["guid"], name: "index_polls_on_guid", unique: true, length: {"guid"=>191}, using: :btree add_index "polls", ["status_message_id"], name: "index_polls_on_status_message_id", using: :btree create_table "posts", force: :cascade do |t| t.integer "author_id", limit: 4, null: false t.boolean "public", default: false, null: false - t.string "diaspora_handle", limit: 255 t.string "guid", limit: 255, null: false - t.boolean "pending", default: false, null: false t.string "type", limit: 40, null: false t.text "text", limit: 65535 - t.text "remote_photo_path", limit: 65535 - t.string "remote_photo_name", limit: 255 - t.string "random_string", limit: 255 - t.string "processed_image", limit: 255 t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "unprocessed_image", limit: 255 - t.string "object_url", limit: 255 - t.string "image_url", limit: 255 - t.integer "image_height", limit: 4 - t.integer "image_width", limit: 4 t.string "provider_display_name", limit: 255 - t.string "actor_url", limit: 255 - t.string "objectId", limit: 255 t.string "root_guid", limit: 255 - t.string "status_message_guid", limit: 255 t.integer "likes_count", limit: 4, default: 0 t.integer "comments_count", limit: 4, default: 0 t.integer "o_embed_cache_id", limit: 4 t.integer "reshares_count", limit: 4, default: 0 t.datetime "interacted_at" - t.string "frame_name", limit: 255 t.string "facebook_id", limit: 255 t.string "tweet_id", limit: 255 t.integer "open_graph_cache_id", limit: 4 @@ -385,11 +444,20 @@ ActiveRecord::Schema.define(version: 20160327103605) do add_index "posts", ["author_id"], name: "index_posts_on_person_id", using: :btree add_index "posts", ["guid"], name: "index_posts_on_guid", unique: true, length: {"guid"=>191}, using: :btree add_index "posts", ["id", "type", "created_at"], name: "index_posts_on_id_and_type_and_created_at", using: :btree + add_index "posts", ["id", "type"], name: "index_posts_on_id_and_type", using: :btree add_index "posts", ["root_guid"], name: "index_posts_on_root_guid", length: {"root_guid"=>191}, using: :btree - add_index "posts", ["status_message_guid", "pending"], name: "index_posts_on_status_message_guid_and_pending", length: {"status_message_guid"=>190, "pending"=>nil}, using: :btree - add_index "posts", ["status_message_guid"], name: "index_posts_on_status_message_guid", length: {"status_message_guid"=>191}, using: :btree add_index "posts", ["tweet_id"], name: "index_posts_on_tweet_id", length: {"tweet_id"=>191}, using: :btree - add_index "posts", ["type", "pending", "id"], name: "index_posts_on_type_and_pending_and_id", using: :btree + + create_table "ppid", force: :cascade do |t| + t.integer "o_auth_application_id", limit: 4 + t.integer "user_id", limit: 4 + t.string "guid", limit: 32 + t.string "string", limit: 32 + t.string "identifier", limit: 255 + end + + add_index "ppid", ["o_auth_application_id"], name: "index_ppid_on_o_auth_application_id", using: :btree + add_index "ppid", ["user_id"], name: "index_ppid_on_user_id", using: :btree create_table "profiles", force: :cascade do |t| t.string "diaspora_handle", limit: 255 @@ -408,6 +476,7 @@ ActiveRecord::Schema.define(version: 20160327103605) do t.string "location", limit: 255 t.string "full_name", limit: 70 t.boolean "nsfw", default: false + t.boolean "public_details", default: false end add_index "profiles", ["full_name", "searchable"], name: "index_profiles_on_full_name_and_searchable", using: :btree @@ -461,18 +530,22 @@ ActiveRecord::Schema.define(version: 20160327103605) do add_index "services", ["user_id"], name: "index_services_on_user_id", using: :btree create_table "share_visibilities", force: :cascade do |t| - t.integer "shareable_id", limit: 4, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.boolean "hidden", default: false, null: false - t.integer "contact_id", limit: 4, null: false - t.string "shareable_type", limit: 60, default: "Post", null: false + t.integer "shareable_id", limit: 4, null: false + t.boolean "hidden", default: false, null: false + t.string "shareable_type", limit: 60, default: "Post", null: false + t.integer "user_id", limit: 4, null: false end - add_index "share_visibilities", ["contact_id"], name: "index_post_visibilities_on_contact_id", using: :btree - add_index "share_visibilities", ["shareable_id", "shareable_type", "contact_id"], name: "shareable_and_contact_id", using: :btree - add_index "share_visibilities", ["shareable_id", "shareable_type", "hidden", "contact_id"], name: "shareable_and_hidden_and_contact_id", using: :btree + add_index "share_visibilities", ["shareable_id", "shareable_type", "hidden", "user_id"], name: "shareable_and_hidden_and_user_id", using: :btree + add_index "share_visibilities", ["shareable_id", "shareable_type", "user_id"], name: "shareable_and_user_id", using: :btree add_index "share_visibilities", ["shareable_id"], name: "index_post_visibilities_on_post_id", using: :btree + add_index "share_visibilities", ["user_id"], name: "index_share_visibilities_on_user_id", using: :btree + + create_table "signature_orders", force: :cascade do |t| + t.string "order", limit: 255, null: false + end + + add_index "signature_orders", ["order"], name: "index_signature_orders_on_order", unique: true, length: {"order"=>191}, using: :btree create_table "simple_captcha_data", force: :cascade do |t| t.string "key", limit: 40 @@ -524,15 +597,13 @@ ActiveRecord::Schema.define(version: 20160327103605) do end create_table "users", force: :cascade do |t| - t.string "username", limit: 255 + t.string "username", limit: 255, null: false t.text "serialized_private_key", limit: 65535 t.boolean "getting_started", default: true, null: false t.boolean "disable_mail", default: false, null: false t.string "language", limit: 255 t.string "email", limit: 255, default: "", null: false t.string "encrypted_password", limit: 255, default: "", null: false - t.string "invitation_token", limit: 60 - t.datetime "invitation_sent_at" t.string "reset_password_token", limit: 255 t.datetime "remember_created_at" t.integer "sign_in_count", limit: 4, default: 0 @@ -542,11 +613,7 @@ ActiveRecord::Schema.define(version: 20160327103605) do t.string "last_sign_in_ip", limit: 255 t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "invitation_service", limit: 127 - t.string "invitation_identifier", limit: 127 - t.integer "invitation_limit", limit: 4 t.integer "invited_by_id", limit: 4 - t.string "invited_by_type", limit: 255 t.string "authentication_token", limit: 30 t.string "unconfirmed_email", limit: 255 t.string "confirm_email_token", limit: 30 @@ -565,30 +632,40 @@ ActiveRecord::Schema.define(version: 20160327103605) do t.string "exported_photos_file", limit: 255 t.datetime "exported_photos_at" t.boolean "exporting_photos", default: false + t.string "color_theme", limit: 255 end add_index "users", ["authentication_token"], name: "index_users_on_authentication_token", unique: true, using: :btree - add_index "users", ["email"], name: "index_users_on_email", length: {"email"=>191}, using: :btree - add_index "users", ["invitation_service", "invitation_identifier"], name: "index_users_on_invitation_service_and_invitation_identifier", unique: true, length: {"invitation_service"=>64, "invitation_identifier"=>nil}, using: :btree - add_index "users", ["invitation_token"], name: "index_users_on_invitation_token", using: :btree + add_index "users", ["email"], name: "index_users_on_email", unique: true, length: {"email"=>191}, using: :btree add_index "users", ["username"], name: "index_users_on_username", unique: true, length: {"username"=>191}, using: :btree add_foreign_key "aspect_memberships", "aspects", name: "aspect_memberships_aspect_id_fk", on_delete: :cascade add_foreign_key "aspect_memberships", "contacts", name: "aspect_memberships_contact_id_fk", on_delete: :cascade add_foreign_key "aspect_visibilities", "aspects", name: "aspect_visibilities_aspect_id_fk", on_delete: :cascade + add_foreign_key "authorizations", "o_auth_applications" + add_foreign_key "authorizations", "users" + add_foreign_key "comment_signatures", "comments", name: "comment_signatures_comment_id_fk", on_delete: :cascade + add_foreign_key "comment_signatures", "signature_orders", name: "comment_signatures_signature_orders_id_fk" add_foreign_key "comments", "people", column: "author_id", name: "comments_author_id_fk", on_delete: :cascade add_foreign_key "contacts", "people", name: "contacts_person_id_fk", on_delete: :cascade add_foreign_key "conversation_visibilities", "conversations", name: "conversation_visibilities_conversation_id_fk", on_delete: :cascade add_foreign_key "conversation_visibilities", "people", name: "conversation_visibilities_person_id_fk", on_delete: :cascade add_foreign_key "conversations", "people", column: "author_id", name: "conversations_author_id_fk", on_delete: :cascade - add_foreign_key "invitations", "users", column: "recipient_id", name: "invitations_recipient_id_fk", on_delete: :cascade - add_foreign_key "invitations", "users", column: "sender_id", name: "invitations_sender_id_fk", on_delete: :cascade + add_foreign_key "like_signatures", "likes", name: "like_signatures_like_id_fk", on_delete: :cascade + add_foreign_key "like_signatures", "signature_orders", name: "like_signatures_signature_orders_id_fk" add_foreign_key "likes", "people", column: "author_id", name: "likes_author_id_fk", on_delete: :cascade add_foreign_key "messages", "conversations", name: "messages_conversation_id_fk", on_delete: :cascade add_foreign_key "messages", "people", column: "author_id", name: "messages_author_id_fk", on_delete: :cascade add_foreign_key "notification_actors", "notifications", name: "notification_actors_notification_id_fk", on_delete: :cascade + add_foreign_key "o_auth_access_tokens", "authorizations" + add_foreign_key "o_auth_applications", "users" + add_foreign_key "people", "pods", name: "people_pod_id_fk", on_delete: :cascade + add_foreign_key "poll_participation_signatures", "poll_participations", name: "poll_participation_signatures_poll_participation_id_fk", on_delete: :cascade + add_foreign_key "poll_participation_signatures", "signature_orders", name: "poll_participation_signatures_signature_orders_id_fk" add_foreign_key "posts", "people", column: "author_id", name: "posts_author_id_fk", on_delete: :cascade + add_foreign_key "ppid", "o_auth_applications" + add_foreign_key "ppid", "users" add_foreign_key "profiles", "people", name: "profiles_person_id_fk", on_delete: :cascade add_foreign_key "services", "users", name: "services_user_id_fk", on_delete: :cascade - add_foreign_key "share_visibilities", "contacts", name: "post_visibilities_contact_id_fk", on_delete: :cascade + add_foreign_key "share_visibilities", "users", name: "share_visibilities_user_id_fk", on_delete: :cascade end diff --git a/features/desktop/accepts_invitation.feature b/features/desktop/accepts_invitation.feature deleted file mode 100644 index 02a02a7ef38e230d4c4e3e4c8a5260f0c7436d24..0000000000000000000000000000000000000000 --- a/features/desktop/accepts_invitation.feature +++ /dev/null @@ -1,45 +0,0 @@ -@javascript -Feature: invitation acceptance - Scenario: accept invitation from admin - Given I have been invited by an admin - And I am on my acceptance form page - And I fill in the new user form - And I press "Sign up" - Then I should be on the getting started page - And I should see "Well, hello there!" - And I fill in the following: - | profile_first_name | O | - - And I follow "awesome_button" - And I confirm the alert - Then I should be on the stream page - And I close the publisher - - Scenario: accept invitation from user - Given I have been invited by bob - And I am on my acceptance form page - And I fill in the new user form - And I press "Sign up" - Then I should be on the getting started page - And I should see "Well, hello there!" - And I fill in the following: - | profile_first_name | O | - - And I follow "awesome_button" - And I confirm the alert - Then I should be on the stream page - And I close the publisher - And I log out - And I sign in as "bob@bob.bob" - And I click on selector ".btn-link[data-target='#invitationsModal']" - Then I should see one less invite - - Scenario: sends an invitation - Given a user with email "bob@bob.bob" - When I sign in as "bob@bob.bob" - And I click on selector ".btn-link[data-target='#invitationsModal']" - And I fill in the following: - | email_inviter_emails | alex@example.com | - And I press "Send an invitation" - Then I should have 1 Devise email delivery - And I should not see "change your notification settings" in the last sent email diff --git a/features/desktop/activity_stream.feature b/features/desktop/activity_stream.feature new file mode 100644 index 0000000000000000000000000000000000000000..7fb9e5277425714b11ff2118f5106f86ea67a55d --- /dev/null +++ b/features/desktop/activity_stream.feature @@ -0,0 +1,36 @@ +@javascript +Feature: The activity stream + Background: + Given following users exist: + | username | email | + | Bob Jones | bob@bob.bob | + | Alice Smith | alice@alice.alice | + And a user with email "bob@bob.bob" is connected with "alice@alice.alice" + When "alice@alice.alice" has posted a status message with a photo + + Scenario: delete a comment + When "bob@bob.bob" has commented "is that a poodle?" on "Look at this dog" + And I sign in as "bob@bob.bob" + And I go to the activity stream page + Then I should see "Look at this dog" + And I should see "is that a poodle?" + + When I am on "alice@alice.alice"'s page + And I confirm the alert after I click to delete the first comment + + And I go to the activity stream page + Then I should not see "Look at this dog" + + Scenario: unliking a post + When I sign in as "bob@bob.bob" + And I am on "alice@alice.alice"'s page + Then I should see "Look at this dog" + + When I like the post "Look at this dog" in the stream + And I go to the activity stream page + Then I should see "Look at this dog" + + When I am on "alice@alice.alice"'s page + And I unlike the post "Look at this dog" in the stream + And I go to the activity stream page + Then I should not see "Look at this dog" diff --git a/features/desktop/aspect_navigation.feature b/features/desktop/aspect_navigation.feature index 84d6018577695507f9f7d49d58b828c0f09c667d..d6a70ab3b934e7d6a7974177e218621faf799742 100644 --- a/features/desktop/aspect_navigation.feature +++ b/features/desktop/aspect_navigation.feature @@ -17,6 +17,9 @@ Feature: Aspect navigation on the left menu Scenario: Aspects selection is remembered through site navigation When I select only "Besties" aspect + Then I should be on the aspects page + + When I go to the stream page And I go to the aspects page Then I should see "Besties" aspect selected And I should see "Unicorns" aspect unselected diff --git a/features/desktop/blocks_user.feature b/features/desktop/blocks_user.feature index b93bf28c89ae750b62c335a36d553d1db426c8a8..d0beb8a8c3236ee7d7be8882dbb8bb3ad96fd861 100644 --- a/features/desktop/blocks_user.feature +++ b/features/desktop/blocks_user.feature @@ -7,16 +7,17 @@ Feature: Blocking a user from the stream | Alice Smith | alice@alice.alice | And a user with email "bob@bob.bob" is connected with "alice@alice.alice" And Alice has a post mentioning Bob + And "alice@alice.alice" has a public post with text "All your base are belong to us!" And I sign in as "bob@bob.bob" Scenario: Blocking a user - When I click on the first block button - And I confirm the alert + When I confirm the alert after I click on the first block button And I go to the home page Then I should not see any posts in my stream Scenario: Blocking a user from the profile page When I am on "alice@alice.alice"'s page - When I click on the profile block button - And I confirm the alert + And I confirm the alert after I click on the profile block button + Then "All your base are belong to us!" should be post 1 + When I go to the home page Then I should not see any posts in my stream diff --git a/features/desktop/change_email.feature b/features/desktop/change_email.feature index 87eed0b013e82de17373663456dabca5d7672454..c13b532752fa0210f49e30da10a7c449da769132 100644 --- a/features/desktop/change_email.feature +++ b/features/desktop/change_email.feature @@ -3,7 +3,7 @@ Feature: Change email Scenario: Change my email Given I am signed in - When I go to the users edit page + When I go to the edit user page And I fill in the following: | user_email | new_email@newplac.es | And I press "Change email" @@ -14,7 +14,7 @@ Feature: Change email Scenario: Change my email preferences Given I am signed in - When I go to the users edit page + When I go to the edit user page And I uncheck "user_email_preferences_mentioned" And I press "change_email_preferences" Then I should see "Email notifications changed" diff --git a/features/desktop/change_password.feature b/features/desktop/change_password.feature index 4b20caa56b69af1f7436c6020be7e63144252922..f37ebe0455ceaa7a2a41d587505e617aa7b415e4 100644 --- a/features/desktop/change_password.feature +++ b/features/desktop/change_password.feature @@ -3,7 +3,7 @@ Feature: Change password Scenario: Change my password Given I am signed in - When I go to the users edit page + When I go to the edit user page And I fill out change password section with my password and "newsecret" and "newsecret" And I press "Change password" Then I should see "Password changed" @@ -27,8 +27,8 @@ Feature: Change password And I submit forgot password form Then I should see "You will receive an email with instructions" When I follow the "Change my password" link from the last sent email - When I fill out reset password form with "supersecret" and "supersecret" - And I submit reset password form + When I fill out the password reset form with "supersecret" and "supersecret" + And I submit the password reset form Then I should be on the stream page And I sign out manually And I sign in manually as "georges_abitbol" with password "supersecret" @@ -40,7 +40,7 @@ Feature: Change password When I fill out forgot password form with "forgetful@users.net" And I submit forgot password form When I follow the "Change my password" link from the last sent email - When I fill out reset password form with "too" and "short" + When I fill out the password reset form with "too" and "short" And I press "Change my password" Then I should be on the user password page And I should see "Password is too short" diff --git a/features/desktop/closes_account.feature b/features/desktop/closes_account.feature index 3f8cf71abcf38bf42c4cb3dd21f4b3df2e6fc375..613029c1369f66287bb4adcfda8e2be57407c261 100644 --- a/features/desktop/closes_account.feature +++ b/features/desktop/closes_account.feature @@ -6,11 +6,12 @@ Feature: Close account Scenario: user closes account Given I am signed in - When I go to the users edit page + When I go to the edit user page And I click on selector "#close_account" - And I put in my password in "close_account_password" - And I press "close_account_confirm" - And I confirm the alert + Then I should see a modal + And I should see "Hey, please don’t go!" within "#closeAccountModal" + When I put in my password in "close_account_password" + And I confirm the alert after I press "Close account" in the modal Then I should be on the new user session page When I try to sign in manually diff --git a/features/desktop/comments.feature b/features/desktop/comments.feature index c30e7f14449a139127fdd6c5d8c2f2576c1b4584..3b9fb1aa2af640b82a653820a5d067779ada6e7d 100644 --- a/features/desktop/comments.feature +++ b/features/desktop/comments.feature @@ -11,10 +11,10 @@ Feature: commenting | Alice Smith | alice@alice.alice | And a user with email "bob@bob.bob" is connected with "alice@alice.alice" When "alice@alice.alice" has posted a status message with a photo + And I sign in as "bob@bob.bob" Scenario: comment on a post from within a user's stream - When I sign in as "bob@bob.bob" - And I am on "alice@alice.alice"'s page + When I am on "alice@alice.alice"'s page Then I should see "Look at this dog" When I focus the comment field And I fill in the following: @@ -24,63 +24,52 @@ Feature: commenting And I should see "less than a minute ago" within ".comment time" Scenario: delete a comment - When I sign in as "bob@bob.bob" + When "bob@bob.bob" has commented "is that a poodle?" on "Look at this dog" And I am on "alice@alice.alice"'s page - Then I should see "Look at this dog" - When I comment "is that a poodle?" on "Look at this dog" - And I click to delete the first comment - And I confirm the alert + Then I should see "is that a poodle?" + When I confirm the alert after I click to delete the first comment Then I should not see "is that a poodle?" Scenario: expand the comment form in the main stream and an individual aspect stream - When I sign in as "bob@bob.bob" Then I should see "Look at this dog" - Then the first comment field should be closed + And the first comment field should be closed When I focus the comment field Then the first comment field should be open When I select only "Besties" aspect Then I should see "Look at this dog" - Then the first comment field should be closed + And the first comment field should be closed When I focus the comment field Then the first comment field should be open Scenario: comment on a status show page - When I sign in as "bob@bob.bob" - And I am on "alice@alice.alice"'s page + When I am on "alice@alice.alice"'s page Then I should see "Look at this dog" When I follow "less than a minute ago" Then I should see "Look at this dog" - And I make a show page comment "I think thats a cat" + When I make a show page comment "I think that’s a cat" Then I should see "less than a minute ago" within "#comments" When I go to "alice@alice.alice"'s page - Then I should see "I think thats a cat" + Then I should see "I think that’s a cat" Scenario: permalink to comment from within a users stream - When I sign in as "bob@bob.bob" + When "bob@bob.bob" has commented a lot on "Look at this dog" + And "bob@bob.bob" has commented "I think that’s a cat" on "Look at this dog" And I am on "alice@alice.alice"'s page Then I should see "Look at this dog" - When I comment a lot on "Look at this dog" - And I focus the comment field - And I fill in the following: - | text | I think thats a cat | - And I press "Comment" - Then I should see "I think thats a cat" within ".comment:last-child" + And I should see "I think that’s a cat" within ".comment:last-child" When I follow "less than a minute ago" within ".comment:last-child" - Then I should see "I think thats a cat" within ".comment .highlighted" + Then I should see "Look at this dog" within "#single-post-content" + And I should see "I think that’s a cat" within ".comment .highlighted" And I should have scrolled down Scenario: permalink to comment from a status show page - When I sign in as "bob@bob.bob" + When "bob@bob.bob" has commented a lot on "Look at this dog" + And "bob@bob.bob" has commented "I think that’s a cat" on "Look at this dog" And I am on "alice@alice.alice"'s page Then I should see "Look at this dog" - When I comment a lot on "Look at this dog" - When I focus the comment field - And I fill in the following: - | text | I think thats a cat | - And I press "Comment" - When I follow "less than a minute ago" within "span.details.grey" - Then I should see "I think thats a cat" within ".comments .comment:last-child" + When I follow "less than a minute ago" within "span.details.gray" + Then I should see "I think that’s a cat" within ".comments .comment:last-child" When I follow "less than a minute ago" within ".comments .comment:last-child" - Then I should see "I think thats a cat" within ".comments .comment .highlighted" + Then I should see "I think that’s a cat" within ".comments .comment .highlighted" And I should have scrolled down diff --git a/features/desktop/connects_users.feature b/features/desktop/connects_users.feature index f6ac162a89b38ca1ab772931bdef431fc5e0708d..60a514e4aafa306f2d25fc9a7e9b19f3cb69c75a 100644 --- a/features/desktop/connects_users.feature +++ b/features/desktop/connects_users.feature @@ -12,30 +12,12 @@ Feature: following and being followed And I add the person to my "Besties" aspect And I sign out - Scenario: seeing a follower's posts on their profile page, but not in your stream - Given "bob@bob.bob" has a non public post with text "I am following you" - When I sign in as "alice@alice.alice" - And I am on "bob@bob.bob"'s page - Then I should see "I am following you" - - When I go to the home page - Then I should not see "I am following you" - - Scenario: seeing public posts of someone you follow - Given "alice@alice.alice" has a public post with text "I am ALICE" - - When I sign in as "bob@bob.bob" - And I am on "alice@alice.alice"'s page - Then I should see "I am ALICE" - - When I go to the home page - Then I should see "I am ALICE" - Scenario: I follow a malicious user When I sign in as "bob@bob.bob" And I go to the edit profile page And I fill in the following: | profile_first_name | <script>alert(0)// | + | profile_last_name || And I press "update_profile" Then I should be on my edit profile page @@ -44,21 +26,6 @@ Feature: following and being followed And I add the person to my "Besties" aspect Then I should see a flash message containing "You have started sharing with <script>alert(0)//!" - Scenario: seeing non-public posts of someone you follow who also follows you - When I sign in as "alice@alice.alice" - And I am on "bob@bob.bob"'s page - And I add the person to my "Besties" aspect - And I add the person to my "Unicorns" aspect - And I go to the home page - Then I should have 1 contact in "Unicorns" - And I should have 1 contact in "Besties" - - When I click the publisher and post "I am following you back" - And I sign out - And I sign in as "bob@bob.bob" - Then I should have 1 contacts in "Besties" - And I should see "I am following you back" - Scenario: adding someone who follows you while creating a new aspect When I sign in as "alice@alice.alice" And I am on "bob@bob.bob"'s page @@ -67,7 +34,7 @@ Feature: following and being followed And I press the first "a" within ".add_aspect" And I fill in "aspect_name" with "Super People" in the aspect creation modal - And I click on selector ".btn.creation" in the aspect creation modal + And I click on selector ".btn-primary" in the aspect creation modal When I go to the home page Then I should have 1 contact in "Super People" diff --git a/features/desktop/contacts.feature b/features/desktop/contacts.feature index 97bc87a1bd96b8bdacd595438169d62a750426ea..5521f74fe2b3a50f5875777cc54abc0816297e66 100644 --- a/features/desktop/contacts.feature +++ b/features/desktop/contacts.feature @@ -22,11 +22,12 @@ Feature: show contacts And I sign out And I sign in as "alice@alice.alice" And I am on "robert@grimm.grimm"'s page - Then I should see "Contacts" within "#profile_horizontal_bar" + Then I should see "Contacts" within "#profile-horizontal-bar" When I press the first "#contacts_link" - And I press the first "a" within "#people_stream .media-body" - Then I should see "Bob Jones" + Then I should see "Bob Jones" within "#people_stream .media-body" + When I add the person to my "Besties" aspect within "#people_stream" + Then I should see a flash message containing "You have started sharing with Bob Jones!" Scenario: don't see contacts of an invisible aspect list When I am on "bob@bob.bob"'s page @@ -38,4 +39,4 @@ Feature: show contacts And I sign in as "alice@alice.alice" And I am on "robert@grimm.grimm"'s page - Then I should not see "Contacts" within "#profile_horizontal_bar" + Then I should not see "Contacts" within "#profile-horizontal-bar" diff --git a/features/desktop/conversations.feature b/features/desktop/conversations.feature index d1186ae6b7bc294e2446e95e7474d6fe2d075a76..2f152b8ef8f2490c146f6b79465ff2560cec7e0a 100644 --- a/features/desktop/conversations.feature +++ b/features/desktop/conversations.feature @@ -43,3 +43,18 @@ Feature: private conversations When I sign in as "alice@alice.alice" Then I should have 2 unread private messages And I should have 2 email delivery + + Scenario: delete a conversation + When I sign in as "bob@bob.bob" + And I send a message with subject "Greetings" and text "hello, alice!" to "Alice Awesome" + Then I should see "Greetings" within "#conversation_inbox" + When I click on selector ".hide_conversation" + Then I should not see "Greetings" within "#conversation_inbox" + When I sign in as "alice@alice.alice" + Then I should have 1 unread private message + And I should have 1 email delivery + When I reply with "hey, how you doing?" + Then I should see "hey, how you doing?" within ".stream_container" + When I sign in as "bob@bob.bob" + Then I should have 1 email delivery + And I should have no unread private messages diff --git a/features/desktop/donations.feature b/features/desktop/donations.feature index 9bf0b28180c639a3e1c7cb8b425ce0b31ba60709..0985ff132cfc2d08712e47447323ed526a6210fe 100644 --- a/features/desktop/donations.feature +++ b/features/desktop/donations.feature @@ -13,4 +13,6 @@ Feature: donations Scenario: Bitcoin donations Given I have configured a Bitcoin address And I go to the home page + Then I should see "Donate" within ".info-bar" + And I click on "Donate" navbar title Then I should see the Bitcoin address diff --git a/features/desktop/edits_profile.feature b/features/desktop/edits_profile.feature index 3db0978e9a85b4b5300ec816ac9f645181eaa84c..9d07b5806366ceffa88821094e3e29d0ec005b7f 100644 --- a/features/desktop/edits_profile.feature +++ b/features/desktop/edits_profile.feature @@ -25,21 +25,27 @@ Feature: editing your profile And the "profile_gender" field should contain "Fearless" And the "profile_first_name" field should contain "Boba" And the "profile_last_name" field should contain "Fett" - And I should see "This is a bio" + And the "profile_bio" field should contain "This is a bio" And the "profile_date_year" field should be filled with "1986" And the "profile_date_month" field should be filled with "11" And the "profile_date_day" field should be filled with "30" And the "profile_location" field should be filled with "Kamino" And I should see "#starwars" within "ul#as-selections-tags" + And the "#profile_public_details" bootstrap-switch should be off When I fill in "profile[tag_string]" with "#kamino" And I press the first ".as-result-item" within ".as-results" + And I toggle the "#profile_public_details" bootstrap-switch And I press "update_profile" Then I should see "#kamino" within "ul#as-selections-tags" And I should see "#starwars" within "ul#as-selections-tags" + And the "#profile_public_details" bootstrap-switch should be on - When I attach the file "spec/fixtures/bad_urls.txt" to "file" within "#file-upload" - And I confirm the alert + When I confirm the alert after I attach the file "spec/fixtures/bad_urls.txt" to "file" within "#file-upload" And I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload" + Then I should see "button.png completed" + And I should see a "img" within "#profile_photo_upload" + + When I go to my edit profile page Then I should see a "img" within "#profile_photo_upload" diff --git a/features/desktop/follows_tags.feature b/features/desktop/follows_tags.feature index 2965df10c5f47508dee4fd37fce3921c47c90ea3..78692e71c4ee3525782f49c1b7aae2b93dbee4c6 100644 --- a/features/desktop/follows_tags.feature +++ b/features/desktop/follows_tags.feature @@ -6,21 +6,19 @@ Feature: posting Background: Given following users exist: - | username | - | bob | - | alice | - - When I sign in as "bob@bob.bob" - And I post a status with the text "I am da #boss" - When I sign out - And I sign in as "alice@alice.alice" - And I search for "#boss" + | username | email | + | Alice Smith | alice@alice.alice | + | Bob Jones | bob@bob.bob | + And "bob@bob.bob" has a public post with text "I am da #boss" + When I sign in as "alice@alice.alice" + And I go to the tag page for "boss" And I press "Follow #boss" + Then I should see a ".tag-following-action .followed" Scenario: can post a message from the tag page Then I should see "#boss" within "#publisher" - And I click the publisher and post "#boss from the tag page" - And I search for "#boss" + When I click the publisher and post "#boss from the tag page" + And I go to the tag page for "boss" Then I should see "#boss from the tag page" Scenario: see a tag that I am following @@ -35,7 +33,7 @@ Feature: posting Then I should see "#boss from the #boss tag page" within "body" Scenario: can stop following a tag from the tag page - When I press "Stop following #boss" + When I press "Following #boss" And I go to the followed tags stream page Then I should not see "#boss" within "#tags_list" @@ -43,3 +41,7 @@ Feature: posting When I go to the followed tags stream page And I unfollow the "boss" tag Then I should not see "#tag-following-boss" within "#tags_list" + + Scenario: Go to a tags page with no posts + When I go to the tag page for "NoPosts" + Then I should not see any posts in my stream diff --git a/features/desktop/invitations.feature b/features/desktop/invitations.feature index e1d857d79f09842930666949d20a96c9f766ae6a..5aafd11dff0557dcf1b3fd5d3157ff8e594b080e 100644 --- a/features/desktop/invitations.feature +++ b/features/desktop/invitations.feature @@ -1,9 +1,61 @@ @javascript Feature: Invitations + Background: + Given following users exist: + | username | email | + | Alice Smith | alice@alice.alice | - Scenario: Accepting an invitation - When I visit alice's invitation code url - When I fill in the new user form - And I press "Sign up" - Then I should see the "welcome to diaspora" message - And I should be able to friend Alice + Scenario: accept invitation from admin + Given I have been invited by an admin + And I am on my acceptance form page + And I fill in the new user form + And I press "Create account" + Then I should be on the getting started page + And I should see "Well, hello there!" + And I fill in the following: + | profile_first_name | O | + + And I confirm the alert after I follow "awesome_button" + Then I should be on the stream page + And I close the publisher + + Scenario: accept invitation from user + Given I have been invited by "alice@alice.alice" + And I am on my acceptance form page + And I fill in the new user form + And I press "Create account" + Then I should be on the getting started page + And I should see "Well, hello there!" + And I should be able to friend "alice@alice.alice" + And I fill in the following: + | profile_first_name | O | + + And I confirm the alert after I follow "awesome_button" + Then I should be on the stream page + And I close the publisher + And I log out + And I sign in as "alice@alice.alice" + And I click on "Invite your friends" navbar title + And I click on selector "#invitations-button" + Then I should see one less invite + + Scenario: sends an invitation + When I sign in as "alice@alice.alice" + And I click on "Invite your friends" navbar title + And I click on selector "#invitations-button" + And I fill in the following: + | email_inviter_emails | alex@example.com | + And I press "Send an invitation" + Then I should have 1 Devise email delivery + And I should not see "change your notification settings" in the last sent email + + Scenario: sends an invitation from the people search page + When I sign in as "alice@alice.alice" + And I search for "test" + Then I should see "Users matching test" within "#search_title" + When I click on selector "#invitations-button" + And I fill in the following: + | email_inviter_emails | alex@example.com | + And I press "Send an invitation" + Then I should have 1 Devise email delivery + And I should not see "change your notification settings" in the last sent email diff --git a/features/desktop/keyboard_navigation.feature b/features/desktop/keyboard_navigation.feature index aed65c3f65d6d35006bd794c68ce42b521cb8d86..f153e6e8fbf831f38f3e6b3c2e3f39007e6a7459 100644 --- a/features/desktop/keyboard_navigation.feature +++ b/features/desktop/keyboard_navigation.feature @@ -25,7 +25,7 @@ Feature: Keyboard navigation Scenario: navigate downwards after changing the stream When I go to the activity stream page And I click on selector "[data-stream='stream'] a" - Then I should see "Stream" within ".stream_title" + Then I should see "Stream" within "#stream_selection .selected" When I press the "J" key somewhere Then post 1 should be highlighted @@ -36,8 +36,12 @@ Feature: Keyboard navigation And I should have navigated to the highlighted post Scenario: navigate upwards - When I scroll to post 3 - And I press the "K" key somewhere + When I press the "J" key somewhere + And I press the "J" key somewhere + And I press the "J" key somewhere + Then post 3 should be highlighted + + When I press the "K" key somewhere Then post 2 should be highlighted And I should have navigated to the highlighted post @@ -46,7 +50,7 @@ Feature: Keyboard navigation When I press the "J" key somewhere And I press the "C" key somewhere Then the first comment field should be open - + Scenario: navigate downwards on a profile page When I am on "alice@alice.alice"'s page And I press the "J" key somewhere @@ -56,3 +60,18 @@ Feature: Keyboard navigation When I press the "J" key somewhere Then post 2 should be highlighted And I should have navigated to the highlighted post + + Scenario: navigate downwards on a small screen + When I resize my window to 800x600 + And I press the "J" key somewhere + Then post 1 should be highlighted + And I should have navigated to the highlighted post + + When I press the "J" key somewhere + Then post 2 should be highlighted + And I should have navigated to the highlighted post + + Given I expand the publisher + When I press the "J" key in the publisher + Then post 2 should be highlighted + And I close the publisher diff --git a/features/desktop/likes.feature b/features/desktop/likes.feature index a961ff41baa4a0dc550a79a0f074dfe274cae9e9..3fff3ce5679abd64b4afd6f20f1b9ae83821c4d4 100644 --- a/features/desktop/likes.feature +++ b/features/desktop/likes.feature @@ -15,10 +15,13 @@ Feature: Liking posts Scenario: Liking and unliking a post from the stream When I like the post "I like unicorns" in the stream - Then I should see a ".likes" within "#main_stream .stream_element" + Then I should see "Unlike" within ".stream_element .feedback" + And I should see a ".likes .media" within "#main_stream .stream_element" When I unlike the post "I like unicorns" in the stream - Then I should not see a ".likes" within "#main_stream .stream_element" + Then I should see "Like" within ".stream_element .feedback" + And I should not see a ".likes .media" within "#main_stream .stream_element" + Scenario: Liking and unliking a post from a single post page When I open the show page of the "I like unicorns" post diff --git a/features/desktop/manages_aspects.feature b/features/desktop/manages_aspects.feature index 784e05254883b0778fed46eeb572b25cc92ac1ab..30770b6689374b086b19764e4bf820bd43552203 100644 --- a/features/desktop/manages_aspects.feature +++ b/features/desktop/manages_aspects.feature @@ -7,9 +7,9 @@ Feature: User manages contacts Scenario: creating an aspect from contacts index Given I am signed in And I am on the contacts page - And I follow "+ Add an aspect" + And I follow "Add an aspect" And I fill in "aspect_name" with "Dorm Mates" in the aspect creation modal - And I click on selector ".btn.creation" in the aspect creation modal + And I click on selector ".btn-primary" in the aspect creation modal Then I should see "Dorm Mates" within "#aspect_nav" Scenario: creating an aspect from homepage @@ -17,16 +17,16 @@ Feature: User manages contacts And I go to the aspects page When I follow "Add an aspect" And I fill in "aspect_name" with "losers" in the aspect creation modal - And I click on selector ".btn.creation" in the aspect creation modal - Then I should see "losers" within "#aspect_nav" + And I click on selector ".btn-primary" in the aspect creation modal + Then I should be on the contacts page + And I should see "losers" within "#aspect_nav" Scenario: deleting an aspect from contacts index Given I am signed in And I have an aspect called "People" When I am on the contacts page And I follow "People" - And I click on selector "#delete_aspect" - And I confirm the alert + And I confirm the alert after I click on selector "#delete_aspect" Then I should be on the contacts page And I should not see "People" within "#aspect_nav" @@ -35,8 +35,7 @@ Feature: User manages contacts And I have an aspect called "People" When I am on the aspects page And I click on "People" aspect edit icon - And I click on selector "#delete_aspect" - And I confirm the alert + And I confirm the alert after I click on selector "#delete_aspect" Then I should be on the contacts page And I should not see "People" within "#aspect_nav" @@ -67,21 +66,24 @@ Feature: User manages contacts And I have 0 contacts And I click on my name in the header When I follow "Contacts" - Then I should see "Community spotlight" within ".span9" + Then I should see "Community spotlight" within ".col-md-9" Scenario: clicking on the contacts link in the header with contacts does not send a user to the featured users page Given I am signed in And I have 2 contacts And I click on my name in the header When I follow "Contacts" - Then I should not see "Community spotlight" within ".span9" + Then I should not see "Community spotlight" within ".col-md-9" Scenario: sorting the aspects Given I am signed in And I have an aspect called "People" And I have an aspect called "Cat People" When I am on the contacts page + And I have turned off jQuery effects And I drag "Cat People" up - And I go to the contacts page + Then I should see "Cat People" as 2. aspect + And I should see "People" as 3. aspect + When I go to the contacts page Then I should see "Cat People" as 2. aspect And I should see "People" as 3. aspect diff --git a/features/desktop/mentions.feature b/features/desktop/mentions.feature index 08e792ac77ec90a55e69c8ffd71e3a3a2e29d09a..9c613bcf66d9ad58444eeb0b77b26c2af9c604e6 100644 --- a/features/desktop/mentions.feature +++ b/features/desktop/mentions.feature @@ -23,8 +23,32 @@ Feature: Mentions And a user with email "bob@bob.bob" is connected with "alice@alice.alice" When I sign in as "alice@alice.alice" And I expand the publisher - When I fill in the following: - | status_message_fake_text | @Bo | + And I append "@Bob" to the publisher + And I click on the first user in the mentions dropdown list + And I press "Share" + Then I should see "Bob Jones" within ".stream_element" + When I follow "Bob Jones" + Then I should see "Bob Jones" + + Scenario: A user tries to mention another user multiple times + Given following users exist: + | username | email | + | Bob Jones | bob@bob.bob | + | Alice Smith | alice@alice.alice | + And a user with email "bob@bob.bob" is connected with "alice@alice.alice" + When I sign in as "alice@alice.alice" + And I expand the publisher + And I append "@Bob" to the publisher + Then I should see "Bob Jones" within ".tt-suggestion" + When I click on the first user in the mentions dropdown list + When I press the "A" key in the publisher + And I append "@Bob" to the publisher + Then I should not see the mentions dropdown list + When I press "Share" + Then I should see "Bob Jones" within ".stream_element" + + When I expand the publisher + And I append "@Bob" to the publisher And I click on the first user in the mentions dropdown list And I press "Share" Then I should see "Bob Jones" within ".stream_element" diff --git a/features/desktop/mentions_from_profile_page.feature b/features/desktop/mentions_from_profile_page.feature index f18812d05ea7f66a11f9089a420e7a0d04395abe..eb41c50494798c3e0824079ff34555289767aad1 100644 --- a/features/desktop/mentions_from_profile_page.feature +++ b/features/desktop/mentions_from_profile_page.feature @@ -22,7 +22,7 @@ Feature: mentioning a contact from their profile page Scenario: mentioning while posting to all aspects Given I am on "alice@alice.alice"'s page And I want to mention her from the profile - And I append "I am eating a yogurt" to the publisher + And I append "I am eating a yogurt" to the publisher in the mention modal And I press "Share" in the mention modal Then I should see a flash message indicating success When I am on the aspects page @@ -36,10 +36,10 @@ Feature: mentioning a contact from their profile page Scenario: mentioning while posting to just one aspect Given I am on "alice@alice.alice"'s page And I want to mention her from the profile + And I append "I am eating a yogurt" to the publisher in the mention modal And I press the aspect dropdown in the mention modal And I toggle the aspect "NotPostingThingsHere" in the mention modal And I press the aspect dropdown in the mention modal - And I append "I am eating a yogurt" to the publisher And I press "Share" in the mention modal Then I should see a flash message indicating success diff --git a/features/desktop/not_safe_for_work.feature b/features/desktop/not_safe_for_work.feature index 6d7f7fd7d249280cd01e6d7b17d1428c78004471..432d38947aa42e66d70ebb7bb2caaf94e23d39b9 100644 --- a/features/desktop/not_safe_for_work.feature +++ b/features/desktop/not_safe_for_work.feature @@ -42,8 +42,7 @@ Scenario: Resharing a nsfw post And "tommy@pr0nking.com" has a public post with text "Sexy Senators Gone Wild!" And I sign in as "laura@officeworkers.com" And I toggle nsfw posts - And I follow "Reshare" - And I confirm the alert + And I confirm the alert after I follow "Reshare" And I go to the home page Then I should not see "Sexy Senators Gone Wild!" And I should have 2 nsfw posts diff --git a/features/desktop/notifications.feature b/features/desktop/notifications.feature index efb697c0d8ac95ac7bd7b4a4b6e59c124d226032..70a454d615dded90a0a79b837b369634e17630d9 100644 --- a/features/desktop/notifications.feature +++ b/features/desktop/notifications.feature @@ -29,8 +29,7 @@ Feature: Notifications And "alice@alice.alice" has a public post with text "check this out!" When I sign in as "bob@bob.bob" And I am on "alice@alice.alice"'s page - And I follow "Reshare" - And I confirm the alert + And I confirm the alert after I follow "Reshare" And I sign out When I sign in as "alice@alice.alice" And I follow "Notifications" in the header @@ -54,14 +53,7 @@ Feature: Notifications Scenario: someone comments on my post Given a user with email "bob@bob.bob" is connected with "alice@alice.alice" And "alice@alice.alice" has a public post with text "check this out!" - When I sign in as "bob@bob.bob" - And I am on "alice@alice.alice"'s page - And I focus the comment field - And I fill in the following: - | text | great post! | - And I press "Comment" - Then I should see "less than a minute ago" within ".comment" - And I sign out + And "bob@bob.bob" has commented "great post!" on "check this out!" When I sign in as "alice@alice.alice" And I follow "Notifications" in the header Then the notification dropdown should be visible @@ -70,23 +62,9 @@ Feature: Notifications Scenario: unconnected user comments in reply to comment by another user who commented a post of someone who she shares with Given "alice@alice.alice" has a public post with text "check this out!" + And "bob@bob.bob" has commented "great post, alice!" on "check this out!" + And "carol@carol.carol" has commented "great comment, bob!" on "check this out!" When I sign in as "bob@bob.bob" - And I am on "alice@alice.alice"'s page - And I focus the comment field - And I fill in the following: - | text | great post, alice! | - And I press "Comment" - Then I should see "less than a minute ago" within ".comment" - When I sign out - And I sign in as "carol@carol.carol" - And I am on "alice@alice.alice"'s page - And I focus the comment field - And I fill in the following: - | text | great comment, bob! | - And I press "Comment" - Then I should see "less than a minute ago" within ".comment:nth-child(2)" - When I sign out - And I sign in as "bob@bob.bob" And I follow "Notifications" in the header Then the notification dropdown should be visible And I should see "also commented on" @@ -95,23 +73,9 @@ Feature: Notifications Scenario: unconnected user comments in reply to my comment to her post Given "alice@alice.alice" has a public post with text "check this out!" + And "carol@carol.carol" has commented "great post, alice!" on "check this out!" + And "alice@alice.alice" has commented "great comment, carol!" on "check this out!" When I sign in as "carol@carol.carol" - And I am on "alice@alice.alice"'s page - And I focus the comment field - And I fill in the following: - | text | great post, alice! | - And I press "Comment" - Then I should see "less than a minute ago" within ".comment" - When I sign out - And I sign in as "alice@alice.alice" - And I am on "alice@alice.alice"'s page - And I focus the comment field - And I fill in the following: - | text | great post, carol! | - And I press "Comment" - Then I should see "less than a minute ago" within ".comment:nth-child(2)" - When I sign out - And I sign in as "carol@carol.carol" And I follow "Notifications" in the header Then the notification dropdown should be visible And I should see "also commented on" @@ -120,23 +84,9 @@ Feature: Notifications Scenario: connected user comments in reply to my comment to an unconnected user's post Given "alice@alice.alice" has a public post with text "check this out!" And a user with email "bob@bob.bob" is connected with "carol@carol.carol" + And "carol@carol.carol" has commented "great post, alice!" on "check this out!" + And "bob@bob.bob" has commented "great post!" on "check this out!" When I sign in as "carol@carol.carol" - And I am on "alice@alice.alice"'s page - And I focus the comment field - And I fill in the following: - | text | great post! | - And I press "Comment" - Then I should see "less than a minute ago" within ".comment" - When I sign out - And I sign in as "bob@bob.bob" - And I am on "alice@alice.alice"'s page - And I focus the comment field - And I fill in the following: - | text | great post! | - And I press "Comment" - Then I should see "less than a minute ago" within ".comment:nth-child(2)" - When I sign out - And I sign in as "carol@carol.carol" And I follow "Notifications" in the header Then the notification dropdown should be visible And I should see "also commented on" @@ -168,11 +118,24 @@ Feature: Notifications And I add the person to my "Besties" aspect And I sign out When I sign in as "alice@alice.alice" + And I go to the edit profile page And I follow "Notifications" in the header - And I active the first hovercard after loading the notifications page + And I activate the first hovercard after loading the notifications page When I press the aspect dropdown Then the aspect dropdown should be visible + Scenario: show hovercard in notification dropdown + When I sign in as "bob@bob.bob" + And I am on "alice@alice.alice"'s page + And I add the person to my "Besties" aspect + And I sign out + When I sign in as "alice@alice.alice" + And I follow "Notifications" in the header + Then the notification dropdown should be visible + When I activate the first hovercard after loading the notifications page + And I press the aspect dropdown + Then the aspect dropdown should be visible + Scenario: scrollbar shows up when >5 notifications Given a user with email "bob@bob.bob" is connected with "alice@alice.alice" And Alice has 6 posts mentioning Bob diff --git a/features/desktop/oidc_auth_code_flow.feature b/features/desktop/oidc_auth_code_flow.feature new file mode 100644 index 0000000000000000000000000000000000000000..22460b7d13d3f1fda79feb67935f7583f6a84fd7 --- /dev/null +++ b/features/desktop/oidc_auth_code_flow.feature @@ -0,0 +1,26 @@ +@javascript +Feature: Access protected resources using auth code flow + Background: + Given a user with username "kent" + + Scenario: Invalid client id to auth endpoint + When I register a new client + And I send a post request from that client to the code flow authorization endpoint using a invalid client id + And I sign in as "kent@kent.kent" + Then I should see a message containing "Invalid client id or redirect uri" + + Scenario: Application is denied authorization + When I register a new client + And I send a post request from that client to the code flow authorization endpoint + And I sign in as "kent@kent.kent" + And I deny authorization to the client + Then I should not see any tokens in the redirect url + + Scenario: Application is authorized + When I register a new client + And I send a post request from that client to the code flow authorization endpoint + And I sign in as "kent@kent.kent" + And I give my consent and authorize the client + And I parse the auth code and create a request to the token endpoint + And I parse the tokens and use it obtain user info + Then I should receive "kent"'s id, username, and email diff --git a/features/desktop/oidc_implicit_flow.feature b/features/desktop/oidc_implicit_flow.feature new file mode 100644 index 0000000000000000000000000000000000000000..3e090a30346575d42536bdca175029e9c1712115 --- /dev/null +++ b/features/desktop/oidc_implicit_flow.feature @@ -0,0 +1,35 @@ +@javascript +Feature: Access protected resources using implicit flow + Background: + Given a user with username "kent" + + Scenario: Invalid client id to auth endpoint + When I register a new client + And I send a post request from that client to the authorization endpoint using a invalid client id + And I sign in as "kent@kent.kent" + Then I should see a message containing "Invalid client id or redirect uri" + + Scenario: Application is denied authorization + When I register a new client + And I send a post request from that client to the authorization endpoint + And I sign in as "kent@kent.kent" + And I deny authorization to the client + Then I should not see any tokens in the redirect url + + Scenario: Application is authorized + When I register a new client + And I send a post request from that client to the authorization endpoint + And I sign in as "kent@kent.kent" + And I give my consent and authorize the client + And I parse the bearer tokens and use it to access user info + Then I should receive "kent"'s id, username, and email + + Scenario: Application is authorized and uses small value for the max_age parameter + When I register a new client + And I sign in as "kent@kent.kent" + And I have signed in 5 minutes ago + And I send a post request from that client to the authorization endpoint with max age + And I sign in as "kent@kent.kent" + And I give my consent and authorize the client + And I parse the bearer tokens and use it to access user info + Then I should receive "kent"'s id, username, and email diff --git a/features/desktop/photo_gallery.feature b/features/desktop/photo_gallery.feature new file mode 100644 index 0000000000000000000000000000000000000000..bb86819bba5bdd8e06c359021e10ba5f2e1a394c --- /dev/null +++ b/features/desktop/photo_gallery.feature @@ -0,0 +1,15 @@ +@javascript +Feature: viewing the photo lightbox + Background: + Given a user with username "alice" + And "alice@alice.alice" has posted a status message with a photo + And I sign in as "alice@alice.alice" + + Scenario: viewing a photo + When I press the attached image + Then I should see the photo lightbox + + Scenario: closing the lightbox by clicking the close link + When I press the attached image + And I press the close lightbox link + Then I should not see the photo lightbox diff --git a/features/desktop/photo_lightbox.feature b/features/desktop/photo_lightbox.feature deleted file mode 100644 index 264280829d96b362f7671fc5e4c1bd1d529f5b76..0000000000000000000000000000000000000000 --- a/features/desktop/photo_lightbox.feature +++ /dev/null @@ -1,27 +0,0 @@ -@javascript -Feature: viewing the photo lightbox - Background: - Given a user with username "bob" - And I sign in as "bob@bob.bob" - And I expand the publisher - And I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload" - And I fill in the following: - | status_message_fake_text | Look at this dog | - And I press "Share" - - Scenario: viewing a photo - Then I should see an image attached to the post - And I press the attached image - Then I should see the photo lightbox - - Scenario: closing the lightbox by clicking the close link - Then I should see an image attached to the post - And I press the attached image - And I press the close lightbox link - Then I should not see the photo lightbox - - Scenario: closing the lightbox by clicking the backdrop - Then I should see an image attached to the post - And I press the attached image - And I press the lightbox backdrop - Then I should not see the photo lightbox diff --git a/features/desktop/post_preview.feature b/features/desktop/post_preview.feature index beb86a9740d4030dfe4b2761fad72a48c47df508..20e78547130eecced2ebc74defd2ccdf026f0444 100644 --- a/features/desktop/post_preview.feature +++ b/features/desktop/post_preview.feature @@ -16,26 +16,27 @@ Feature: preview posts in the stream Scenario: preview and post a text-only message Given I expand the publisher When I write the status message "I am eating yogurt" - And I press "Preview" - Then "I am eating yogurt" should be post 1 - And the first post should be a preview + And I preview the post + Then I should see "I am eating yogurt" in the preview + Given I edit the post When I write the status message "This preview rocks" - And I press "Preview" - Then "This preview rocks" should be post 1 - And I should not see "I am eating a yogurt" + And I preview the post + Then I should see "This preview rocks" in the preview + And I should not see "I am eating a yogurt" in the preview + Given I edit the post When I write the status message "I like rocks" And I press "Share" Then "I like rocks" should be post 1 - And I should not see "This preview rocks" + When I expand the publisher + Then I should not be in preview mode Scenario: preview a very long message Given I expand the publisher When I insert an extremely long status message - And I press "Preview" + And I preview the post Then the preview should not be collapsed - When I press "Share" Then the post should be collapsed @@ -44,30 +45,27 @@ Feature: preview posts in the stream And I attach "spec/fixtures/button.png" to the publisher When I fill in the following: | status_message_fake_text | Look at this dog | - And I press "Preview" - Then I should see a "img" within ".stream_element div.photo_attachments" - And I should see "Look at this dog" within ".stream_element" + And I preview the post + Then I should see a "img" within ".md-preview .stream_element .photo_attachments" + And I should see "Look at this dog" within ".md-preview .stream_element" And I close the publisher Scenario: preview a post with mentions Given I expand the publisher And I mention Alice in the publisher - And I press "Preview" - And I follow "Alice Smith" - And I confirm the alert + And I preview the post + And I confirm the alert after I follow "Alice Smith" Then I should see "Alice Smith" Scenario: preview a post on tag page Given there is a user "Samuel Beckett" who's tagged "#rockstar" - When I search for "#rockstar" - Then I should be on the tag page for "rockstar" - And I should see "Samuel Beckett" - Given I expand the publisher - When I fill in the following: + When I go to the tag page for "rockstar" + Then I should see "Samuel Beckett" + When I expand the publisher + And I fill in the following: | status_message_fake_text | This preview rocks | - And I press "Preview" - Then "This preview rocks" should be post 1 - And the first post should be a preview + And I preview the post + Then I should see "This preview rocks" in the preview And I close the publisher Scenario: preview a post with the poll @@ -81,7 +79,21 @@ Feature: preview posts in the stream And I fill in the following for the options: | normal | | not normal | - And I press "Preview" - Then I should see a ".poll_form" within ".stream_element" - And I should see a "form" within ".stream_element" + And I preview the post + Then I should see a ".poll_form" within ".md-preview .stream_element" + And I should see a "form" within ".md-preview .stream_element" + And I close the publisher + + Scenario: preview a post with location + Given I expand the publisher + When I fill in the following: + | status_message_fake_text | I am eating yogurt | + And I allow geolocation + And I click on selector "#locator" + When I fill in the following: + | status_message_fake_text | I am eating yogurt | + | location_address | Some cool place | + And I preview the post + Then I should see a ".near-from" within ".md-preview .stream_element" + And I should see "Some cool place" within ".md-preview .stream_element .near-from" And I close the publisher diff --git a/features/desktop/posts_from_main_page.feature b/features/desktop/posts_from_main_page.feature index 6375a4b195f52b592cf581b9ea7b828871019446..465bf8c0e07b48a7d254e4ba1b69f7c6db492014 100644 --- a/features/desktop/posts_from_main_page.feature +++ b/features/desktop/posts_from_main_page.feature @@ -24,7 +24,8 @@ Feature: posting from the main page When I expand the publisher Then I should see "You can use Markdown to format your post" within ".markdownIndications" Then I should see "All aspects" within ".options_and_submit" - Then I should see "Preview" within ".options_and_submit" + Then I should see a ".md-write-tab" within ".md-header" + Then I should see a ".md-preview-tab" within ".md-header" Scenario: post a text-only message to all aspects Given I expand the publisher @@ -156,6 +157,7 @@ Feature: posting from the main page When I expand the publisher And I press the aspect dropdown And I toggle the aspect "PostingTo" + And I press the aspect dropdown And I append "I am eating a yogurt" to the publisher And I submit the publisher @@ -171,12 +173,14 @@ Feature: posting from the main page When I expand the publisher And I press the aspect dropdown And I toggle the aspect "PostingTo" + And I press the aspect dropdown And I append "I am eating a yogurt" to the publisher And I submit the publisher And I expand the publisher And I press the aspect dropdown And I toggle the aspect "Besties" + And I press the aspect dropdown And I append "And cornflakes also" to the publisher And I submit the publisher @@ -193,6 +197,12 @@ Feature: posting from the main page And I select only "NotPostingThingsHere" aspect Then I should not see "I am eating a yogurt" and "And cornflakes also" + Scenario: Write html in the publisher + When I expand the publisher + Then I should not see any alert after I write the status message "<script>alert();</script>" + When I submit the publisher + Then "<script>alert();</script>" should be post 1 + # (NOTE) make this a jasmine spec Scenario: reject deletion one of my posts When I expand the publisher @@ -200,6 +210,5 @@ Feature: posting from the main page And I submit the publisher And I hover over the ".stream_element" - And I prepare the deletion of the first post - And I reject the alert + And I reject the alert after I prepare the deletion of the first post Then I should see "I am eating a yogurt" diff --git a/features/desktop/profile_photos.feature b/features/desktop/profile_photos.feature index 7af405fb2ccbe7787c90bbb35897e5a09621ab75..644b21ecf23a7e51652dddbbf324b4bbf6405524 100644 --- a/features/desktop/profile_photos.feature +++ b/features/desktop/profile_photos.feature @@ -7,30 +7,32 @@ Feature: show photos | Bob Jones | bob@bob.bob | | Alice Smith | alice@alice.alice | | Robert Grimm | robert@grimm.grimm | + And "robert@grimm.grimm" has posted a status message with a photo And I sign in as "robert@grimm.grimm" - Given I expand the publisher - And I have turned off jQuery effects - And I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload" - And I press "Share" - Then I should see a "img" within ".stream_element div.photo_attachments" - Scenario: see my own photos When I am on "robert@grimm.grimm"'s page - #TODO: find out why images don't show on first load - And I am on "robert@grimm.grimm"'s page And I press the first "#photos_link" Then I should be on person_photos page Scenario: I cannot see photos of people who don't share with me When I sign in as "alice@alice.alice" And I am on "robert@grimm.grimm"'s page - Then I should not see "Photos" within "#profile_horizontal_bar" + Then I should not see "Photos" within "#profile-horizontal-bar" + + Scenario: I can see public photos of people who share with me + When "robert@grimm.grimm" has posted a public status message with a photo + And I sign in as "alice@alice.alice" + And I am on "robert@grimm.grimm"'s page + Then I should see "Photos" within "#profile-horizontal-bar" + When I press the first "#photos_link" + Then I should be on "robert@grimm.grimm"'s photos page + And I should see "Photos" within "#profile-horizontal-bar" Scenario: I delete a photo When I am on "robert@grimm.grimm"'s photos page - And I delete a photo - And I confirm the alert - Then I should not see a ".stream" + Then I should see a ".thumbnail" within "#main_stream" + When I confirm the alert after I delete a photo + Then I should not see a ".thumbnail" within "#main_stream" When I am on "robert@grimm.grimm"'s page - Then I should not see "Photos" within "#profile_horizontal_bar" + Then I should not see "Photos" within "#profile-horizontal-bar" diff --git a/features/desktop/public_stream.feature b/features/desktop/public_stream.feature index 7d9c27f5dccd4fe7740abfe8fc720f2e6906c1b1..02449b93c15cf09e460c9c5a8cea21206a393b55 100644 --- a/features/desktop/public_stream.feature +++ b/features/desktop/public_stream.feature @@ -5,26 +5,10 @@ Feature: The public stream | username | email | | Alice Smith | alice@alice.alice | | Bob Jones | bob@bob.bob | - | Eve Doe | eve@eve.eve | - And a user with email "alice@alice.alice" is connected with "bob@bob.bob" + And "bob@bob.bob" has a public post with text "Bob’s public post" - And "bob@bob.bob" has a non public post with text "Bob’s private post" - And "eve@eve.eve" has a public post with text "Eve’s public post" - - Scenario: seeing public posts of someone you don't follow - When I sign in as "alice@alice.alice" - Then I should not see "Eve’s public post" - When I am on the public stream page - Then I should see "Eve’s public post" - Scenario: seeing public posts of someone you follow + Scenario: seeing public posts When I sign in as "alice@alice.alice" + And I am on the public stream page Then I should see "Bob’s public post" - When I am on the public stream page - Then I should see "Bob’s public post" - - Scenario: not seeing private posts of someone you follow - When I sign in as "alice@alice.alice" - Then I should see "Bob’s private post" - When I am on the public stream page - Then I should not see "Bob’s private post" diff --git a/features/desktop/reshare.feature b/features/desktop/reshare.feature index 26c760be5bb24396b2477efa74b03899884b6308..9c56da684c3268d0fc4dfe1f50b4b182f936da83 100644 --- a/features/desktop/reshare.feature +++ b/features/desktop/reshare.feature @@ -18,8 +18,7 @@ Feature: public repost Given I sign in as "alice@alice.alice" And I am on "bob@bob.bob"'s page And I open the show page of the "reshare this!" post - And I click on selector "a.reshare" - And I confirm the alert + And I confirm the alert after I click on selector "a.reshare" Then I should see a flash message indicating success And I should see a flash message containing "successfully" @@ -28,8 +27,7 @@ Feature: public repost And I sign in as "alice@alice.alice" And I am on "bob@bob.bob"'s page And I open the show page of the "reshare this!" post - And I click on selector "a.reshare" - And I confirm the alert + And I confirm the alert after I click on selector "a.reshare" Then I should see a flash message indicating success And I should see a flash message containing "successfully" @@ -48,8 +46,7 @@ Feature: public repost # app.stream in jasmine should be enough coverage Scenario: When I reshare, it shows up on my profile page Given I sign in as "alice@alice.alice" - And I follow "Reshare" - And I confirm the alert + And I confirm the alert after I follow "Reshare" Then I should see a flash message indicating success And I should see a flash message containing "successfully" And I should not see a ".reshare" within ".feedback" diff --git a/features/desktop/search.feature b/features/desktop/search.feature index da49164df39deee80ca1f780f7649749b22f5d93..03e8fc343e5b1eb46dcea625121804933d9bbbeb 100644 --- a/features/desktop/search.feature +++ b/features/desktop/search.feature @@ -6,28 +6,58 @@ Feature: search for users and hashtags Background: Given following users exist: - | username | email | - | Bob Jones | bob@bob.bob | - | Alice Smith | alice@alice.alice | - And I sign in as "bob@bob.bob" + | username | email | + | Bob Jones | bob@bob.bob | + | Alice Smith | alice@alice.alice | + | Carol Williams | carol@example.com | Scenario: search for a user and go to its profile - When I enter "Alice Sm" in the search input - Then I should see "Alice Smith" within ".ac_results" + When I sign in as "bob@bob.bob" + And I enter "Alice Sm" in the search input + Then I should see "Alice Smith" within ".tt-menu" When I click on the first search result Then I should see "Alice Smith" within ".profile_header #name" Scenario: search for a inexistent user and go to the search page - When I enter "Trinity" in the search input - Then I should see "Search for Trinity" within ".ac_even" + When I sign in as "bob@bob.bob" + And I enter "Trinity" in the search input + And I press enter in the search input - When I click on the first search result Then I should see "Users matching Trinity" within "#search_title" +Scenario: search for a user in background + When I sign in as "bob@bob.bob" + And I search for "user@pod.tld" + And a person with ID "user@pod.tld" has been discovered + Then I should see "user@pod.tld" within ".stream .info.diaspora_handle" + And I should see a ".aspect_dropdown" within ".stream" + +Scenario: search for a not searchable user + When I sign in as "carol@example.com" + And I go to the edit profile page + And I mark myself as not searchable + And I submit the form + Then I should be on the edit profile page + And the "profile[searchable]" checkbox should not be checked + + When I sign out + And I sign in as "bob@bob.bob" + And I enter "Carol Wi" in the search input + Then I should not see any search results + + Given a user with email "bob@bob.bob" is connected with "carol@example.com" + When I go to the home page + And I enter "Carol Wi" in the search input + Then I should see "Carol Williams" within ".tt-menu" + + When I click on the first search result + Then I should see "Carol Williams" within ".profile_header #name" + Scenario: search for a tag - When I enter "#Matrix" in the search input - Then I should see "#matrix" within ".ac_even" + When I sign in as "bob@bob.bob" + And I enter "#Matrix" in the search input + Then I should see "#Matrix" within ".tt-menu" When I click on the first search result Then I should be on the tag page for "matrix" diff --git a/features/desktop/signs_up.feature b/features/desktop/signs_up.feature index 0f955a19c13abe1973c0437fcea3516c3e7d8ac7..dbbbf73fa82bc2d7815c8a83ac1d24686e64c6cf 100644 --- a/features/desktop/signs_up.feature +++ b/features/desktop/signs_up.feature @@ -11,11 +11,11 @@ Feature: new user registration Scenario: new user goes through the setup wizard When I fill in the following: | profile_first_name | O | - And I follow "awesome_button" - And I confirm the alert + And I confirm the alert after I follow "awesome_button" Then I should be on the stream page And I close the publisher And I should not see "awesome_button" + And I should not see any posts in my stream Scenario: new user tries to XSS itself When I fill in the following: @@ -28,20 +28,17 @@ Feature: new user registration | profile_first_name | some name | And I focus the "follow_tags" field Then I should see a flash message containing "Hey, some name!" - When I follow "awesome_button" - And I reject the alert + When I reject the alert after I follow "awesome_button" Then I should be on the getting started page And I should see a flash message containing "All right, I’ll wait." Scenario: new user skips the setup wizard - When I follow "awesome_button" - And I confirm the alert + When I confirm the alert after I follow "awesome_button" Then I should be on the stream page And I close the publisher Scenario: new user without any tags posts first status message - When I follow "awesome_button" - And I confirm the alert + When I confirm the alert after I follow "awesome_button" Then I should be on the stream page When I submit the publisher Then "Hey everyone, I’m #newhere." should be post 1 @@ -57,10 +54,8 @@ Feature: new user registration Then "Hey everyone, I’m #newhere. I’m interested in #rockstar." should be post 1 Scenario: closing a popover clears getting started - When I follow "awesome_button" - And I confirm the alert + When I confirm the alert after I follow "awesome_button" Then I should be on the stream page - And I have turned off jQuery effects And I wait for the popovers to appear And I click close on all the popovers And I close the publisher @@ -71,21 +66,21 @@ Feature: new user registration And I go to the new user registration page And I fill in the following: | user_username | $%&(/&%$&/=)(/ | - And I press "Sign up" + And I press "Create account" Then I should not be able to sign up And I should have a validation error on "user_username, user_password, user_email" When I fill in the following: | user_username | valid_user | | user_email | this is not a valid email $%&/()( | - And I press "Sign up" + And I press "Create account" Then I should not be able to sign up And I should have a validation error on "user_password, user_email" When I fill in the following: | user_email | valid@email.com | | user_password | 1 | - And I press "Sign up" + And I press "Create account" Then I should not be able to sign up And I should have a validation error on "user_password, user_password_confirmation" diff --git a/features/desktop/single_post_view_moderation.feature b/features/desktop/single_post_view_moderation.feature index c47db4a48aa72d423f910591b91d2132b4c67239..af90de2c46366adb2ab6aa99c181b59455b09f0a 100644 --- a/features/desktop/single_post_view_moderation.feature +++ b/features/desktop/single_post_view_moderation.feature @@ -18,8 +18,7 @@ And I sign in as "alice@alice.alice" And I open the show page of the "Here is a post to test with" post - And I click to hide the post - And I confirm the alert + And I confirm the alert after I click to hide the post Then I should be on the stream page @@ -32,8 +31,7 @@ And I sign in as "alice@alice.alice" And I open the show page of the "Here is a post to test with" post - And I click to block the user - And I confirm the alert + And I confirm the alert after I click to block the user Then I should be on the stream page @@ -46,8 +44,7 @@ And I sign in as "alice@alice.alice" And I open the show page of the "Here is a post to test with" post - And I click to report the post - And I confirm the alert + And I confirm the alert after I click to report the post And I should see a flash message containing "The report has successfully been created" @@ -57,6 +54,5 @@ And I submit the publisher And I open the show page of the "Here is a post to test with" post - And I click to delete the post - And I confirm the alert + And I confirm the alert after I click to delete the post Then I should be on the stream page diff --git a/features/desktop/user_applications.feature b/features/desktop/user_applications.feature new file mode 100644 index 0000000000000000000000000000000000000000..b1147ae1a3b22ea0c58cb9e6c7291fd9e16a9636 --- /dev/null +++ b/features/desktop/user_applications.feature @@ -0,0 +1,23 @@ +@javascript +Feature: managing authorized applications + Background: + Given following users exist: + | username | email | + | Augier | augier@example.org | + And a client with a provided picture exists for user "augier@example.org" + And a client exists for user "augier@example.org" + + Scenario: displaying authorizations + When I sign in as "augier@example.org" + And I go to the user applications page + Then I should see 2 authorized applications + And I should see 1 authorized applications with no provided image + And I should see 1 authorized applications with an image + + Scenario: revoke an authorization + When I sign in as "augier@example.org" + And I go to the user applications page + And I revoke the first authorization + Then I should see 1 authorized applications + And I revoke the first authorization + Then I should see 0 authorized applications diff --git a/features/mobile/activity_stream.feature b/features/mobile/activity_stream.feature index dcb9f615a7e88071f505851a741d5a14e7a1e031..72a444c7942e653ccf89629f9063b3c77cb5a389 100644 --- a/features/mobile/activity_stream.feature +++ b/features/mobile/activity_stream.feature @@ -5,19 +5,28 @@ Feature: Viewing my activity on the steam mobile page I want to view my activity stream Background: - Given a user with username "alice" + Given following users exist: + | username | + | alice | + | bob | + And a user with username "bob" is connected with "alice" And "alice@alice.alice" has a public post with text "Hello! I am #newhere" - And I sign in as "alice@alice.alice" on the mobile website Scenario: Show my activity empty - When I open the drawer - And I follow "My activity" - Then I should see "My activity" + When I sign in as "bob@bob.bob" on the mobile website + When I go to the activity stream page + Then I should see "My activity" within "#main" And I should not see "Hello! I am #newhere" - Scenario: Show post on my activity - When I click on selector "a.image_link.like_action.inactive" - And I open the drawer - And I follow "My activity" - Then I should see "My activity" + Scenario: Show liked post on my activity + When I sign in as "bob@bob.bob" on the mobile website + When I click on selector "a.like-action.inactive" + And I go to the activity stream page + Then I should see "My activity" within "#main" + And I should see "Hello! I am #newhere" within ".ltr" + + Scenario: Show own post on my activity + When I sign in as "alice@alice.alice" on the mobile website + And I go to the activity stream page + Then I should see "My activity" within "#main" And I should see "Hello! I am #newhere" within ".ltr" diff --git a/features/mobile/change_password.feature b/features/mobile/change_password.feature new file mode 100644 index 0000000000000000000000000000000000000000..f30edb215b30110984e689d52a4916fb9003cc86 --- /dev/null +++ b/features/mobile/change_password.feature @@ -0,0 +1,56 @@ +@javascript @mobile +Feature: Change password + As a mobile user + I want to Change my password + + + Scenario: Change my password + Given I am signed in on the mobile website + When I go to the edit user page + And I fill out change password section with my password and "newsecret" and "newsecret" + And I press "Change password" + Then I should see "Password changed" + And I should be on the new user session page + When I sign in with password "newsecret" on the mobile website + Then I should be on the stream page + + Scenario: Attempt to change my password with invalid input + Given I am signed in on the mobile website + When I go to the edit user page + And I fill out change password section with my password and "too" and "short" + And I press "Change password" + Then I should see "Password is too short" + And I should see "Password confirmation doesn't match" + + Scenario: Reset my password + Given a user named "Georges Abitbol" with email "forgetful@users.net" + And I am on forgot password page + When I fill out forgot password form with "forgetful@users.net" + And I submit forgot password form + Then I should see "You will receive an email with instructions" + When I follow the "Change my password" link from the last sent email + And I fill out the password reset form with "supersecret" and "supersecret" + And I submit the password reset form + Then I should be on the stream page + When I sign out + And I go to the login page + And I sign in manually as "georges_abitbol" with password "supersecret" on the mobile website + Then I should be on the stream page + + Scenario: Attempt to reset password with invalid password + Given a user named "Georges Abitbol" with email "forgetful@users.net" + And I am on forgot password page + When I fill out forgot password form with "forgetful@users.net" + And I submit forgot password form + And I follow the "Change my password" link from the last sent email + And I fill out the password reset form with "too" and "short" + And I press "Change my password" + Then I should be on the user password page + And I should see "Password is too short" + And I should see "Password confirmation doesn't match" + + Scenario: Attempt to reset password with invalid email + Given I am on forgot password page + When I fill out forgot password form with "notanemail" + And I submit forgot password form + Then I should see "No account with this email exists" diff --git a/features/mobile/closes_account.feature b/features/mobile/closes_account.feature index 1d3f4d6f4895e4aef7a6786143c305ced55b5b07..2854e1d6ec4b625f21a0f9586f85ff5d6d86167e 100644 --- a/features/mobile/closes_account.feature +++ b/features/mobile/closes_account.feature @@ -5,13 +5,15 @@ Feature: Close account I want to sign in, close my account and try to log in again Scenario: user closes account - Given I am signed in - When I go to the users edit page - And I put in my password in "close_account_password" - And I press "close_account_confirm" - And I confirm the alert + Given I am signed in on the mobile website + When I go to the edit user page + And I click on selector "#close_account" + Then I should see a modal + And I should see "Hey, please don’t go!" within "#closeAccountModal" + When I put in my password in the close account modal + And I confirm the alert after I press "Close account" in the modal + Then I should be on the mobile new user session page - When I am on the new user session page - And I try to sign in manually + When I try to sign in manually Then I should be on the new user session page And I should see a flash message with a warning diff --git a/features/mobile/conversations.feature b/features/mobile/conversations.feature index aa5901749297d9c47cfff1f34ed16fe073f8ab66..c64e0ba2d4e7726ab521bdb41ec2b320989ba441 100644 --- a/features/mobile/conversations.feature +++ b/features/mobile/conversations.feature @@ -21,6 +21,5 @@ Feature: private conversations mobile And I reply with "hey, how you doing?" And I press the first ".ltr" within ".conversation" Then I should see "hey, how you doing?" - When I click on selector "a.remove" - And I confirm the alert + When I confirm the alert after I click on selector "a.remove" Then I should not see "hey, how you doing" diff --git a/features/mobile/drawer.feature b/features/mobile/drawer.feature index d0228aef762933158c9e7bddb589dbe34132a725..d861eb68369fe7eed6a916826b744b01709d3f34 100644 --- a/features/mobile/drawer.feature +++ b/features/mobile/drawer.feature @@ -9,92 +9,79 @@ Feature: Navigate between pages using the header menu and the drawer | Bob Jones | bob@bob.bob | | Alice Smith | alice@alice.alice | - And I sign in as "alice@alice.alice" And a user with email "bob@bob.bob" is connected with "alice@alice.alice" + And I sign in as "alice@alice.alice" on the mobile website Scenario: navigate to the stream page - When I open the drawer - And I follow "My activity" - And I click on selector "#header_title" - Then I should see "There are no posts yet." within "#main_stream" + When I go to the activity stream page + And I click on selector "#header-title" + Then I should be on the stream page Scenario: navigate to the notification page - When I click on selector "#notification_badge" - Then I should see "Notifications" within "#main" + When I click on selector "#notification-badge" + Then I should be on the notifications page Scenario: navigate to the conversation page - When I click on selector "#conversations_badge" - Then I should see "Inbox" within "#main" + When I click on selector "#conversations-badge" + Then I should be on the conversations page Scenario: navigate to the publisher page - When I click on selector "#compose_badge" - Then I should see "All aspects" within "#new_status_message" + When I click on selector "#compose-badge" + Then I should be on the new status message page Scenario: search a user When I open the drawer - And I search for "Bob" + Then I should see a "#q" within "#drawer" + When I search for "Bob" Then I should see "Users matching Bob" within "#search_title" Scenario: search for a tag When I open the drawer - And I search for "#bob" - Then I should see "#bob" within "#main > h1" + Then I should see a "#q" within "#drawer" + When I search for "#bob" + Then I should be on the tag page for "bob" Scenario: navigate to my activity page When I open the drawer - And I follow "My activity" - Then I should see "My activity" within "#main" + And I click on "My activity" in the drawer + Then I should be on the activity stream page Scenario: navigate to my mentions page - Given Alice has a post mentioning Bob - And I sign in as "bob@bob.bob" When I open the drawer - And I follow "@Mentions" - Then I should see "Bob Jones" within ".stream_element" + And I click on "@Mentions" in the drawer + Then I should be on the mentioned stream page Scenario: navigate to my aspects page Given "bob@bob.bob" has a public post with text "bob's text" When I open the drawer - And I follow "My aspects" - Then I should see "Besties" within "#all_aspects + li > ul" - And I follow "Besties" + And I click on "My aspects" in the drawer + And I click on "Besties" in the drawer Then I should see "bob's text" within "#main_stream" Scenario: navigate to the followed tags page - Given "bob@bob.bob" has a public post with text "bob is da #boss" - And I toggle the mobile view - And I search for "#boss" - And I press "Follow #boss" - And I toggle the mobile view - When I open the drawer - And I follow "#Followed tags" - Then I should see "#boss" within "#followed_tags + li > ul" - And I follow "#boss" - Then I should see "bob is da #boss" within "#main_stream" - - Scenario: navigate to the manage followed tags page - Given "bob@bob.bob" has a public post with text "bob is da #boss" - And I toggle the mobile view - And I search for "#boss" - And I press "Follow #boss" - And I toggle the mobile view + When I follow the "boss" tag + And I go to the stream page + And I open the drawer + And I click on "#Followed tags" in the drawer + And I click on "#boss" in the drawer + Then I should be on the tag page for "boss" + When I open the drawer - And I follow "#Followed tags" - Then I should see "Manage followed tags" within "#followed_tags + li > ul" - And I follow "Manage followed tags" - Then I should see "#boss" within "ul.followed_tags" + And I click on "#Followed tags" in the drawer + And I click on "Manage followed tags" in the drawer + Then I should be on the manage tag followings page Scenario: navigate to my profile page When I open the drawer - And I follow "Profile" - Then I should see "Alice" within "#author_info" + And I click on "Profile" in the drawer + Then I should be on my profile page - Scenario: navigate to my mentions page + Scenario: navigate to my contacts page When I open the drawer - And I follow "Contacts" - Then I should see "Contacts" within "#main" + And I click on "Contacts" in the drawer + Then I should be on the contacts page - Scenario: navigate to my mentions page + Scenario: navigate to my settings page When I open the drawer - And I follow "Settings" - Then I should see "Settings" within "#main" + And I click on "Settings" in the drawer + Then I should be on my account settings page diff --git a/features/mobile/edits_profile.feature b/features/mobile/edits_profile.feature index 583d3de6e887eb5161e65ff750dcd548526f055f..77a41ab7e3753dce6cc8e0f5264b60ff364c85f6 100644 --- a/features/mobile/edits_profile.feature +++ b/features/mobile/edits_profile.feature @@ -1,7 +1,7 @@ @javascript @mobile Feature: editing the profile in the mobile view Scenario: editing profile fields - Given I am signed in + Given I am signed in on the mobile website And I go to the edit profile page When I fill in the following: @@ -25,7 +25,7 @@ Feature: editing the profile in the mobile view And the "profile_gender" field should contain "Fearless" And the "profile_first_name" field should contain "Boba" And the "profile_last_name" field should contain "Fett" - And I should see "This is a bio" + And the "profile_bio" field should contain "This is a bio" And the "profile_date_year" field should be filled with "1986" And the "profile_date_month" field should be filled with "11" And the "profile_date_day" field should be filled with "30" @@ -39,7 +39,10 @@ Feature: editing the profile in the mobile view Then I should see "#kamino" within "ul#as-selections-tags" And I should see "#starwars" within "ul#as-selections-tags" - When I attach the file "spec/fixtures/bad_urls.txt" to "file" within "#file-upload" - And I confirm the alert + When I confirm the alert after I attach the file "spec/fixtures/bad_urls.txt" to "file" within "#file-upload" And I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload" + Then I should see "button.png completed" + And I should see a "img" within "#profile_photo_upload" + + When I go to my edit profile page Then I should see a "img" within "#profile_photo_upload" diff --git a/features/mobile/getting_started.feature b/features/mobile/getting_started.feature index 7e51ec1510d7ab3e205341602b3f4635eab0a5aa..7714f8807a7fd13892f1f30848f01538db1fa582 100644 --- a/features/mobile/getting_started.feature +++ b/features/mobile/getting_started.feature @@ -3,7 +3,7 @@ Feature: editing the getting started in the mobile view Background: Given I am on the login page - When I follow "Sign up" + When I follow "Create account" within ".navbar" And I fill in the new user form And I submit the form Then I should be on the getting started page @@ -17,8 +17,7 @@ Feature: editing the getting started in the mobile view And I should not see "awesome_button" Scenario: new user adds a profile photo and tags - When I attach the file "spec/fixtures/bad_urls.txt" to "file" within "#file-upload" - And I confirm the alert + When I confirm the alert after I attach the file "spec/fixtures/bad_urls.txt" to "file" within "#file-upload" And I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload" Then I should see a "img" within "#profile_photo_upload" @@ -30,3 +29,15 @@ Feature: editing the getting started in the mobile view When I follow "awesome_button" Then I should be on the stream page And I should not see "awesome_button" + + Scenario: new user completes getting started and signs in again later + When I sign out + And I go to the login page + And I sign in manually as "ohai" with password "secret" on the mobile website + Then I should be on the getting started page + When I follow "awesome_button" + Then I should be on the stream page + When I sign out + And I go to the login page + And I sign in manually as "ohai" with password "secret" on the mobile website + Then I should be on the stream page diff --git a/features/mobile/home.feature b/features/mobile/home.feature index 2b678a193419308e194ff633d2785daad26e82cd..d0fea1ccdec7b7b927364ca63eecb519f333a14f 100644 --- a/features/mobile/home.feature +++ b/features/mobile/home.feature @@ -15,5 +15,3 @@ Feature: Visit the landing page of the pod Then I should see "Welcome, friend" When I go to the mobile path Then I should see "LOG IN" - When I go to the mobile path - Then I should see "LOG IN" diff --git a/features/mobile/invitations.feature b/features/mobile/invitations.feature index a81c19eaf8a0ed8abf2c7a3b2f0a4de89768a79c..97b34643f6f09657c5b7add855d2ae5a44aa516e 100644 --- a/features/mobile/invitations.feature +++ b/features/mobile/invitations.feature @@ -1,9 +1,16 @@ @javascript @mobile Feature: Invitations + Background: + Given following users exist: + | username | email | + | Alice Smith | alice@alice.alice | Scenario: Accepting an invitation - When I visit alice's invitation code url + Given I have been invited by "alice@alice.alice" + And I am on my acceptance form page When I fill in the new user form - And I press "Create my account!" + And I press "Create account" Then I should see the "welcome to diaspora" message - And I should be able to friend Alice + And I should be able to friend "alice@alice.alice" + When I select "Family" from "user_aspects" within "#hello-there" + Then the aspect dropdown within "#hello-there" should be labeled "Family" diff --git a/features/mobile/logged_out_browsing.feature b/features/mobile/logged_out_browsing.feature index cbab125a42a171327c1c17a7dd20db5cd5e11376..2609ca2f677d3b180390a00d09c17ef55c825d33 100644 --- a/features/mobile/logged_out_browsing.feature +++ b/features/mobile/logged_out_browsing.feature @@ -1,21 +1,21 @@ @javascript @mobile Feature: Browsing Diaspora as a logged out user mobile - In order to view public diaspora content - as a random internet user - I want to view public post and comments + In order to view public diaspora content + as a random internet user + I want to view public post and comments - Background: - Given a user named "Bob Jones" with email "bob@bob.bob" - And "bob@bob.bob" has a public post with text "public stuff" - And I sign in as "bob@bob.bob" - And I click on selector "a.image_link.comment_action.inactive" - And I fill in the following: - | text | this also | - And I press "Comment" - And I log out + Background: + Given a user named "Bob Jones" with email "bob@bob.bob" + And "bob@bob.bob" has a public post with text "public stuff" + And I sign in as "bob@bob.bob" on the mobile website + And I click on selector "a.comment-action.inactive" + And I fill in the following: + | text | this also | + And I press "Comment" + And I log out - Scenario: Visiting a profile page - When I am on "bob@bob.bob"'s page - Then I should see "public stuff" within ".ltr" - And I click on selector "a.show_comments" - And I should see "this also" within ".comment" + Scenario: Visiting a profile page + When I am on "bob@bob.bob"'s page + Then I should see "public stuff" within ".ltr" + And I click on selector "a.show-comments" + And I should see "this also" within ".comment" diff --git a/features/mobile/more-button.feature b/features/mobile/more-button.feature index a2a2816b9bf066dde7f929543aaaa1b8e33e6553..b34b1c89a098c9391e86e2a232e3ad77bf87b1af 100644 --- a/features/mobile/more-button.feature +++ b/features/mobile/more-button.feature @@ -1,43 +1,43 @@ @javascript @mobile Feature: using the more button on mobile stream - As a mobile user - I want to navigate the stream - And I want to test the text of the more-button in different environments + As a mobile user + I want to navigate the stream + And I want to test the text of the more-button in different environments - Background: - Given a user with username "bob" - And I sign in as "bob@bob.bob" on the mobile website + Background: + Given a user with username "bob" + And I sign in as "bob@bob.bob" on the mobile website - Scenario: There are no posts - Given I am on the home page + Scenario: There are no posts + Given I am on the home page - When I go to the stream page - Then I should see "There are no posts yet." + When I go to the stream page + Then I should see "There are no posts yet." - Scenario: There are <15 posts - Given I am on the home page - And "bob@bob.bob" has a public post with text "post 1" + Scenario: There are <15 posts + Given I am on the home page + And "bob@bob.bob" has a public post with text "post 1" - When I go to the stream page - Then I should see "You have reached the end of the stream." + When I go to the stream page + Then I should see "You have reached the end of the stream." - Scenario: There are 15 posts - Given I am on the home page - Given there are 15 public posts from "bob@bob.bob" - And "bob@bob.bob" has a public post with text "post 1" + Scenario: There are 15 posts + Given I am on the home page + Given there are 15 public posts from "bob@bob.bob" + And "bob@bob.bob" has a public post with text "post 1" - When I go to the stream page - Then I should see "More" + When I go to the stream page + Then I should see "More" - When I click on selector ".more-link" - Then I should see "You have reached the end of the stream." + When I click on selector ".more-link" + Then I should see "You have reached the end of the stream." - Scenario: There are 15 +1 posts - Given I am on the home page - Given there are 16 public posts from "bob@bob.bob" + Scenario: There are 15 +1 posts + Given I am on the home page + Given there are 16 public posts from "bob@bob.bob" - When I go to the stream page - Then I should see "More" + When I go to the stream page + Then I should see "More" - When I click on selector ".more-link" - Then I should see "You have reached the end of the stream." + When I click on selector ".more-link" + Then I should see "You have reached the end of the stream." diff --git a/features/mobile/multiphoto.feature b/features/mobile/multiphoto.feature index 956db048bfa2a823fdcd0fe9faf750a412d1d4de..ddc79a2c161bbaa2c8585a18dff1f5905ece153c 100644 --- a/features/mobile/multiphoto.feature +++ b/features/mobile/multiphoto.feature @@ -6,27 +6,36 @@ Feature: viewing photos on the mobile main page Background: Given a user with username "bob" - When I sign in as "bob@bob.bob" on the mobile website - And I click on selector "#compose_badge" + And I sign in as "bob@bob.bob" on the mobile website Scenario: view full size image - Given I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload-publisher" + Given I visit the mobile publisher page + When I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload-publisher" + Then I should see "button.png completed" + And I should see an uploaded image within the photo drop zone When I press "Share" + And I go to the stream page And I click on selector "img.stream-photo" Then I should see a "img" within "#show_content" - And I should not see a "#right" within "#main" + And I should not see a "#arrow-right" within "#main" + And I should not see a "#arrow-left" within "#main" Scenario: view multiphoto post - Given I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload-publisher" - And I attach the file "spec/fixtures/button.gif" to hidden "file" within "#file-upload-publisher" + Given I visit the mobile publisher page + When I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload-publisher" + Then I should see "button.png completed" + When I attach the file "spec/fixtures/button.gif" to hidden "file" within "#file-upload-publisher" + Then I should see "button.gif completed" When I press "Share" + And I go to the stream page Then I should see "+ 1" within ".additional_photo_count" When I click on selector "img.stream-photo" - Then I should see a "#right" within "tbody" + Then I should see a "#arrow-right" within "#main" + And I should not see a "#arrow-left" within "#main" - When I click on selector "img#arrow-right" - And I should see a "#left" within "tbody" - And I should not see a "#right" within "tbody" + When I click on selector "#arrow-right" + Then I should see a "#arrow-left" within "#main" + And I should not see a "#arrow-right" within "#main" diff --git a/features/mobile/not_safe_for_work.feature b/features/mobile/not_safe_for_work.feature new file mode 100644 index 0000000000000000000000000000000000000000..ea97bca1cfa92d372d21b388ab8d8d82a561193d --- /dev/null +++ b/features/mobile/not_safe_for_work.feature @@ -0,0 +1,78 @@ +@javascript @mobile +Feature: Not safe for work + Background: + Given a nsfw user with email "tommy@nsfw.example.com" + And a user with email "laura@office.example.com" + And a user with email "laura@office.example.com" is connected with "tommy@nsfw.example.com" + + Scenario: Setting not safe for work + When I sign in as "tommy@nsfw.example.com" on the mobile website + And I go to the edit profile page + And I mark myself as not safe for work + And I submit the form + Then I should be on the edit profile page + And the "profile[nsfw]" checkbox should be checked + + When I go to the edit profile page + And I mark myself as safe for work + And I submit the form + Then I should be on the edit profile page + And the "profile[nsfw]" checkbox should not be checked + + Scenario: Toggling nsfw state + #Nsfw users posts are marked nsfw + Given "tommy@nsfw.example.com" has a public post with text "I love 0bj3ction4bl3 c0nt3nt!" and a poll + And "tommy@nsfw.example.com" has a public post with text "I love 0bj3ction4bl3 c0nt3nt!" and a location + And "tommy@nsfw.example.com" has a public post with text "I love 0bj3ction4bl3 c0nt3nt!" and a picture + + #toggling nsfw state + When I sign in as "laura@office.example.com" on the mobile website + Then I should not see "I love 0bj3ction4bl3 c0nt3nt!" + And I should not see "What do you think about 1 ninjas?" + And I should not see "Posted from:" + And I should not see any picture in my stream + + When I toggle all nsfw posts + Then I should see "I love 0bj3ction4bl3 c0nt3nt!" + And I should see "What do you think about 1 ninjas?" + And I should see "Posted from:" + And I should see 1 pictures in my stream + + Scenario: Resharing a nsfw post with a poll + Given "tommy@nsfw.example.com" has a public post with text "Sexy Senators Gone Wild!" and a poll + + When I sign in as "laura@office.example.com" on the mobile website + And I toggle all nsfw posts + And I confirm the alert after I follow "Reshare" + Then I should see a "a.reshare-action.active" + + When I go to the home page + Then I should not see "Sexy Senators Gone Wild!" + And I should not see "What do you think about 1 ninjas?" + And I should have 2 nsfw posts + + Scenario: Resharing a nsfw post with a location + Given "tommy@nsfw.example.com" has a public post with text "Sexy Senators Gone Wild!" and a location + + When I sign in as "laura@office.example.com" on the mobile website + And I toggle all nsfw posts + And I confirm the alert after I follow "Reshare" + Then I should see a "a.reshare-action.active" + + When I go to the home page + Then I should not see "Sexy Senators Gone Wild!" + And I should not see "Posted from:" + And I should have 2 nsfw posts + + Scenario: Resharing a nsfw post with a picture + Given "tommy@nsfw.example.com" has a public post with text "Sexy Senators Gone Wild!" and a picture + + When I sign in as "laura@office.example.com" on the mobile website + And I toggle all nsfw posts + And I confirm the alert after I follow "Reshare" + Then I should see a "a.reshare-action.active" + + When I go to the home page + Then I should not see "Sexy Senators Gone Wild!" + And I should not see any picture in my stream + And I should have 2 nsfw posts diff --git a/features/mobile/people_aspects.feature b/features/mobile/people_aspects.feature index c5a095ab6a0ea95df76e83361194c08834ab2748..8750c15263c39ce92172bc2d57a07862efe25cea 100644 --- a/features/mobile/people_aspects.feature +++ b/features/mobile/people_aspects.feature @@ -1,42 +1,42 @@ @javascript @mobile Feature: adding and removing people from aspects - In order to add people to my contacts - As a mobile user - I want to add and remove people from my contacts - - Background: - Given following users exist: - | username | - | bob | - | alice | - And I sign in as "bob@bob.bob" on the mobile website - - Scenario: verify different states of the cover button - When I am on "alice@alice.alice"'s page - Then the aspect dropdown within "#author_info" should be labeled "Add contact" - - When I select "Unicorns" from "user_aspects" within "#author_info" - Then the aspect dropdown within "#author_info" should be labeled "Unicorns" - - When I select "Besties" from "user_aspects" within "#author_info" - Then the aspect dropdown within "#author_info" should be labeled "In 2 aspects" - - Scenario: add contact to aspect - When I am on "alice@alice.alice"'s page - And I select "Unicorns" from "user_aspects" within "#author_info" - Then the aspect dropdown within "#author_info" should be labeled "Unicorns" - Then I should have 1 contacts in "Unicorns" - - Scenario: remove contact to aspect - When I am on "alice@alice.alice"'s page - And I select "Unicorns" from "user_aspects" within "#author_info" - Then the aspect dropdown within "#author_info" should be labeled "Unicorns" - - And I select "Besties" from "user_aspects" within "#author_info" - Then the aspect dropdown within "#author_info" should be labeled "In 2 aspects" - Then I should have 1 contacts in "Unicorns" - - When I am on "alice@alice.alice"'s page - And I select "Unicorns" from "user_aspects" within "#author_info" - Then the aspect dropdown within "#author_info" should be labeled "Besties" - Then I should have 0 contacts in "Unicorns" + In order to add people to my contacts + As a mobile user + I want to add and remove people from my contacts + + Background: + Given following users exist: + | username | + | bob | + | alice | + And I sign in as "bob@bob.bob" on the mobile website + + Scenario: verify different states of the cover button + When I am on "alice@alice.alice"'s page + Then the aspect dropdown within "#author_info" should be labeled "Add contact" + + When I select "Unicorns" from "user_aspects" within "#author_info" + Then the aspect dropdown within "#author_info" should be labeled "Unicorns" + + When I select "Besties" from "user_aspects" within "#author_info" + Then the aspect dropdown within "#author_info" should be labeled "In 2 aspects" + + Scenario: add contact to aspect + When I am on "alice@alice.alice"'s page + And I select "Unicorns" from "user_aspects" within "#author_info" + Then the aspect dropdown within "#author_info" should be labeled "Unicorns" + Then I should have 1 contacts in "Unicorns" + + Scenario: remove contact to aspect + When I am on "alice@alice.alice"'s page + And I select "Unicorns" from "user_aspects" within "#author_info" + Then the aspect dropdown within "#author_info" should be labeled "Unicorns" + + And I select "Besties" from "user_aspects" within "#author_info" + Then the aspect dropdown within "#author_info" should be labeled "In 2 aspects" + Then I should have 1 contacts in "Unicorns" + + When I am on "alice@alice.alice"'s page + And I select "Unicorns" from "user_aspects" within "#author_info" + Then the aspect dropdown within "#author_info" should be labeled "Besties" + Then I should have 0 contacts in "Unicorns" diff --git a/features/mobile/posts_from_main_page.feature b/features/mobile/posts_from_main_page.feature index 74b176eefb5b1cb92a21df745be0beff63a59a6c..27016314fe416fabef7d49add455eb2fcf9742b1 100644 --- a/features/mobile/posts_from_main_page.feature +++ b/features/mobile/posts_from_main_page.feature @@ -1,62 +1,60 @@ @javascript @mobile Feature: posting from the mobile main page - In order to navigate Diaspora* - As a mobile user - I want to tell the world I am eating a yogurt + In order to navigate Diaspora* + As a mobile user + I want to tell the world I am eating a yogurt - Background: - Given following users exist: - | username | - | bob | - | alice | - And I am on the home page - And I sign in as "bob@bob.bob" on the mobile website - And a user with username "bob" is connected with "alice" - Given I have following aspects: - | PostingTo | - | NotPostingThingsHere | - And I have user with username "alice" in an aspect called "PostingTo" - And I have user with username "alice" in an aspect called "NotPostingThingsHere" + Background: + Given following users exist: + | username | + | bob | + | alice | + And I am on the home page + And I sign in as "bob@bob.bob" on the mobile website + And a user with username "bob" is connected with "alice" + Given I have following aspects: + | PostingTo | + | NotPostingThingsHere | + And I have user with username "alice" in an aspect called "PostingTo" + And I have user with username "alice" in an aspect called "NotPostingThingsHere" - Scenario: post and delete some text - Given I visit the mobile publisher page - And I append "I am eating yogurt" to the mobile publisher - And I select "Unicorns" from "aspect_ids_" - And I press "Share" - When I go to the stream page - Then I should see "I am eating yogurt" - When I click on selector "a.remove" - And I confirm the alert - Then I should not see "I am eating yogurt" + Scenario: post and delete some text + Given I visit the mobile publisher page + And I append "I am eating yogurt" to the mobile publisher + And I select "Unicorns" from "aspect_ids_" + And I press "Share" + When I go to the stream page + Then I should see "I am eating yogurt" + When I confirm the alert after I click on selector "a.remove" + Then I should not see "I am eating yogurt" - Scenario: post a photo without text - Given I visit the mobile publisher page - When I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload-publisher" - Then I should see an uploaded image within the photo drop zone - And I should see "button.png completed" - When I press "Share" - When I go to the stream page - Then I should see a "img" within ".stream_element div.photo_attachments" - When I log out - And I sign in as "alice@alice.alice" on the mobile website - When I go to the stream page - Then I should see a "img" within ".stream_element div.photo_attachments" + Scenario: post a photo without text + Given I visit the mobile publisher page + When I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload-publisher" + Then I should see "button.png completed" + And I should see an uploaded image within the photo drop zone + When I press "Share" + When I go to the stream page + Then I should see a "img" within ".stream_element div.photo_attachments" + When I log out + And I sign in as "alice@alice.alice" on the mobile website + When I go to the stream page + Then I should see a "img" within ".stream_element div.photo_attachments" - Scenario: back out of posting a photo-only post - Given I visit the mobile publisher page - When I attach the file "spec/fixtures/bad_urls.txt" to "file" within "#file-upload-publisher" - And I confirm the alert - Then I should not see an uploaded image within the photo drop zone - When I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload-publisher" - And I should see "button.png completed" - And I click to delete the first uploaded photo - Then I should not see an uploaded image within the photo drop zone + Scenario: back out of posting a photo-only post + Given I visit the mobile publisher page + When I confirm the alert after I attach the file "spec/fixtures/bad_urls.txt" to "file" within "#file-upload-publisher" + Then I should not see an uploaded image within the photo drop zone + When I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload-publisher" + And I should see "button.png completed" + And I click to delete the first uploaded photo + Then I should not see an uploaded image within the photo drop zone - Scenario: back out of uploading a picture when another has been attached - Given I visit the mobile publisher page - And I append "I am eating yogurt" to the mobile publisher - And I attach the file "spec/fixtures/button.gif" to hidden "file" within "#file-upload-publisher" - And I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload-publisher" - And I click to delete the first uploaded photo - Then I should see an uploaded image within the photo drop zone - And the text area wrapper mobile should be with attachments + Scenario: back out of uploading a picture when another has been attached + Given I visit the mobile publisher page + And I append "I am eating yogurt" to the mobile publisher + And I attach the file "spec/fixtures/button.gif" to hidden "file" within "#file-upload-publisher" + And I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload-publisher" + And I click to delete the first uploaded photo + Then I should see an uploaded image within the photo drop zone + And the text area wrapper mobile should be with attachments diff --git a/features/mobile/reactions.feature b/features/mobile/reactions.feature index 3fceef45add04fa5dc5ea087978de2484d8cd671..5f15cde82b0f6e21adc569bb453ded8abd9ce4f7 100644 --- a/features/mobile/reactions.feature +++ b/features/mobile/reactions.feature @@ -14,26 +14,34 @@ Feature: reactions mobile post And I sign in as "bob@bob.bob" on the mobile website Scenario: like on a mobile post - When I should see "No reactions" within ".show_comments" - And I click on selector "span.show_comments" - And I click on selector "a.image_link.like_action.inactive" - Then I should see a "a.image_link.like_action.active" + When I should see "No reactions" within ".show-comments" + And I click on selector "a.like-action.inactive" + Then I should see a "a.like-action.active" When I go to the stream page - And I should see "1 reaction" within ".show_comments" - And I click on selector "a.show_comments" - Then I should see "1" within ".like_count" + And I should see "1 reaction" within ".show-comments" + And I click on selector "a.show-comments" + Then I should see "1" within ".like-count" + + Scenario: liking from the profile view + When I am on "alice@alice.alice"'s page + Then I should see "No reactions" within ".show-comments" + And I click on selector "a.like-action.inactive" + Then I should see a "a.like-action.active" + When I go to the stream page + And I should see "1 reaction" within ".show-comments" + And I click on selector "a.show-comments" + Then I should see "1" within ".like-count" Scenario: comment and delete a mobile post - When I click on selector "a.image_link.comment_action.inactive" + When I click on selector "a.comment-action.inactive" And I fill in the following: | text | is that a poodle? | And I press "Comment" - Then I should see "is that a poodle?" + Then I should see "is that a poodle?" within ".comment-container" When I go to the stream page - And I should see "1 reaction" within ".show_comments" - And I click on selector "a.show_comments" - And I should see "1" within ".comment_count" - When I click on selector "a.image_link.comment_action.inactive" - And I click on selector "a.remove" - And I confirm the alert - Then I should not see "1 reaction" within ".show_comments" + And I should see "1 reaction" within ".show-comments" + And I click on selector "a.show-comments" + And I should see "1" within ".comment-count" + When I click on selector "a.comment-action" + And I confirm the alert after I click on selector "a.remove" + Then I should not see "1 reaction" within ".show-comments" diff --git a/features/mobile/reshare.feature b/features/mobile/reshare.feature index a072b97e182393ce5ec1ebd24591c31f0090bc50..26441a78a78e0a2c1035529b8cf2e735497793a2 100644 --- a/features/mobile/reshare.feature +++ b/features/mobile/reshare.feature @@ -13,21 +13,19 @@ Feature: resharing from the mobile And a user with email "bob@bob.bob" is connected with "alice@alice.alice" And a user with email "eve@eve.eve" is connected with "bob@bob.bob" Given "bob@bob.bob" has a public post with text "reshare this!" - And I sign in as "alice@alice.alice" + And I sign in as "alice@alice.alice" on the mobile website Scenario: Resharing a post from a single post page - And I click on selector "a.image_link.reshare_action.inactive" - And I confirm the alert - Then I should see a "a.image_link.reshare_action.active" + And I confirm the alert after I click on selector ".reshare-action.inactive" + Then I should see a ".reshare-action.active" When I go to the stream page Then I should see "Reshared via" within ".reshare_via" Scenario: Resharing a post from a single post page that is reshared Given the post with text "reshare this!" is reshared by "eve@eve.eve" And a user with email "alice@alice.alice" is connected with "eve@eve.eve" - And I click on the first selector "a.image_link.reshare_action.inactive" - And I confirm the alert - Then I should see a "a.image_link.reshare_action.active" + And I confirm the alert after I click on the first selector ".reshare-action.inactive" + Then I should see a ".reshare-action.active" When I go to the stream page Then I should see "Reshared via" within ".reshare_via" @@ -45,3 +43,11 @@ Feature: resharing from the mobile And I sign in as "eve@eve.eve" on the mobile website And I toggle the mobile view Then I should see "Original post deleted by author" within ".reshare" + + Scenario: Not resharing own post + Given I sign in as "bob@bob.bob" on the mobile website + Then I should see a ".reshare-action.disabled" + And I should not see any alert after I click on selector ".reshare-action" + And I should not see a ".reshare-action.active" + When I go to the stream page + Then I should not see a ".reshare_via" diff --git a/features/mobile/signs_up.feature b/features/mobile/signs_up.feature index a17a1a085de67cf7bcf374693325eb2b6f5f24c8..3277ef13140788b8a061d06e991e3c1ea8572720 100644 --- a/features/mobile/signs_up.feature +++ b/features/mobile/signs_up.feature @@ -6,28 +6,31 @@ Feature: New user registration Background: Given I am on the login page - And I follow "Sign up" + And I follow "Create account" within "#main-nav" Scenario: user signs up and goes to getting started When I fill in the new user form - And I submit the form + And I press "Create account" Then I should be on the getting started page - Then I should see the 'getting started' contents + And I should see the 'getting started' contents Scenario: user fills in bogus data - client side validation When I fill in the following: | user_username | $%&(/&%$&/=)(/ | - And I submit the form + And I press "Create account" Then I should not be able to sign up + And I should have a validation error on "user_username, user_password, user_email" When I fill in the following: | user_username | valid_user | | user_email | this is not a valid email $%&/()( | - And I submit the form + And I press "Create account" Then I should not be able to sign up + And I should have a validation error on "user_password, user_email" When I fill in the following: | user_email | valid@email.com | | user_password | 1 | - And I submit the form + And I press "Create account" Then I should not be able to sign up + And I should have a validation error on "user_password, user_password_confirmation" diff --git a/features/mobile/tags.feature b/features/mobile/tags.feature index edca7f60c9635b553423c8fe2bef2f50644dac21..6f608780151115211b4fa61c147628698942fc07 100644 --- a/features/mobile/tags.feature +++ b/features/mobile/tags.feature @@ -7,9 +7,9 @@ Feature: Interacting with tags | bob | | alice | And "alice@alice.alice" has a public post with text "Hello! I am #newhere" - When I sign in as "bob@bob.bob" + When I sign in as "bob@bob.bob" on the mobile website And I visit the mobile search page - And I fill in the following: + And I fill in the following within "#main": | q | #newhere | And I press "Search" Then I should see "Follow #newhere" within ".tag_following_action" @@ -21,7 +21,7 @@ Feature: Interacting with tags Then I should see "Hello! I am #newhere" When I visit the mobile search page - And I fill in the following: + And I fill in the following within "#main": | q | #newhere | And I press "Search" Then I should see "Stop following #newhere" within ".tag_following_action" @@ -37,8 +37,7 @@ Feature: Interacting with tags When I am on the manage tag followings page Then I should see "#newhere" within "ul.followed_tags" - When I click on selector ".tag_following_action.only-delete" - And I confirm the alert + When I confirm the alert after I click on selector ".tag_following_action.only-delete" Then I should see "You aren't following any tags." When I am on the home page Then I should not see "Hello! I am #newhere" diff --git a/features/mobile/user_applications.feature b/features/mobile/user_applications.feature new file mode 100644 index 0000000000000000000000000000000000000000..281d328c1e01b854e14b045fe1f60e7ca2d409f4 --- /dev/null +++ b/features/mobile/user_applications.feature @@ -0,0 +1,23 @@ +@javascript @mobile +Feature: managing authorized applications + Background: + Given following users exist: + | username | email | + | Augier | augier@example.org | + And a client with a provided picture exists for user "augier@example.org" + And a client exists for user "augier@example.org" + + Scenario: displaying authorizations + When I sign in as "augier@example.org" on the mobile website + And I go to the user applications page + Then I should see 2 authorized applications + And I should see 1 authorized applications with no provided image + And I should see 1 authorized applications with an image + + Scenario: revoke an authorization + When I sign in as "augier@example.org" on the mobile website + And I go to the user applications page + And I revoke the first authorization + Then I should see 1 authorized applications + And I revoke the first authorization + Then I should see 0 authorized applications diff --git a/features/step_definitions/aspects_steps.rb b/features/step_definitions/aspects_steps.rb index 53290bed19796cdfc500de443565789f4040ec1d..473ab2ab267f82309bb1e346d5b592afe23afc44 100644 --- a/features/step_definitions/aspects_steps.rb +++ b/features/step_definitions/aspects_steps.rb @@ -1,6 +1,6 @@ module AspectCukeHelpers def click_aspect_dropdown - find('.aspect_dropdown .dropdown-toggle').click + find(".aspect_dropdown .dropdown-toggle").trigger "click" end def toggle_aspect(a_name) @@ -12,19 +12,18 @@ module AspectCukeHelpers def toggle_aspect_via_ui(aspect_name) aspects_dropdown = find(".aspect_membership_dropdown .dropdown-toggle", match: :first) - aspects_dropdown.click + aspects_dropdown.trigger "click" selected_aspect_count = all(".aspect_membership_dropdown.open .dropdown-menu li.selected").length aspect = find(".aspect_membership_dropdown.open .dropdown-menu li", text: aspect_name) aspect_selected = aspect["class"].include? "selected" - aspect.click + aspect.trigger "click" aspect.parent.should have_no_css(".loading") # close dropdown page.should have_no_css('#profile.loading') unless selected_aspect_count == 0 or (selected_aspect_count == 1 and aspect_selected ) - aspects_dropdown.click + aspects_dropdown.trigger "click" end - aspects_dropdown.should have_no_xpath("..[contains(@class, 'active')]") end def aspect_dropdown_visible? @@ -34,7 +33,7 @@ end World(AspectCukeHelpers) When /^I click on "([^"]*)" aspect edit icon$/ do |aspect_name| - within(".all_aspects") do + within(".all-aspects") do li = find('li', text: aspect_name) li.hover li.find('.modify_aspect').click @@ -42,10 +41,10 @@ When /^I click on "([^"]*)" aspect edit icon$/ do |aspect_name| end When /^I select only "([^"]*)" aspect$/ do |aspect_name| - click_link 'My aspects' - within('#aspects_list') do - click_link 'Deselect all' - current_scope.should have_no_css '.selected' + click_link "My aspects" + within("#aspects_list") do + all(".selected").each {|node| node.find(:xpath, "..").click } + expect(current_scope).to have_no_css ".selected" end step %Q(I select "#{aspect_name}" aspect as well) end @@ -89,20 +88,14 @@ When /^(.*) in the aspect creation modal$/ do |action| end When /^I drag "([^"]*)" (up|down)$/ do |aspect_name, direction| + page.execute_script("$('#aspect_nav .list-group').sortable('option', 'tolerance', 'pointer');") aspect_id = @me.aspects.where(name: aspect_name).first.id - aspect = find(:xpath, "//div[@id='aspect_nav']/ul/li[@data-aspect-id='#{aspect_id}']") - target = direction == "up" ? aspect.all(:xpath, "./preceding-sibling::li").last : - aspect.all(:xpath, "./following-sibling::li").first - browser = aspect.base.driver.browser - mouse = browser.mouse - native_aspect = aspect.base.native - native_target = target.base.native - mouse.down native_aspect - mouse.move_to native_target, native_target.size.width / 2, 0 - sleep 1 - mouse.up + aspect = find(:xpath, "//div[@id='aspect_nav']/ul/a[@data-aspect-id='#{aspect_id}']") + target = direction == "up" ? aspect.all(:xpath, "./preceding-sibling::a").last : + aspect.all(:xpath, "./following-sibling::a").first + aspect.drag_to target expect(page).to have_no_css "#aspect_nav .ui-sortable.syncing" - end +end And /^I toggle the aspect "([^"]*)"$/ do |name| toggle_aspect(name) @@ -127,5 +120,5 @@ Then /^the aspect dropdown should be visible$/ do end Then /^I should see "([^"]*)" as (\d+). aspect$/ do |aspect_name, position| - expect(find("#aspect_nav li:nth-child(#{position.to_i + 2})")).to have_text aspect_name + expect(find("#aspect_nav a:nth-child(#{position.to_i + 2})")).to have_text aspect_name end diff --git a/features/step_definitions/auth_code_steps.rb b/features/step_definitions/auth_code_steps.rb new file mode 100644 index 0000000000000000000000000000000000000000..0e3cb9616b1645cac157b83e718cbf5d398da6e5 --- /dev/null +++ b/features/step_definitions/auth_code_steps.rb @@ -0,0 +1,40 @@ +O_AUTH_QUERY_PARAMS_WITH_CODE = { + redirect_uri: "http://example.org/", + response_type: "code", + scope: "openid profile read", + nonce: "hello", + state: "hi" +} + +Given /^I send a post request from that client to the code flow authorization endpoint$/ do + client_json = JSON.parse(last_response.body) + @client_id = client_json["client_id"] + @client_secret = client_json["client_secret"] + params = O_AUTH_QUERY_PARAMS_WITH_CODE.merge(client_id: @client_id) + visit new_api_openid_connect_authorization_path(params) +end + +Given /^I send a post request from that client to the code flow authorization endpoint using a invalid client id/ do + params = O_AUTH_QUERY_PARAMS_WITH_CODE.merge(client_id: "randomid") + visit new_api_openid_connect_authorization_path(params) +end + +When /^I parse the auth code and create a request to the token endpoint$/ do + current_url = page.driver.network_traffic.last.url # We get a redirect to example.org that we can't follow + code = current_url[/(?<=code=)[^&]+/] + expect(code).to be_present + post api_openid_connect_access_tokens_path, code: code, + redirect_uri: "http://example.org/", grant_type: "authorization_code", + client_id: @client_id, client_secret: @client_secret +end + +When /^I parse the tokens and use it obtain user info$/ do + client_json = JSON.parse(last_response.body) + expect(client_json).to_not have_key "error" + access_token = client_json["access_token"] + encoded_id_token = client_json["id_token"] + decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, + Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY + expect(decoded_token.sub).to eq(@me.diaspora_handle) + get api_openid_connect_user_info_path, access_token: access_token +end diff --git a/features/step_definitions/comment_steps.rb b/features/step_definitions/comment_steps.rb index c8ee0084f05a1a37c97e3f6a452e84e52df186ac..38f1428ada99bb0bd649de3157c13208ff78b1c5 100644 --- a/features/step_definitions/comment_steps.rb +++ b/features/step_definitions/comment_steps.rb @@ -7,24 +7,29 @@ Then /^the first comment field should be open/ do end Then /^the first comment field should be closed$/ do - page.should have_css(".stream_element") + page.should have_css(".stream_element .media") page.should_not have_selector("#main_stream .stream_element .new_comment", match: :first) end -When /^I comment "([^"]*)" on "([^"]*)"$/ do |comment_text, post_text| - comment_on_post(post_text, comment_text) -end - When /^I make a show page comment "([^"]*)"$/ do |comment_text| comment_on_show_page(comment_text) end -When /^I comment a lot on "([^"]*)"$/ do |post_text| - within_post(post_text) do +Given /^"([^"]*)" has commented "([^"]*)" on "([^"]*)"$/ do |email, comment_text, post_text| + user = User.find_by(email: email) + post = StatusMessage.find_by(text: post_text) + user.comment!(post, comment_text) +end + +Given /^"([^"]*)" has commented a lot on "([^"]*)"$/ do |email, post_text| + user = User.find_by(email: email) + post = StatusMessage.find_by(text: post_text) + time = Time.zone.now - 1.year + Timecop.freeze do (1..10).each do |n| - focus_comment_box - make_comment(n) + Timecop.travel time += 1.day + user.comment!(post, "Comment #{n}") end end + Timecop.return end - diff --git a/features/step_definitions/conversations_steps.rb b/features/step_definitions/conversations_steps.rb index 8f5a78d9975e8c1c3f4b46fb76add97230914dc1..918e834d0eae45870c9916756f92e9219822483a 100644 --- a/features/step_definitions/conversations_steps.rb +++ b/features/step_definitions/conversations_steps.rb @@ -1,11 +1,15 @@ Then /^"([^"]*)" should be part of active conversation$/ do |name| - within(".conversation_participants") do + within(".conversation-participants") do find("img.avatar[title^='#{name}']").should_not be_nil end end Then /^I should have (\d+) unread private messages?$/ do |n_unread| - find("header #conversations_badge .badge_count").should have_content(n_unread) + expect(find("header #conversations-link .badge")).to have_content(n_unread) +end + +Then /^I should have no unread private messages$/ do + expect(page).to have_no_css "header #conversations-link .badge" end Then /^I send a message with subject "([^"]*)" and text "([^"]*)" to "([^"]*)"$/ do |subject, text, person| @@ -26,7 +30,7 @@ Then /^I send a message with subject "([^"]*)" and text "([^"]*)" to "([^"]*)" u step %(I press the first ".as-result-item" within ".as-results") step %(I fill in "conversation_subject" with "#{subject}") step %(I fill in "conversation_text" with "#{text}") - find("#conversation_text").native.send_keys :control, :return + find("#conversation_text").native.send_key %i(Ctrl Return) end end @@ -41,7 +45,7 @@ When /^I reply with "([^"]*)" using keyboard shortcuts$/ do |text| step %(I am on the conversations page) step %(I press the first ".conversation" within ".conversations") step %(I fill in "message_text" with "#{text}") - find("#message_text").native.send_keys :control, :return + find("#message_text").native.send_key %i(Ctrl Return) end Then /^I send a mobile message with subject "([^"]*)" and text "([^"]*)" to "([^"]*)"$/ do |subject, text, person| diff --git a/features/step_definitions/custom_web_steps.rb b/features/step_definitions/custom_web_steps.rb index 0c7a8f14924525c20c5d69dcd6ef3ef5ab441375..3883d2acf44efae65f92730abdcf44336b60e0b1 100644 --- a/features/step_definitions/custom_web_steps.rb +++ b/features/step_definitions/custom_web_steps.rb @@ -65,7 +65,7 @@ And /^I expand the publisher$/ do end And /^I close the publisher$/ do - find("#publisher #hide_publisher").click + find("#publisher .md-cancel").click end Then /^the publisher should be expanded$/ do @@ -88,6 +88,7 @@ And /^I hover over the "([^"]+)"$/ do |element| end When /^I prepare the deletion of the first post$/ do + find(".stream .stream_element", match: :first).hover within(find(".stream .stream_element", match: :first)) do ctrl = find(".control-icons") ctrl.hover @@ -96,6 +97,7 @@ When /^I prepare the deletion of the first post$/ do end When /^I prepare hiding the first post$/ do + find(".stream .stream_element", match: :first).hover within(find(".stream .stream_element", match: :first)) do ctrl = find(".control-icons") ctrl.hover @@ -104,25 +106,26 @@ When /^I prepare hiding the first post$/ do end When /^I click to delete the first post$/ do - step "I prepare the deletion of the first post" - step "I confirm the alert" + accept_alert do + step "I prepare the deletion of the first post" + end end When /^I click to hide the first post$/ do - step "I prepare hiding the first post" - step "I confirm the alert" + accept_alert do + step "I prepare hiding the first post" + end end When /^I click to delete the first comment$/ do within("div.comment", match: :first) do - find(".control-icons").hover - find(".comment_delete").click + find(".comment_delete", visible: false).click end end When /^I click to delete the first uploaded photo$/ do page.execute_script("$('#photodropzone .x').css('display', 'block');") - find("#photodropzone .x", match: :first).click + find("#photodropzone .x", match: :first).trigger "click" end And /^I click on selector "([^"]*)"$/ do |selector| @@ -133,20 +136,26 @@ And /^I click on the first selector "([^"]*)"$/ do |selector| find(selector, match: :first).click end -And /^I confirm the alert$/ do - page.driver.browser.switch_to.alert.accept -end - -And /^I reject the alert$/ do - page.driver.browser.switch_to.alert.dismiss +And /^I confirm the alert after (.*)$/ do |action| + accept_alert do + step action + end end -When /^(.*) in the modal window$/ do |action| - within('#facebox') do +And /^I reject the alert after (.*)$/ do |action| + dismiss_confirm do step action end end +And /^I should not see any alert after (.*)$/ do |action| + expect { + accept_alert do + step action + end + }.to raise_error(Capybara::ModalNotFound) +end + When /^(.*) in the mention modal$/ do |action| within('#mentionModal') do step action @@ -185,12 +194,6 @@ When /^I have turned off jQuery effects$/ do page.execute_script("$.fx.off = true") end -When /^I search for "([^\"]*)"$/ do |search_term| - fill_in "q", :with => search_term - find_field("q").native.send_key(:enter) - have_content(search_term) -end - Then /^the "([^"]*)" field(?: within "([^"]*)")? should be filled with "([^"]*)"$/ do |field, selector, value| with_scope(selector) do field = find_field(field) @@ -212,16 +215,16 @@ And /^I scroll down on the notifications dropdown$/ do end Then /^I should have scrolled down$/ do - page.evaluate_script("window.pageYOffset").should > 0 + expect(page.evaluate_script("window.pageYOffset")).to be > 0 end Then /^I should have scrolled down on the notification dropdown$/ do - page.evaluate_script("$('.notifications').scrollTop()").should > 0 + expect(page.evaluate_script("$('.notifications').scrollTop()")).to be > 0 end Then /^the notification dropdown should be visible$/ do - find(:css, "#notification_dropdown").should be_visible + expect(find(:css, "#notification-dropdown")).to be_visible end Then /^the notification dropdown scrollbar should be visible$/ do @@ -238,9 +241,7 @@ And "I wait for notifications to load" do end When /^I resize my window to 800x600$/ do - page.execute_script <<-JS - window.resizeTo(800,600); - JS + page.driver.resize(800, 600) end Then 'I should see an image attached to the post' do @@ -252,12 +253,16 @@ Then 'I press the attached image' do end And "I wait for the popovers to appear" do - page.should have_selector(".popover", count: 3) + expect(page).to have_selector(".popover", count: 3) end And /^I click close on all the popovers$/ do - page.execute_script("$('.popover .close').click();") - page.should_not have_selector(".popover .close") + find(".popover .close", match: :first).click + expect(page).to have_selector(".popover", count: 2, visible: false) + find(".popover .close", match: :first).click + expect(page).to have_selector(".popover", count: 1, visible: false) + find(".popover .close", match: :first).click + expect(page).to_not have_selector(".popover", visible: false) end Then /^I should see a flash message indicating success$/ do @@ -317,7 +322,7 @@ Then(/^I should have a validation error on "(.*?)"$/) do |field_list| check_fields_validation_error field_list end -And /^I active the first hovercard after loading the notifications page$/ do +And /^I activate the first hovercard after loading the notifications page$/ do page.should have_css '.notifications .hovercardable' first('.notifications .hovercardable').hover end diff --git a/features/step_definitions/drawer_steps.rb b/features/step_definitions/drawer_steps.rb new file mode 100644 index 0000000000000000000000000000000000000000..7f7359366b75a3d8f7b5ac2c0c36a6aff08761d0 --- /dev/null +++ b/features/step_definitions/drawer_steps.rb @@ -0,0 +1,5 @@ +And /^I click on "([^"]*)" in the drawer$/ do |txt| + within("#drawer") do + find_link(txt).trigger "click" + end +end diff --git a/features/step_definitions/gallery_steps.rb b/features/step_definitions/gallery_steps.rb new file mode 100644 index 0000000000000000000000000000000000000000..2dc5e262f39be8d715ea18e64c24595cbc1fe2fd --- /dev/null +++ b/features/step_definitions/gallery_steps.rb @@ -0,0 +1,11 @@ +Then "I should see the photo lightbox" do + step %(I should see a "#blueimp-gallery" within "body") +end + +Then "I should not see the photo lightbox" do + step %(I should not see a "#blueimp-gallery" within "body") +end + +Then "I press the close lightbox link" do + find(:css, "#blueimp-gallery .close").click +end diff --git a/features/step_definitions/implicit_flow_steps.rb b/features/step_definitions/implicit_flow_steps.rb new file mode 100644 index 0000000000000000000000000000000000000000..d8b9b1d69edb525aeb821090aa9c273cc9d93bb9 --- /dev/null +++ b/features/step_definitions/implicit_flow_steps.rb @@ -0,0 +1,63 @@ +O_AUTH_QUERY_PARAMS = { + redirect_uri: "http://example.org/", + response_type: "id_token token", + scope: "openid profile read", + nonce: "hello", + state: "hi", + prompt: "login" +} + +O_AUTH_QUERY_PARAMS_WITH_MAX_AGE = { + redirect_uri: "http://example.org/", + response_type: "id_token token", + scope: "openid profile read", + nonce: "hello", + state: "hi", + prompt: "login", + max_age: 30 +} + +Given /^I send a post request from that client to the authorization endpoint$/ do + client_json = JSON.parse(last_response.body) + visit new_api_openid_connect_authorization_path(O_AUTH_QUERY_PARAMS.merge(client_id: client_json["client_id"])) +end + +Given /^I have signed in (\d+) minutes ago$/ do |minutes| + @me.update_attribute(:current_sign_in_at, Time.zone.now - minutes.to_i.minute) +end + +Given /^I send a post request from that client to the authorization endpoint with max age$/ do + client_json = JSON.parse(last_response.body) + visit new_api_openid_connect_authorization_path( + O_AUTH_QUERY_PARAMS_WITH_MAX_AGE.merge(client_id: client_json["client_id"])) +end + +Given /^I send a post request from that client to the authorization endpoint using a invalid client id$/ do + visit new_api_openid_connect_authorization_path(O_AUTH_QUERY_PARAMS.merge(client_id: "randomid")) +end + +When /^I give my consent and authorize the client$/ do + click_button "Approve" +end + +When /^I deny authorization to the client$/ do + click_button "Deny" +end + +Then /^I should not see any tokens in the redirect url$/ do + access_token = current_url[/(?<=access_token=)[^&]+/] + id_token = current_url[/(?<=access_token=)[^&]+/] + expect(access_token).to eq(nil) + expect(id_token).to eq(nil) +end + +When /^I parse the bearer tokens and use it to access user info$/ do + current_url = page.driver.network_traffic.last.url # We get a redirect to example.org that we can't follow + access_token = current_url[/(?<=access_token=)[^&]+/] + expect(access_token).to be_present + get api_openid_connect_user_info_path, access_token: access_token +end + +Then /^I should see an "([^\"]*)" error$/ do |error_message| + expect(page).to have_content(error_message) +end diff --git a/features/step_definitions/keyboard_navigation_steps.rb b/features/step_definitions/keyboard_navigation_steps.rb index 9c7a08d7cd8a21c544b29dd5e655cf504fb46aee..9bf47c478c17ad08de7c8fcd4ee3be3899c92935 100644 --- a/features/step_definitions/keyboard_navigation_steps.rb +++ b/features/step_definitions/keyboard_navigation_steps.rb @@ -5,7 +5,7 @@ When /^I press the "([^\"]*)" key somewhere$/ do |key| end When /^I press the "([^\"]*)" key in the publisher$/ do |key| - find("#status_message_fake_text").native.send_keys(key) + find("#status_message_fake_text").native.send_key(key) end Then /^post (\d+) should be highlighted$/ do |position| @@ -13,12 +13,5 @@ Then /^post (\d+) should be highlighted$/ do |position| end And /^I should have navigated to the highlighted post$/ do - find(".shortcut_selected")["offsetTop"].to_i.should == page.evaluate_script("window.pageYOffset + 50").to_i -end - -When /^I scroll to post (\d+)$/ do |position| - page.should have_css("div.stream_element") - page.driver.browser.execute_script(" - window.scrollTo(window.pageXOffset, $('div.stream_element')[#{position}-1].offsetTop-50); - ") + expect(page.evaluate_script("window.pageYOffset + 60 - $('.shortcut_selected').offset().top").to_i).to be(0) end diff --git a/features/step_definitions/lightbox_steps.rb b/features/step_definitions/lightbox_steps.rb deleted file mode 100644 index 6efdd8546c27bff90ec7bb15dfc2007ee514e377..0000000000000000000000000000000000000000 --- a/features/step_definitions/lightbox_steps.rb +++ /dev/null @@ -1,19 +0,0 @@ -Then 'I should see the photo lightbox' do - step %{I should see a "img" within "#lightbox-imageset"} - step %{I should see a "#lightbox-backdrop" within "body"} - step %{I should see a "#lightbox-image" within "body"} -end - -Then 'I should not see the photo lightbox' do - step %{I should not see a "#lightbox-imageset" within "body"} - step %{I should not see a "#lightbox-backdrop" within "body"} - step %{I should not see a "#lightbox-image" within "body"} -end - -Then 'I press the close lightbox link' do - find(:css, "#lightbox-close-link").click -end - -Then 'I press the lightbox backdrop' do - find(:css, "#lightbox-backdrop").click -end diff --git a/features/step_definitions/location_steps.rb b/features/step_definitions/location_steps.rb new file mode 100644 index 0000000000000000000000000000000000000000..cfd41f0e72d80189d0dfb20d2d1911df1ab7c7e2 --- /dev/null +++ b/features/step_definitions/location_steps.rb @@ -0,0 +1,11 @@ +When /^I allow geolocation$/ do + page.execute_script <<-JS + window.navigator = { + geolocation: { + getCurrentPosition: function(success) { + success({coords: {latitude: 42.42424242, longitude: 3.14159}}); + } + } + }; + JS +end diff --git a/features/step_definitions/mention_steps.rb b/features/step_definitions/mention_steps.rb index f7939afbe9f604e507624720fe8b70ef1ed86435..7f2ce1256a5c6e7945e8eaa61d49c23d61ed75cd 100644 --- a/features/step_definitions/mention_steps.rb +++ b/features/step_definitions/mention_steps.rb @@ -1,24 +1,28 @@ And /^Alice has a post mentioning Bob$/ do - alice = User.find_by_email 'alice@alice.alice' - bob = User.find_by_email 'bob@bob.bob' + alice = User.find_by_email "alice@alice.alice" + bob = User.find_by_email "bob@bob.bob" aspect = alice.aspects.where(:name => "Besties").first alice.post(:status_message, :text => "@{Bob Jones; #{bob.person.diaspora_handle}}", :to => aspect) end And /^Alice has (\d+) posts mentioning Bob$/ do |n| n.to_i.times do - alice = User.find_by_email 'alice@alice.alice' - bob = User.find_by_email 'bob@bob.bob' + alice = User.find_by_email "alice@alice.alice" + bob = User.find_by_email "bob@bob.bob" aspect = alice.aspects.where(:name => "Besties").first alice.post(:status_message, :text => "@{Bob Jones; #{bob.person.diaspora_handle}}", :to => aspect) end end And /^I mention Alice in the publisher$/ do - alice = User.find_by_email 'alice@alice.alice' - write_in_publisher("@{Alice Smith ; #{alice.person.diaspora_handle}}") + step %(I append "@alice" to the publisher) + step %(I click on the first user in the mentions dropdown list) end And /^I click on the first user in the mentions dropdown list$/ do - find('.mentions-autocomplete-list li', match: :first).click + find(".tt-menu .tt-suggestion", match: :first).click +end + +Then /^I should not see the mentions dropdown list$/ do + expect(page).to have_no_css ".tt-menu" end diff --git a/features/step_definitions/message_steps.rb b/features/step_definitions/message_steps.rb index 43399d007163d357f6e56e2174fd572a95f12060..a85c1bd9dd7d0571e31b4d6bc0544761f244e2f5 100644 --- a/features/step_definitions/message_steps.rb +++ b/features/step_definitions/message_steps.rb @@ -5,8 +5,6 @@ Then /^I should see the "(.*)" message$/ do |message| I18n.translate('invitation_codes.excited', :name => @alice.name) when "welcome to diaspora" I18n.translate('users.getting_started.well_hello_there') - when 'post not public' - I18n.translate('error_messages.post_not_public_or_not_exist') else raise "muriel, you don't have that message key, add one here" end diff --git a/features/step_definitions/mobile_steps.rb b/features/step_definitions/mobile_steps.rb index 3162abd72f6aeea2944f3648eee211510c842d02..28a966e3aea9d043adeb1ac415c0ebf118837113 100644 --- a/features/step_definitions/mobile_steps.rb +++ b/features/step_definitions/mobile_steps.rb @@ -1,21 +1,23 @@ When /^I toggle the mobile view$/ do - visit('/mobile/toggle') + visit("/mobile/toggle") end Given /^I visit the mobile publisher page$/ do - visit('/status_messages/new.mobile') + visit("/status_messages/new.mobile") end When /^I visit the mobile search page$/ do - visit('/people.mobile') + visit("/people.mobile") end When /^I open the drawer$/ do - find('#menu_badge').click + find("#menu-badge").click + expect(page).to have_css("#app.draw") end Then /^the aspect dropdown within "([^"]*)" should be labeled "([^"]*)"/ do |selector, label| within(selector) do - current_scope.should have_css("option.list_cover", :text => label) + current_scope.should have_no_css("option.list_cover", text: "updating...") + current_scope.should have_css("option.list_cover", text: label) end end diff --git a/features/step_definitions/modal_steps.rb b/features/step_definitions/modal_steps.rb index f672d9f0389eba111cb75a33708c92c62e226226..ad74522eb8584f83543f02a381ce0c9fdd12a083 100644 --- a/features/step_definitions/modal_steps.rb +++ b/features/step_definitions/modal_steps.rb @@ -1,3 +1,20 @@ -Then /I should see the mention modal/ do +Then /^I should see a modal$/ do + step %{I should see a ".modal.in"} +end + +Then /^I should see the mention modal$/ do step %{I should see a "#mentionModal.in"} end + +When /^I put in my password in the close account modal$/ do + # Capybara helpers fill_in, set and send_keys currently don't work + # inside of Bootstrap modals on Travis CI + execute_script("$(\"#closeAccountModal input#close_account_password\").val(\"#{@me.password}\")") + expect(find("#closeAccountModal input#close_account_password").value).to eq(@me.password) +end + +When /^I press "(.*)" in the modal$/ do |txt| + within(".modal.in") do + find_button(txt).trigger "click" + end +end diff --git a/features/step_definitions/notifications_steps.rb b/features/step_definitions/notifications_steps.rb index 6151b85607c716a9deca6c2f60c1d6082cf0eb40..c61fbf5673218ef77c7b8516625d24674bdad375 100644 --- a/features/step_definitions/notifications_steps.rb +++ b/features/step_definitions/notifications_steps.rb @@ -1,7 +1,7 @@ When /^I filter notifications by likes$/ do - step %(I follow "Liked" within "#notifications_container ul.nav.nav-tabs") + step %(I follow "Liked" within "#notifications_container .list-group") end When /^I filter notifications by mentions$/ do - step %(I follow "Mentioned" within "#notifications_container ul.nav.nav-tabs") + step %(I follow "Mentioned" within "#notifications_container .list-group") end diff --git a/features/step_definitions/oidc_common_steps.rb b/features/step_definitions/oidc_common_steps.rb new file mode 100644 index 0000000000000000000000000000000000000000..24f5437540a494b516eb90bd362c02549ab24534 --- /dev/null +++ b/features/step_definitions/oidc_common_steps.rb @@ -0,0 +1,39 @@ +Given /^a client with a provided picture exists for user "([^\"]*)"$/ do |email| + app = FactoryGirl.create(:o_auth_application_with_image) + user = User.find_by(email: email) + FactoryGirl.create(:auth_with_read, user: user, o_auth_application: app) +end + +Given /^a client exists for user "([^\"]*)"$/ do |email| + user = User.find_by(email: email) + FactoryGirl.create(:auth_with_read, user: user) +end + +When /^I register a new client$/ do + post api_openid_connect_clients_path, redirect_uris: ["http://example.org/"], client_name: "diaspora client" +end + +When /^I use received valid bearer tokens to access user info$/ do + access_token_json = JSON.parse(last_response.body) + get api_openid_connect_user_info_path, access_token: access_token_json["access_token"] +end + +When /^I use invalid bearer tokens to access user info$/ do + get api_openid_connect_user_info_path, access_token: SecureRandom.hex(32) +end + +Then /^I should receive "([^\"]*)"'s id, username, and email$/ do |username| + user_info_json = JSON.parse(last_response.body) + user = User.find_by_username(username) + user_profile_url = File.join(AppConfig.environment.url, "people", user.guid).to_s + expect(user_info_json["profile"]).to have_content(user_profile_url) +end + +Then /^I should receive an "([^\"]*)" error$/ do |error_message| + user_info_json = JSON.parse(last_response.body) + expect(user_info_json["error"]).to have_content(error_message) +end + +Then(/^I should see a message containing "(.*?)"$/) do |message| + expect(find("#openid_connect_error_description").text).to include(message) +end diff --git a/features/step_definitions/post_preview_steps.rb b/features/step_definitions/post_preview_steps.rb index 015400e15e5afa646b1354becac0f072e681a375..f79b4e32ee99475400fe4e6fba4f9c68b31b8abb 100644 --- a/features/step_definitions/post_preview_steps.rb +++ b/features/step_definitions/post_preview_steps.rb @@ -1,9 +1,35 @@ -Then /^the first post should be a preview$/ do - find(".post_preview .post-content").text.should == first_post_text +And /^I edit the post$/ do + with_scope(".publisher-textarea-wrapper") do + find(".md-write-tab").click + end end Then /^the preview should not be collapsed$/ do - find(".post_preview").should_not have_selector('.collapsed') - find(".post_preview").should have_selector('.opened') + with_scope(".publisher-textarea-wrapper .collapsible") do + expect(current_scope).not_to have_css(".collapsed") + end end +And /^I preview the post$/ do + with_scope(".publisher-textarea-wrapper") do + find(".md-preview-tab").click + end +end + +Then /^I should see "([^"]*)" in the preview$/ do |text| + with_scope(".publisher-textarea-wrapper .md-preview") do + expect(current_scope).to have_content(text) + end +end + +Then /^I should not see "([^"]*)" in the preview$/ do |text| + with_scope(".publisher-textarea-wrapper .md-preview") do + expect(current_scope).to_not have_content(text) + end +end + +Then /^I should not be in preview mode$/ do + with_scope(".publisher-textarea-wrapper") do + expect(current_scope).to_not have_css(".md-preview") + end +end diff --git a/features/step_definitions/post_with_poll_steps.rb b/features/step_definitions/post_with_poll_steps.rb index 523e60dc7f1ea42ceea197b30fb587a93deffd98..4d95ef1dbc4d48a43963377edc961f1eb7724df3 100644 --- a/features/step_definitions/post_with_poll_steps.rb +++ b/features/step_definitions/post_with_poll_steps.rb @@ -13,7 +13,7 @@ end When /^I fill in the following for the options:$/ do |table| i = 0 table.raw.flatten.each do |value| - all(".poll-answer input")[i].set(value) + all(".poll-answer input")[i].native.send_keys(value) i+=1 end end @@ -25,7 +25,7 @@ end When(/^I fill in values for the first two options$/) do all(".poll-answer input").each_with_index do |answer, i| - answer.set "answer option #{i}" + answer.native.send_keys "answer option #{i}" end end diff --git a/features/step_definitions/posts_steps.rb b/features/step_definitions/posts_steps.rb index dd0a725c0eb19d8c3b691378134ce17a478945bc..40799cd8654e3aa5bbac078f7e9d51f0c1b6b72a 100644 --- a/features/step_definitions/posts_steps.rb +++ b/features/step_definitions/posts_steps.rb @@ -7,7 +7,7 @@ Then /^the post should be expanded$/ do end Then /^I should see an uploaded image within the photo drop zone$/ do - find("#photodropzone img")["src"].should include("uploads/images") + expect(find("#photodropzone img")["src"]).to include("uploads/images") end Then /^I should not see an uploaded image within the photo drop zone$/ do @@ -15,8 +15,17 @@ Then /^I should not see an uploaded image within the photo drop zone$/ do end Then /^I should not see any posts in my stream$/ do - page.assert_selector("#paginate .loader", visible: :hidden) - page.assert_selector(".stream_element", count: 0) + expect(page).not_to have_selector("#paginate .loader") + expect(page).not_to have_selector(".stream_element .media") + expect(page).to have_selector(".stream_element .no-posts-info") +end + +Then /^I should not see any picture in my stream$/ do + expect(page).to have_selector(".photo_area img", count: 0) +end + +Then /^I should see (\d+) pictures in my stream$/ do |count| + expect(page).to have_selector(".photo_area img", count: count) end Then /^I should not be able to submit the publisher$/ do @@ -28,6 +37,24 @@ Given /^"([^"]*)" has a public post with text "([^"]*)"$/ do |email, text| user.post(:status_message, :text => text, :public => true, :to => user.aspect_ids) end +Given /^"([^"]*)" has a public post with text "([^"]*)" and a poll$/ do |email, text| + user = User.find_by(email: email) + post = user.post(:status_message, text: text, public: true, to: user.aspect_ids) + FactoryGirl.create(:poll, status_message: post) +end + +Given /^"([^"]*)" has a public post with text "([^"]*)" and a location$/ do |email, text| + user = User.find_by(email: email) + post = user.post(:status_message, text: text, public: true, to: user.aspect_ids) + FactoryGirl.create(:location, status_message: post) +end + +Given /^"([^"]*)" has a public post with text "([^"]*)" and a picture/ do |email, text| + user = User.find_by(email: email) + post = user.post(:status_message, text: text, public: true, to: user.aspect_ids) + FactoryGirl.create(:photo, status_message: post) +end + Given /^there are (\d+) public posts from "([^"]*)"$/ do |n_posts, email| user = User.find_by_email(email) (1..n_posts.to_i).each do |n| diff --git a/features/step_definitions/profile_steps.rb b/features/step_definitions/profile_steps.rb index 28a5a3489d40430203ac0a051f4d0e525411671a..af9949d9320b8920e33e02553663804a4ac17f3e 100644 --- a/features/step_definitions/profile_steps.rb +++ b/features/step_definitions/profile_steps.rb @@ -6,6 +6,10 @@ And /^I mark myself as safe for work$/ do uncheck('profile[nsfw]') end +And /^I mark myself as not searchable$/ do + uncheck("profile[searchable]") +end + When(/^I delete a photo$/) do find('.photo.loaded .thumbnail', :match => :first).hover find('.delete', :match => :first).click diff --git a/features/step_definitions/search_steps.rb b/features/step_definitions/search_steps.rb index c623c202db4a1ea13526a6352c98982682983874..35fd296fa34109ad14a070a442332dea65700455 100644 --- a/features/step_definitions/search_steps.rb +++ b/features/step_definitions/search_steps.rb @@ -1,9 +1,24 @@ When /^I enter "([^"]*)" in the search input$/ do |search_term| - fill_in "q", :with => search_term + find("input#q").native.send_keys(search_term) end When /^I click on the first search result$/ do - within(".ac_results") do - find("li", match: :first).click + within(".tt-menu") do + find(".tt-suggestion", match: :first).click end end + +When /^I press enter in the search input$/ do + find("input#q").native.send_keys :return +end + +When /^I search for "([^\"]*)"$/ do |search_term| + field = find_field("q") + fill_in "q", with: search_term + field.native.send_key(:enter) + expect(page).to have_content(search_term) +end + +Then /^I should not see any search results$/ do + expect(page).to_not have_selector(".tt-suggestion") +end diff --git a/features/step_definitions/session_steps.rb b/features/step_definitions/session_steps.rb index 4179799fd8fe6087589d1070d566f0fb10f12d39..03f5bd3ed79e37d1580dbe2175933389d4fd452f 100644 --- a/features/step_definitions/session_steps.rb +++ b/features/step_definitions/session_steps.rb @@ -1,37 +1,31 @@ -Given /^(?:I am signed in)$/ do +Given /^I am signed in( on the mobile website)?$/ do |mobile| automatic_login - confirm_login + confirm_login mobile end When /^I try to sign in manually$/ do manual_login end -When /^I (?:sign|log) in manually as "([^"]*)" with password "([^"]*)"$/ do |username, password| +When /^I (?:sign|log) in manually as "([^"]*)" with password "([^"]*)"( on the mobile website)?$/ \ +do |username, password, mobile| @me = User.find_by_username(username) @me.password ||= password manual_login - confirm_login + confirm_login mobile end -When /^I (?:sign|log) in as "([^"]*)"$/ do |email| +When /^I (?:sign|log) in as "([^"]*)"( on the mobile website)?$/ do |email, mobile| @me = User.find_by_email(email) @me.password ||= 'password' automatic_login - confirm_login + confirm_login mobile end -When /^I (?:sign|log) in as "([^"]*)" on the mobile website$/ do |email| - @me = User.find_by_email(email) - @me.password ||= 'password' - automatic_login - confirm_login_mobile -end - -When /^I (?:sign|log) in with password "([^"]*)"$/ do |password| +When /^I (?:sign|log) in with password "([^"]*)"( on the mobile website)?$/ do |password, mobile| @me.password = password automatic_login - confirm_login + confirm_login mobile end When /^I put in my password in "([^"]*)"$/ do |field| @@ -50,22 +44,27 @@ When /^I submit forgot password form$/ do submit_forgot_password_form end -When /^I fill out reset password form with "([^"]*)" and "([^"]*)"$/ do |new_pass,confirm_pass| - fill_reset_password_form(new_pass, confirm_pass) +When /^I fill out the password reset form with "([^"]*)" and "([^"]*)"$/ do |new_pass,confirm_pass| + fill_password_reset_form(new_pass, confirm_pass) end -When /^I submit reset password form$/ do - submit_reset_password_form +When /^I submit the password reset form$/ do + submit_password_reset_form end When /^I (?:log|sign) out$/ do logout + step "I go to the root page" end When /^I (?:log|sign) out manually$/ do manual_logout end +When /^I (?:log|sign) out manually on the mobile website$/ do + manual_logout_mobile +end + Then(/^I should not be able to sign up$/) do confirm_not_signed_up end diff --git a/features/step_definitions/stream_steps.rb b/features/step_definitions/stream_steps.rb index 901f4da3d31b3ebbe0e18a8a7bdef6a3165b5caf..22c285439c334bca0e5f7d91857b6141222e5192 100644 --- a/features/step_definitions/stream_steps.rb +++ b/features/step_definitions/stream_steps.rb @@ -2,6 +2,10 @@ When /^I (?:like|unlike) the post "([^"]*)" in the stream$/ do |post_text| like_stream_post(post_text) end +Then /^I should see an image in the publisher$/ do + photo_in_publisher.should be_present +end + Then /^"([^"]*)" should be post (\d+)$/ do |post_text, position| stream_element_numbers_content(position).should have_content(post_text) end @@ -10,6 +14,16 @@ When /^I toggle nsfw posts$/ do find(".toggle_nsfw_state", match: :first).click end +When /^I toggle all nsfw posts$/ do + all("a.toggle_nsfw_state").each &:click +end + Then /^I should have (\d+) nsfw posts$/ do |num_posts| page.should have_css(".nsfw-shield", count: num_posts.to_i) end + +When /^(?:|I )click on "([^"]*)" navbar title$/ do |title| + with_scope(".info-bar") do + find("h5", text: title).click + end +end diff --git a/features/step_definitions/tag_steps.rb b/features/step_definitions/tag_steps.rb index c1a6bc46cba5425d0e432702bec6db56ea49bcac..7ea491c4ebd4e96da2168187d04e3d7f026f526c 100644 --- a/features/step_definitions/tag_steps.rb +++ b/features/step_definitions/tag_steps.rb @@ -1,8 +1,13 @@ When(/^I unfollow the "(.*?)" tag$/) do |tag| - within("#tags_list") do - li = find('li', text: tag) - li.hover - li.find('.delete_tag_following').click + accept_alert do + within("#tags_list") do + li = find("li", text: tag) + li.hover + li.find(".delete-tag-following").click + end end - step 'I confirm the alert' +end + +When /^I follow the "(.*?)" tag$/ do |tag| + TagFollowing.create!(tag: FactoryGirl.create(:tag, name: tag), user: @me) end diff --git a/features/step_definitions/user_applications_steps.rb b/features/step_definitions/user_applications_steps.rb new file mode 100644 index 0000000000000000000000000000000000000000..7cef790501063de39666ed90435999e685ffccf6 --- /dev/null +++ b/features/step_definitions/user_applications_steps.rb @@ -0,0 +1,16 @@ +Then /^I should see (\d+) authorized applications$/ do |num| + expect(page).to have_selector(".applications-page", count: 1) + expect(page).to have_selector(".authorized-application", count: num.to_i) +end + +Then /^I should see (\d+) authorized applications with no provided image$/ do |num| + expect(page).to have_selector(".application-img > .entypo-browser", count: num.to_i) +end + +Then /^I should see (\d+) authorized applications with an image$/ do |num| + expect(page).to have_selector(".application-img > .img-responsive", count: num.to_i) +end + +When /^I revoke the first authorization$/ do + find(".app-revoke", match: :first).click +end diff --git a/features/step_definitions/user_steps.rb b/features/step_definitions/user_steps.rb index 7442c926e27875d98173c297ffd0d311f22ecabe..ed1abe5f14dd0fc63ef69f6a06876fffc377cc1c 100644 --- a/features/step_definitions/user_steps.rb +++ b/features/step_definitions/user_steps.rb @@ -46,8 +46,9 @@ Given /^I have been invited by an admin$/ do i.send! end -Given /^I have been invited by bob$/ do - @inviter = FactoryGirl.create(:user, :email => 'bob@bob.bob') +Given /^I have been invited by "([^\"]+)"$/ do |email| + AppConfig.settings.enable_registrations = false + @inviter = User.find_by_email(email) @inviter_invite_count = @inviter.invitation_code.count i = EmailInviter.new("new_invitee@example.com", @inviter) i.send! @@ -118,8 +119,10 @@ Then /^I should have (\d) contacts? in "([^"]*)"$/ do |n_contacts, aspect_name| @me.aspects.where(:name => aspect_name).first.contacts.count.should == n_contacts.to_i end -When /^I (?:add|remove) the person (?:to|from) my "([^\"]*)" aspect$/ do |aspect_name| - toggle_aspect_via_ui(aspect_name) +When /^I (?:add|remove) the person (?:to|from) my "([^\"]*)" aspect(?: within "([^"]*)")?$/ do |aspect_name, within_selector| # rubocop:disable Metrics/LineLength + with_scope(within_selector) do + toggle_aspect_via_ui(aspect_name) + end end When /^I post a status with the text "([^\"]*)"$/ do |text| @@ -156,9 +159,14 @@ Then /^I should not see "([^\"]*)" in the last sent email$/ do |text| email_text.should_not match(text) end -When /^"([^\"]+)" has posted a status message with a photo$/ do |email| +When /^"([^\"]+)" has posted a (public )?status message with a photo$/ do |email, public_status| user = User.find_for_database_authentication(:username => email) - post = FactoryGirl.create(:status_message_with_photo, :text => "Look at this dog", :author => user.person) + post = FactoryGirl.create( + :status_message_with_photo, + text: "Look at this dog", + author: user.person, + public: public_status.present? + ) [post, post.photos.first].each do |p| user.add_to_streams(p, user.aspects) user.dispatch_post(p) @@ -200,20 +208,14 @@ When /^I view "([^\"]*)"'s first post$/ do |email| visit post_path(post) end -Given /^I visit alice's invitation code url$/ do - @alice ||= FactoryGirl.create(:user, :username => 'alice', :getting_started => false) - invite_code = InvitationCode.find_or_create_by(user_id: @alice.id) - visit invite_code_path(invite_code) -end - When /^I fill in the new user form/ do fill_in_new_user_form end -And /^I should be able to friend Alice$/ do - alice = User.find_by_username 'alice' - step 'I should see "Add contact"' - step "I should see \"#{alice.name}\"" +And /^I should be able to friend "([^\"]*)"$/ do |email| + user = User.find_by_email(email) + step 'I should see a ".aspect_dropdown"' + step "I should see \"#{user.name}\"" end When /^I click the sign in button$/ do @@ -225,5 +227,9 @@ Given /^I did request my photos$/ do end Then /^I should get a zipped file$/ do - expect(DownloadHelpers.download).to end_with("zip") + expect(page.response_headers["Content-Type"]).to eq("application/zip") +end + +And /^a person with ID "([^\"]*)" has been discovered$/ do |diaspora_id| + FactoryGirl.create(:person, diaspora_handle: diaspora_id) end diff --git a/features/step_definitions/web_steps.rb b/features/step_definitions/web_steps.rb index a9ed77abfd8ae41b8aa3d25dca32cca7bd9f0de9..7c8da90545df29c31607f2f81e4f14caa65d08d2 100644 --- a/features/step_definitions/web_steps.rb +++ b/features/step_definitions/web_steps.rb @@ -39,13 +39,7 @@ When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector| end end -When /^(?:|I )fill in "([^"]*)" with "([^"]*)"(?: within "([^"]*)")?$/ do |field, value, selector| - with_scope(selector) do - fill_in(field, :with => value) - end -end - -When /^(?:|I )fill in "([^"]*)" for "([^"]*)"(?: within "([^"]*)")?$/ do |value, field, selector| +When /^(?:|I )fill in "([^"]*)" (?:for|with) "([^"]*)"(?: within "([^"]*)")?$/ do |field, value, selector| with_scope(selector) do fill_in(field, :with => value) end @@ -156,18 +150,28 @@ end Then /^the "([^"]*)" checkbox(?: within "([^"]*)")? should be checked$/ do |label, selector| with_scope(selector) do - field_checked = find_field(label)['checked'] - field_checked.should eq('true') + expect(find_field(label)["checked"]).to be_truthy end end Then /^the "([^"]*)" checkbox(?: within "([^"]*)")? should not be checked$/ do |label, selector| with_scope(selector) do - field_checked = find_field(label)['checked'] - field_checked.should be_falsey + expect(find_field(label)["checked"]).to be_falsey end end +Then /^the "([^"]*)" bootstrap-switch should be (on|off)$/ do |label, state| + if state == "on" + expect(page.evaluate_script("$('#{label}').bootstrapSwitch('state')")).to be_truthy + else + expect(page.evaluate_script("$('#{label}').bootstrapSwitch('state')")).to be_falsey + end +end + +Then /^I toggle the "([^"]*)" bootstrap-switch$/ do |label| + page.execute_script("return $('#{label}').bootstrapSwitch('toggleState')") +end + Then /^(?:|I )should be on (.+)$/ do |page_name| confirm_on_page(page_name) end diff --git a/features/support/application_cuke_helpers.rb b/features/support/application_cuke_helpers.rb index f45054494030e166d793c7037bfa3ed23614f93c..082c05b1af12d9394cf4abb35aa4f5c31a555268 100644 --- a/features/support/application_cuke_helpers.rb +++ b/features/support/application_cuke_helpers.rb @@ -1,14 +1,14 @@ module ApplicationCukeHelpers def flash_message_success? - flash_message(selector: "notice").visible? + flash_message(selector: "success").visible? end def flash_message_failure? - flash_message(selector: "error").visible? + flash_message(selector: "danger").visible? end def flash_message_alert? - flash_message(selector: "alert").visible? + flash_message(selector: "danger").visible? end def flash_message_containing?(text) @@ -17,21 +17,19 @@ module ApplicationCukeHelpers def flash_message(opts={}) selector = opts.delete(:selector) - selector &&= "#flash_#{selector}" - find(selector || '.message', {match: :first}.merge(opts)) + selector &&= ".alert-#{selector}" + find(selector || ".flash-message", {match: :first}.merge(opts)) end def confirm_form_validation_error(element) - is_invalid = page.evaluate_script("$('#{element}').is(':invalid')") - expect(is_invalid).to be true + expect(page.evaluate_script("$('#{element}')[0].checkValidity();")).to be false end def check_fields_validation_error(field_list) - field_list.split(',').each do |f| - confirm_form_validation_error('input#'+f.strip) + field_list.split(",").each do |f| + confirm_form_validation_error("input##{f.strip}") end end - end World(ApplicationCukeHelpers) diff --git a/features/support/download_helpers.rb b/features/support/download_helpers.rb deleted file mode 100644 index a3fb9fd49daab91b3f1323183937a25c0c2a5a4b..0000000000000000000000000000000000000000 --- a/features/support/download_helpers.rb +++ /dev/null @@ -1,40 +0,0 @@ -# Credits goes to Steve Richert -# http://collectiveidea.com/blog/archives/2012/01/27/testing-file-downloads-with-capybara-and-chromedriver/ -module DownloadHelpers - TIMEOUT ||= 5 - PATH ||= Rails.root.join("tmp/downloads") - - module_function - - def downloads - Dir[PATH.join("*")] - end - - def download - wait_for_download - downloads.first - end - - def download_content - wait_for_download - File.read(download) - end - - def wait_for_download - Timeout.timeout(TIMEOUT) do - sleep 0.1 until downloaded? - end - end - - def downloaded? - !downloading? && downloads.any? - end - - def downloading? - downloads.grep(/\.part$/).any? - end - - def clear_downloads - FileUtils.rm_f(downloads) - end -end diff --git a/features/support/env.rb b/features/support/env.rb index 99e84a7a5dbc7065c19cc3bf41a3f859574e614d..c26248a98fe76bfdae01016fce3e7af761b64455 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -2,45 +2,32 @@ require "rubygems" ENV["RAILS_ENV"] ||= "test" - # Have all rests run with english browser locale +# Have all rests run with english browser locale ENV["LANG"] = "C" +require 'coveralls' +Coveralls.wear!('rails') + require "cucumber/rails" require "capybara/rails" require "capybara/cucumber" require "capybara/session" -require "selenium/webdriver" +require "capybara/poltergeist" + +require "cucumber/api_steps" +require "json_spec/cucumber" # Ensure we know the appservers port Capybara.server_port = AppConfig.pod_uri.port Rails.application.routes.default_url_options[:host] = AppConfig.pod_uri.host Rails.application.routes.default_url_options[:port] = AppConfig.pod_uri.port -# Use a version of Firefox defined by environment variable, if set -Selenium::WebDriver::Firefox::Binary.path = ENV["FIREFOX_BINARY_PATH"] || Selenium::WebDriver::Firefox::Binary.path - -Capybara.register_driver :selenium do |app| - profile = Selenium::WebDriver::Firefox::Profile.new - # Set the download directory to "tmp/downloads" - profile["browser.download.dir"] = DownloadHelpers::PATH.to_s - # Save the file instead of opening it - profile["browser.download.folderList"] = 2 - # Hide the download Manager - profile["browser.download.manager.showWhenStarting"] = false - # Suppress "open with" dialog for zipped files only - profile["browser.helperApps.neverAsk.saveToDisk"] = "application/zip" - # Start Firefox using our profile - Capybara::Selenium::Driver.new(app, browser: :firefox, profile: profile) -end - -Capybara.register_driver :mobile do |app| - profile = Selenium::WebDriver::Firefox::Profile.new - profile["general.useragent.override"] = "Mozilla/5.0 (Mobile; rv:18.0) Gecko/18.0 Firefox/18.0" - Capybara::Selenium::Driver.new(app, profile: profile) +Capybara.register_driver :poltergeist do |app| + Capybara::Poltergeist::Driver.new(app, timeout: 60) end -Capybara.default_driver = :selenium +Capybara.javascript_driver = :poltergeist # Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In # order to ease the transition to Capybara we set the default here. If you'd @@ -49,10 +36,10 @@ Capybara.default_driver = :selenium Capybara.default_selector = :css # We have a ridiculously high wait time to account for build machines of various beefiness. -# Capybara.default_max_wait_time = 30 +Capybara.default_max_wait_time = 30 # While there are a lot of failures, wait less, avoiding travis timeout -Capybara.default_max_wait_time = 15 +# Capybara.default_max_wait_time = 15 # If you set this to false, any error raised from within your app will bubble # up to your step definition and out to cucumber unless you catch it somewhere @@ -78,8 +65,14 @@ require Rails.root.join('spec', 'support', 'inlined_jobs') require Rails.root.join('spec', 'support', 'user_methods') include HelperMethods -Before do +Before do |scenario| Devise.mailer.deliveries = [] - # Delete all files in "tmp/downloads" - DownloadHelpers.clear_downloads + page.driver.headers = if scenario.source_tag_names.include? "@mobile" + {"User-Agent" => "Mozilla/5.0 (Mobile; rv:18.0) Gecko/18.0 Firefox/18.0"} + else + {} + end + + # Reset overridden settings + AppConfig.reset_dynamic! end diff --git a/features/support/matchers.rb b/features/support/matchers.rb index 24ddc6ff8a6aa7bc23b3eff60184925e41ea7ebe..f38e8935d2373a23f3b044e8b5ad96f4255dfea7 100644 --- a/features/support/matchers.rb +++ b/features/support/matchers.rb @@ -11,6 +11,18 @@ RSpec::Matchers.define :have_path do |expected| end end +RSpec::Matchers.define :have_path_in do |expected| + match do |actual| + await_condition { expected.include? actual.current_path } + end + + failure_message_for_should do |actual| + "expected #{actual.inspect} to have path in #{expected.inspect} but was #{actual.current_path.inspect}" + end + failure_message_for_should_not do |actual| + "expected #{actual.inspect} to not have path in #{expected.inspect} but it had" + end +end RSpec::Matchers.define :have_value do |expected| match do |actual| @@ -25,7 +37,6 @@ RSpec::Matchers.define :have_value do |expected| end end - def await_condition &condition start_time = Time.zone.now until condition.call diff --git a/features/support/paths.rb b/features/support/paths.rb index 90743f5e168342a9a87584a7f85bd5ed737f2905..ae9f0d404e1b4f7685aa0ad2186223300277cf86 100644 --- a/features/support/paths.rb +++ b/features/support/paths.rb @@ -1,49 +1,47 @@ module NavigationHelpers def path_to(page_name) case page_name - when /^person_photos page$/ - person_photos_path(@me.person) - when /^the home(?: )?page$/ - stream_path - when /^the mobile path$/ - force_mobile_path - when /^step (\d)$/ - if $1.to_i == 1 - getting_started_path - else - getting_started_path(:step => $1) - end - when /^the tag page for "([^\"]*)"$/ - tag_path($1) - when /^its ([\w ]+) page$/ - send("#{$1.gsub(/\W+/, '_')}_path", @it) - when /^the ([\w ]+) page$/ - send("#{$1.gsub(/\W+/, '_')}_path") - when /^my edit profile page$/ - edit_profile_path - when /^my profile page$/ - person_path(@me.person) - when /^my acceptance form page$/ - invite_code_path(InvitationCode.first) - when /^the requestors profile$/ - person_path(Request.where(:recipient_id => @me.person.id).first.sender) - when /^"([^\"]*)"'s page$/ - p = User.find_by_email($1).person - { path: person_path(p), - # '#diaspora_handle' on desktop, '.description' on mobile - special_elem: { selector: '#diaspora_handle, .description', text: p.diaspora_handle } - } - when /^"([^\"]*)"'s photos page$/ - p = User.find_by_email($1).person - person_photos_path p - when /^my account settings page$/ - edit_user_path - when /^forgot password page$/ - new_user_password_path - when /^"(\/.*)"/ - $1 - else - raise "Can't find mapping from \"#{page_name}\" to a path." + when /^person_photos page$/ + person_photos_path(@me.person) + when /^the home(?: )?page$/ + stream_path + when /^the mobile path$/ + force_mobile_path + when /^the user applications page$/ + api_openid_connect_user_applications_path + when /^the tag page for "([^\"]*)"$/ + tag_path(Regexp.last_match(1)) + when /^its ([\w ]+) page$/ + send("#{Regexp.last_match(1).gsub(/\W+/, '_')}_path", @it) + when /^the mobile ([\w ]+) page$/ + public_send("#{Regexp.last_match(1).gsub(/\W+/, '_')}_path", format: "mobile") + when /^the ([\w ]+) page$/ + public_send("#{Regexp.last_match(1).gsub(/\W+/, '_')}_path") + when /^my edit profile page$/ + edit_profile_path + when /^my profile page$/ + person_path(@me.person) + when /^my acceptance form page$/ + invite_code_path(InvitationCode.first) + when /^the requestors profile$/ + person_path(Request.where(recipient_id: @me.person.id).first.sender) + when /^"([^\"]*)"'s page$/ + p = User.find_by_email(Regexp.last_match(1)).person + {path: person_path(p), + # '#diaspora_handle' on desktop, '.description' on mobile + special_elem: {selector: "#diaspora_handle, .description", text: p.diaspora_handle} + } + when /^"([^\"]*)"'s photos page$/ + p = User.find_by_email(Regexp.last_match(1)).person + person_photos_path p + when /^my account settings page$/ + edit_user_path + when /^forgot password page$/ + new_user_password_path + when %r{^"(/.*)"} + Regexp.last_match(1) + else + raise "Can't find mapping from \"#{page_name}\" to a path." end end @@ -58,17 +56,21 @@ module NavigationHelpers def navigate_to(page_name) path = path_to(page_name) - unless path.is_a?(Hash) - visit(path) - else + if path.is_a?(Hash) visit(path[:path]) await_elem = path[:special_elem] find(await_elem.delete(:selector), await_elem) + else + visit(path) end end def confirm_on_page(page_name) - expect(page).to have_path(path_to(page_name)) + if page_name == "my profile page" + expect(page).to have_path_in([person_path(@me.person), user_profile_path(@me.username)]) + else + expect(page).to have_path(path_to(page_name)) + end end end diff --git a/features/support/poor_mans_webmock.rb b/features/support/poor_mans_webmock.rb index ea9073869b21681edd88b313ab45758a2791634d..061441a8fa33133c4f4d1162b80641a9dbb588ed 100644 --- a/features/support/poor_mans_webmock.rb +++ b/features/support/poor_mans_webmock.rb @@ -4,20 +4,32 @@ module Workers class PublishToHub < Base - def perform(_sender_atom_url) + def perform(*_args) # don't publish to pubsubhubbub in cucumber end end - class HttpMulti < Base - def perform(_user_id, _enc_object_xml, _person_ids, _retry_count=0) + class SendPrivate < Base + def perform(*_args) + # don't federate in cucumber + end + end + + class SendPublic < Base + def perform(*_args) # don't federate in cucumber end end class PostToService < Base - def perform(_service_id, _post_id, _url) + def perform(*_args) # don't post to services in cucumber end end + + class FetchWebfinger < Base + def perform(*_args) + # don't do real discovery in cucumber + end + end end diff --git a/features/support/publishing_cuke_helpers.rb b/features/support/publishing_cuke_helpers.rb index c76c46f681a059c1d7df969f8ffceaea5ac0ce3e..3953182115ae01c01d66c00485a51d78f847c29f 100644 --- a/features/support/publishing_cuke_helpers.rb +++ b/features/support/publishing_cuke_helpers.rb @@ -4,11 +4,18 @@ module PublishingCukeHelpers end def append_to_publisher(txt, input_selector='#status_message_fake_text') - elem = find(input_selector) - elem.native.send_keys(' ' + txt) + status_message_text = find("#status_message_text", visible: false).value + find(input_selector).native.send_key(" #{txt}") # make sure the other text field got the new contents - expect(find("#status_message_text", visible: false)).to have_value txt + if input_selector == "#status_message_fake_text" + begin + expect(page).to have_selector("#status_message_text[value='#{status_message_text} #{txt}']", visible: false) + rescue RSpec::Expectations::ExpectationNotMetError + puts "Value was instead: #{find('#status_message_text', visible: false).value.inspect}" + raise + end + end end def upload_file_with_publisher(path) @@ -26,10 +33,10 @@ module PublishingCukeHelpers end def submit_publisher - txt = find('#publisher #status_message_fake_text').value - find('#publisher .creation').click + txt = find("#publisher #status_message_fake_text").value + find("#publisher .btn-primary").click # wait for the content to appear - expect(find('#main_stream')).to have_content(txt) + expect(find("#main_stream")).to have_content(txt) end def click_and_post(text) @@ -38,10 +45,8 @@ module PublishingCukeHelpers end def click_publisher - page.execute_script(' - $("#publisher").removeClass("closed"); - $("#publisher").find("#status_message_fake_text").focus(); - ') + find("#status_message_fake_text").click + expect(find("#publisher")).to have_css(".publisher-textarea-wrapper.active") end def publisher_submittable? @@ -106,18 +111,6 @@ module PublishingCukeHelpers end end - def stream_posts - all('.stream_element') - end - - def comment_on_post(post_text, comment_text) - within_post(post_text) do - focus_comment_box - make_comment(comment_text) - end - step %Q(I should see "#{comment_text}" within ".comment") - end - def comment_on_show_page(comment_text) within("#single-post-interactions") do make_comment(comment_text) diff --git a/features/support/user_cuke_helpers.rb b/features/support/user_cuke_helpers.rb index fb8b339f8e90ea79a7b5ef9f6265a2483e40e1a1..5043d0a0a4a4ae26bffd95482149e40453c14768 100644 --- a/features/support/user_cuke_helpers.rb +++ b/features/support/user_cuke_helpers.rb @@ -43,27 +43,30 @@ module UserCukeHelpers end # checks the page content to see, if the login was successful - def confirm_login - page.has_content?("#{@me.first_name} #{@me.last_name}") - end - - # checks the mobile page content to see, if the login was successful - def confirm_login_mobile - page.has_css?("#notification_badge") + def confirm_login(mobile) + if mobile + expect(page).to have_css "#menu-badge" + else + expect(find("#user_menu")).to have_content "#{@me.first_name} #{@me.last_name}" + end end # delete all cookies, destroying the current session def logout - $browser.delete_cookie('_session', 'path=/') if $browser - $browser.delete_all_visible_cookies if $browser + page.driver.clear_cookies end # go to user menu, expand it, and click logout def manual_logout - find("#user_menu li:first-child a").click + find("#user_menu .dropdown-toggle").click find("#user_menu li:last-child a").click end + def manual_logout_mobile + find("#menu-badge").click + find("#drawer ul li:last-child a").click + end + def fill_in_new_user_form @username = "ohai" fill_in('user_username', with: @username) @@ -93,14 +96,14 @@ module UserCukeHelpers find("#new_user input.btn").click end - # fill the reset password form - def fill_reset_password_form(new_pass, confirm_pass) + # fill the password reset form + def fill_password_reset_form(new_pass, confirm_pass) fill_in 'user_password', :with => new_pass fill_in 'user_password_confirmation', :with => confirm_pass end - # submit reset password form - def submit_reset_password_form + # submit the password reset form + def submit_password_reset_form find(".btn").click end diff --git a/graphics/README.md b/graphics/README.md index 7e7736920fc467d8dfb5c619924dc70fdea6a728..0687353c71dae7bf2279c77759fb8ea58582f544 100644 --- a/graphics/README.md +++ b/graphics/README.md @@ -3,3 +3,7 @@ the Diaspora frontend. This includes GIMP files, Photoshop files, SVG files, and all other image files of this sort. They are not shown directly to end users, but are used to generate the actual graphics used in the frontend (PNGs, etc.). They can be scaled, tinted, shaded, etc. + +## License + +[dandelion.jpg](https://www.flickr.com/photos/pixagraphic/7218285148/) by pixagraphic has been released under [CC-BY-ND](https://creativecommons.org/licenses/by-nd/2.0/) diff --git a/graphics/dandelion.jpg b/graphics/dandelion.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f406ddc5e5a7d3c5fb104eefb77bbc4ebad2770e Binary files /dev/null and b/graphics/dandelion.jpg differ diff --git a/lib/account_deleter.rb b/lib/account_deleter.rb index 7aaf4093733a10701e58e3c2a7d5df3dee757ccc..83c31c5285ec8babb049dd007d95dfd89337ec2a 100644 --- a/lib/account_deleter.rb +++ b/lib/account_deleter.rb @@ -27,7 +27,6 @@ class AccountDeleter #person delete_standard_person_associations remove_conversation_visibilities - remove_share_visibilities_on_persons_posts delete_contacts_of_me tombstone_person_and_profile @@ -35,7 +34,6 @@ class AccountDeleter #user deletion methods remove_share_visibilities_on_contacts_posts delete_standard_user_associations - disassociate_invitations disconnect_contacts tombstone_user end @@ -46,15 +44,17 @@ class AccountDeleter #user deletions def normal_ar_user_associates_to_delete - [:tag_followings, :invitations_to_me, :services, :aspects, :user_preferences, :notifications, :blocks] + %i(tag_followings services aspects user_preferences + notifications blocks authorizations o_auth_applications pairwise_pseudonymous_identifiers) end def special_ar_user_associations - [:invitations_from_me, :person, :profile, :contacts, :auto_follow_back_aspect] + %i(person profile contacts auto_follow_back_aspect) end def ignored_ar_user_associations - [:followed_tags, :invited_by, :contact_people, :aspect_memberships, :ignored_people, :conversation_visibilities, :conversations, :reports] + %i(followed_tags invited_by contact_people aspect_memberships + ignored_people share_visibilities conversation_visibilities conversations reports) end def delete_standard_user_associations @@ -69,24 +69,14 @@ class AccountDeleter end end - def disassociate_invitations - user.invitations_from_me.each do |inv| - inv.convert_to_admin! - end - end - def disconnect_contacts user.contacts.destroy_all end # Currently this would get deleted due to the db foreign key constrainsts, # but we'll keep this method here for completeness - def remove_share_visibilities_on_persons_posts - ShareVisibility.for_contacts_of_a_person(person).destroy_all - end - def remove_share_visibilities_on_contacts_posts - ShareVisibility.for_a_users_contacts(user).destroy_all + ShareVisibility.for_a_user(user).destroy_all end def remove_conversation_visibilities @@ -107,11 +97,11 @@ class AccountDeleter end def normal_ar_person_associates_to_delete - [:posts, :photos, :mentions, :participations, :roles] + %i(posts photos mentions participations roles) end def ignored_or_special_ar_person_associations - [:comments, :contacts, :notification_actors, :notifications, :owner, :profile, :conversation_visibilities] + %i(comments contacts notification_actors notifications owner profile conversation_visibilities pod) end def mark_account_deletion_complete diff --git a/lib/api/openid_connect/authorization_point/endpoint.rb b/lib/api/openid_connect/authorization_point/endpoint.rb new file mode 100644 index 0000000000000000000000000000000000000000..8f3392bd97760ceda87530d583345e76dbef481f --- /dev/null +++ b/lib/api/openid_connect/authorization_point/endpoint.rb @@ -0,0 +1,62 @@ +module Api + module OpenidConnect + module AuthorizationPoint + class Endpoint + attr_accessor :app, :user, :o_auth_application, :redirect_uri, :response_type, + :scopes, :request_uri, :request_object, :nonce + delegate :call, to: :app + + def initialize(user) + @user = user + @app = Rack::OAuth2::Server::Authorize.new do |req, res| + build_from_request_object(req) + build_attributes(req, res) + if OAuthApplication.available_response_types.include? Array(req.response_type).join(" ") + handle_response_type(req, res) + else + req.unsupported_response_type! + end + end + end + + def build_attributes(req, res) + build_client(req) + build_redirect_uri(req, res) + verify_nonce(req, res) + build_scopes(req) + end + + def handle_response_type(_req, _res) + raise NotImplementedError # Implemented by subclass + end + + private + + def build_client(req) + @o_auth_application = OAuthApplication.find_by_client_id(req.client_id) || req.bad_request! + end + + def build_redirect_uri(req, res) + res.redirect_uri = @redirect_uri = req.verify_redirect_uri!(@o_auth_application.redirect_uris) + end + + def verify_nonce(req, res) + req.invalid_request! "nonce required" if res.protocol_params_location == :fragment && req.nonce.blank? + end + + def build_scopes(req) + replace_profile_scope_with_specific_claims(req) + @scopes = req.scope.map {|scope| + scope.tap do |scope_name| + req.invalid_scope! "Unknown scope: #{scope_name}" unless auth_scopes.include? scope_name + end + } + end + + def auth_scopes + Api::OpenidConnect::Authorization::SCOPES + end + end + end + end +end diff --git a/lib/api/openid_connect/authorization_point/endpoint_confirmation_point.rb b/lib/api/openid_connect/authorization_point/endpoint_confirmation_point.rb new file mode 100644 index 0000000000000000000000000000000000000000..08e99b25db12ddfad2b94cadf3d846fbb1da733e --- /dev/null +++ b/lib/api/openid_connect/authorization_point/endpoint_confirmation_point.rb @@ -0,0 +1,72 @@ +module Api + module OpenidConnect + module AuthorizationPoint + class EndpointConfirmationPoint < Endpoint + def initialize(current_user, approved=false) + super(current_user) + @approved = approved + end + + def handle_response_type(req, res) + handle_approval(@approved, req, res) + end + + def handle_approval(approved, req, res) + if approved + approved!(req, res) + else + req.access_denied! + end + end + + def replace_profile_scope_with_specific_claims(_req) + # Empty + end + + def build_from_request_object(_req) + # Empty + end + + private + + def approved!(req, res) + auth = find_or_build_auth(req) + handle_approved_response_type(auth, req, res) + res.approve! + end + + def find_or_build_auth(req) + OpenidConnect::Authorization.find_or_create_by!( + o_auth_application: @o_auth_application, user: @user, redirect_uri: @redirect_uri).tap do |auth| + auth.nonce = req.nonce + auth.scopes = @scopes + auth.save + end + end + + def handle_approved_response_type(auth, req, res) + response_types = Array(req.response_type) + handle_approved_auth_code(auth, res, response_types) + handle_approved_access_token(auth, res, response_types) + handle_approved_id_token(auth, res, response_types) + end + + def handle_approved_auth_code(auth, res, response_types) + return unless response_types.include?(:code) + res.code = auth.create_code + end + + def handle_approved_access_token(auth, res, response_types) + return unless response_types.include?(:token) + res.access_token = auth.create_access_token + end + + def handle_approved_id_token(auth, res, response_types) + return unless response_types.include?(:id_token) + id_token = auth.create_id_token + res.id_token = id_token.to_jwt(code: res.try(:code), access_token: res.try(:access_token)) + end + end + end + end +end diff --git a/lib/api/openid_connect/authorization_point/endpoint_start_point.rb b/lib/api/openid_connect/authorization_point/endpoint_start_point.rb new file mode 100644 index 0000000000000000000000000000000000000000..007a2c592ceb2c3ded42b9078832a46d724fad07 --- /dev/null +++ b/lib/api/openid_connect/authorization_point/endpoint_start_point.rb @@ -0,0 +1,35 @@ +module Api + module OpenidConnect + module AuthorizationPoint + class EndpointStartPoint < Endpoint + def build_from_request_object(req) + request_object = build_request_object(req) + return unless request_object + claims = request_object.raw_attributes.with_indifferent_access[:claims].try(:[], :userinfo).try(:keys) + return unless claims + req.update_param("scope", req.scope + claims) + end + + def handle_response_type(req, _res) + @response_type = req.response_type + end + + def replace_profile_scope_with_specific_claims(req) + profile_claims = %w(sub aud name nickname profile picture) + scopes_as_claims = req.scope.flat_map {|scope| scope == "profile" ? profile_claims : [scope] }.uniq + req.update_param("scope", scopes_as_claims) + end + + private + + def build_request_object(req) + if req.request_uri.present? + OpenIDConnect::RequestObject.fetch req.request_uri + elsif req.request.present? + OpenIDConnect::RequestObject.decode req.request + end + end + end + end + end +end diff --git a/lib/api/openid_connect/error.rb b/lib/api/openid_connect/error.rb new file mode 100644 index 0000000000000000000000000000000000000000..56059ad59249506a4b0482ccbd93c69e5c256ec9 --- /dev/null +++ b/lib/api/openid_connect/error.rb @@ -0,0 +1,16 @@ +module Api + module OpenidConnect + module Error + class InvalidRedirectUri < ::ArgumentError + def initialize + super "Redirect uri contains fragment" + end + end + class InvalidSectorIdentifierUri < ::ArgumentError + def initialize + super "Invalid sector identifier uri" + end + end + end + end +end diff --git a/lib/api/openid_connect/id_token.rb b/lib/api/openid_connect/id_token.rb new file mode 100644 index 0000000000000000000000000000000000000000..cb665317610e9b668a0a6cc0dbf8f0a1f90b41a6 --- /dev/null +++ b/lib/api/openid_connect/id_token.rb @@ -0,0 +1,70 @@ +# Copyright (c) 2011 nov matake +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# See https://github.com/nov/openid_connect_sample/blob/master/app/models/id_token.rb + +require "uri" + +module Api + module OpenidConnect + class IdToken + def initialize(authorization, nonce) + @authorization = authorization + @nonce = nonce + @created_at = Time.current + @expires_at = 30.minutes.from_now + end + + def to_jwt(options={}) + to_response_object(options).to_jwt(OpenidConnect::IdTokenConfig::PRIVATE_KEY) do |jwt| + jwt.kid = :default + end + end + + private + + def to_response_object(options={}) + OpenIDConnect::ResponseObject::IdToken.new(claims).tap do |id_token| + id_token.code = options[:code] if options[:code] + id_token.access_token = options[:access_token] if options[:access_token] + end + end + + def claims + sub = build_sub + @claims ||= { + iss: AppConfig.environment.url, + sub: sub, + aud: @authorization.o_auth_application.client_id, + exp: @expires_at.to_i, + iat: @created_at.to_i, + auth_time: @authorization.user.current_sign_in_at.to_i, + nonce: @nonce, + acr: 0 + } + end + + def build_sub + Api::OpenidConnect::SubjectIdentifierCreator.create(@authorization) + end + end + end +end diff --git a/lib/api/openid_connect/id_token_config.rb b/lib/api/openid_connect/id_token_config.rb new file mode 100644 index 0000000000000000000000000000000000000000..f76fa09613e08002c838f73946dc77075a3c55ba --- /dev/null +++ b/lib/api/openid_connect/id_token_config.rb @@ -0,0 +1,16 @@ +module Api + module OpenidConnect + class IdTokenConfig + key_file_path = File.join(Rails.root, "config", "oidc_key.pem") + if File.exist?(key_file_path) + private_key = OpenSSL::PKey::RSA.new(File.read(key_file_path)) + else + private_key = OpenSSL::PKey::RSA.new(4096) + File.write key_file_path, private_key.to_pem + File.chmod(0600, key_file_path) + end + PRIVATE_KEY = private_key + PUBLIC_KEY = private_key.public_key + end + end +end diff --git a/lib/api/openid_connect/protected_resource_endpoint.rb b/lib/api/openid_connect/protected_resource_endpoint.rb new file mode 100644 index 0000000000000000000000000000000000000000..540b69d1d63cb478b3cb912fb2cb0d726276f066 --- /dev/null +++ b/lib/api/openid_connect/protected_resource_endpoint.rb @@ -0,0 +1,38 @@ +# Copyright (c) 2011 nov matake +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# See https://github.com/nov/openid_connect_sample/blob/master/lib/authentication.rb#L56 + +module Api + module OpenidConnect + module ProtectedResourceEndpoint + attr_reader :current_token + + def require_access_token(required_scopes) + @current_token = request.env[Rack::OAuth2::Server::Resource::ACCESS_TOKEN] + raise Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new("Unauthorized user") unless + @current_token && @current_token.authorization + raise Rack::OAuth2::Server::Resource::Bearer::Forbidden.new(:insufficient_scope) unless + @current_token.authorization.try(:accessible?, required_scopes) + end + end + end +end diff --git a/lib/api/openid_connect/subject_identifier_creator.rb b/lib/api/openid_connect/subject_identifier_creator.rb new file mode 100644 index 0000000000000000000000000000000000000000..b6a771fa0ca46d3ef54947889d717313eac0fd93 --- /dev/null +++ b/lib/api/openid_connect/subject_identifier_creator.rb @@ -0,0 +1,17 @@ +module Api + module OpenidConnect + module SubjectIdentifierCreator + def self.create(auth) + if auth.o_auth_application.ppid? + identifier = auth.o_auth_application.sector_identifier_uri || + URI.parse(auth.o_auth_application.redirect_uris[0]).host + pairwise_pseudonymous_identifier = + auth.user.pairwise_pseudonymous_identifiers.find_or_create_by(identifier: identifier) + pairwise_pseudonymous_identifier.guid + else + auth.user.diaspora_handle + end + end + end + end +end diff --git a/lib/api/openid_connect/token_endpoint.rb b/lib/api/openid_connect/token_endpoint.rb new file mode 100644 index 0000000000000000000000000000000000000000..a2e8c8ac20c4b011d437ed94e04f10e40c8a0700 --- /dev/null +++ b/lib/api/openid_connect/token_endpoint.rb @@ -0,0 +1,57 @@ +# Inspired by https://github.com/nov/openid_connect_sample/blob/master/lib/token_endpoint.rb + +module Api + module OpenidConnect + class TokenEndpoint + attr_accessor :app + delegate :call, to: :app + + def initialize + @app = Rack::OAuth2::Server::Token.new do |req, res| + o_auth_app = retrieve_client(req) + if app_valid?(o_auth_app, req) + handle_flows(req, res) + else + req.invalid_client! + end + end + end + + def handle_flows(req, res) + case req.grant_type + when :refresh_token + handle_refresh_flow(req, res) + when :authorization_code + auth = Api::OpenidConnect::Authorization.with_redirect_uri(req.redirect_uri).use_code(req.code) + req.invalid_grant! if auth.blank? + res.access_token = auth.create_access_token + if auth.accessible? "openid" + id_token = auth.create_id_token + res.id_token = id_token.to_jwt(access_token: res.access_token) + end + else + req.unsupported_grant_type! + end + end + + def handle_refresh_flow(req, res) + # Handle as if scope request was omitted even if provided. + # See https://tools.ietf.org/html/rfc6749#section-6 for handling + auth = Api::OpenidConnect::Authorization.find_by_refresh_token req.client_id, req.refresh_token + if auth + res.access_token = auth.create_access_token + else + req.invalid_grant! + end + end + + def retrieve_client(req) + Api::OpenidConnect::OAuthApplication.find_by client_id: req.client_id + end + + def app_valid?(o_auth_app, req) + o_auth_app.client_secret == req.client_secret + end + end + end +end diff --git a/lib/assets/javascripts/charcount.js b/lib/assets/javascripts/charcount.js new file mode 100644 index 0000000000000000000000000000000000000000..bd70a4285e7e7eac1d1f29f6bec791ea5f8e6ab2 --- /dev/null +++ b/lib/assets/javascripts/charcount.js @@ -0,0 +1,33 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later + +/* + * char count plugin + * options are: + * - allowed: number of allowed characters + * - warning: number of left characters when a warning should be displayed + * - counter: jQuery element to use as the counter + */ +$.fn.charCount = function(opts) { + this.each(function() { + var $this = $(this); + var counter = opts.counter; + + var update = function() { + var count = $this.val().length; + + if (count > opts.allowed) { + counter.removeClass("text-warning").addClass("text-danger"); + } else if (count > opts.allowed - opts.warning) { + counter.removeClass("text-danger").addClass("text-warning"); + } else { + counter.removeClass("text-danger").removeClass("text-warning"); + } + + counter.text(opts.allowed - count); + }; + + $this.on("textchange", update); + update(); + }); +}; +// @license-end diff --git a/lib/assets/javascripts/jquery.autoresize.js b/lib/assets/javascripts/jquery.autoresize.js deleted file mode 100644 index 4bc0959ae72fda75d67fe7927b2ef14a46606cb9..0000000000000000000000000000000000000000 --- a/lib/assets/javascripts/jquery.autoresize.js +++ /dev/null @@ -1,274 +0,0 @@ -/* - * jQuery.fn.autoResize 1.14 - * -- - * https://github.com/padolsey/jQuery.fn.autoResize - * -- - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. */ - -(function($){ - - var uid = 'ar' + +new Date, - - defaults = autoResize.defaults = { - onResize: function(){}, - onBeforeResize: function(){return 123}, - onAfterResize: function(){return 555}, - animate: { - duration: 200, - complete: function(){} - }, - extraSpace: 50, - minHeight: 'original', - maxHeight: 500, - minWidth: 'original', - maxWidth: 500 - }; - - autoResize.cloneCSSProperties = [ - 'lineHeight', 'textDecoration', 'letterSpacing', - 'fontSize', 'fontFamily', 'fontStyle', 'fontWeight', - 'textTransform', 'textAlign', 'direction', 'wordSpacing', 'fontSizeAdjust', - 'paddingTop', 'paddingLeft', 'paddingBottom', 'paddingRight', 'width' - ]; - - autoResize.cloneCSSValues = { - position: 'absolute', - top: -9999, - left: -9999, - opacity: 0, - overflow: 'hidden' - }; - - autoResize.resizableFilterSelector = [ - 'textarea:not(textarea.' + uid + ')', - 'input:not(input[type])', - 'input[type=text]', - 'input[type=password]', - 'input[type=email]', - 'input[type=url]' - ].join(','); - - autoResize.AutoResizer = AutoResizer; - - $.fn.autoResize = autoResize; - - function autoResize(config) { - this.filter(autoResize.resizableFilterSelector).each(function(){ - new AutoResizer( $(this), config ); - }); - return this; - } - - function AutoResizer(el, config) { - - if (el.data('AutoResizer')) { - el.data('AutoResizer').destroy(); - } - - config = this.config = $.extend({}, autoResize.defaults, config); - this.el = el; - - this.nodeName = el[0].nodeName.toLowerCase(); - - this.originalHeight = el.height(); - this.previousScrollTop = null; - - this.value = el.val(); - - if (config.maxWidth === 'original') config.maxWidth = el.width(); - if (config.minWidth === 'original') config.minWidth = el.width(); - if (config.maxHeight === 'original') config.maxHeight = el.height(); - if (config.minHeight === 'original') config.minHeight = el.height(); - - if (this.nodeName === 'textarea') { - el.css({ - resize: 'none', - overflowY: 'hidden' - }); - } - - el.data('AutoResizer', this); - - // Make sure onAfterResize is called upon animation completion - config.animate.complete = (function(f){ - return function() { - config.onAfterResize.call(el); - return f.apply(this, arguments); - }; - }(config.animate.complete)); - - this.bind(); - - } - - AutoResizer.prototype = { - - bind: function() { - - var check = $.proxy(function(){ - this.check(); - return true; - }, this); - - this.unbind(); - - this.el - .bind('keyup.autoResize', check) - //.bind('keydown.autoResize', check) - .bind('change.autoResize', check) - .bind('paste.autoResize', function() { - setTimeout(function() { check(); }, 0); - }); - - if (!this.el.is(':hidden')) { - this.check(null, true); - } - - }, - - unbind: function() { - this.el.unbind('.autoResize'); - }, - - createClone: function() { - - var el = this.el, - clone = this.nodeName === 'textarea' ? el.clone() : $('<span/>'); - - this.clone = clone; - - $.each(autoResize.cloneCSSProperties, function(i, p){ - clone[0].style[p] = el.css(p); - }); - - clone - .removeAttr('name') - .removeAttr('id') - .addClass(uid) - .attr('tabIndex', -1) - .css(autoResize.cloneCSSValues); - - if (this.nodeName === 'textarea') { - clone.height('auto'); - } else { - clone.width('auto').css({ - whiteSpace: 'nowrap' - }); - } - - }, - - check: function(e, immediate) { - - if (!this.clone) { - this.createClone(); - this.injectClone(); - } - - var config = this.config, - clone = this.clone, - el = this.el, - value = el.val(); - - // Do nothing if value hasn't changed - if (value === this.prevValue) { return true; } - this.prevValue = value; - - if (this.nodeName === 'input') { - - clone.text(value); - - // Calculate new width + whether to change - var cloneWidth = clone.width(), - newWidth = (cloneWidth + config.extraSpace) >= config.minWidth ? - cloneWidth + config.extraSpace : config.minWidth, - currentWidth = el.width(); - - newWidth = Math.min(newWidth, config.maxWidth); - - if ( - (newWidth < currentWidth && newWidth >= config.minWidth) || - (newWidth >= config.minWidth && newWidth <= config.maxWidth) - ) { - - config.onBeforeResize.call(el); - config.onResize.call(el); - - el.scrollLeft(0); - - if (config.animate && !immediate) { - el.stop(1,1).animate({ - width: newWidth - }, config.animate); - } else { - el.width(newWidth); - config.onAfterResize.call(el); - } - - } - - return; - - } - - // TEXTAREA - - clone.width(el.width()).height(0).val(value).scrollTop(10000); - - var scrollTop = clone[0].scrollTop; - - // Don't do anything if scrollTop hasen't changed: - if (this.previousScrollTop === scrollTop) { - return; - } - - this.previousScrollTop = scrollTop; - - if (scrollTop + config.extraSpace >= config.maxHeight) { - el.css('overflowY', ''); - scrollTop = config.maxHeight; - immediate = true; - } else if (scrollTop <= config.minHeight) { - scrollTop = config.minHeight; - } else { - el.css('overflowY', 'hidden'); - scrollTop += config.extraSpace; - } - - config.onBeforeResize.call(el); - config.onResize.call(el); - - // Either animate or directly apply height: - if (config.animate && !immediate) { - el.stop(1,1).animate({ - height: scrollTop - }, config.animate); - } else { - el.height(scrollTop); - config.onAfterResize.call(el); - } - - }, - - destroy: function() { - this.unbind(); - this.el.removeData('AutoResizer'); - this.clone.remove(); - delete this.el; - delete this.clone; - }, - - injectClone: function() { - ( - autoResize.cloneContainer || - (autoResize.cloneContainer = $('<arclones/>').appendTo('body')) - ).append(this.clone); - } - - }; - -})(jQuery); diff --git a/lib/assets/javascripts/jquery.mentionsInput.js b/lib/assets/javascripts/jquery.mentionsInput.js deleted file mode 100644 index 7693caaeef872f2ee1ff7a4e5ca224fc27c3b9dd..0000000000000000000000000000000000000000 --- a/lib/assets/javascripts/jquery.mentionsInput.js +++ /dev/null @@ -1,443 +0,0 @@ -// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat -/* - * Mentions Input - * Version 1.0.2 - * Written by: Kenneth Auchenberg (Podio) - * - * Using underscore.js - * - * License: MIT License - http://www.opensource.org/licenses/mit-license.php - * - * Modifications for Diaspora: - * - * Prevent replacing the wrong text by marking the replacement position with a special character - * Don't add a space after inserting a mention - * Only use the first div as a wrapperBox - * Binded paste event on input box to trigger contacts search for autocompletion while adding mention via clipboard - */ - -(function ($, _, undefined) { - - // Settings - var KEY = { PASTE : 118, BACKSPACE : 8, TAB : 9, RETURN : 13, ESC : 27, LEFT : 37, UP : 38, RIGHT : 39, - DOWN : 40, COMMA : 188, SPACE : 32, HOME : 36, END : 35 }; // Keys "enum" - var defaultSettings = { - triggerChar : '@', - onDataRequest : $.noop, - minChars : 2, - showAvatars : true, - elastic : true, - classes : { - autoCompleteItemActive : "active" - }, - templates : { - wrapper : _.template('<div class="mentions-input-box"></div>'), - autocompleteList : _.template('<div class="mentions-autocomplete-list"></div>'), - autocompleteListItem : _.template('<li data-ref-id="<%= id %>" data-ref-type="<%= type %>" data-display="<%= display %>"><%= content %></li>'), - autocompleteListItemAvatar : _.template('<img src="<%= avatar %>" />'), - autocompleteListItemIcon : _.template('<div class="icon <%= icon %>"></div>'), - mentionsOverlay : _.template('<div class="mentions-box"><div class="mentions"><div></div></div></div>'), - mentionItemSyntax : _.template('@[<%= value %>](<%= type %>:<%= id %>)'), - mentionItemHighlight : _.template('<strong><span><%= value %></span></strong>') - } - }; - - var utils = { - htmlEncode : function (str) { - return _.escape(str); - }, - highlightTerm : function (value, term) { - if (!term && !term.length) { - return value; - } - return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<b>$1</b>"); - }, - setCaratPosition : function (domNode, caretPos) { - if (domNode.createTextRange) { - var range = domNode.createTextRange(); - range.move('character', caretPos); - range.select(); - } else { - if (domNode.selectionStart) { - domNode.focus(); - domNode.setSelectionRange(caretPos, caretPos); - } else { - domNode.focus(); - } - } - }, - rtrim: function(string) { - return string.replace(/\s+$/,""); - } - }; - - var MentionsInput = function (settings) { - - var domInput, elmInputBox, elmInputWrapper, elmAutocompleteList, elmWrapperBox, elmMentionsOverlay, elmActiveAutoCompleteItem; - var mentionsCollection = []; - var autocompleteItemCollection = {}; - var inputBuffer = []; - var currentDataQuery = ''; - var mentionChar = "\u200B"; // zero width space - - settings = $.extend(true, {}, defaultSettings, settings ); - - function initTextarea() { - elmInputBox = $(domInput); - - if (elmInputBox.attr('data-mentions-input') == 'true') { - return; - } - - elmInputWrapper = elmInputBox.parent(); - elmWrapperBox = $(settings.templates.wrapper()); - elmInputBox.wrapAll(elmWrapperBox); - elmWrapperBox = elmInputWrapper.find('> div').first(); - - elmInputBox.attr('data-mentions-input', 'true'); - elmInputBox.bind('keydown', onInputBoxKeyDown); - elmInputBox.bind('keypress', onInputBoxKeyPress); - elmInputBox.bind('paste',onInputBoxPaste); - elmInputBox.bind('input', onInputBoxInput); - elmInputBox.bind('click', onInputBoxClick); - elmInputBox.bind('blur', onInputBoxBlur); - - // Elastic textareas, internal setting for the Dispora guys - if( settings.elastic ) { - elmInputBox.elastic(); - } - - } - - function initAutocomplete() { - elmAutocompleteList = $(settings.templates.autocompleteList()); - elmAutocompleteList.appendTo(elmWrapperBox); - elmAutocompleteList.delegate('li', 'mousedown', onAutoCompleteItemClick); - } - - function initMentionsOverlay() { - elmMentionsOverlay = $(settings.templates.mentionsOverlay()); - elmMentionsOverlay.prependTo(elmWrapperBox); - } - - function updateValues() { - var syntaxMessage = getInputBoxValue(); - - _.each(mentionsCollection, function (mention) { - var textSyntax = settings.templates.mentionItemSyntax(mention); - syntaxMessage = syntaxMessage.replace(mentionChar + mention.value, textSyntax); - }); - - var mentionText = utils.htmlEncode(syntaxMessage); - - _.each(mentionsCollection, function (mention) { - var formattedMention = _.extend({}, mention, {value: mentionChar + utils.htmlEncode(mention.value)}); - var textSyntax = settings.templates.mentionItemSyntax(formattedMention); - var textHighlight = settings.templates.mentionItemHighlight(formattedMention); - - mentionText = mentionText.replace(textSyntax, textHighlight); - }); - - mentionText = mentionText.replace(/\n/g, '<br />'); - mentionText = mentionText.replace(/ {2}/g, ' '); - - elmInputBox.data('messageText', syntaxMessage); - elmMentionsOverlay.find('div > div').html(mentionText); - } - - function resetBuffer() { - inputBuffer = []; - } - - function updateMentionsCollection() { - var inputText = getInputBoxValue(); - - mentionsCollection = _.reject(mentionsCollection, function (mention, index) { - return !mention.value || inputText.indexOf(mention.value) == -1; - }); - mentionsCollection = _.compact(mentionsCollection); - } - - function addMention(mention) { - - var currentMessage = getInputBoxValue(); - - // Using a regex to figure out positions - var regex = new RegExp("\\" + settings.triggerChar + currentDataQuery, "gi"); - regex.exec(currentMessage); - - var startCaretPosition = regex.lastIndex - currentDataQuery.length - 1; - var currentCaretPosition = regex.lastIndex; - - var start = currentMessage.substr(0, startCaretPosition); - var end = currentMessage.substr(currentCaretPosition, currentMessage.length); - var startEndIndex = (start + mention.value).length + 1; - - mentionsCollection.push(mention); - - // Cleaning before inserting the value, otherwise auto-complete would be triggered with "old" inputbuffer - resetBuffer(); - currentDataQuery = ''; - hideAutoComplete(); - - // Mentions & syntax message - var updatedMessageText = start + mentionChar + mention.value + end; - elmInputBox.val(updatedMessageText); - updateValues(); - - // Set correct focus and selection - elmInputBox.focus(); - utils.setCaratPosition(elmInputBox[0], startEndIndex); - } - - function getInputBoxValue() { - return $.trim(elmInputBox.val()); - } - - function onAutoCompleteItemClick(e) { - var elmTarget = $(this); - var mention = autocompleteItemCollection[elmTarget.attr('data-uid')]; - - addMention(mention); - - return false; - } - - function onInputBoxClick(e) { - resetBuffer(); - } - - function onInputBoxBlur(e) { - hideAutoComplete(); - } - - function onInputBoxPaste(e) { - pastedData = e.originalEvent.clipboardData.getData("text/plain"); - dataArray = pastedData.split(""); - _.each(dataArray, function(value) { - inputBuffer.push(value); - }); - } - function onInputBoxInput(e) { - updateValues(); - updateMentionsCollection(); - hideAutoComplete(); - - var triggerCharIndex = _.lastIndexOf(inputBuffer, settings.triggerChar); - if (triggerCharIndex > -1) { - currentDataQuery = inputBuffer.slice(triggerCharIndex + 1).join(''); - currentDataQuery = utils.rtrim(currentDataQuery); - - _.defer(_.bind(doSearch, this, currentDataQuery)); - } - } - - function onInputBoxKeyPress(e) { - // Excluding ctrl+v from key press event in firefox - if (!((e.which === KEY.PASTE && e.ctrlKey) || (e.keyCode === KEY.BACKSPACE))) { - var typedValue = String.fromCharCode(e.which || e.keyCode); - inputBuffer.push(typedValue); - } - } - - function onInputBoxKeyDown(e) { - - // This also matches HOME/END on OSX which is CMD+LEFT, CMD+RIGHT - if (e.keyCode == KEY.LEFT || e.keyCode == KEY.RIGHT || e.keyCode == KEY.HOME || e.keyCode == KEY.END) { - // Defer execution to ensure carat pos has changed after HOME/END keys - _.defer(resetBuffer); - - // IE9 doesn't fire the oninput event when backspace or delete is pressed. This causes the highlighting - // to stay on the screen whenever backspace is pressed after a highlighed word. This is simply a hack - // to force updateValues() to fire when backspace/delete is pressed in IE9. - if (navigator.userAgent.indexOf("MSIE 9") > -1) { - _.defer(updateValues); - } - - return; - } - - if (e.keyCode == KEY.BACKSPACE) { - inputBuffer = inputBuffer.slice(0, -1 + inputBuffer.length); // Can't use splice, not available in IE - return; - } - - if (!elmAutocompleteList.is(':visible')) { - return true; - } - - switch (e.keyCode) { - case KEY.UP: - case KEY.DOWN: - var elmCurrentAutoCompleteItem = null; - if (e.keyCode == KEY.DOWN) { - if (elmActiveAutoCompleteItem && elmActiveAutoCompleteItem.length) { - elmCurrentAutoCompleteItem = elmActiveAutoCompleteItem.next(); - } else { - elmCurrentAutoCompleteItem = elmAutocompleteList.find('li').first(); - } - } else { - elmCurrentAutoCompleteItem = $(elmActiveAutoCompleteItem).prev(); - } - - if (elmCurrentAutoCompleteItem.length) { - selectAutoCompleteItem(elmCurrentAutoCompleteItem); - } - - return false; - - case KEY.RETURN: - case KEY.TAB: - if (elmActiveAutoCompleteItem && elmActiveAutoCompleteItem.length) { - elmActiveAutoCompleteItem.trigger('mousedown'); - return false; - } - - break; - } - - return true; - } - - function hideAutoComplete() { - elmActiveAutoCompleteItem = null; - elmAutocompleteList.empty().hide(); - } - - function selectAutoCompleteItem(elmItem) { - elmItem.addClass(settings.classes.autoCompleteItemActive); - elmItem.siblings().removeClass(settings.classes.autoCompleteItemActive); - - elmActiveAutoCompleteItem = elmItem; - } - - function populateDropdown(query, results) { - elmAutocompleteList.show(); - - // Filter items that has already been mentioned - var mentionValues = _.pluck(mentionsCollection, 'value'); - results = _.reject(results, function (item) { - return _.include(mentionValues, item.name); - }); - - if (!results.length) { - hideAutoComplete(); - return; - } - - elmAutocompleteList.empty(); - var elmDropDownList = $("<ul>").appendTo(elmAutocompleteList).hide(); - - _.each(results, function (item, index) { - var itemUid = _.uniqueId('mention_'); - - autocompleteItemCollection[itemUid] = _.extend({}, item, {value: item.name}); - - var elmListItem = $(settings.templates.autocompleteListItem({ - 'id' : utils.htmlEncode(item.id), - 'display' : utils.htmlEncode(item.name), - 'type' : utils.htmlEncode(item.type), - 'content' : utils.highlightTerm(utils.htmlEncode((item.name)), query) - })).attr('data-uid', itemUid); - - if (index === 0) { - selectAutoCompleteItem(elmListItem); - } - - if (settings.showAvatars) { - var elmIcon; - - if (item.avatar) { - elmIcon = $(settings.templates.autocompleteListItemAvatar({ avatar : item.avatar })); - } else { - elmIcon = $(settings.templates.autocompleteListItemIcon({ icon : item.icon })); - } - elmIcon.prependTo(elmListItem); - } - elmListItem = elmListItem.appendTo(elmDropDownList); - }); - - elmAutocompleteList.show(); - elmDropDownList.show(); - } - - function doSearch(query) { - if (query && query.length && query.length >= settings.minChars) { - settings.onDataRequest.call(this, 'search', query, function (responseData) { - populateDropdown(query, responseData); - }); - } - } - - function resetInput() { - elmInputBox.val(''); - mentionsCollection = []; - updateValues(); - } - - // Public methods - return { - init : function (domTarget) { - - domInput = domTarget; - - initTextarea(); - initAutocomplete(); - initMentionsOverlay(); - resetInput(); - - if( settings.prefillMention ) { - addMention( settings.prefillMention ); - } - - }, - - val : function (callback) { - if (!_.isFunction(callback)) { - return; - } - - var value = mentionsCollection.length ? elmInputBox.data('messageText') : getInputBoxValue(); - callback.call(this, value); - }, - - reset : function () { - resetInput(); - }, - - getMentions : function (callback) { - if (!_.isFunction(callback)) { - return; - } - - callback.call(this, mentionsCollection); - } - }; - }; - - $.fn.mentionsInput = function (method, settings) { - - var outerArguments = arguments; - - if (typeof method === 'object' || !method) { - settings = method; - } - - return this.each(function () { - var instance = $.data(this, 'mentionsInput') || $.data(this, 'mentionsInput', new MentionsInput(settings)); - - if (_.isFunction(instance[method])) { - return instance[method].apply(this, Array.prototype.slice.call(outerArguments, 1)); - - } else if (typeof method === 'object' || !method) { - return instance.init.call(this, this); - - } else { - $.error('Method ' + method + ' does not exist'); - } - - }); - }; - -})(jQuery, _); -// @license-end diff --git a/lib/assets/javascripts/keycodes.js b/lib/assets/javascripts/keycodes.js new file mode 100644 index 0000000000000000000000000000000000000000..c0bcb3af59faad72464092f5201fcabedab51452 --- /dev/null +++ b/lib/assets/javascripts/keycodes.js @@ -0,0 +1,117 @@ +window.Keycodes = { + BACKSPACE: 8, + TAB: 9, + ENTER: 13, + RETURN: 13, + SHIFT: 16, + CTRL: 17, + ALT: 18, + PAUSE: 19, + BREAK: 19, + CAPSLOCK: 20, + ESCAPE: 27, + ESC: 27, + SPACEBAR: 32, + SPACE: 32, + PAGEUP: 33, + PAGEDOWN: 34, + END: 35, + HOME: 36, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + INSERT: 45, + DEL: 46, + DELETE: 46, + 0: 48, + 1: 49, + 2: 50, + 3: 51, + 4: 52, + 5: 53, + 6: 54, + 7: 55, + 8: 56, + 9: 57, + A: 65, + B: 66, + C: 67, + D: 68, + E: 69, + F: 70, + G: 71, + H: 72, + I: 73, + J: 74, + K: 75, + L: 76, + M: 77, + N: 78, + O: 79, + P: 80, + Q: 81, + R: 82, + S: 83, + T: 84, + U: 85, + V: 86, + W: 87, + X: 88, + Y: 89, + Z: 90, + LEFTWINDOW: 91, + RIGHTWINDOW: 92, + SELECT: 93, + NUMPAD0: 96, + NUMPAD1: 97, + NUMPAD2: 98, + NUMPAD3: 99, + NUMPAD4: 100, + NUMPAD5: 101, + NUMPAD6: 102, + NUMPAD7: 103, + NUMPAD8: 104, + NUMPAD9: 105, + MULTIPLY: 106, + ADD: 107, + SUBTRACT: 109, + DECIMALPOINT: 110, + DIVIDE: 111, + F1: 112, + F2: 113, + F3: 114, + F4: 115, + F5: 116, + F6: 117, + F7: 118, + F8: 119, + F9: 120, + F10: 121, + F11: 122, + F12: 123, + NUMLOCK: 144, + SCROLLLOCK: 145, + SEMICOLON: 186, + EQUALSIGN: 187, + COMMA: 188, + DASH: 189, + PERIOD: 190, + FORWARDSLASH: 191, + ACCENTGRAVE: 192, + OPENBRACKET: 219, + BACKSLASH: 220, + CLOSEBRACKET: 221, + SINGLEQUOTE: 222, + isInsertion: function(keyCode) { + if(keyCode <= 46 && keyCode !== this.RETURN && keyCode !== this.SPACEBAR) { + return false; + } else if(keyCode > 90 && keyCode < 96) { + return false; + } else if(keyCode >= 112 && keyCode <= 145) { + return false; + } else { + return true; + } + } +}; diff --git a/lib/bookmarklet_renderer.rb b/lib/bookmarklet_renderer.rb new file mode 100644 index 0000000000000000000000000000000000000000..3114d5a807b01733e9a7d105da4d7cd3520882ae --- /dev/null +++ b/lib/bookmarklet_renderer.rb @@ -0,0 +1,28 @@ + +class BookmarkletRenderer + class << self + def cached_name + @cached ||= Rails.root.join("public", "assets", "bookmarklet.js") + end + + def source_name + @source ||= Rails.application.assets["bookmarklet.js"].pathname.to_s + end + + def body + if !File.exist?(cached_name) && Rails.env.production? + raise "please run the Rake task to compile the bookmarklet: `bundle exec rake assets:uglify_bookmarklet`" + end + + compile unless Rails.env.production? # don't make me re-run rake in development + @body ||= File.read(cached_name) + end + + def compile + src = File.read(source_name) + @body = Uglifier.compile(src) + FileUtils.mkdir_p cached_name.dirname + File.open(cached_name, "w") {|f| f.write(@body) } + end + end +end diff --git a/lib/configuration_methods.rb b/lib/configuration_methods.rb index 81d769b78e133eeb4afacb6b79bdf6282cf7a4c9..d9546dce796901550db676c9b4bf5ec7435c956b 100644 --- a/lib/configuration_methods.rb +++ b/lib/configuration_methods.rb @@ -6,15 +6,16 @@ module Configuration return @pod_uri.dup unless @pod_uri.nil? url = environment.url.get - url = "http://#{url}" unless url =~ /^(https?:\/\/)/ - url << "/" unless url.end_with?("/") begin - @pod_uri = Addressable::URI.parse(url) + @pod_uri = Addressable::URI.heuristic_parse(url) rescue puts "WARNING: pod url #{url} is not a legal URI" end + @pod_uri.scheme = "https" if environment.require_ssl? + @pod_uri.path = "/" + @pod_uri.dup end @@ -89,40 +90,25 @@ module Configuration get_git_info if git_available? @git_revision end - attr_writer :git_revision def git_update get_git_info if git_available? @git_update end - attr_writer :git_update def rails_asset_id (git_revision || version)[0..8] end def get_redis_options - if redistogo_url.present? - warn "WARNING: using the REDISTOGO_URL environment variable is deprecated, please use REDIS_URL now." - ENV['REDIS_URL'] = redistogo_url - end - - redis_options = {} + redis_url = ENV["REDIS_URL"] || environment.redis.get - redis_url = ENV['REDIS_URL'] || environment.redis.get + return {} unless redis_url.present? - if ENV['RAILS_ENV']== 'integration2' - redis_options[:url] = "redis://localhost:6380" - elsif redis_url.present? - unless redis_url.start_with?("redis://") || redis_url.start_with?("unix:///") - warn "WARNING: Your redis url (#{redis_url}) doesn't start with redis:// or unix:///" - end - redis_options[:url] = redis_url + unless redis_url.start_with?("redis://", "unix:///") + warn "WARNING: Your redis url (#{redis_url}) doesn't start with redis:// or unix:///" end - - redis_options[:namespace] = AppConfig.environment.sidekiq.namespace.get - - redis_options + {url: redis_url} end def sidekiq_log diff --git a/lib/connection_tester.rb b/lib/connection_tester.rb new file mode 100644 index 0000000000000000000000000000000000000000..6619250e5079bbe479699f1ad2410259012d6dbc --- /dev/null +++ b/lib/connection_tester.rb @@ -0,0 +1,271 @@ + +class ConnectionTester + include Diaspora::Logging + + NODEINFO_SCHEMA = "http://nodeinfo.diaspora.software/ns/schema/1.0".freeze + NODEINFO_FRAGMENT = "/.well-known/nodeinfo".freeze + + class << self + # Test the reachability of a server by the given HTTP/S URL. + # In the first step, a DNS query is performed to check whether the + # given name even resolves correctly. + # The second step is to send a HTTP request and look at the returned + # status code or any returned errors. + # This function isn't intended to check for the availability of a + # specific page, instead a GET request is sent to the root directory + # of the server. + # In the third step an attempt is made to determine the software version + # used on the server, via the nodeinfo page. + # + # @api This is the entry point you're supposed to use for testing + # connections to other diaspora-compatible servers. + # @param [String] url URL + # @return [Result] result object containing information about the + # server and to what point the connection was successful + def check(url) + result = Result.new + + begin + ct = ConnectionTester.new(url, result) + + # test DNS resolving + ct.resolve + + # test HTTP request + ct.request + + # test for the diaspora* version + ct.nodeinfo + + rescue Failure => e + result_from_failure(result, e) + end + + result.freeze + end + + private + + # infer some attributes of the result object based on the failure + def result_from_failure(result, error) + result.error = error + + case error + when AddressFailure, DNSFailure, NetFailure + result.reachable = false + when SSLFailure + result.reachable = true + result.ssl = false + when HTTPFailure + result.reachable = true + when NodeInfoFailure + result.software_version = "" + end + end + end + + # @raise [AddressFailure] if the specified url is not http(s) + def initialize(url, result=Result.new) + @url ||= url + @result ||= result + @uri ||= URI.parse(@url) + raise AddressFailure, + "invalid protocol: '#{@uri.scheme.upcase}'" unless http_uri?(@uri) + rescue AddressFailure => e + raise e + rescue URI::InvalidURIError => e + raise AddressFailure, e.message + rescue StandardError => e + unexpected_error(e) + end + + # Perform the DNS query, the IP address will be stored in the result + # @raise [DNSFailure] caused by a failure to resolve or a timeout + def resolve + @result.ip = IPSocket.getaddress(@uri.host) + rescue SocketError => e + raise DNSFailure, "'#{@uri.host}' - #{e.message}" + rescue StandardError => e + unexpected_error(e) + end + + # Perform a HTTP GET request to determine the following information + # * is the host reachable + # * is port 80/443 open + # * is the SSL certificate valid (only on HTTPS) + # * does the server return a successful HTTP status code + # * is there a reasonable amount of redirects (3 by default) + # * is there a /.well-known/host-meta (this is needed to work, this can be replaced with a mandatory NodeInfo later) + # (can't do a HEAD request, since that's not a defined route in the app) + # + # @raise [NetFailure, SSLFailure, HTTPFailure] if any of the checks fail + # @return [Integer] HTTP status code + def request + with_http_connection do |http| + capture_response_time { http.get("/") } + response = http.get("/.well-known/host-meta") + handle_http_response(response) + end + rescue HTTPFailure => e + raise e + rescue Faraday::ConnectionFailed, Faraday::TimeoutError => e + raise NetFailure, e.message + rescue Faraday::SSLError => e + raise SSLFailure, e.message + rescue ArgumentError, FaradayMiddleware::RedirectLimitReached, Faraday::ClientError => e + raise HTTPFailure, e.message + rescue StandardError => e + unexpected_error(e) + end + + # Try to find out the version of the other servers software. + # Assuming the server speaks nodeinfo + # + # @raise [NodeInfoFailure] if the document can't be fetched + # or the attempt to parse it failed + def nodeinfo + with_http_connection do |http| + ni_resp = http.get(NODEINFO_FRAGMENT) + nd_resp = http.get(find_nodeinfo_url(ni_resp.body)) + find_software_version(nd_resp.body) + end + rescue NodeInfoFailure => e + raise e + rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError => e + raise NodeInfoFailure, "#{e.class}: #{e.message}" + rescue Faraday::ResourceNotFound, JSON::JSONError => e + raise NodeInfoFailure, e.message[0..255].encode(Encoding.default_external, undef: :replace) + rescue StandardError => e + unexpected_error(e) + end + + private + + def with_http_connection + @http ||= Faraday.new(@url) do |c| + c.use Faraday::Response::RaiseError + c.use FaradayMiddleware::FollowRedirects, limit: 3 + c.adapter(Faraday.default_adapter) + c.headers[:user_agent] = "diaspora-connection-tester" + c.options.timeout = 12 + c.options.open_timeout = 6 + # use the configured CA + c.ssl.ca_file = Faraday.default_connection.ssl.ca_file + end + yield(@http) if block_given? + end + + def http_uri?(uri) + uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS) + end + + # request root path, measure response time + # measured time may be skewed, if there are redirects + # + # @return [Faraday::Response] + def capture_response_time + start = Time.zone.now + resp = yield if block_given? + @result.rt = ((Time.zone.now - start) * 1000.0).to_i # milliseconds + resp + end + + def handle_http_response(response) + @result.status_code = Integer(response.status) + + if response.success? + raise HTTPFailure, "redirected to other hostname: #{response.env.url}" unless @uri.host == response.env.url.host + + @result.reachable = true + @result.ssl = (response.env.url.scheme == "https") + else + raise HTTPFailure, "unsuccessful response code: #{response.status}" + end + end + + # walk the JSON document, get the actual document location + def find_nodeinfo_url(body) + jrd = JSON.parse(body) + links = jrd.fetch("links") + raise NodeInfoFailure, "invalid JRD: '#/links' is not an array!" unless links.is_a?(Array) + links.find { |entry| + entry.fetch("rel") == NODEINFO_SCHEMA + }.fetch("href") + end + + # walk the JSON document, find the version string + def find_software_version(body) + info = JSON.parse(body) + JSON::Validator.validate!(NodeInfo.schema("1.0"), info) + sw = info.fetch("software") + @result.software_version = "#{sw.fetch('name')} #{sw.fetch('version')}" + end + + def unexpected_error(error) + logger.error "unexpected error: #{error.class}: #{error.message}\n#{error.backtrace.first(15).join("\n")}" + raise Failure, error.inspect + end + + class Failure < StandardError + end + + class AddressFailure < Failure + end + + class DNSFailure < Failure + end + + class NetFailure < Failure + end + + class SSLFailure < Failure + end + + class HTTPFailure < Failure + end + + class NodeInfoFailure < Failure + end + + Result = Struct.new( + :ip, :reachable, :ssl, :status_code, :rt, :software_version, :error + ) do + # @!attribute ip + # @return [String] resolved IP address from DNS query + + # @!attribute reachable + # @return [Boolean] whether the host was reachable over the network + + # @!attribute ssl + # @return [Boolean] whether the host has working ssl + + # @!attribute status_code + # @return [Integer] HTTP status code that was returned for the HEAD request + + # @!attribute rt + # @return [Integer] response time for the HTTP request + + # @!attribute software_version + # @return [String] version of diaspora* as reported by nodeinfo + + # @!attribute error + # @return [Exception] if the test is unsuccessful, this will contain + # an exception of type {ConnectionTester::Failure} + + def initialize + self.rt = -1 + end + + def success? + error.nil? + end + + def error? + !error.nil? + end + + def failure_message + "#{error.class.name}: #{error.message}" if error? + end + end +end diff --git a/lib/diaspora.rb b/lib/diaspora.rb index 2cf2579c2b9cb54f8474a3eda5f674866fa2307e..f1785738eb4118e00068d388e9f67da49a29f54f 100644 --- a/lib/diaspora.rb +++ b/lib/diaspora.rb @@ -12,5 +12,4 @@ module Diaspora require "diaspora/markdownify" require "diaspora/mentionable" require "diaspora/message_renderer" - require "diaspora/parser" end diff --git a/lib/diaspora/encryptable.rb b/lib/diaspora/encryptable.rb deleted file mode 100644 index 486e23fac70d9f5b745f0dbc6da390d7283446f3..0000000000000000000000000000000000000000 --- a/lib/diaspora/encryptable.rb +++ /dev/null @@ -1,52 +0,0 @@ -module Diaspora - module Encryptable - include Diaspora::Logging - - # Check that signature is a correct signature of #signable_string by person - # - # @param [String] signature The signature to be verified. - # @param [Person] person The signer. - # @return [Boolean] - def verify_signature(signature, person) - if person.nil? - logger.warn "event=verify_signature status=abort reason=no_person guid=#{guid}" - return false - elsif person.public_key.nil? - logger.warn "event=verify_signature status=abort reason=no_key guid=#{guid}" - return false - elsif signature.nil? - logger.warn "event=verify_signature status=abort reason=no_signature guid=#{guid}" - return false - end - validity = person.public_key.verify OpenSSL::Digest::SHA256.new, Base64.decode64(signature), signable_string - logger.info "event=verify_signature status=complete guid=#{guid} validity=#{validity}" - validity - end - - # @param [OpenSSL::PKey::RSA] key An RSA key - # @return [String] A Base64 encoded signature of #signable_string with key - def sign_with_key(key) - sig = Base64.strict_encode64(key.sign( OpenSSL::Digest::SHA256.new, signable_string )) - logger.info "event=sign_with_key status=complete guid=#{guid}" - sig - end - - # @return [Array<String>] The ROXML attrs other than author_signature and parent_author_signature. - def signable_accessors - accessors = self.class.roxml_attrs.collect do |definition| - definition.accessor - end - ['author_signature', 'parent_author_signature'].each do |acc| - accessors.delete acc - end - accessors - end - - # @return [String] Defaults to the ROXML attrs which are not signatures. - def signable_string - signable_accessors.collect{ |accessor| - (self.send accessor.to_sym).to_s - }.join(';') - end - end -end diff --git a/lib/diaspora/exceptions.rb b/lib/diaspora/exceptions.rb index 5e537594e9bf8a31686b88ea55da1fd7678327d2..f17689e3183e3bbbbe5dae01d49153b4839127d3 100644 --- a/lib/diaspora/exceptions.rb +++ b/lib/diaspora/exceptions.rb @@ -16,26 +16,4 @@ module Diaspora # that prevents further execution class NotMine < StandardError end - - # Received a message without having a contact - class ContactRequiredUnlessRequest < StandardError - end - - # Got a relayable (comment, like etc.) without having the parent - class RelayableObjectWithoutParent < StandardError - end - - # After building an object the author doesn't match the one in the - # original XML message - class AuthorXMLAuthorMismatch < StandardError - end - - # Tried to fetch a post but it was deleted, not valid - # or the remote end doesn't support post fetching - class PostNotFetchable < StandardError - end - - # Error while parsing an received message and got nil - class XMLNotParseable < StandardError - end end diff --git a/lib/diaspora/federated.rb b/lib/diaspora/federated.rb index b554d2b7133e76301b6e50afe01ffae672f01ac1..348364fa09e911834c7f49280f86240334b49198 100644 --- a/lib/diaspora/federated.rb +++ b/lib/diaspora/federated.rb @@ -4,9 +4,7 @@ module Diaspora module Federated - require 'diaspora/federated/request' - require 'diaspora/federated/retraction' - require 'diaspora/federated/signed_retraction' - require 'diaspora/federated/relayable_retraction' + require "diaspora/federated/base" + require "diaspora/federated/retraction" end -end \ No newline at end of file +end diff --git a/lib/diaspora/federated/base.rb b/lib/diaspora/federated/base.rb index 70f46dc7930b3d9380b493ef373940ba71228889..ebceec3fa23494a0547e23f140da3addf8cd0477 100644 --- a/lib/diaspora/federated/base.rb +++ b/lib/diaspora/federated/base.rb @@ -2,56 +2,21 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -#the base level federation contract, which right now means that the object -#can be serialized and deserialized from xml, and respond to methods -#in the federation flow - - -#including this module lets you federate an object at the most basic of level +# including this module lets you federate an object at the most basic of level module Diaspora module Federated module Base - include Diaspora::Logging - - def self.included(model) - model.instance_eval do - include ROXML - include Diaspora::Federated::Base::InstanceMethods - end + # object for local recipients + def object_to_receive + self end - module InstanceMethods - def to_diaspora_xml - xml = to_xml - ::Logging::Logger["XMLLogger"].debug "to_xml: #{xml}" - <<-XML - <XML> - <post>#{xml}</post> - </XML> - XML - end - - def x(input) - input.to_s.to_xs - end - - # @abstract - # @note this must return [Array<Person>] - # @return [Array<Person>] - def subscribers(user) - raise 'You must override subscribers in order to enable federation on this model' - end - - # @abstract - def receive(user, person) - raise 'You must override receive in order to enable federation on this model' - end - - # @param [User] sender - # @note this is a hook(optional) - def after_dispatch(sender) - end + # @abstract + # @note this must return [Array<Person>] + # @return [Array<Person>] + def subscribers + raise "You must override subscribers in order to enable federation on this model" end end end diff --git a/lib/diaspora/federated/generator.rb b/lib/diaspora/federated/generator.rb new file mode 100644 index 0000000000000000000000000000000000000000..deebe80cc5df719fdc9949348f5ed82cc7a70968 --- /dev/null +++ b/lib/diaspora/federated/generator.rb @@ -0,0 +1,31 @@ +module Diaspora + module Federated + class Generator + include Diaspora::Logging + + def initialize(user, target) + @user = user + @target = target + end + + def create!(options={}) + relayable = build(options) + if relayable.save! + logger.info "user:#{@user.id} dispatching #{relayable.class}:#{relayable.guid}" + Diaspora::Federation::Dispatcher.defer_dispatch(@user, relayable) + relayable + end + end + + def build(options={}) + self.class.federated_class.new(options.merge(relayable_options).merge(author_id: @user.person.id)) + end + + protected + + def relayable_options + raise NotImplementedError, "You must override relayable_options" + end + end + end +end diff --git a/lib/diaspora/federated/relayable_retraction.rb b/lib/diaspora/federated/relayable_retraction.rb deleted file mode 100644 index 64b396797ef7fa3baeb7507bb5ad8a9b5743893a..0000000000000000000000000000000000000000 --- a/lib/diaspora/federated/relayable_retraction.rb +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -class RelayableRetraction < SignedRetraction - xml_name :relayable_retraction - xml_attr :parent_author_signature - - attr_accessor :parent_author_signature - - delegate :parent, :parent_author, to: :target, allow_nil: true - - def signable_accessors - super - ['parent_author_signature'] - end - - # @param sender [User] - # @param target [Object] - def self.build(sender, target) - retraction = super - retraction.parent_author_signature = retraction.sign_with_key(sender.encryption_key) if defined?(target.parent) && sender.person == target.parent.author - retraction - end - - def diaspora_handle - self.sender_handle - end - - def relayable? - true - end - - def perform receiving_user - logger.debug "Performing relayable retraction for #{target_guid}" - if not self.parent_author_signature.nil? or self.parent.author.remote? - # Don't destroy a relayable unless the top-level owner has received it, otherwise it may not get relayed - self.target.destroy - logger.info "event=relayable_retraction status=complete target_type=#{target_type} guid=#{target_guid}" - end - end - - def receive(recipient, sender) - if self.target.nil? - logger.warn "event=retraction status=abort reason='no post found' sender=#{sender.diaspora_handle} " \ - "target_guid=#{target_guid}" - return - elsif self.parent.author == recipient.person && self.target_author_signature_valid? - #this is a retraction from the downstream object creator, and the recipient is the upstream owner - self.parent_author_signature = self.sign_with_key(recipient.encryption_key) - Postzord::Dispatcher.build(recipient, self).post - self.perform(recipient) - elsif self.parent_author_signature_valid? - #this is a retraction from the upstream owner - self.perform(recipient) - else - logger.warn "event=receive status=abort reason='object signature not valid' " \ - "recipient=#{recipient.diaspora_handle} sender=#{parent.author.diaspora_handle} " \ - "payload_type=#{self.class} parent_id=#{parent.id}" - return - end - self - end - - def parent_author_signature_valid? - verify_signature(self.parent_author_signature, self.parent.author) - end - - def parent_diaspora_handle - target.author.diaspora_handle - end -end diff --git a/lib/diaspora/federated/request.rb b/lib/diaspora/federated/request.rb deleted file mode 100644 index 5de3c00998bc50050ea0c0176746b390631026d9..0000000000000000000000000000000000000000 --- a/lib/diaspora/federated/request.rb +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# t -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -class Request - include Diaspora::Federated::Base - include ActiveModel::Validations - - attr_accessor :sender, :recipient, :aspect - - xml_accessor :sender_handle - xml_accessor :recipient_handle - - validates :sender, :presence => true - validates :recipient, :presence => true - - validate :not_already_connected - validate :not_friending_yourself - - # Initalize variables - # @note we should be using ActiveModel::Serialization for this - # @return [Request] - def self.diaspora_initialize(opts = {}) - req = self.new - req.sender = opts[:from] - req.recipient = opts[:to] - req.aspect = opts[:into] - req - end - - # Alias of sender_handle - # @return [String] - def diaspora_handle - sender_handle - end - - # @note Used for XML marshalling - # @return [String] - def sender_handle - sender.diaspora_handle - end - def sender_handle= sender_handle - self.sender = Person.where(:diaspora_handle => sender_handle).first - end - - # @note Used for XML marshalling - # @return [String] - def recipient_handle - recipient.diaspora_handle - end - def recipient_handle= recipient_handle - self.recipient = Person.where(:diaspora_handle => recipient_handle).first - end - - # Defines the abstract interface used in sending a corresponding [Notification] given the [Request] - # @param user [User] - # @param person [Person] - # @return [Notifications::StartedSharing] - def notification_type(user, person) - Notifications::StartedSharing - end - - # Defines the abstract interface used in sending the [Request] - # @param user [User] - # @return [Array<Person>] The recipient of the request - def subscribers(user) - [self.recipient] - end - - # Finds or initializes a corresponding [Contact], and will set Contact#sharing to true - # Follows back if user setting is set so - # @note A [Contact] may already exist if the [Request]'s recipient is sharing with the sender - # @return [Request] - def receive(user, person) - logger.info("event=receive payload_type=request sender=#{sender} to=#{recipient}") - - contact = user.contacts.find_or_initialize_by(person_id: self.sender.id) - contact.sharing = true - contact.save - - user.share_with(person, user.auto_follow_back_aspect) if user.auto_follow_back && !contact.receiving - - # also, schedule to fetch a few public posts from that person - Diaspora::Fetcher::Public.queue_for(person) - - self - end - - private - - # Checks if a [Contact] does not already exist between the requesting [User] and receiving [Person] - def not_already_connected - if sender && recipient && Contact.where(:user_id => self.recipient.owner_id, :person_id => self.sender.id).exists? - errors[:base] << 'You have already connected to this person' - end - end - - # Checks to see that the requesting [User] is not sending a request to himself - def not_friending_yourself - if self.recipient == self.sender - errors[:base] << 'You can not friend yourself' - end - end -end diff --git a/lib/diaspora/federated/retraction.rb b/lib/diaspora/federated/retraction.rb index 61a5e254e763bcbf50d88cf579cf7c8ebe39ce43..75dd1312f08b4e30fa649b25c9970eb01cbb413e 100644 --- a/lib/diaspora/federated/retraction.rb +++ b/lib/diaspora/federated/retraction.rb @@ -1,74 +1,72 @@ # Copyright (c) 2010-2011, Diaspora Inc. This file is # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. + class Retraction include Diaspora::Federated::Base + include Diaspora::Logging - xml_accessor :post_guid - xml_accessor :diaspora_handle - xml_accessor :type + attr_reader :subscribers, :data - attr_accessor :person, :object, :subscribers + def initialize(data, subscribers, target=nil) + @data = data + @subscribers = subscribers + @target = target + end - def subscribers(user) - unless self.type == 'Person' - @subscribers ||= self.object.subscribers(user) - @subscribers -= self.object.resharers unless self.object.is_a?(Photo) - @subscribers - else - raise 'HAX: you must set the subscribers manaully before unfriending' if @subscribers.nil? - @subscribers - end + def self.for(target, sender=nil) + federation_retraction = case target + when Diaspora::Relayable + Diaspora::Federation::Entities.relayable_retraction(target, sender) + when Post + Diaspora::Federation::Entities.signed_retraction(target, sender) + else + Diaspora::Federation::Entities.retraction(target) + end + + new(federation_retraction.to_h, target.subscribers.select(&:remote?), target) end - def self.for(object) - retraction = self.new - if object.is_a? User - retraction.post_guid = object.person.guid - retraction.type = object.person.class.to_s - else - retraction.post_guid = object.guid - retraction.type = object.class.to_s - retraction.object = object - end - retraction.diaspora_handle = object.diaspora_handle - retraction + def defer_dispatch(user, include_target_author=true) + subscribers = dispatch_subscribers(include_target_author) + sender = dispatch_sender(user) + Workers::DeferredRetraction.perform_async(sender.id, data, subscribers.map(&:id), service_opts(user)) end - def target - @target ||= self.type.constantize.where(:guid => post_guid).first + def perform + logger.debug "Performing retraction for #{target.class.base_class}:#{target.guid}" + target.destroy! + logger.info "event=retraction status=complete target=#{data[:target_type]}:#{data[:target_guid]}" end - def perform receiving_user - logger.debug "Performing retraction for #{post_guid}" + def public? + # TODO: backward compatibility for pre 0.6 pods, they don't relay public retractions + data[:target][:public] && (!data[:target][:parent] || data[:target][:parent][:local]) + end + + private + + attr_reader :target - self.target.destroy if self.target - logger.info "event=retraction status=complete type=#{type} guid=#{post_guid}" + def dispatch_subscribers(include_target_author) + subscribers << target.author if target.is_a?(Diaspora::Relayable) && include_target_author && target.author.remote? + subscribers end - def correct_authorship? - if target.respond_to?(:relayable?) && target.relayable? - [target.author, target.parent.author].include?(person) - else - target.author == person - end + # @deprecated This is only needed for pre 0.6 pods + def dispatch_sender(user) + target.try(:sender_for_dispatch) || user end - def receive(user, person) - if self.type == 'Person' - unless self.person.guid.to_s == self.post_guid.to_s - logger.warn "event=receive status=abort reason='sender is not the person he is trying to retract' " \ - "recipient=#{diaspora_handle} sender=#{self.person.diaspora_handle} " \ - "payload_type=#{self.class} retraction_type=person" - return + def service_opts(user) + return {} unless target.is_a?(StatusMessage) + + user.services.each_with_object(service_types: []) do |service, opts| + service_opts = service.post_opts(target) + if service_opts + opts.merge!(service_opts) + opts[:service_types] << service.class.to_s end - user.disconnected_by(self.target) - elsif target.nil? || !correct_authorship? - logger.warn "event=retraction status=abort reason='no post found authored by retractor' " \ - "sender=#{person.diaspora_handle} post_guid=#{post_guid}" - else - self.perform(user) end - self end end diff --git a/lib/diaspora/federated/shareable.rb b/lib/diaspora/federated/shareable.rb deleted file mode 100644 index 0b29da8d8c019d1d658c55c87bf5ceff4eb2cc19..0000000000000000000000000000000000000000 --- a/lib/diaspora/federated/shareable.rb +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (c) 2012, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -# this module attempts to be what you need to mix into -# base level federation objects that are not relayable, and not persistable -# assumes there is an author, author_id, id, -module Diaspora - module Federated - module Shareable - def self.included(model) - model.instance_eval do - # we are order dependant so you don't have to be! - include Diaspora::Federated::Base - include Diaspora::Federated::Shareable::InstanceMethods - include Diaspora::Guid - - xml_attr :diaspora_handle - xml_attr :public - xml_attr :created_at - end - end - - module InstanceMethods - include Diaspora::Logging - def diaspora_handle - read_attribute(:diaspora_handle) || author.diaspora_handle - end - - def diaspora_handle=(author_handle) - self.author = Person.where(diaspora_handle: author_handle).first - write_attribute(:diaspora_handle, author_handle) - end - - # @param [User] user The user that is receiving this shareable. - # @param [Person] person The person who dispatched this shareable to the - # @return [void] - def receive(user, person) - local_shareable = persisted_shareable - if local_shareable - receive_persisted(user, person, local_shareable) if verify_persisted_shareable(local_shareable) - else - receive_non_persisted(user, person) - end - end - - # @return [void] - def receive_public - local_shareable = persisted_shareable - if local_shareable - update_existing_sharable(local_shareable) if verify_persisted_shareable(local_shareable) - else - save! - end - end - - # The list of people that should receive this Shareable. - # - # @param [User] user The context, or dispatching user. - # @return [Array<Person>] The list of subscribers to this shareable - def subscribers(user) - if self.public? - user.contact_people - else - user.people_in_aspects(user.aspects_with_shareable(self.class, id)) - end - end - - protected - - # @return [Shareable,void] - def persisted_shareable - self.class.where(guid: guid).first - end - - # @return [Boolean] - def verify_persisted_shareable(persisted_shareable) - return true if persisted_shareable.author_id == author_id - logger.warn "event=receive payload_type=#{self.class} update=true status=abort " \ - "sender=#{diaspora_handle} reason='update not from shareable owner' guid=#{guid}" - false - end - - def receive_persisted(user, person, shareable) - known_shareable = user.find_visible_shareable_by_id(self.class.base_class, guid, key: :guid) - if known_shareable - update_existing_sharable(known_shareable) - else - receive_shareable_visibility(user, person, shareable) - end - end - - def update_existing_sharable(shareable) - if shareable.mutable? - shareable.update_attributes(attributes.except("id")) - logger.info "event=receive payload_type=#{self.class} update=true status=complete " \ - "sender=#{diaspora_handle} guid=#{shareable.guid}" - else - logger.warn "event=receive payload_type=#{self.class} update=true status=abort " \ - "sender=#{diaspora_handle} reason=immutable guid=#{shareable.guid}" - end - end - - def receive_shareable_visibility(user, person, shareable) - user.contact_for(person).receive_shareable(shareable) - user.notify_if_mentioned(shareable) - logger.info "event=receive payload_type=#{self.class} status=complete " \ - "sender=#{diaspora_handle} receiver=#{person.diaspora_handle} guid=#{shareable.guid}" - end - - def receive_non_persisted(user, person) - if save - logger.info "event=receive payload_type=#{self.class} status=complete sender=#{diaspora_handle} " \ - "guid=#{guid}" - receive_shareable_visibility(user, person, self) - else - logger.warn "event=receive payload_type=#{self.class} status=abort sender=#{diaspora_handle} " \ - "reason=#{errors.full_messages} guid=#{guid}" - end - rescue ActiveRecord::RecordNotUnique => e - # this happens, when two share-visibilities are received parallel. Retry again with local shareable. - logger.info "event=receive payload_type=#{self.class} status=retry sender=#{diaspora_handle} guid=#{guid}" - local_shareable = persisted_shareable - raise e unless local_shareable - receive_shareable_visibility(user, person, local_shareable) if verify_persisted_shareable(local_shareable) - end - end - end - end -end diff --git a/lib/diaspora/federated/signed_retraction.rb b/lib/diaspora/federated/signed_retraction.rb deleted file mode 100644 index b2ce3fd51782681becf2d6d32344a6d6c94b5674..0000000000000000000000000000000000000000 --- a/lib/diaspora/federated/signed_retraction.rb +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -class SignedRetraction - include Diaspora::Federated::Base - - include Diaspora::Encryptable - - xml_name :signed_retraction - xml_attr :target_guid - xml_attr :target_type - xml_attr :sender_handle - xml_attr :target_author_signature - - attr_accessor :target_guid, - :target_type, - :target_author_signature, - :sender - - #NOTE(fix this hack -- go through the app and make sure we only call RelayableRetraction in a unified way) - def author - if sender.is_a?(User) - sender.person - else - sender - end - end - - def signable_accessors - accessors = self.class.roxml_attrs.collect do |definition| - definition.accessor - end - accessors - ['target_author_signature', 'sender_handle'] - end - - def sender_handle= new_sender_handle - @sender = Person.where(:diaspora_handle => new_sender_handle).first - end - - def sender_handle - @sender.diaspora_handle - end - - def diaspora_handle - self.sender_handle - end - - def subscribers(user) - self.target.subscribers(user) - end - - def self.build(sender, target) - retraction = self.new - retraction.sender = sender - retraction.target = target - retraction.target_author_signature = retraction.sign_with_key(sender.encryption_key) if sender.person == target.author - retraction - end - - def target - @target ||= self.target_type.constantize.where(:guid => target_guid).first - end - - def guid - target_guid - end - def target= new_target - @target = new_target - @target_type = new_target.class.to_s - @target_guid = new_target.guid - end - - def perform receiving_user - logger.debug "Performing retraction for #{target_guid}" - if reshare = Reshare.where(:author_id => receiving_user.person.id, :root_guid => target_guid).first - onward_retraction = self.dup - onward_retraction.sender = receiving_user.person - Postzord::Dispatcher.build(receiving_user, onward_retraction).post - end - if target && !target.destroyed? - self.target.destroy - end - logger.info "event=retraction status=complete target_type=#{target_type} guid=#{target_guid}" - end - - def receive(recipient, sender) - if self.target.nil? - logger.warn "event=retraction status=abort reason='no post found' sender=#{sender.diaspora_handle} " \ - "target_guid=#{target_guid}" - return - elsif self.target_author_signature_valid? - #this is a retraction from the upstream owner - self.perform(recipient) - else - logger.warn "event=receive status=abort reason='object signature not valid' " \ - "recipient=#{recipient.diaspora_handle} sender=#{sender_handle} payload_type=#{self.class}" - return - end - self - end - - def target_author_signature_valid? - verify_signature(self.target_author_signature, self.target.author) - end -end - diff --git a/lib/diaspora/federation.rb b/lib/diaspora/federation.rb index 710e3349e49947ba4c187b2e9ef4372a50be3d4c..d43e2b4f03d332c25704aedbf43f76bd2baad849 100644 --- a/lib/diaspora/federation.rb +++ b/lib/diaspora/federation.rb @@ -1,78 +1,16 @@ module Diaspora module Federation - def self.post(post) - case post - when StatusMessage - status_message(post) - when Reshare - reshare(post) - else - raise ArgumentError, "unknown post-class: #{post.class}" - end + # Raised, if author is ignored by the relayable parent author + class AuthorIgnored < RuntimeError end - def self.location(location) - DiasporaFederation::Entities::Location.new( - address: location.address, - lat: location.lat, - lng: location.lng - ) - end - - def self.photo(photo) - DiasporaFederation::Entities::Photo.new( - author: photo.diaspora_handle, - guid: photo.guid, - public: photo.public, - created_at: photo.created_at, - remote_photo_path: photo.remote_photo_path, - remote_photo_name: photo.remote_photo_name, - text: photo.text, - status_message_guid: photo.status_message_guid, - height: photo.height, - width: photo.width - ) - end - - def self.poll(poll) - DiasporaFederation::Entities::Poll.new( - guid: poll.guid, - question: poll.question, - poll_answers: poll.poll_answers.map {|answer| poll_answer(answer) } - ) - end - - def self.poll_answer(poll_answer) - DiasporaFederation::Entities::PollAnswer.new( - guid: poll_answer.guid, - answer: poll_answer.answer - ) - end - - def self.reshare(reshare) - DiasporaFederation::Entities::Reshare.new( - root_author: reshare.root_diaspora_id, - root_guid: reshare.root_guid, - author: reshare.diaspora_handle, - guid: reshare.guid, - public: reshare.public, - created_at: reshare.created_at, - provider_display_name: reshare.provider_display_name - ) - end - - def self.status_message(status_message) - DiasporaFederation::Entities::StatusMessage.new( - author: status_message.diaspora_handle, - guid: status_message.guid, - raw_message: status_message.raw_message, - photos: status_message.photos.map {|photo| photo(photo) }, - location: status_message.location ? location(status_message.location) : nil, - poll: status_message.poll ? poll(status_message.poll) : nil, - public: status_message.public, - created_at: status_message.created_at, - provider_display_name: status_message.provider_display_name - ) + # Raised, if the author of the existing object doesn't match the received author + class InvalidAuthor < RuntimeError end end end + +require "diaspora/federation/dispatcher" +require "diaspora/federation/entities" +require "diaspora/federation/mappings" +require "diaspora/federation/receive" diff --git a/lib/diaspora/federation/dispatcher.rb b/lib/diaspora/federation/dispatcher.rb new file mode 100644 index 0000000000000000000000000000000000000000..c2b212a568828d5fc215e76f536089a5d76901bf --- /dev/null +++ b/lib/diaspora/federation/dispatcher.rb @@ -0,0 +1,80 @@ +module Diaspora + module Federation + class Dispatcher + include Diaspora::Logging + + def initialize(sender, object, opts={}) + @sender = sender + @object = object + @opts = opts + end + + def self.build(sender, object, opts={}) + sender = object.try(:sender_for_dispatch) || sender + if object.try(:public?) + Public.new(sender, object, opts) + else + Private.new(sender, object, opts) + end + end + + def self.defer_dispatch(sender, object, opts={}) + Workers::DeferredDispatch.perform_async(sender.id, object.class.to_s, object.id, opts) + end + + def dispatch + deliver_to_services + deliver_to_subscribers + end + + private + + attr_reader :sender, :object, :opts + + def deliver_to_services + deliver_to_user_services if opts[:service_types] + end + + def deliver_to_subscribers + local_people, remote_people = subscribers.partition(&:local?) + + deliver_to_local(local_people) unless local_people.empty? + deliver_to_remote(remote_people) + end + + def deliver_to_local(people) + object_to_receive = object.object_to_receive + return unless object_to_receive + Workers::ReceiveLocal.perform_async(object_to_receive.class.to_s, object_to_receive.id, people.map(&:owner_id)) + end + + def deliver_to_remote(_people) + raise NotImplementedError, "This is an abstract base method. Implement in your subclass." + end + + def deliver_to_user_services + case object + when StatusMessage + each_service {|service| Workers::PostToService.perform_async(service.id, object.id, opts[:url]) } + when Retraction + each_service {|service| Workers::DeletePostFromService.perform_async(service.id, opts) } + end + end + + def each_service + sender.services.where(type: opts[:service_types]).each {|service| yield(service) } + end + + def subscribers + opts[:subscribers] || subscribers_from_ids || object.subscribers + end + + def subscribers_from_ids + Person.where(id: opts[:subscriber_ids]) if opts[:subscriber_ids] + end + end + end +end + +require "diaspora/federation/dispatcher/private" +require "diaspora/federation/dispatcher/public" diff --git a/lib/diaspora/federation/dispatcher/private.rb b/lib/diaspora/federation/dispatcher/private.rb new file mode 100644 index 0000000000000000000000000000000000000000..c959dd3b6a2f9fc3f2e0adb92474d5a2c95ebda9 --- /dev/null +++ b/lib/diaspora/federation/dispatcher/private.rb @@ -0,0 +1,28 @@ +module Diaspora + module Federation + class Dispatcher + class Private < Dispatcher + private + + def deliver_to_remote(people) + return if people.empty? + + entity = Entities.build(object) + Workers::SendPrivate.perform_async(sender.id, entity.to_s, targets(people, salmon_slap(entity))) + end + + def targets(people, salmon_slap) + people.map {|person| [person.receive_url, salmon_slap.generate_xml(person.public_key)] }.to_h + end + + def salmon_slap(entity) + DiasporaFederation::Salmon::EncryptedSlap.prepare( + sender.diaspora_handle, + sender.encryption_key, + entity + ) + end + end + end + end +end diff --git a/lib/diaspora/federation/dispatcher/public.rb b/lib/diaspora/federation/dispatcher/public.rb new file mode 100644 index 0000000000000000000000000000000000000000..c063ed118c90c61b4093ad86af14ae02a2da2fe9 --- /dev/null +++ b/lib/diaspora/federation/dispatcher/public.rb @@ -0,0 +1,45 @@ +module Diaspora + module Federation + class Dispatcher + class Public < Dispatcher + private + + def deliver_to_services + deliver_to_hub if object.instance_of?(StatusMessage) + super + end + + def deliver_to_remote(people) + targets = target_urls(people) + additional_target_urls + + return if targets.empty? + + entity = Entities.build(object) + Workers::SendPublic.perform_async(sender.id, entity.to_s, targets, salmon_xml(entity)) + end + + def target_urls(people) + Pod.where(id: people.map(&:pod_id).uniq).map {|pod| pod.url_to("/receive/public") } + end + + def additional_target_urls + return [] unless AppConfig.relay.outbound.send? && object.instance_of?(StatusMessage) + [AppConfig.relay.outbound.url] + end + + def salmon_xml(entity) + DiasporaFederation::Salmon::Slap.generate_xml( + sender.diaspora_handle, + sender.encryption_key, + entity + ) + end + + def deliver_to_hub + logger.debug "deliver to pubsubhubbub sender: #{sender.diaspora_handle}" + Workers::PublishToHub.perform_async(sender.atom_url) + end + end + end + end +end diff --git a/lib/diaspora/federation/entities.rb b/lib/diaspora/federation/entities.rb new file mode 100644 index 0000000000000000000000000000000000000000..cf8d463b6503520aeba10c25430a4a26ba504e5a --- /dev/null +++ b/lib/diaspora/federation/entities.rb @@ -0,0 +1,257 @@ +module Diaspora + module Federation + module Entities + def self.build(entity) + public_send(Mappings.builder_for(entity.class), entity) + end + + def self.build_retraction(retraction) + case retraction.data[:target_type] + when "Comment", "Like", "PollParticipation" + DiasporaFederation::Entities::RelayableRetraction.new(retraction.data) + when "Post" + DiasporaFederation::Entities::SignedRetraction.new(retraction.data) + else + DiasporaFederation::Entities::Retraction.new(retraction.data) + end + end + + def self.post(post) + case post + when StatusMessage + status_message(post) + when Reshare + reshare(post) + else + raise ArgumentError, "unknown post-class: #{post.class}" + end + end + + def self.account_deletion(account_deletion) + DiasporaFederation::Entities::AccountDeletion.new( + author: account_deletion.diaspora_handle + ) + end + + def self.comment(comment) + DiasporaFederation::Entities::Comment.new( + { + author: comment.diaspora_handle, + guid: comment.guid, + parent_guid: comment.post.guid, + text: comment.text, + author_signature: comment.signature.try(:author_signature), + parent: related_entity(comment.post) + }, + comment.signature.try(:order), + comment.signature.try(:additional_data) || {} + ) + end + + def self.contact(contact) + # TODO: use DiasporaFederation::Entities::Contact + DiasporaFederation::Entities::Request.new( + author: contact.user.diaspora_handle, + recipient: contact.person.diaspora_handle + ) + end + + def self.conversation(conversation) + DiasporaFederation::Entities::Conversation.new( + author: conversation.diaspora_handle, + guid: conversation.guid, + subject: conversation.subject, + created_at: conversation.created_at, + participants: conversation.participant_handles, + messages: conversation.messages.map {|message| message(message) } + ) + end + + def self.like(like) + DiasporaFederation::Entities::Like.new( + { + author: like.diaspora_handle, + guid: like.guid, + parent_guid: like.target.guid, + positive: like.positive, + parent_type: Mappings.entity_name_for(like.target), + author_signature: like.signature.try(:author_signature), + parent: related_entity(like.target) + }, + like.signature.try(:order), + like.signature.try(:additional_data) || {} + ) + end + + def self.location(location) + DiasporaFederation::Entities::Location.new( + address: location.address, + lat: location.lat, + lng: location.lng + ) + end + + def self.message(message) + DiasporaFederation::Entities::Message.new( + author: message.diaspora_handle, + guid: message.guid, + text: message.text, + created_at: message.created_at, + parent_guid: message.conversation.guid, + conversation_guid: message.conversation.guid, + author_signature: message.author_signature, + parent: related_entity(message.conversation) + ) + end + + def self.participation(participation) + DiasporaFederation::Entities::Participation.new( + author: participation.diaspora_handle, + guid: participation.guid, + parent_guid: participation.target.guid, + parent_type: Mappings.entity_name_for(participation.target), + parent: related_entity(participation.target) + ) + end + + def self.photo(photo) + DiasporaFederation::Entities::Photo.new( + author: photo.diaspora_handle, + guid: photo.guid, + public: photo.public, + created_at: photo.created_at, + remote_photo_path: photo.remote_photo_path, + remote_photo_name: photo.remote_photo_name, + text: photo.text, + status_message_guid: photo.status_message_guid, + height: photo.height, + width: photo.width + ) + end + + def self.poll(poll) + DiasporaFederation::Entities::Poll.new( + guid: poll.guid, + question: poll.question, + poll_answers: poll.poll_answers.map {|answer| poll_answer(answer) } + ) + end + + def self.poll_answer(poll_answer) + DiasporaFederation::Entities::PollAnswer.new( + guid: poll_answer.guid, + answer: poll_answer.answer + ) + end + + def self.poll_participation(poll_participation) + DiasporaFederation::Entities::PollParticipation.new( + { + author: poll_participation.diaspora_handle, + guid: poll_participation.guid, + parent_guid: poll_participation.poll.guid, + poll_answer_guid: poll_participation.poll_answer.guid, + author_signature: poll_participation.signature.try(:author_signature), + parent: related_entity(poll_participation.poll) + }, + poll_participation.signature.try(:order), + poll_participation.signature.try(:additional_data) || {} + ) + end + + def self.profile(profile) + DiasporaFederation::Entities::Profile.new( + author: profile.diaspora_handle, + first_name: profile.first_name, + last_name: profile.last_name, + image_url: profile.image_url, + image_url_medium: profile.image_url_medium, + image_url_small: profile.image_url_small, + birthday: profile.birthday, + gender: profile.gender, + bio: profile.bio, + location: profile.location, + searchable: profile.searchable, + nsfw: profile.nsfw, + tag_string: profile.tag_string + ) + end + + # @deprecated + def self.relayable_retraction(target, sender) + DiasporaFederation::Entities::RelayableRetraction.new( + target_guid: target.guid, + target_type: Mappings.entity_name_for(target), + target: related_entity(target), + author: sender.diaspora_handle + ) + end + + def self.reshare(reshare) + DiasporaFederation::Entities::Reshare.new( + root_author: reshare.root_diaspora_id, + root_guid: reshare.root_guid, + author: reshare.diaspora_handle, + guid: reshare.guid, + public: reshare.public, + created_at: reshare.created_at, + provider_display_name: reshare.provider_display_name + ) + end + + def self.retraction(target) + case target + when Contact + # TODO: deprecated + author = target.user.diaspora_handle + DiasporaFederation::Entities::Retraction.new( + target_guid: target.user.guid, + target_type: "Person", + target: DiasporaFederation::Entities::RelatedEntity.new(author: author, local: true), + author: author + ) + else + DiasporaFederation::Entities::Retraction.new( + target_guid: target.guid, + target_type: Mappings.entity_name_for(target), + target: related_entity(target), + author: target.diaspora_handle + ) + end + end + + # @deprecated + def self.signed_retraction(target, sender) + DiasporaFederation::Entities::SignedRetraction.new( + target_guid: target.guid, + target_type: Mappings.entity_name_for(target), + target: related_entity(target), + author: sender.diaspora_handle + ) + end + + def self.status_message(status_message) + DiasporaFederation::Entities::StatusMessage.new( + author: status_message.diaspora_handle, + guid: status_message.guid, + text: status_message.text, + photos: status_message.photos.map {|photo| photo(photo) }, + location: status_message.location ? location(status_message.location) : nil, + poll: status_message.poll ? poll(status_message.poll) : nil, + public: status_message.public, + created_at: status_message.created_at, + provider_display_name: status_message.provider_display_name + ) + end + + def self.related_entity(entity) + DiasporaFederation::Entities::RelatedEntity.new( + author: entity.author.diaspora_handle, + local: entity.author.local?, + public: entity.respond_to?(:public?) && entity.public?, + parent: entity.respond_to?(:parent) ? related_entity(entity.parent) : nil + ) + end + end + end +end diff --git a/lib/diaspora/federation/mappings.rb b/lib/diaspora/federation/mappings.rb new file mode 100644 index 0000000000000000000000000000000000000000..2b761b6976ffd1aaab60e877bed3cd763d73eb69 --- /dev/null +++ b/lib/diaspora/federation/mappings.rb @@ -0,0 +1,81 @@ +module Diaspora + module Federation + module Mappings + # used in Diaspora::Federation::Receive + def self.receiver_for(federation_class) + fetch_from(ENTITY_RECEIVERS, federation_class) + end + + # used in Diaspora::Federation::Entities + def self.builder_for(diaspora_class) + fetch_from(ENTITY_BUILDERS, diaspora_class) + end + + def self.model_class_for(entity_name) + fetch_from(ENTITY_MODELS, entity_name) + end + + def self.entity_name_for(model) + fetch_from(ENTITY_NAMES, model.class.base_class) + end + + private_class_method def self.fetch_from(mapping, key) + mapping.fetch(key) { raise DiasporaFederation::Entity::UnknownEntity, "unknown entity: #{key}" } + end + + ENTITY_RECEIVERS = { + DiasporaFederation::Entities::Comment => :comment, + DiasporaFederation::Entities::Contact => :contact, + DiasporaFederation::Entities::Conversation => :conversation, + DiasporaFederation::Entities::Like => :like, + DiasporaFederation::Entities::Message => :message, + DiasporaFederation::Entities::Participation => :participation, + DiasporaFederation::Entities::Photo => :photo, + DiasporaFederation::Entities::PollParticipation => :poll_participation, + DiasporaFederation::Entities::Profile => :profile, + DiasporaFederation::Entities::Reshare => :reshare, + DiasporaFederation::Entities::StatusMessage => :status_message + }.freeze + + ENTITY_BUILDERS = { + AccountDeletion => :account_deletion, + Comment => :comment, + Contact => :contact, + Conversation => :conversation, + Like => :like, + Message => :message, + Participation => :participation, + Photo => :photo, + PollParticipation => :poll_participation, + Profile => :profile, + Reshare => :reshare, + Retraction => :build_retraction, + StatusMessage => :status_message + }.freeze + + ENTITY_MODELS = { + "Comment" => Comment, + "Conversation" => Conversation, + "Like" => Like, + "Participation" => Participation, + "PollParticipation" => PollParticipation, + "Photo" => Photo, + "Poll" => Poll, + "Post" => Post, + # TODO: deprecated + "Person" => Person, + "Reshare" => Post, + "StatusMessage" => Post + }.freeze + + ENTITY_NAMES = { + Comment => "Comment", + Like => "Like", + Participation => "Participation", + PollParticipation => "PollParticipation", + Photo => "Photo", + Post => "Post" + }.freeze + end + end +end diff --git a/lib/diaspora/federation/receive.rb b/lib/diaspora/federation/receive.rb new file mode 100644 index 0000000000000000000000000000000000000000..a61566402cf1c7950d00de1e070f80f2565ce863 --- /dev/null +++ b/lib/diaspora/federation/receive.rb @@ -0,0 +1,323 @@ +module Diaspora + module Federation + module Receive + extend Diaspora::Logging + + def self.perform(entity) + public_send(Mappings.receiver_for(entity.class), entity) + end + + def self.account_deletion(entity) + AccountDeletion.create!(person: author_of(entity), diaspora_handle: entity.author) + end + + def self.comment(entity) + receive_relayable(Comment, entity) do + Comment.new( + author: author_of(entity), + guid: entity.guid, + created_at: entity.created_at, + text: entity.text, + commentable: Post.find_by(guid: entity.parent_guid) + ) + end + end + + def self.contact(entity) + recipient = Person.find_by(diaspora_handle: entity.recipient).owner + if entity.sharing.to_s == "true" + Contact.create_or_update_sharing_contact(recipient, author_of(entity)) + else + recipient.disconnected_by(author_of(entity)) + nil + end + end + + def self.conversation(entity) + author = author_of(entity) + ignore_existing_guid(Conversation, entity.guid, author) do + Conversation.create!( + author: author, + guid: entity.guid, + subject: entity.subject, + created_at: entity.created_at, + participant_handles: entity.participants, + messages: entity.messages.map {|message| build_message(message) } + ) + end + end + + def self.like(entity) + receive_relayable(Like, entity) do + Like.new( + author: author_of(entity), + guid: entity.guid, + positive: entity.positive, + target: Mappings.model_class_for(entity.parent_type).find_by(guid: entity.parent_guid) + ) + end + end + + def self.message(entity) + save_message(entity).tap {|message| relay_relayable(message) if message } + end + + def self.participation(entity) + author = author_of(entity) + ignore_existing_guid(Participation, entity.guid, author) do + Participation.create!( + author: author, + guid: entity.guid, + target: Mappings.model_class_for(entity.parent_type).find_by(guid: entity.parent_guid) + ) + end + end + + def self.photo(entity) + author = author_of(entity) + persisted_photo = load_from_database(Photo, entity.guid, author) + + if persisted_photo + persisted_photo.tap do |photo| + photo.update_attributes( + text: entity.text, + public: entity.public, + created_at: entity.created_at, + remote_photo_path: entity.remote_photo_path, + remote_photo_name: entity.remote_photo_name, + status_message_guid: entity.status_message_guid, + height: entity.height, + width: entity.width + ) + end + else + save_photo(entity) + end + end + + def self.poll_participation(entity) + receive_relayable(PollParticipation, entity) do + PollParticipation.new( + author: author_of(entity), + guid: entity.guid, + poll: Poll.find_by(guid: entity.parent_guid), + poll_answer_guid: entity.poll_answer_guid + ) + end + end + + def self.profile(entity) + author_of(entity).profile.tap do |profile| + profile.update_attributes( + first_name: entity.first_name, + last_name: entity.last_name, + image_url: entity.image_url, + image_url_medium: entity.image_url_medium, + image_url_small: entity.image_url_small, + birthday: entity.birthday, + gender: entity.gender, + bio: entity.bio, + location: entity.location, + searchable: entity.searchable, + nsfw: entity.nsfw, + tag_string: entity.tag_string + ) + end + end + + def self.reshare(entity) + author = author_of(entity) + ignore_existing_guid(Reshare, entity.guid, author) do + Reshare.create!( + author: author, + guid: entity.guid, + created_at: entity.created_at, + provider_display_name: entity.provider_display_name, + public: entity.public, + root_guid: entity.root_guid + ) + end + end + + def self.retraction(entity, recipient_id) + model_class = Diaspora::Federation::Mappings.model_class_for(entity.target_type) + object = model_class.where(guid: entity.target_guid).take! + + case object + when Person + User.find(recipient_id).disconnected_by(object) + when Diaspora::Relayable + if object.parent.author.local? + parent_author = object.parent.author.owner + retraction = Retraction.for(object, parent_author) + retraction.defer_dispatch(parent_author, false) + retraction.perform + else + object.destroy! + end + else + object.destroy! + end + end + + def self.status_message(entity) + try_load_existing_guid(StatusMessage, entity.guid, author_of(entity)) do + StatusMessage.new( + author: author_of(entity), + guid: entity.guid, + text: entity.text, + public: entity.public, + created_at: entity.created_at, + provider_display_name: entity.provider_display_name + ).tap do |status_message| + status_message.location = build_location(entity.location) if entity.location + status_message.poll = build_poll(entity.poll) if entity.poll + status_message.photos = save_or_load_photos(entity.photos) + + status_message.save! + end + end + end + + private_class_method def self.author_of(entity) + Person.by_account_identifier(entity.author) + end + + private_class_method def self.build_location(entity) + Location.new( + address: entity.address, + lat: entity.lat, + lng: entity.lng + ) + end + + private_class_method def self.build_message(entity) + Message.new( + author: author_of(entity), + guid: entity.guid, + text: entity.text, + created_at: entity.created_at, + conversation_guid: entity.conversation_guid + ) + end + + private_class_method def self.build_poll(entity) + Poll.new( + guid: entity.guid, + question: entity.question + ).tap do |poll| + poll.poll_answers = entity.poll_answers.map do |answer| + PollAnswer.new( + guid: answer.guid, + answer: answer.answer + ) + end + end + end + + private_class_method def self.save_message(entity) + ignore_existing_guid(Message, entity.guid, author_of(entity)) do + build_message(entity).tap do |message| + message.author_signature = entity.author_signature if message.conversation.author.local? + message.save! + end + end + end + + private_class_method def self.save_photo(entity) + Photo.create!( + author: author_of(entity), + guid: entity.guid, + text: entity.text, + public: entity.public, + created_at: entity.created_at, + remote_photo_path: entity.remote_photo_path, + remote_photo_name: entity.remote_photo_name, + status_message_guid: entity.status_message_guid, + height: entity.height, + width: entity.width + ) + end + + private_class_method def self.save_or_load_photos(photos) + photos.map do |photo| + try_load_existing_guid(Photo, photo.guid, author_of(photo)) { save_photo(photo) } + end + end + + private_class_method def self.receive_relayable(klass, entity) + save_relayable(klass, entity) { yield }.tap {|relayable| relay_relayable(relayable) if relayable } + end + + private_class_method def self.save_relayable(klass, entity) + ignore_existing_guid(klass, entity.guid, author_of(entity)) do + yield.tap do |relayable| + retract_if_author_ignored(relayable) + + relayable.signature = build_signature(klass, entity) if relayable.parent.author.local? + relayable.save! + end + end + end + + private_class_method def self.build_signature(klass, entity) + klass.reflect_on_association(:signature).klass.new( + author_signature: entity.author_signature, + additional_data: entity.additional_xml_elements, + signature_order: SignatureOrder.find_or_create_by!(order: entity.xml_order.join(" ")) + ) + end + + private_class_method def self.retract_if_author_ignored(relayable) + parent_author = relayable.parent.author.owner + return unless parent_author && parent_author.ignored_people.include?(relayable.author) + + retraction = Retraction.for(relayable, parent_author) + Diaspora::Federation::Dispatcher.build(parent_author, retraction, subscribers: [relayable.author]).dispatch + + raise Diaspora::Federation::AuthorIgnored + end + + private_class_method def self.relay_relayable(relayable) + parent_author = relayable.parent.author.owner + Diaspora::Federation::Dispatcher.defer_dispatch(parent_author, relayable) if parent_author + end + + # check if the object already exists, otherwise save it. + # if save fails (probably because of a second object received parallel), + # check again if an object with the same guid already exists, but maybe has a different author. + # @raise [InvalidAuthor] if the author of the existing object doesn't match + private_class_method def self.ignore_existing_guid(klass, guid, author) + yield unless klass.where(guid: guid, author_id: author.id).exists? + rescue => e + raise e unless load_from_database(klass, guid, author) + logger.warn "ignoring error on receive #{klass}:#{guid}: #{e.class}: #{e.message}" + nil + end + + # try to load the object first from the DB and if not available, save it. + # if save fails (probably because of a second object received parallel), + # try again to load it, because it is possibly there now. + # @raise [InvalidAuthor] if the author of the existing object doesn't match + private_class_method def self.try_load_existing_guid(klass, guid, author) + load_from_database(klass, guid, author) || yield + rescue Diaspora::Federation::InvalidAuthor => e + raise e # don't try loading from db twice + rescue => e + logger.warn "failed to save #{klass}:#{guid} (#{e.class}: #{e.message}) - try loading it from DB" + load_from_database(klass, guid, author).tap do |object| + raise e unless object + end + end + + # @raise [InvalidAuthor] if the author of the loaded object doesn't match + private_class_method def self.load_from_database(klass, guid, author) + klass.find_by(guid: guid).tap do |object| + if object && object.author_id != author.id + raise Diaspora::Federation::InvalidAuthor, "#{klass}:#{guid}: #{author.diaspora_handle}" + end + end + end + end + end +end diff --git a/lib/diaspora/fetcher.rb b/lib/diaspora/fetcher.rb index a27831e2fdffef5bf73fb4493aba543347c4a9fa..adb82e55254d69e69abfba6bf960a17f58023de6 100644 --- a/lib/diaspora/fetcher.rb +++ b/lib/diaspora/fetcher.rb @@ -1,6 +1,5 @@ module Diaspora module Fetcher require 'diaspora/fetcher/public' - require 'diaspora/fetcher/single' end end diff --git a/lib/diaspora/fetcher/public.rb b/lib/diaspora/fetcher/public.rb index 7b7e90d1e276cc685fbfe2fb034af4de165c113d..34af2f30efbf35a2260acbedc091571f80300a38 100644 --- a/lib/diaspora/fetcher/public.rb +++ b/lib/diaspora/fetcher/public.rb @@ -109,14 +109,13 @@ module Diaspora; module Fetcher; class Public :author => @person, :public => true ) - entry.assign_attributes({ - :guid => post['guid'], - :text => post['text'], - :provider_display_name => post['provider_display_name'], - :created_at => ActiveSupport::TimeZone.new('UTC').parse(post['created_at']).to_datetime, - :interacted_at => ActiveSupport::TimeZone.new('UTC').parse(post['interacted_at']).to_datetime, - :frame_name => post['frame_name'] - }) + entry.assign_attributes( + guid: post["guid"], + text: post["text"], + provider_display_name: post["provider_display_name"], + created_at: ActiveSupport::TimeZone.new("UTC").parse(post["created_at"]).to_datetime, + interacted_at: ActiveSupport::TimeZone.new("UTC").parse(post["interacted_at"]).to_datetime + ) entry.save # re-enable everything we disabled before diff --git a/lib/diaspora/fetcher/single.rb b/lib/diaspora/fetcher/single.rb deleted file mode 100644 index 797fc3cccafd32549be8d8baa0e282d174fa7de5..0000000000000000000000000000000000000000 --- a/lib/diaspora/fetcher/single.rb +++ /dev/null @@ -1,41 +0,0 @@ -module Diaspora - module Fetcher - module Single - module_function - - # Fetch and store a remote public post - # @param [String] guid the remote posts guid - # @param [String] author_id Diaspora ID of a user known to have the post, - # preferably the author - # @yield [Post, Person] If a block is given it is yielded the post - # and the author prior save - # @return a saved post - def find_or_fetch_from_remote guid, author_id - post = Post.where(guid: guid).first - return post if post - - post_author = Person.find_or_fetch_by_identifier(author_id) - post_author.save! unless post_author.persisted? - - if fetched_post = fetch_post(post_author, guid) - yield fetched_post, post_author if block_given? - raise Diaspora::PostNotFetchable unless fetched_post.save - end - - fetched_post - end - - # Fetch a remote public post, used for receiving of unknown public posts - # @param [Person] author the remote post's author - # @param [String] guid the remote post's guid - # @return [Post] an unsaved remote post or false if the post was not found - def fetch_post author, guid - url = URI.join(author.url, "/p/#{guid}.xml") - response = Faraday.get(url) - raise Diaspora::PostNotFetchable if response.status == 404 # Old pod, Friendika, deleted - raise "Failed to get #{url}" unless response.success? # Other error, N/A for example - Diaspora::Parser.from_xml(response.body) - end - end - end -end diff --git a/lib/diaspora/fields/author.rb b/lib/diaspora/fields/author.rb new file mode 100644 index 0000000000000000000000000000000000000000..29bf5204d2d4bfba47b50c32ae2d69b6a0fea3a7 --- /dev/null +++ b/lib/diaspora/fields/author.rb @@ -0,0 +1,15 @@ +module Diaspora + module Fields + module Author + def self.included(model) + model.class_eval do + belongs_to :author, class_name: "Person" + + delegate :diaspora_handle, to: :author + + validates :author, presence: true + end + end + end + end +end diff --git a/lib/diaspora/fields/guid.rb b/lib/diaspora/fields/guid.rb new file mode 100644 index 0000000000000000000000000000000000000000..16876c9aaaf0a57258892b233c259dcf78472134 --- /dev/null +++ b/lib/diaspora/fields/guid.rb @@ -0,0 +1,18 @@ +module Diaspora + module Fields + module Guid + # Creates a after_initialize callback which calls #set_guid + def self.included(model) + model.class_eval do + after_initialize :set_guid + validates :guid, uniqueness: true + end + end + + # @return [String] The model's guid. + def set_guid + self.guid = UUID.generate(:compact) if guid.blank? + end + end + end +end diff --git a/lib/diaspora/fields/target.rb b/lib/diaspora/fields/target.rb new file mode 100644 index 0000000000000000000000000000000000000000..1fbbf97960ffead1233595aef880fe33d60f1b31 --- /dev/null +++ b/lib/diaspora/fields/target.rb @@ -0,0 +1,14 @@ +module Diaspora + module Fields + module Target + def self.included(model) + model.class_eval do + belongs_to :target, polymorphic: true + + validates :target_id, uniqueness: {scope: %i(target_type author_id)} + validates :target, presence: true + end + end + end + end +end diff --git a/lib/diaspora/guid.rb b/lib/diaspora/guid.rb deleted file mode 100644 index baf840a1fda9b3a11d25ed45c927ae3cce36e84d..0000000000000000000000000000000000000000 --- a/lib/diaspora/guid.rb +++ /dev/null @@ -1,18 +0,0 @@ -#implicitly requires roxml - -module Diaspora::Guid - # Creates a before_create callback which calls #set_guid and makes the guid serialize in to_xml - def self.included(model) - model.class_eval do - after_initialize :set_guid - xml_attr :guid - validates :guid, :uniqueness => true - - end - end - - # @return [String] The model's guid. - def set_guid - self.guid = UUID.generate :compact if self.guid.blank? - end -end diff --git a/lib/diaspora/markdownify/html.rb b/lib/diaspora/markdownify/html.rb index 04b2e8f167dff728fb8a7d739e7e55dbdc4a4a73..a9c516869afbfa9287247f3cb3b21c0d71f59d4e 100644 --- a/lib/diaspora/markdownify/html.rb +++ b/lib/diaspora/markdownify/html.rb @@ -4,7 +4,11 @@ module Diaspora include ActionView::Helpers::TextHelper def autolink link, type - Twitter::Autolink.auto_link_urls(link, url_target: "_blank") + Twitter::Autolink.auto_link_urls( + link, + url_target: "_blank", + link_attribute_block: lambda {|_, attr| attr[:rel] += " noopener noreferrer" } + ) end end end diff --git a/lib/diaspora/mentionable.rb b/lib/diaspora/mentionable.rb index f64857f7716a84edc19ba5876e55eacd6998187e..8645d90200830a108c83ae4244ebe81772c7448a 100644 --- a/lib/diaspora/mentionable.rb +++ b/lib/diaspora/mentionable.rb @@ -14,8 +14,8 @@ module Diaspora::Mentionable mention = mention_str.match(REGEX)[2] del_pos = mention.rindex(/;/) - name = mention[0..(del_pos-1)].strip - handle = mention[(del_pos+1)..-1].strip + name = mention[0..(del_pos - 1)].strip + handle = mention[(del_pos + 1)..-1].strip [name, handle] end @@ -46,12 +46,11 @@ module Diaspora::Mentionable # @return [Array<Person>] array of people def self.people_from_string(msg_text) identifiers = msg_text.to_s.scan(REGEX).map do |match_str| - _, handle = mention_attrs(match_str.first) - handle + _, identifier = mention_attrs(match_str.first) + identifier if Validation::Rule::DiasporaId.new.valid_value?(identifier) end - return [] if identifiers.empty? - Person.where(diaspora_handle: identifiers) + identifiers.compact.uniq.map {|identifier| find_or_fetch_person_by_identifier(identifier) }.compact end # takes a message text and converts mentions for people that are not in the @@ -81,37 +80,43 @@ module Diaspora::Mentionable private + private_class_method def self.find_or_fetch_person_by_identifier(identifier) + Person.find_or_fetch_by_identifier(identifier) + rescue DiasporaFederation::Discovery::DiscoveryError + nil + end + # inline module for namespacing module MentionsInternal extend ::PeopleHelper - # output a formatted mention link as defined by the given options, - # use the fallback name if the person is unavailable + # output a formatted mention link as defined by the given arguments. + # if the display name is blank, falls back to the person's name. # @see Diaspora::Mentions#format # # @param [Person] AR Person - # @param [String] fallback name + # @param [String] display name # @param [Hash] formatting options - def self.mention_link(person, fallback_name, opts) - return fallback_name unless person.present? + def self.mention_link(person, display_name, opts) + return display_name unless person.present? if opts[:plain_text] - person.name + display_name.presence || person.name else - person_link(person, class: PERSON_HREF_CLASS) + person_link(person, class: PERSON_HREF_CLASS, display_name: display_name) end end - # output a markdown formatted link to the given person or the given fallback - # string, in case the person is not present + # output a markdown formatted link to the given person with the display name as the link text. + # if the display name is blank, falls back to the person's name. # # @param [Person] AR Person - # @param [String] fallback name + # @param [String] display name # @return [String] markdown person link - def self.profile_link(person, fallback_name) - return fallback_name unless person.present? + def self.profile_link(person, display_name) + return display_name unless person.present? - "[#{person.name}](#{local_or_remote_person_path(person)})" + "[#{display_name.presence || person.name}](#{local_or_remote_person_path(person)})" end # takes a user and an array of aspect ids or an array containing "all" as diff --git a/lib/diaspora/message_renderer.rb b/lib/diaspora/message_renderer.rb index 85d0441420841212f920d04e6ec8ad004c878ef9..7c39470fb09dd998e712f24d05c81d997bfc0fd4 100644 --- a/lib/diaspora/message_renderer.rb +++ b/lib/diaspora/message_renderer.rb @@ -43,12 +43,6 @@ module Diaspora def escape if options[:escape] @message = ERB::Util.html_escape_once message - - # Special case Hex entities since escape_once - # doesn't catch them. - # TODO: Watch for https://github.com/rails/rails/pull/9102 - # on whether this can be removed - @message = message.gsub(/&(#[xX][\dA-Fa-f]{1,4});/, '&\1;') end end @@ -126,7 +120,7 @@ module Diaspora delegate :empty?, :blank?, :present?, to: :raw - # @param [String] raw_message Raw input text + # @param [String] text Raw input text # @param [Hash] opts Global options affecting output # @option opts [Array<Person>] :mentioned_people ([]) List of people # allowed to mention @@ -153,8 +147,8 @@ module Diaspora # to Redcarpet # @option opts [Hash] :markdown_render_options Override default options # passed to the Redcarpet renderer - def initialize raw_message, opts={} - @raw_message = raw_message + def initialize(text, opts={}) + @text = text @options = DEFAULTS.deep_merge opts end @@ -217,12 +211,12 @@ module Diaspora # this length. If not given defaults to 70. def title opts={} # Setext-style header - heading = if /\A(?<setext_content>.{1,200})\n(?:={1,200}|-{1,200})(?:\r?\n|$)/ =~ @raw_message.lstrip - setext_content - # Atx-style header - elsif /\A\#{1,6}\s+(?<atx_content>.{1,200}?)(?:\s+#+)?(?:\r?\n|$)/ =~ @raw_message.lstrip - atx_content - end + heading = if /\A(?<setext_content>.{1,200})\n(?:={1,200}|-{1,200})(?:\r?\n|$)/ =~ @text.lstrip + setext_content + # Atx-style header + elsif /\A\#{1,6}\s+(?<atx_content>.{1,200}?)(?:\s+#+)?(?:\r?\n|$)/ =~ @text.lstrip + atx_content + end heading &&= self.class.new(heading).plain_text_without_markdown @@ -242,7 +236,7 @@ module Diaspora end def raw - @raw_message + @text end def to_s @@ -251,8 +245,8 @@ module Diaspora private - def process opts, &block - Processor.process(@raw_message, @options.deep_merge(opts), &block) + def process(opts, &block) + Processor.process(@text, @options.deep_merge(opts), &block) end end end diff --git a/lib/diaspora/parser.rb b/lib/diaspora/parser.rb deleted file mode 100644 index 4142b542a36708b2cdc34c32586b331b932fff18..0000000000000000000000000000000000000000 --- a/lib/diaspora/parser.rb +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Diaspora - module Parser - def self.from_xml(xml) - doc = Nokogiri::XML(xml) {|cfg| cfg.noblanks } - return unless body = doc.xpath("/XML/post").children.first - class_name = body.name.gsub("-", "/") - ::Logging::Logger["XMLLogger"].debug "from_xml: #{body}" - begin - class_name.camelize.constantize.from_xml body.to_s - rescue NameError => e - # A pods is trying to federate an object we don't recognize. - # i.e. their codebase is different from ours. - ::Logging::Logger[self].warn("Error while parsing the xml: #{e.message}") - nil - end - end - end -end diff --git a/lib/diaspora/relayable.rb b/lib/diaspora/relayable.rb index a99ef1a9501391b3c3411aecb7199d9bd6b7b6dc..8db901f4af96f707763c67ea98f4ffeb058a5a8e 100644 --- a/lib/diaspora/relayable.rb +++ b/lib/diaspora/relayable.rb @@ -4,17 +4,9 @@ module Diaspora module Relayable - include Encryptable - def self.included(model) model.class_eval do - #these fields must be in the schema for a relayable model - xml_attr :parent_guid - xml_attr :parent_author_signature - xml_attr :author_signature - validates_associated :parent - validates :author, :presence => true validate :author_is_not_ignored delegate :public?, to: :parent @@ -23,136 +15,39 @@ module Diaspora after_commit :on => :create do parent.touch(:interacted_at) if parent.respond_to?(:interacted_at) end - end end def author_is_not_ignored - if self.new_record? && self.parent.present? - post_author = self.parent.author - relayable_author = self.author - - if post_author.local? && post_author.owner.ignored_people.include?(relayable_author) - self.errors.add(:author_id, 'This person is ignored by the post author') - #post_author.owner.retract(self) - end + unless new_record? && parent.present? && parent.author.local? && + parent.author.owner.ignored_people.include?(author) + return end - end - - # @return [Boolean] true - def relayable? - true - end - # @return [String] - def parent_guid - return nil unless parent.present? - self.parent.guid - end - - def parent_guid= new_parent_guid - @parent_guid = new_parent_guid - self.parent = parent_class.where(guid: new_parent_guid).first + errors.add(:author_id, "This relayable author is ignored by the post author") end # @return [Array<Person>] - def subscribers(user) - if user.owns?(self.parent) - self.parent.subscribers(user) - elsif user.owns?(self) - [self.parent.author] + def subscribers + if parent.author.local? + if author.local? + parent.subscribers + else + parent.subscribers.select(&:remote?).reject {|person| person.pod_id == author.pod_id } + end else - [] + [parent.author, author] end end - def receive(user, person=nil) - comment_or_like = self.class.where(guid: self.guid).first || self - - unless comment_or_like.signature_valid? - logger.warn "event=receive status=abort reason='object signature not valid' recipient=#{user.diaspora_handle} "\ - "sender=#{comment_or_like.author.diaspora_handle} payload_type=#{self.class} parent_id=#{parent.id}" - return - end - - # Check to make sure the signature of the comment or like comes from the person claiming to author it - unless comment_or_like.parent_author == user.person || comment_or_like.verify_parent_author_signature - logger.warn "event=receive status=abort reason='object signature not valid' recipient=#{user.diaspora_handle} "\ - "sender=#{parent.author.diaspora_handle} payload_type=#{self.class} parent_id=#{parent.id}" - return - end - - # As the owner of the post being liked or commented on, you need to add your own signature in order to - # pass it to the people who received your original post - if user.owns? comment_or_like.parent - comment_or_like.parent_author_signature = comment_or_like.sign_with_key(user.encryption_key) - comment_or_like.save! - end - - # Dispatch object DOWNSTREAM, received it via UPSTREAM - unless user.owns?(comment_or_like) - comment_or_like.save! - Postzord::Dispatcher.build(user, comment_or_like).post - end - - if comment_or_like.after_receive(user, person) - comment_or_like - end - end - - # @return [Object] - def after_receive(user, person) - self - end - - def initialize_signatures - #sign relayable as model creator - self.author_signature = self.sign_with_key(author.owner.encryption_key) - - if !self.parent.blank? && self.author.owns?(self.parent) - #sign relayable as parent object owner - self.parent_author_signature = sign_with_key(author.owner.encryption_key) - end - end - - # @return [Boolean] - def verify_parent_author_signature - verify_signature(self.parent_author_signature, self.parent.author) - end - - # @return [Boolean] - def signature_valid? - verify_signature(self.author_signature, self.author) + # @deprecated This is only needed for pre 0.6 pods + def sender_for_dispatch + parent.author.owner if parent.author.local? end # @abstract - # @return [Class] - def parent_class - raise NotImplementedError.new('you must override parent_class in order to enable relayable on this model') - end - - # @abstract - # @return An instance of Relayable#parent_class def parent raise NotImplementedError.new('you must override parent in order to enable relayable on this model') end - - # @abstract - # @param parent An instance of Relayable#parent_class - def parent= parent - raise NotImplementedError.new('you must override parent= in order to enable relayable on this model') - end - - # ROXML hook ensuring our own hooks are called - def after_parse - if @parent_guid - self.parent ||= fetch_parent(@parent_guid) - end - end - - # Childs should override this to support fetching a missing parent - # @param guid the parents guid - def fetch_parent guid - end end end diff --git a/lib/diaspora/shareable.rb b/lib/diaspora/shareable.rb index 5c34115f8f3faba873dcaa6e0c908509270d7955..96895f521a7154fa7615353883102b0cf7a11568 100644 --- a/lib/diaspora/shareable.rb +++ b/lib/diaspora/shareable.rb @@ -1,55 +1,88 @@ # Copyright (c) 2010, Diaspora Inc. This file is # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -#the pont of this object is to centralize the simmilarities of Photo and post, + +# the point of this object is to centralize the simmilarities of Photo and Post, # as they used to be the same class module Diaspora module Shareable def self.included(model) model.instance_eval do + include Diaspora::Fields::Guid + include Diaspora::Fields::Author - has_many :aspect_visibilities, :as => :shareable, :validate => false - has_many :aspects, :through => :aspect_visibilities - - has_many :share_visibilities, :as => :shareable - has_many :contacts, :through => :share_visibilities + has_many :aspect_visibilities, as: :shareable, validate: false, dependent: :delete_all + has_many :aspects, through: :aspect_visibilities - belongs_to :author, :class_name => 'Person' + has_many :share_visibilities, as: :shareable, dependent: :delete_all delegate :id, :name, :first_name, to: :author, prefix: true - #scopes - scope :all_public, -> { where(:public => true, :pending => false) } - - def self.owned_or_visible_by_user(user) - self.joins("LEFT OUTER JOIN share_visibilities ON share_visibilities.shareable_id = posts.id AND share_visibilities.shareable_type = 'Post'"). - joins("LEFT OUTER JOIN contacts ON contacts.id = share_visibilities.contact_id"). - where( - Contact.arel_table[:user_id].eq(user.id).or( - self.arel_table[:public].eq(true).or( - self.arel_table[:author_id].eq(user.person_id) - ) - ) - ). - select("DISTINCT #{self.table_name}.*") - end - - def self.for_visible_shareable_sql(max_time, order, limit = 15, types = Stream::Base::TYPES_OF_POST_IN_STREAM) - by_max_time(max_time, order). - where(:type => types). - limit(limit) - end - - def self.by_max_time(max_time, order='created_at') - where("#{self.table_name}.#{order} < ?", max_time).order("#{self.table_name}.#{order} desc") - end + # scopes + scope :with_visibility, -> { + joins("LEFT OUTER JOIN share_visibilities ON share_visibilities.shareable_id = #{table_name}.id AND "\ + "share_visibilities.shareable_type = '#{base_class}'") + } + + scope :with_aspects, -> { + joins("LEFT OUTER JOIN aspect_visibilities ON aspect_visibilities.shareable_id = #{table_name}.id AND "\ + " aspect_visibilities.shareable_type = '#{base_class}'") + } end + model.extend Diaspora::Shareable::QueryMethods + end + + def receive(recipient_user_ids) + return if recipient_user_ids.empty? || public? + + ShareVisibility.batch_import(recipient_user_ids, self) end - # @return [Integer] - def update_reshares_counter - self.class.where(:id => self.id). - update_all(:reshares_count => self.reshares.count) + # The list of people that should receive this Shareable. + # + # @return [Array<Person>] The list of subscribers to this shareable + def subscribers + user = author.owner + if public? + [*user.contact_people, author] + else + user.people_in_aspects(user.aspects_with_shareable(self.class, id)) + end + end + + module QueryMethods + def owned_or_visible_by_user(user) + with_visibility.where( + visible_by_user(user).or(arel_table[:public].eq(true) + .or(arel_table[:author_id].eq(user.person_id))) + ).select("DISTINCT #{table_name}.*") + end + + def from_person_visible_by_user(user, person) + return owned_by_user(user) if person == user.person + + with_visibility.where(author_id: person.id).where( + visible_by_user(user).or(arel_table[:public].eq(true)) + ).select("DISTINCT #{table_name}.*") + end + + def for_visible_shareable_sql(max_time, order, limit=15, types=Stream::Base::TYPES_OF_POST_IN_STREAM) + by_max_time(max_time, order).order(table_name + ".id DESC").where(type: types).limit(limit) + end + + def by_max_time(max_time, order="created_at") + where("#{table_name}.#{order} < ?", max_time).order("#{table_name}.#{order} DESC") + end + + def owned_by_user(user) + user.person.public_send(table_name) + end + + private + + def visible_by_user(user) + ShareVisibility.arel_table[:user_id].eq(user.id) + end end end end diff --git a/lib/diaspora/signature.rb b/lib/diaspora/signature.rb new file mode 100644 index 0000000000000000000000000000000000000000..fb571b3ccaa3755c6e59b08bdc55dbbeaf43cd94 --- /dev/null +++ b/lib/diaspora/signature.rb @@ -0,0 +1,18 @@ +module Diaspora + module Signature + def self.included(model) + model.class_eval do + belongs_to :signature_order + validates :signature_order, presence: true + + validates :author_signature, presence: true + + serialize :additional_data, Hash + + def order + signature_order.order.split + end + end + end + end +end diff --git a/lib/email_inviter.rb b/lib/email_inviter.rb index 7f8c5447598ed602219d5a9cac852357971cc71b..3fdfd567dafe33736c5ecd2d93342a695c6434d2 100644 --- a/lib/email_inviter.rb +++ b/lib/email_inviter.rb @@ -5,7 +5,7 @@ class EmailInviter options = options.symbolize_keys self.message = options[:message] self.locale = options.fetch(:locale, 'en') - self.inviter = inviter + self.inviter = inviter self.emails = emails end @@ -16,7 +16,7 @@ class EmailInviter end def invitation_code - @invitation_code ||= inviter.invitation_code + @invitation_code ||= inviter.invitation_code end def send! @@ -26,6 +26,6 @@ class EmailInviter private def mail(email) - Notifier.invite(email, message, inviter, invitation_code, locale).deliver_now! + Notifier.invite(email, message, inviter, invitation_code, locale).deliver_now end end diff --git a/lib/encryptor.rb b/lib/encryptor.rb deleted file mode 100644 index a81302b851c9805b725c63fd6db7c3a9c82ac999..0000000000000000000000000000000000000000 --- a/lib/encryptor.rb +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Encryptor - module Public - def encrypt cleartext - aes_key = gen_aes_key - ciphertext = aes_encrypt(cleartext, aes_key) - encrypted_key = encrypt_aes_key aes_key - cipher_hash = {:aes_key => encrypted_key, :ciphertext => ciphertext} - Base64.strict_encode64( cipher_hash.to_json ) - end - - def gen_aes_key - cipher = OpenSSL::Cipher.new('AES-256-CBC') - key = cipher.random_key - iv = cipher.random_iv - {'key' => Base64.strict_encode64(key), 'iv' => Base64.strict_encode64(iv)} - end - - def aes_encrypt(txt, key) - cipher = OpenSSL::Cipher.new('AES-256-CBC') - cipher.encrypt - cipher.key = Base64.decode64 key['key'] - cipher.iv = Base64.decode64 key['iv'] - ciphertext = '' - ciphertext << cipher.update(txt) - ciphertext << cipher.final - Base64.strict_encode64(ciphertext) - end - - def encrypt_aes_key key - Base64.strict_encode64(public_key.public_encrypt( key.to_json )) - end - end - - module Private - def decrypt cipher_json - json = JSON.parse(Base64.decode64 cipher_json) - aes_key = get_aes_key json['aes_key'] - aes_decrypt(json['ciphertext'], aes_key) - end - - def get_aes_key encrypted_key - clear_key = encryption_key.private_decrypt( Base64.decode64 encrypted_key ) - JSON::parse(clear_key) - end - - def aes_decrypt(ciphertext, key) - cipher = OpenSSL::Cipher.new('AES-256-CBC') - cipher.decrypt - cipher.key = Base64.decode64 key['key'] - cipher.iv = Base64.decode64 key['iv'] - txt = '' - txt << cipher.update(Base64.decode64 ciphertext) - txt << cipher.final - txt - end - - end -end diff --git a/lib/error_page_renderer.rb b/lib/error_page_renderer.rb new file mode 100644 index 0000000000000000000000000000000000000000..dae92f41932200c4f5e93419295bfef5b72eaf14 --- /dev/null +++ b/lib/error_page_renderer.rb @@ -0,0 +1,47 @@ + +# Inspired by https://github.com/route/errgent/blob/master/lib/errgent/renderer.rb +class ErrorPageRenderer + def initialize options={} + @codes = options.fetch :codes, [404, 500] + @output = options.fetch :output, "public/%s.html" + @vars = options.fetch :vars, {} + @template = options.fetch :template, "errors/error_%s" + @layout = options.fetch :layout, "layouts/error_page" + end + + def render + @codes.each do |code| + view = build_action_view + view.assign @vars.merge(code: code) + path = Rails.root.join(@output % code) + File.write path, view.render(template: @template % code, layout: @layout) + end + end + + def helpers(&block) + @helpers = block + end + + private + + def build_action_view + paths = ::ActionController::Base.view_paths + ::ActionView::Base.new(paths).tap do |view| + view.class_eval do + include Rails.application.helpers + include Rails.application.routes.url_helpers + end + view.assets_manifest = build_manifest(Rails.application) + view.class_eval(&@helpers) if @helpers + end + end + + # Internal API from the sprocket-rails railtie, if somebody finds a way to + # call it, please replace it. Might need to be updated on sprocket-rails + # updates. + def build_manifest(app) + config = app.config + path = File.join(config.paths['public'].first, config.assets.prefix) + Sprockets::Manifest.new(app.assets, path, config.assets.manifest) + end +end diff --git a/lib/evil_query.rb b/lib/evil_query.rb index 20e0e66d6464f0a03917b649b1152e12a2aa6a82..78599ead13f6635ae2cc87449919ed5e6435fb5b 100644 --- a/lib/evil_query.rb +++ b/lib/evil_query.rb @@ -19,7 +19,12 @@ module EvilQuery end def posts - Post.joins(:participations).where(:participations => {:author_id => @user.person.id}).order("posts.interacted_at DESC") + author_id = @user.person_id + Post.joins("LEFT OUTER JOIN participations ON participations.target_id = posts.id AND " \ + "participations.target_type = 'Post'") + .where(::Participation.arel_table[:author_id].eq(author_id).or(Post.arel_table[:author_id].eq(author_id))) + .order("posts.interacted_at DESC") + .distinct end end @@ -61,7 +66,7 @@ module EvilQuery def aspects_post_ids! logger.debug("[EVIL-QUERY] aspect_post_ids!") - @user.visible_shareable_ids(Post, :limit => 15, :order => "#{@order} DESC", :max_time => @max_time, :all_aspects? => true, :by_members_of => @user.aspect_ids) + @user.visible_shareable_ids(Post, limit: 15, order: "#{@order} DESC", max_time: @max_time, all_aspects?: true) end def followed_tags_posts! @@ -94,13 +99,16 @@ module EvilQuery def post! #small optimization - is this optimal order?? - querent_is_contact.first || querent_is_author.first || public_post.first + querent_has_visibility.first || querent_is_author.first || public_post.first end protected - def querent_is_contact - @class.where(@key => @id).joins(:contacts).where(:contacts => {:user_id => @querent.id}).where(@conditions).select(@class.table_name+".*") + def querent_has_visibility + @class.where(@key => @id).joins(:share_visibilities) + .where(share_visibilities: {user_id: @querent.id}) + .where(@conditions) + .select(@class.table_name + ".*") end def querent_is_author @@ -111,49 +119,4 @@ module EvilQuery @class.where(@key => @id, :public => true).where(@conditions) end end - - class ShareablesFromPerson < Base - def initialize(querent, klass, person) - @querent = querent - @class = klass - @person = person - end - - def make_relation! - return querents_posts if @person == @querent.person - - # persons_private_visibilities and persons_public_posts have no limit which is making shareable_ids gigantic. - # perhaps they should the arrays should be merged and sorted - # then the query at the bottom of this method can be paginated or something? - - shareable_ids = contact.present? ? fetch_ids!(persons_private_visibilities, "share_visibilities.shareable_id") : [] - shareable_ids += fetch_ids!(persons_public_posts, table_name + ".id") - - @class.where(:id => shareable_ids, :pending => false). - select('DISTINCT '+table_name+'.*'). - order(table_name+".created_at DESC") - end - - protected - - def table_name - @class.table_name - end - - def contact - @contact ||= @querent.contact_for(@person) - end - - def querents_posts - @querent.person.send(table_name).where(:pending => false).order("#{table_name}.created_at DESC") - end - - def persons_private_visibilities - contact.share_visibilities.where(:hidden => false, :shareable_type => @class.to_s) - end - - def persons_public_posts - @person.send(table_name).where(:public => true).select(table_name+'.id') - end - end end diff --git a/lib/federated/generator.rb b/lib/federated/generator.rb deleted file mode 100644 index 062d13168d27fd69cb0b8630c478f8d5140e248c..0000000000000000000000000000000000000000 --- a/lib/federated/generator.rb +++ /dev/null @@ -1,43 +0,0 @@ -module Federated - class Generator - include Diaspora::Logging - - def initialize(user, target) - @user = user - @target = target - @dispatcher_opts ||= {} - end - - def create!(options={}) - relayable = build(options) - if relayable.save! - logger.info "user:#{@user.id} dispatching #{relayable.class}:#{relayable.guid}" - add_root_author(relayable) - Postzord::Dispatcher.defer_build_and_post(@user, relayable, @dispatcher_opts) - relayable - end - end - - def add_root_author(relayable) - return unless relayable.parent.respond_to?(:root) && relayable.parent.root - # Comment post is a reshare, include original author in subscribers - root_post = relayable.parent.root - @dispatcher_opts[:additional_subscribers] ||= [] - @dispatcher_opts[:additional_subscribers] << root_post.author - end - - def build(options={}) - options.merge!(relayable_options) - relayable = self.class.federated_class.new(options.merge(:author_id => @user.person.id)) - relayable.set_guid - relayable.initialize_signatures - relayable - end - - protected - - def relayable_options - {} - end - end -end diff --git a/lib/federated/relayable.rb b/lib/federated/relayable.rb deleted file mode 100644 index cd5ec3b74aa3526267b03de82eae5e7da4c9453a..0000000000000000000000000000000000000000 --- a/lib/federated/relayable.rb +++ /dev/null @@ -1,46 +0,0 @@ -module Federated - class Relayable < ActiveRecord::Base - self.abstract_class = true - - #crazy ordering issues - DEATH TO ROXML - include Diaspora::Federated::Base - include Diaspora::Guid - - #seriously, don't try to move this shit around until you have killed ROXML - xml_attr :target_type - include Diaspora::Relayable - - xml_attr :diaspora_handle - - belongs_to :target, :polymorphic => true - belongs_to :author, :class_name => 'Person' - #end crazy ordering issues - - validates_uniqueness_of :target_id, :scope => [:target_type, :author_id] - validates :parent, :presence => true #should be in relayable (pending on fixing Message) - - def diaspora_handle - self.author.diaspora_handle - end - - def diaspora_handle=(nh) - self.author = Person.find_or_fetch_by_identifier(nh) - end - - def parent_class - self.target_type.constantize - end - - def parent - self.target - end - - def parent= parent - self.target = parent - end - - def fetch_parent guid - raise Diaspora::PostNotFetchable - end - end -end diff --git a/lib/hydra_wrapper.rb b/lib/hydra_wrapper.rb deleted file mode 100644 index 7461d792a3f492a0f1ce29b923c1d1a9a3bcefe3..0000000000000000000000000000000000000000 --- a/lib/hydra_wrapper.rb +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -class HydraWrapper - include Diaspora::Logging - - OPTS = { - maxredirs: 3, - timeout: 25, - method: :post, - verbose: AppConfig.settings.typhoeus_verbose?, - cainfo: AppConfig.environment.certificate_authorities.get, - headers: { - 'Expect' => '', - 'Transfer-Encoding' => '', - 'User-Agent' => "Diaspora #{AppConfig.version_string}" - } - } - - attr_reader :people_to_retry , :user, :encoded_object_xml - attr_accessor :dispatcher_class, :people - delegate :run, to: :hydra - - def initialize user, people, encoded_object_xml, dispatcher_class - @user = user - @people_to_retry = [] - @people = people - @dispatcher_class = dispatcher_class - @encoded_object_xml = encoded_object_xml - @keep_for_retry_proc = Proc.new do |response| - true - end - end - - # Inserts jobs for all @people - def enqueue_batch - grouped_people.each do |receive_url, people_for_receive_url| - if xml = xml_factory.xml_for(people_for_receive_url.first) - insert_job(receive_url, xml, people_for_receive_url) - end - end - end - - # This method can be used to tell the hydra whether or not to - # retry a request that it made which failed. - # @yieldparam response [Typhoeus::Response] The response object for the failed request. - # @yieldreturn [Boolean] Whether the request whose response was passed to the block should be retried. - def keep_for_retry_if &block - @keep_for_retry_proc = block - end - - private - - def hydra - @hydra ||= Typhoeus::Hydra.new(max_concurrency: AppConfig.settings.typhoeus_concurrency.to_i) - end - - # @return [Salmon] - def xml_factory - @xml_factory ||= @dispatcher_class.salmon @user, Base64.decode64(@encoded_object_xml) - end - - # Group people on their receiving_urls - # @return [Hash] People grouped by receive_url ([String] => [Array<Person>]) - def grouped_people - @people.group_by { |person| - @dispatcher_class.receive_url_for person - } - end - - # Prepares and inserts job into the hydra queue - # @param url [String] - # @param xml [String] - # @params people [Array<Person>] - def insert_job url, xml, people - request = Typhoeus::Request.new url, OPTS.merge(body: {xml: CGI.escape(xml)}) - prepare_request request, people - hydra.queue request - end - - # @param request [Typhoeus::Request] - # @param person [Person] - def prepare_request request, people_for_receive_url - request.on_complete do |response| - # Save the reference to the pod to the database if not already present - Pod.find_or_create_by(url: response.effective_url) - - if redirecting_to_https? response - Person.url_batch_update people_for_receive_url, response.headers_hash['Location'] - end - - unless response.success? - logger.warn "event=http_multi_fail sender_id=#{@user.id} url=#{response.effective_url} " \ - "return_code=#{response.return_code} response_code=#{response.response_code}" - - if @keep_for_retry_proc.call(response) - @people_to_retry += people_for_receive_url.map(&:id) - end - - end - end - end - - # @return [Boolean] - def redirecting_to_https? response - response.code >= 300 && response.code < 400 && - response.headers_hash['Location'] == response.request.url.sub('http://', 'https://') - end -end diff --git a/lib/messagebus/mailer.rb b/lib/messagebus/mailer.rb deleted file mode 100644 index 7593ab705b48c65e7b8d824d9b0829d4d94d5a6d..0000000000000000000000000000000000000000 --- a/lib/messagebus/mailer.rb +++ /dev/null @@ -1,40 +0,0 @@ -module Messagebus - class Mailer - def initialize(api_key) - @client = MessagebusApi::Messagebus.new(api_key) - end - - attr_accessor :settings - - def new(*settings) - self.settings = {} - self - end - - def from_header_parse(string) - string.split('<')[0].delete('"') - end - - def deliver(message) - deliver!(message) - end - - def deliver!(message) - msg = {:toEmail => message.to.first, :subject => message.subject, :fromEmail => AppConfig.mail.sender_address, :fromName => from_header_parse(message[:from].to_s)} - - if message.multipart? - msg[:plaintextBody] = message.text_part.body.to_s if message.text_part - msg[:htmlBody] = message.html_part.body.to_s if message.html_part - else - msg[:plaintextBody] = message.body.to_s - msg[:htmlBody] = message.body.to_s - end - - begin - @client.add_message(msg, true) - rescue => message_bus_api_error - raise "Messagebus API error=#{message_bus_api_error}, message=#{msg.inspect}" - end - end -end -end diff --git a/lib/photo_exporter.rb b/lib/photo_exporter.rb new file mode 100644 index 0000000000000000000000000000000000000000..99c25ab98ace5dbbde1c4933a8fddbec2279ab7c --- /dev/null +++ b/lib/photo_exporter.rb @@ -0,0 +1,44 @@ +class PhotoExporter + attr_reader :user + + def initialize(user) + @user = user + end + + def perform + temp_zip = Tempfile.new([user.username, "_photos.zip"]) + begin + Zip::OutputStream.open(temp_zip.path) do |zip_output_stream| + user.photos.each do |photo| + export_photo(zip_output_stream, photo) + end + end + ensure + temp_zip.close + end + + update_exported_photos_at(temp_zip) + end + + private + + def export_photo(zip_output_stream, photo) + photo_file = photo.unprocessed_image.file + if photo_file + photo_data = photo_file.read + zip_output_stream.put_next_entry(photo.remote_photo_name) + zip_output_stream.print(photo_data) + else + user.logger.info "Export photos error: No file for #{photo.remote_photo_name} not found" + end + rescue Errno::ENOENT + user.logger.info "Export photos error: #{photo.unprocessed_image.file.path} not found" + end + + def update_exported_photos_at(temp_zip) + user.update exported_photos_file: temp_zip, exported_photos_at: Time.zone.now + ensure + user.restore_attributes if user.invalid? + user.update exporting_photos: false + end +end diff --git a/lib/postzord/dispatcher.rb b/lib/postzord/dispatcher.rb deleted file mode 100644 index c438e4ff3e8201c9c1acffce0f56b6a3f8cc2469..0000000000000000000000000000000000000000 --- a/lib/postzord/dispatcher.rb +++ /dev/null @@ -1,178 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - - -class Postzord::Dispatcher - include Diaspora::Logging - - require 'postzord/dispatcher/private' - require 'postzord/dispatcher/public' - - attr_reader :sender, :object, :xml, :subscribers, :opts - - # @param user [User] User dispatching the object in question - # @param object [Object] The object to be sent to other Diaspora installations - # @opt additional_subscribers [Array<Person>] Additional subscribers - def initialize(user, object, opts={}) - @sender = user - @object = object - @xml = @object.to_diaspora_xml - @opts = opts - - additional_subscribers = opts[:additional_subscribers] || [] - @subscribers = subscribers_from_object | [*additional_subscribers] - end - - # @return [Postzord::Dispatcher] Public or private dispatcher depending on the object's intended audience - def self.build(user, object, opts={}) - unless object.respond_to? :to_diaspora_xml - raise 'This object does not respond_to? to_diaspora xml. Try including Diaspora::Federated::Base into your object' - end - - if self.object_should_be_processed_as_public?(object) - Postzord::Dispatcher::Public.new(user, object, opts) - else - Postzord::Dispatcher::Private.new(user, object, opts) - end - end - - def self.defer_build_and_post(user, object, opts={}) - opts[:additional_subscribers] ||= [] - if opts[:additional_subscribers].present? - opts[:additional_subscribers] = [*opts[:additional_subscribers]].map(&:id) - end - - if opts[:to].present? - opts[:to] = [*opts[:to]].map {|e| e.respond_to?(:id) ? e.id : e } - end - - Workers::DeferredDispatch.perform_async(user.id, object.class.to_s, object.id, opts) - end - - # @param object [Object] - # @return [Boolean] - def self.object_should_be_processed_as_public?(object) - if object.respond_to?(:public?) && object.public? - true - else - false - end - end - - # @return [Object] - def post - self.deliver_to_services(@opts[:url], @opts[:services] || []) - self.post_to_subscribers if @subscribers.present? - self.process_after_dispatch_hooks - @object - end - - protected - - # @return [Object] - def process_after_dispatch_hooks - @object.after_dispatch(@sender) - @object - end - - def post_to_subscribers - remote_people, local_people = @subscribers.partition{ |person| person.owner_id.nil? } - - if @object.respond_to?(:relayable?) && @sender.owns?(@object.parent) - self.notify_local_users(local_people) - else - self.deliver_to_local(local_people) - end - - self.deliver_to_remote(remote_people) - end - - # @return [Array<Person>] Recipients of the object, minus any additional subscribers - def subscribers_from_object - @object.subscribers(@sender) - end - - # @param local_people [Array<People>] - # @return [ActiveRecord::Association<User>, Array] - def fetch_local_users(people) - return [] if people.blank? - user_ids = people.map{|x| x.owner_id } - User.where(:id => user_ids) - end - - # @param remote_people [Array<Person>] Recipients of the post on other pods - def deliver_to_remote(remote_people) - return if remote_people.blank? - queue_remote_delivery_job(remote_people) - end - - # Enqueues a job - # @param remote_people [Array<Person>] Recipients of the post on other pods - # @return [void] - def queue_remote_delivery_job(remote_people) - Workers::HttpMulti.perform_async( - @sender.id, - Base64.strict_encode64(@object.to_diaspora_xml), - remote_people.map{|p| p.id}, - self.class.to_s - ) - end - - # @param people [Array<Person>] Recipients of the post - def deliver_to_local(people) - return if people.blank? || @object.is_a?(Profile) - if @object.respond_to?(:persisted?) && !@object.is_a?(Conversation) - batch_deliver_to_local(people) - else - people.each do |person| - logger.info "event=push route=local sender=#{@sender.diaspora_handle} recipient=#{person.diaspora_handle} " \ - "payload_type=#{@object.class}" - Workers::Receive.perform_async(person.owner_id, @xml, @sender.person_id) - end - end - end - - # @param people [Array<Person>] Recipients of the post - def batch_deliver_to_local(people) - ids = people.map{ |p| p.owner_id } - Workers::ReceiveLocalBatch.perform_async(@object.class.to_s, @object.id, ids) - logger.info "event=push route=local sender=#{@sender.diaspora_handle} recipients=#{ids.join(',')} " \ - "payload_type=#{@object.class}" - end - - def deliver_to_hub - logger.debug "event=post_to_service type=pubsub sender_handle=#{@sender.diaspora_handle}" - Workers::PublishToHub.perform_async(@sender.atom_url) - end - - # @param url [String] - # @param services [Array<Service>] - def deliver_to_services(url, services) - if @object.respond_to?(:public) && @object.public - deliver_to_hub - end - services.each do |service| - if @object.instance_of?(StatusMessage) - Workers::PostToService.perform_async(service.id, @object.id, url) - end - if @object.instance_of?(SignedRetraction) - Workers::DeletePostFromService.perform_async(service.id, @object.target.id) - end - end - end - - # @param local_people [Array<People>] - def notify_local_users(local_people) - local_users = fetch_local_users(local_people) - self.notify_users(local_users) - end - - # @param services [Array<User>] - def notify_users(users) - return unless users.present? && @object.respond_to?(:persisted?) - - Workers::NotifyLocalUsers.perform_async(users.map(&:id), @object.class.to_s, @object.id, @object.author.id) - end -end - diff --git a/lib/postzord/dispatcher/private.rb b/lib/postzord/dispatcher/private.rb deleted file mode 100644 index 1622a2b30eb9444214d845f504bd8e3d39c38e28..0000000000000000000000000000000000000000 --- a/lib/postzord/dispatcher/private.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -class Postzord::Dispatcher::Private < Postzord::Dispatcher - - # @param user [User] - # @param activity [String] - # @return [Salmon::EncryptedSlap] - def self.salmon(user, activity) - Salmon::EncryptedSlap.create_by_user_and_activity(user, activity) - end - - # @param person [Person] - # @return [String] - def self.receive_url_for(person) - person.receive_url - end -end diff --git a/lib/postzord/dispatcher/public.rb b/lib/postzord/dispatcher/public.rb deleted file mode 100644 index 6e7b134aa1cf781d1b6bdcde3a742dd9a57d74ab..0000000000000000000000000000000000000000 --- a/lib/postzord/dispatcher/public.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -class Postzord::Dispatcher::Public < Postzord::Dispatcher - - # @param user [User] - # @param activity [String] - # @return [Salmon::EncryptedSlap] - def self.salmon(user, activity) - Salmon::Slap.create_by_user_and_activity(user, activity) - end - - # @param person [Person] - # @return [String] - def self.receive_url_for(person) - person.url + 'receive/public' - end -end diff --git a/lib/postzord/receiver.rb b/lib/postzord/receiver.rb deleted file mode 100644 index ecdf02f6cf5e16011955e786f387c5b321ae8ad0..0000000000000000000000000000000000000000 --- a/lib/postzord/receiver.rb +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - - -class Postzord::Receiver - include Diaspora::Logging - - require 'postzord/receiver/private' - require 'postzord/receiver/public' - require 'postzord/receiver/local_batch' - - def perform! - self.receive! - end - - private - - def author_does_not_match_xml_author? - return false unless @author.diaspora_handle != xml_author - logger.error "event=receive status=abort reason='author in xml does not match retrieved person' " \ - "type=#{@object.class} sender=#{@author.diaspora_handle}" - true - end - - def relayable_without_parent? - return false unless @object.respond_to?(:relayable?) && @object.parent.nil? - logger.error "event=receive status=abort reason='no corresponding post' type=#{@object.class} " \ - "sender=#{@author.diaspora_handle}" - true - end -end diff --git a/lib/postzord/receiver/local_batch.rb b/lib/postzord/receiver/local_batch.rb deleted file mode 100644 index 01a6ff47faa346f1e71c095d0e9de87fe7446a0e..0000000000000000000000000000000000000000 --- a/lib/postzord/receiver/local_batch.rb +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -class Postzord::Receiver::LocalBatch < Postzord::Receiver - - attr_reader :object, :recipient_user_ids, :users - - def initialize(object, recipient_user_ids) - @object = object - @recipient_user_ids = recipient_user_ids - @users = User.where(:id => @recipient_user_ids) - - end - - def receive! - logger.info "receiving local batch for #{@object.inspect}" - if @object.respond_to?(:relayable?) - receive_relayable - else - create_share_visibilities - end - notify_mentioned_users if @object.respond_to?(:mentions) - - # 09/27/11 this is slow - notify_users - - logger.info "receiving local batch completed for #{@object.inspect}" - end - - # NOTE(copied over from receiver public) - # @return [void] - def receive_relayable - if @object.parent_author.local? - # receive relayable object only for the owner of the parent object - @object.receive(@object.parent_author.owner) - end - end - - # Batch import post visibilities for the recipients of the given @object - # @note performs a bulk insert into mySQL - # @return [void] - def create_share_visibilities - contacts_ids = Contact.connection.select_values(Contact.where(:user_id => @recipient_user_ids, :person_id => @object.author_id).select("id").to_sql) - ShareVisibility.batch_import(contacts_ids, object) - end - - # Notify any mentioned users within the @object's text - # @return [void] - def notify_mentioned_users - @object.mentions.each do |mention| - mention.notify_recipient - end - end - - #NOTE(these methods should be in their own module, included in this class) - # Notify users of the new object - # return [void] - def notify_users - return unless @object.respond_to?(:notification_type) - @users.find_each do |user| - Notification.notify(user, @object, @object.author) - end - if @object.respond_to?(:target) - additional_subscriber = @object.target.author.owner - elsif @object.respond_to?(:post) - additional_subscriber = @object.post.author.owner - end - - Notification.notify(additional_subscriber, @object, @object.author) if needs_notification?(additional_subscriber) - end - - private - - def needs_notification?(person) - person && person != @object.author.owner && !@users.exists?(person.id) - end -end diff --git a/lib/postzord/receiver/private.rb b/lib/postzord/receiver/private.rb deleted file mode 100644 index 5e545b9955a5475308eb665426cbee8ca401867a..0000000000000000000000000000000000000000 --- a/lib/postzord/receiver/private.rb +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -class Postzord::Receiver::Private < Postzord::Receiver - - def initialize(user, opts={}) - @user = user - @user_person = @user.person - @salmon_xml = opts[:salmon_xml] - - @author = opts[:person] || Person.find_or_fetch_by_identifier(salmon.author_id) - - @object = opts[:object] - end - - def receive! - if @author && salmon.verified_for_key?(@author.public_key) - parse_and_receive(salmon.parsed_data) - else - logger.error "event=receive status=abort reason='not_verified for key' " \ - "recipient=#{@user.diaspora_handle} sender=#{@salmon.author_id}" - end - rescue => e - logger.error "failed to receive #{@object.class} from sender:#{@author.id} for user:#{@user.id}: #{e.message}\n" \ - "#{@object.inspect}" - raise e - end - - def parse_and_receive(xml) - @object ||= Diaspora::Parser.from_xml(xml) - - logger.info "user:#{@user.id} starting private receive from person:#{@author.guid}" - - validate_object - set_author! - receive_object - end - - # @return [void] - def receive_object - obj = @object.receive(@user, @author) - Notification.notify(@user, obj, @author) if obj.respond_to?(:notification_type) - logger.info "user:#{@user.id} successfully received #{@object.class} from person #{@author.guid}" \ - "#{": #{@object.guid}" if @object.respond_to?(:guid)}" - logger.debug "received: #{@object.inspect}" - end - - protected - - def salmon - @salmon ||= Salmon::EncryptedSlap.from_xml(@salmon_xml, @user) - end - - def xml_author - if @object.respond_to?(:relayable?) - #if A and B are friends, and A sends B a comment from C, we delegate the validation to the owner of the post being commented on - xml_author = @user.owns?(@object.parent) ? @object.diaspora_handle : @object.parent_author.diaspora_handle - @author = Person.find_or_fetch_by_identifier(@object.diaspora_handle) if @object.author - else - xml_author = @object.diaspora_handle - end - xml_author - end - - - def set_author! - return unless @author - @object.author = @author if @object.respond_to? :author= - @object.person = @author if @object.respond_to? :person= - end - - private - - # validations - - def validate_object - raise Diaspora::XMLNotParseable if @object.nil? - raise Diaspora::ContactRequiredUnlessRequest if contact_required_unless_request - raise Diaspora::RelayableObjectWithoutParent if relayable_without_parent? - - assign_sender_handle_if_request - - raise Diaspora::AuthorXMLAuthorMismatch if author_does_not_match_xml_author? - end - - def contact_required_unless_request - unless @object.is_a?(Request) || @user.contact_for(@author) || (@author.owner && @author.owner.podmin_account?) - logger.error "event=receive status=abort reason='sender not connected to recipient' type=#{@object.class} " \ - "recipient=#{@user_person.diaspora_handle} sender=#{@author.diaspora_handle}" - return true - end - end - - def assign_sender_handle_if_request - #special casey - if @object.is_a?(Request) - @object.sender_handle = @author.diaspora_handle - end - end -end diff --git a/lib/postzord/receiver/public.rb b/lib/postzord/receiver/public.rb deleted file mode 100644 index bb821585b167e071c007a83e82ade88b6ac0b7cd..0000000000000000000000000000000000000000 --- a/lib/postzord/receiver/public.rb +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -class Postzord::Receiver::Public < Postzord::Receiver - - attr_accessor :salmon, :author - - def initialize(xml) - @salmon = Salmon::Slap.from_xml(xml) - @author = Person.find_or_fetch_by_identifier(@salmon.author_id) - end - - # @return [Boolean] - def verified_signature? - @salmon.verified_for_key?(@author.public_key) - end - - # @return [void] - def receive! - return unless verified_signature? - # return false unless account_deletion_is_from_author - - parse_and_receive(@salmon.parsed_data) - - logger.info "received a #{@object.inspect}" - if @object.is_a?(SignedRetraction) || @object.is_a?(Retraction) # feels like a hack - self.recipient_user_ids.each do |user_id| - user = User.where(id: user_id).first - @object.perform user if user - end - elsif @object.respond_to?(:relayable?) - receive_relayable - elsif @object.is_a?(AccountDeletion) - #nothing - else - Workers::ReceiveLocalBatch.perform_async(@object.class.to_s, @object.id, self.recipient_user_ids) - end - end - - # @return [void] - def receive_relayable - if @object.parent_author.local? - # receive relayable object only for the owner of the parent object - @object.receive(@object.parent_author.owner, @author) - end - unless @object.signature_valid? - @object.destroy - logger.warn "event=receive status=abort reason='object signature not valid' " - return - end - # notify everyone who can see the parent object - receiver = Postzord::Receiver::LocalBatch.new(@object, self.recipient_user_ids) - receiver.notify_users - end - - # @return [void] - def parse_and_receive(xml) - @object = Diaspora::Parser.from_xml(xml) - - logger.info "starting public receive from person:#{@author.guid}" - - validate_object - receive_object - end - - # @return [void] - def receive_object - if @object.respond_to?(:receive_public) - @object.receive_public - elsif @object.respond_to?(:save!) - @object.save! - end - end - - # @return [Array<Integer>] User ids - def recipient_user_ids - User.all_sharing_with_person(@author).pluck('users.id') - end - - def xml_author - if @object.is_a?(RelayableRetraction) - if [@object.parent_diaspora_handle, @object.target.parent.diaspora_handle].include?(@author.diaspora_handle) - @author.diaspora_handle - end - elsif @object.respond_to?(:relayable?) - #this is public, so it would only be owners sending us other people comments etc - @object.parent_author.local? ? @object.diaspora_handle : @object.parent_diaspora_handle - else - @object.diaspora_handle - end - end - - private - - # validations - - def validate_object - raise Diaspora::XMLNotParseable if @object.nil? - raise Diaspora::NonPublic if object_can_be_public_and_it_is_not? - raise Diaspora::RelayableObjectWithoutParent if relayable_without_parent? - raise Diaspora::AuthorXMLAuthorMismatch if author_does_not_match_xml_author? - end - - def account_deletion_is_from_author - return true unless @object.is_a?(AccountDeletion) - return false if @object.diaspora_handle != @author.diaspora_handle - return true - end - - # @return [Boolean] - def object_can_be_public_and_it_is_not? - @object.respond_to?(:public) && !@object.public? - end -end diff --git a/lib/publisher.rb b/lib/publisher.rb index 3de0d0aed8a4be4de22a90f48660b512b9c402d9..71894b65252ac466d9c7281bee0be9027b249e4e 100644 --- a/lib/publisher.rb +++ b/lib/publisher.rb @@ -10,26 +10,10 @@ class Publisher end def text - formatted_message - end - - def open? - self.open - end - - def public? - self.public - end - - def explain? - self.explain - end - - private - def formatted_message - if self.prefill.present? - sm = StatusMessage.new(:text => self.prefill) - Diaspora::Mentionable.format(sm.raw_message, sm.mentioned_people, plain_text: true) - end + return unless prefill.present? + Diaspora::MessageRenderer.new( + prefill, + mentioned_people: Diaspora::Mentionable.people_from_string(prefill) + ).plain_text end end diff --git a/lib/salmon.rb b/lib/salmon.rb deleted file mode 100644 index 747190d6004890e692a353a04a9f787862e7ad77..0000000000000000000000000000000000000000 --- a/lib/salmon.rb +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -# Add URL safe Base64 support -module Base64 - module_function - # Returns the Base64-encoded version of +bin+. - # This method complies with ``Base 64 Encoding with URL and Filename Safe - # Alphabet'' in RFC 4648. - # The alphabet uses '-' instead of '+' and '_' instead of '/'. - def urlsafe_encode64(bin) - self.strict_encode64(bin).tr("+/", "-_") - end - - # Returns the Base64-decoded version of +str+. - # This method complies with ``Base 64 Encoding with URL and Filename Safe - # Alphabet'' in RFC 4648. - # The alphabet uses '-' instead of '+' and '_' instead of '/'. - def urlsafe_decode64(str) - self.decode64(str.tr("-_", "+/")) - end -end - -# Verify documents secured with Magic Signatures -module Salmon - require "salmon/slap" - require "salmon/encrypted_slap" - require "salmon/magic_sig_envelope" -end diff --git a/lib/salmon/encrypted_slap.rb b/lib/salmon/encrypted_slap.rb deleted file mode 100644 index 64c16788381ffe29b0b20a3c8ba9694e6b73dfda..0000000000000000000000000000000000000000 --- a/lib/salmon/encrypted_slap.rb +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Salmon - class EncryptedSlap < Slap - include Diaspora::Logging - - # Construct an encrypted header - # @return [String] Header XML - def header(person) - <<XML - <encrypted_header> - #{person.encrypt(plaintext_header)} - </encrypted_header> -XML - end - - def plaintext_header - header =<<HEADER -<decrypted_header> - <iv>#{iv}</iv> - <aes_key>#{aes_key}</aes_key> - <author_id>#{@author.diaspora_handle}</author_id> -</decrypted_header> -HEADER - end - - # @return [String, Boolean] False if RSAError; XML if no error - def xml_for(person) - begin - super - rescue OpenSSL::PKey::RSAError => e - logger.error "event=invalid_rsa_key identifier=#{person.diaspora_handle}" - false - end - end - - # Takes in a doc of the header and sets the author id - # returns an empty hash - # @return [Hash] - def process_header(doc) - self.author_id = doc.search('author_id').text - self.aes_key = doc.search('aes_key').text - self.iv = doc.search('iv').text - end - - # Decrypts an encrypted magic sig envelope - # @param key_hash [Hash] Contains 'key' (aes) and 'iv' values - # @param user [User] - def parse_data(user) - user.aes_decrypt(super, {'key' => self.aes_key, 'iv' => self.iv}) - end - - # Decrypts and parses out the salmon header - # @return [Nokogiri::Doc] - def salmon_header(doc, user) - header = user.decrypt(doc.search('encrypted_header').text) - Nokogiri::XML(header) - end - - # Encrypt the magic sig - # @return [String] - def self.payload(activity, user, aes_key_hash) - user.person.aes_encrypt(activity, aes_key_hash) - end - end -end diff --git a/lib/salmon/magic_sig_envelope.rb b/lib/salmon/magic_sig_envelope.rb deleted file mode 100644 index 44527513c13929439d1c311f58c3f1695688bc29..0000000000000000000000000000000000000000 --- a/lib/salmon/magic_sig_envelope.rb +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Salmon - class MagicSigEnvelope - - attr_accessor :data, :data_type, :encoding, :alg, :sig, :author - - # @return [MagicSigEnvelope] - def self.parse(doc) - env = self.new - ns = {'me'=>'http://salmon-protocol.org/ns/magic-env'} - env.encoding = doc.search('//me:env/me:encoding', ns).text.strip - - if env.encoding != 'base64url' - raise ArgumentError, "Magic Signature data must be encoded with base64url, was #{env.encoding}" - end - - env.data = doc.search('//me:env/me:data', ns).text - env.alg = doc.search('//me:env/me:alg', ns).text.strip - - unless 'RSA-SHA256' == env.alg - raise ArgumentError, "Magic Signature data must be signed with RSA-SHA256, was #{env.alg}" - end - - env.sig = doc.search('//me:env/me:sig', ns).text - env.data_type = doc.search('//me:env/me:data', ns).first['type'].strip - - env - end - - # @return [MagicSigEnvelope] - def self.create(user, activity) - env = MagicSigEnvelope.new - env.author = user.person - env.data = Base64.urlsafe_encode64(activity) - env.data_type = env.get_data_type - env.encoding = env.get_encoding - env.alg = env.get_alg - - #TODO: WHY DO WE DOUBLE ENCODE - env.sig = Base64.urlsafe_encode64( - user.encryption_key.sign OpenSSL::Digest::SHA256.new, env.signable_string ) - - env - end - - # @return [String] - def signable_string - [@data, Base64.urlsafe_encode64(@data_type),Base64.urlsafe_encode64(@encoding), Base64.urlsafe_encode64(@alg)].join(".") - end - - # @return [String] - def to_xml - <<ENTRY -<me:env> - <me:data type='#{@data_type}'>#{@data}</me:data> - <me:encoding>#{@encoding}</me:encoding> - <me:alg>#{@alg}</me:alg> - <me:sig>#{@sig}</me:sig> - </me:env> -ENTRY - end - - # @return [String] - def get_encoding - 'base64url' - end - - # @return [String] - def get_data_type - 'application/xml' - end - - # @return [String] - def get_alg - 'RSA-SHA256' - end - end -end diff --git a/lib/salmon/slap.rb b/lib/salmon/slap.rb deleted file mode 100644 index 61ea1499638e4cc88e8680f5081d0e2ebb7445a2..0000000000000000000000000000000000000000 --- a/lib/salmon/slap.rb +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Salmon - class Slap - attr_accessor :magic_sig, :author, :author_id, :parsed_data - attr_accessor :aes_key, :iv - - delegate :sig, :data_type, :to => :magic_sig - - # @param user [User] - # @param activity [String] A decoded string - # @return [Slap] - def self.create_by_user_and_activity(user, activity) - salmon = self.new - salmon.author = user.person - aes_key_hash = user.person.gen_aes_key - - #additional headers - salmon.aes_key = aes_key_hash['key'] - salmon.iv = aes_key_hash['iv'] - - salmon.magic_sig = MagicSigEnvelope.create(user, self.payload(activity, user, aes_key_hash)) - salmon - end - - def self.from_xml(xml, receiving_user=nil) - slap = self.new - doc = Nokogiri::XML(xml) - - root_doc = doc.search('diaspora') - - ### Header ## - header_doc = slap.salmon_header(doc, receiving_user) - slap.process_header(header_doc) - - ### Envelope ## - slap.magic_sig = MagicSigEnvelope.parse(root_doc) - - slap.parsed_data = slap.parse_data(receiving_user) - - slap - end - - # @return [String] - def self.payload(activity, user=nil, aes_key_hash=nil) - activity - end - - # Takes in a doc of the header and sets the author id - # returns an empty hash - # @return [String] Author id - def process_header(doc) - self.author_id = doc.search('author_id').text - end - - # @return [String] - def parse_data(user=nil) - Slap.decode64url(self.magic_sig.data) - end - - # @return [Nokogiri::Doc] - def salmon_header(doc, user=nil) - doc.search('header') - end - - # @return [String] The constructed salmon, given a person - # note this memoizes the xml, as for every user for unsigned salmon will be the same - def xml_for(person) - @xml =<<ENTRY - <?xml version='1.0' encoding='UTF-8'?> - <diaspora xmlns="https://joindiaspora.com/protocol" xmlns:me="http://salmon-protocol.org/ns/magic-env"> - #{header(person)} - #{@magic_sig.to_xml} - </diaspora> -ENTRY - end - - # Wraps plaintext header in <header></header> tags - # @return [String] Header XML - def header(person) - "<header>#{plaintext_header}</header>" - end - - # Generate a plaintext salmon header (unencrypted), sans <header></header> tags - # @return [String] Header XML (sans <header></header> tags) - def plaintext_header - header =<<HEADER - <author_id>#{@author.diaspora_handle}</author_id> -HEADER - end - - # @return [Person] Author of the salmon object - def author - if @author.nil? - @author ||= Person.by_account_identifier @author_id - raise "did you remember to async webfinger?" if @author.nil? - end - @author - end - - # Decode URL-safe-Base64. This implements - def self.decode64url(str) - # remove whitespace - sans_whitespace = str.gsub(/\s/, '') - # pad to a multiple of 4 - string = sans_whitespace + '=' * ((4 - sans_whitespace.size) % 4) - # convert to standard Base64 - # string = padded.tr('-','+').tr('_','/') - - # Base64.decode64(string) - Base64.urlsafe_decode64 string - end - - # Check whether this envelope's signature can be verified with the - # provided OpenSSL::PKey::RSA public_key. - # Example: - # - # env.verified_for_key? OpenSSL::PKey::RSA.new(File.open('public_key.pem')) - # # -> true - def verified_for_key?(public_key) - signature = Base64.urlsafe_decode64(self.magic_sig.sig) - signed_data = self.magic_sig.signable_string# Base64.urlsafe_decode64(self.magic_sig.signable_string) - - public_key.verify(OpenSSL::Digest::SHA256.new, signature, signed_data ) - end - - # Decode a string containing URL safe Base64 into an integer - # Example: - # - # MagicSig.b64_to_n('AQAB') - # # -> 645537 - def self.b64_to_n(str) - packed = decode64url(str) - packed.unpack('B*')[0].to_i(2) - end - - # Parse a string containing a magic-public-key into an OpenSSL::PKey::RSA key. - # Example: - # - # key = MagicSig.parse_key('RSA.mVgY8RN6URBTstndvmUUPb4UZTdwvwmddSKE5z_jvKUEK6yk1u3rrC9yN8k6FilGj9K0eeUPe2hf4Pj-5CmHww.AQAB') - # key.n - # # -> 8031283789075196565022891546563591368344944062154100509645398892293433370859891943306439907454883747534493461257620351548796452092307094036643522661681091 - # key.e - # # -> 65537 - def self.parse_key(str) - n,e = str.match(/^RSA.([^.]*).([^.]*)$/)[1..2] - build_key(b64_to_n(n),b64_to_n(e)) - end - - # Take two integers e, n and create a new OpenSSL::PKey::RSA key with them - # Example: - # - # n = 9487834027867356975347184933768917275269369900665861930617802608089634337052392076689226301419587057117740995382286148368168197915234368486155306558161867 - # e = 65537 - # key = MagicSig.build_key(n,e) - # key.public_encrypt(...) # for sending to strangers - # key.public_decrypt(...) # very rarely used - # key.verify(...) # for verifying signatures - def self.build_key(n,e) - key = OpenSSL::PKey::RSA.new - key.n = n - key.e = e - key - end - end -end diff --git a/lib/stream/multi.rb b/lib/stream/multi.rb index e92ee93d07d579035cd276f1eb13a0af2f4ea157..99580437246d5305f246e078b83763067f1ee735 100644 --- a/lib/stream/multi.rb +++ b/lib/stream/multi.rb @@ -25,7 +25,7 @@ class Stream::Multi < Stream::Base private def publisher_opts if welcome? - {:open => true, :prefill => publisher_prefill, :public => true} + {open: true, prefill: publisher_prefill, public: true, explain: true} else super end diff --git a/lib/stream/person.rb b/lib/stream/person.rb index efbe9e22acb26159e9bb86ffb622eefc12395da7..1a1123d71f613a27a30cb13f04c3ecaa6533c355 100644 --- a/lib/stream/person.rb +++ b/lib/stream/person.rb @@ -15,4 +15,11 @@ class Stream::Person < Stream::Base def posts @posts ||= user.present? ? user.posts_from(@person) : @person.posts.where(:public => true) end + + # @return [Array<Post>] + def stream_posts + posts.for_a_stream(max_time, order, user, true).tap do |posts| + like_posts_for_stream!(posts) # some sql person could probably do this with joins. + end + end end diff --git a/lib/stream/tag.rb b/lib/stream/tag.rb index afb6175a2742582beb62957dbfbd880cd385eb5e..53372ba577eadff7ee62f008f38719ee97fbd06f 100644 --- a/lib/stream/tag.rb +++ b/lib/stream/tag.rb @@ -29,7 +29,16 @@ class Stream::Tag < Stream::Base end def posts - @posts ||= construct_post_query + @posts ||= if user + StatusMessage.user_tag_stream(user, tag.id) + else + StatusMessage.public_tag_stream(tag.id) + end + end + + def stream_posts + return [] unless tag + super end def tag_name=(tag_name) @@ -42,14 +51,4 @@ class Stream::Tag < Stream::Base def publisher_opts {:open => true} end - - def construct_post_query - posts = StatusMessage - if user.present? - posts = posts.owned_or_visible_by_user(user) - else - posts = posts.all_public - end - posts.tagged_with(tag_name, :any => true) - end end diff --git a/lib/tasks/accounts.rake b/lib/tasks/accounts.rake deleted file mode 100644 index fb79a27302b9a609377d4656cfaaefcde0b42b70..0000000000000000000000000000000000000000 --- a/lib/tasks/accounts.rake +++ /dev/null @@ -1,15 +0,0 @@ -namespace :accounts do - desc "Run deletions" - task :run_deletions => :environment do - if ::AccountDeletion.uncompleted.count > 0 - puts "Running account deletions.." - ::AccountDeletion.uncompleted.find_each do |account_delete| - account_delete.perform! - end - puts "OK." - else - puts "No acccount deletions to run." - end - end - -end diff --git a/lib/tasks/assets.rake b/lib/tasks/assets.rake index cc84fbf974f88bcc4b577c00af4d0487945fac32..88147646b0eee11ed89e60d18dc9a800f9f00895 100644 --- a/lib/tasks/assets.rake +++ b/lib/tasks/assets.rake @@ -1,59 +1,18 @@ -# Inspired by https://github.com/route/errgent/blob/master/lib/errgent/renderer.rb -class ErrorPageRenderer - def initialize options={} - @codes = options.fetch :codes, [404, 500] - @output = options.fetch :output, "public/%s.html" - @vars = options.fetch :vars, {} - @template = options.fetch :template, "errors/error_%s" - @layout = options.fetch :layout, "layouts/error_page" - end - - def render - @codes.each do |code| - view = build_action_view - view.assign @vars.merge(code: code) - path = Rails.root.join(@output % code) - File.write path, view.render(template: @template % code, layout: @layout) - end - end - - def helpers(&block) - @helpers = block - end - - private - - def build_action_view - paths = ::ActionController::Base.view_paths - ::ActionView::Base.new(paths).tap do |view| - view.class_eval do - include Rails.application.helpers - include Rails.application.routes.url_helpers - end - view.assets_manifest = build_manifest(Rails.application) - view.class_eval(&@helpers) if @helpers - end - end - - # Internal API from the sprocket-rails railtie, if somebody finds a way to - # call it, please replace it. Might need to be updated on sprocket-rails - # updates. - def build_manifest(app) - config = app.config - path = File.join(config.paths['public'].first, config.assets.prefix) - Sprockets::Manifest.new(app.assets, path, config.assets.manifest) - end -end - namespace :assets do desc "Generate error pages" - task :generate_error_pages do + task :generate_error_pages => :environment do renderer = ErrorPageRenderer.new codes: [404, 422, 500] renderer.render end + desc "Uglify bookmarklet snippet" + task :uglify_bookmarklet => :environment do + BookmarkletRenderer.compile + end + # Augment precompile with error page generation task :precompile do Rake::Task['assets:generate_error_pages'].invoke + Rake::Task['assets:uglify_bookmarklet'].invoke end end diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake index d91a6123b5197ddbf54a9e85f2d276dd38a7fbbc..defd67ce70253b61aa1bb09ba80373f446c74875 100644 --- a/lib/tasks/db.rake +++ b/lib/tasks/db.rake @@ -3,92 +3,15 @@ # the COPYRIGHT file. namespace :db do - desc "rebuild and prepare test db" - task :rebuild do - Rake::Task['db:drop'].invoke - Rake::Task['db:drop_integration'].invoke - Rake::Task['db:create'].invoke - Rake::Task['db:migrate'].invoke - puts "seeding users, this will take awhile" - `rake db:seed` #ghetto hax as we have active record garbage in our models - puts "seeded!" - Rake::Task['db:test:prepare'].invoke - end - - namespace :integration do - # desc 'Check for pending migrations and load the integration schema' - task :prepare => :environment do - abcs = ActiveRecord::Base.configurations - envs = abcs.keys.select{ |k| k.include?("integration") } - puts envs.inspect - envs.each_with_index do |env, i| - Rails.env = env - Rake::Task.tasks.each{ |task| task.reenable } - - print "\n\n## preparing database for #{env}... " - puts (i == 0) ? "(go get yourself a coffee)" : "(time for another coffee)" - - # do drop, schema:load_if_ruby, structure:load_if_sql, seed - Rake::Task['db:drop'].invoke - Rake::Task['db:setup'].invoke - - puts "db #{ActiveRecord::Base.connection.current_database} done" - end - end - end - - desc 'Delete the collections in the current RAILS_ENV database' + desc "Reset the current RAILS_ENV database and delete the upload-folder" task :purge do - require File.join(File.dirname(__FILE__), '..', '..', 'config', 'environment') + require File.join(File.dirname(__FILE__), "..", "..", "config", "environment") puts "Purging the database for #{Rails.env}..." - Rake::Task['db:rebuild'].invoke - - puts 'Deleting tmp folder...' - `rm -rf #{File.dirname(__FILE__)}/../../public/uploads/*` - end - - desc 'Purge and seed the current RAILS_ENV database using information from db/seeds.rb' - task :reset do - puts "Resetting the database for #{Rails.env}".upcase - Rake::Task['db:purge'].invoke - Rake::Task['db:seed'].invoke - puts "Success!" - end - - task :drop_integration do - ActiveRecord::Base.configurations.keys.select{ |k| - k.include?("integration") - }.each{ |k| - drop_database ActiveRecord::Base.configurations[k] rescue Mysql2::Error - } - end - - task :fix_diaspora_handle do - puts "fixing the people in this seed" - require File.join(File.dirname(__FILE__), '..', '..', 'config', 'environment') - Person.where(:url => 'example.org').all.each{|person| - if person.owner - person.url = AppConfig.pod_uri.to_s - person.diaspora_handle = person.owner.diaspora_handle - person.save - end - } - puts "everything should be peachy" - end + Rake::Task["db:reset"].invoke - task :move_private_key do - require File.join(File.dirname(__FILE__), '..', '..', 'config', 'environment') - User.all.each do |user| - if user.serialized_private_key.nil? - user.serialized_private_key = user.person.serialized_key - user.save - person = user.person - person.serialized_key = nil - person.serialized_public_key = user.encryption_key.public_key.to_s - person.save - end - end + puts "Deleting tmp folder..." + `rm -rf #{File.dirname(__FILE__)}/../../public/uploads/*` end end diff --git a/lib/tasks/linter.rake b/lib/tasks/linter.rake index c533ad8206c829842389753c58f9b1a310eda57b..31ff91957d88e403ac340834e8eb4918f22314c1 100644 --- a/lib/tasks/linter.rake +++ b/lib/tasks/linter.rake @@ -1,12 +1,13 @@ begin - require "jshintrb/jshinttask" - Jshintrb::JshintTask.new :jshint do |t| + require "eslintrb/eslinttask" + Eslintrb::EslintTask.new :eslint do |t| t.pattern = "{app/assets,lib/assets,spec}/javascripts/**/*.js" - t.options = :jshintrc + t.exclude_pattern = "app/assets/javascripts/{jasmine-load-all,main,mobile/mobile,templates}.js" + t.options = :eslintrc end rescue LoadError - desc "jshint rake task not available (jshintrb not installed)" - task :jshint do - abort "JSHint rake task is not available. Be sure to install jshintrb." + desc "eslint rake task not available (eslintrb not installed)" + task :eslint do + abort "ESLint rake task is not available. Be sure to install eslintrb." end end diff --git a/lib/tasks/maintenance.rake b/lib/tasks/maintenance.rake index 746a773f5c4b25e739130061f067bbdea4c79ba3..042d78b58638ff8be79f9b232787d66a2a16444b 100644 --- a/lib/tasks/maintenance.rake +++ b/lib/tasks/maintenance.rake @@ -3,40 +3,6 @@ # the COPYRIGHT file. namespace :maintenance do - APP_ROOT = File.expand_path( File.join( File.dirname( __FILE__ ), '..', '..') ) - desc "Clear CarrierWave temp uploads" - task :clear_carrierwave_temp_uploads do - filename = File.join( APP_ROOT, 'tmp', 'uploads', '*') - today_string = Time.now.strftime( '%Y%m%d' ) - Dir.glob( filename ) do |file| - unless file.include?( today_string ) - FileUtils.rm_rf( file ) - end - end - end - - desc "Rotate Diaspora logs" - task :install_logrotate_config do - logrotate_conf = <<-RUBY -#{APP_ROOT}/logs/production.log { - daily - missingok - rotate 8 - compress - delaycompress - notifempty - copytruncate -} -RUBY - begin - File.open('/etc/logrotate.d/diaspora') do |fin| - fin.write logrotate_conf - end - rescue - puts "Could not install logrotate configs. Perhaps you should try running this task as root and ensuring logrotate is installed:\n#{logrotate_conf}" - end - end - desc "Queue users for removal" task :queue_users_for_removal => :environment do # Queue users for removal due to inactivity diff --git a/lib/tasks/migrations.rake b/lib/tasks/migrations.rake index 20d7d42d814019f3caf59a6f0eb18591d98dcec1..45703ed5694d14f077901d8ad047e29685775ee3 100644 --- a/lib/tasks/migrations.rake +++ b/lib/tasks/migrations.rake @@ -3,50 +3,6 @@ # the COPYRIGHT file. namespace :migrations do - - desc 'copy all hidden share visibilities from share_visibilities to users. Can be run with the site still up.' - task :copy_hidden_share_visibilities_to_users => [:environment] do - require Rails.root.join('lib', 'share_visibility_converter') - ShareVisibilityConverter.copy_hidden_share_visibilities_to_users - end - - desc 'puts out information about old invited users' - task :invitations => [:environment] do - puts "email, invitation_token, :invited_by_id, :invitation_identifier" - User.where('username is NULL').select([:id, :email, :invitation_token, :invited_by_id, :invitation_identifier]).find_in_batches do |users| - users.each{|x| puts "#{x.email}, #{x.invitation_token}, #{x.invited_by_id}, #{x.invitation_identifier}" } - end - puts "done" - end - - desc 'absolutify all existing image references' - task :absolutify_image_references do - require File.join(File.dirname(__FILE__), '..', '..', 'config', 'environment') - - Photo.all.each do |photo| - unless photo.remote_photo_path - # extract root - # - pod = URI::parse(photo.person.url) - pod_url = "#{pod.scheme}://#{pod.host}" - - if photo.image.url - remote_path = "#{photo.image.url}" - else - puts pod_url - remote_path = "#{pod_url}#{photo.remote_photo_path}/#{photo.remote_photo_name}" - end - - # get path/filename - name_start = remote_path.rindex '/' - photo.remote_photo_path = "#{remote_path.slice(0, name_start)}/" - photo.remote_photo_name = remote_path.slice(name_start + 1, remote_path.length) - - photo.save! - end - end - end - task :upload_photos_to_s3 do require File.join(File.dirname(__FILE__), '..', '..', 'config', 'environment') puts AppConfig.environment.s3.key @@ -72,59 +28,31 @@ namespace :migrations do end end } - end - # removes hashtags with uppercase letters and re-attaches - # the posts to the lowercase version - task :rewire_uppercase_hashtags => :environment do - evil_tags = ActsAsTaggableOn::Tag.where("lower(name) != name") - puts "found #{evil_tags.count} tags to convert..." - - evil_tags.each_with_index do |tag, i| - good_tag = ActsAsTaggableOn::Tag.first_or_create_by(name: tag.name.mb_chars.downcase) - puts "++ '#{tag.name}' has #{tag.taggings.count} records attached" - - taggings = tag.taggings - deleteme = [] - - taggings.each do |tagging| - if good_tag.taggings.where(:taggable_id => tagging.taggable_id).count > 0 - # the same taggable is already tagged with the correct tag - # just delete the obsolete tagging it - deleteme << tagging - next - end - - # the tagging exists only for the wrong tag, move it to the 'good tag' - good_tag.taggings << tagging - end - - deleteme.each do |tagging| - tagging.destroy + CURRENT_QUEUES = %w(urgent high medium low default).freeze + + desc "Migrate sidekiq jobs, retries, scheduled and dead jobs from any legacy queue to "\ + "the default queue (retries all dead jobs)" + task :legacy_queues do + # Push all retries, scheduled and dead jobs to their queues + Sidekiq::RetrySet.new.retry_all + Sidekiq::DeadSet.new.retry_all + Sidekiq::ScheduledSet.new.reject {|job| CURRENT_QUEUES.include? job.queue }.each(&:add_to_queue) + + # Move all jobs from legacy queues to the default queue + Sidekiq::Queue.all.each do |queue| + next if CURRENT_QUEUES.include? queue.name + + puts "Migrating #{queue.size} jobs from #{queue.name} to default..." + queue.each do |job| + job.item["queue"] = "default" + Sidekiq::Client.push(job.item) + job.delete end - rest = tag.taggings(true) # force reload - if rest.count > 0 - puts "-- the tag #{tag.name} still has some taggings - aborting!" - break - end - - # no more taggings left, delete the tag - tag.destroy - - puts "-- converted '#{tag.name}' to '#{good_tag.name}'" - puts "\n## #{i+1} tags processed\n\n" if ((i+1) % 50 == 0) - end - end - - task :remove_uppercase_hashtags => :environment do - evil_tags = ActsAsTaggableOn::Tag.where("lower(name) != name") - evil_tags.each do |tag| - next if tag.taggings.count > 0 # non-ascii tags - - puts "removing '#{tag.name}'..." - tag.destroy + # Delete the queue + queue.clear end end end diff --git a/lib/unicorn_killer.rb b/lib/unicorn_killer.rb deleted file mode 100644 index 7e908538de1f8260fde3fdf0c3304c6826f1cbd7..0000000000000000000000000000000000000000 --- a/lib/unicorn_killer.rb +++ /dev/null @@ -1,53 +0,0 @@ -# # your config.ru -# require 'unicorn_killer' -# use UnicornKiller::MaxRequests, 1000 -# use UnicornKiller::Oom, 400 * 1024 - -module UnicornKiller - module Kill - def quit - sec = (Time.now - @process_start).to_i - warn "#{self.class} send SIGQUIT (pid: #{Process.pid})\talive: #{sec} sec" - Process.kill :QUIT, Process.pid - end - end - - class Oom - include Kill - - def initialize(app, memory_size= 512 * 1024, check_cycle = 10) - @app = app - @memory_size = memory_size - @check_cycle = check_cycle - @check_count = 0 - end - - def rss - `ps -o rss= -p #{Process.pid}`.to_i - end - - def call(env) - @process_start ||= Time.now - if (@check_count += 1) % @check_cycle == 0 - @check_count = 0 - quit if rss > @memory_size - end - @app.call env - end - end - - class MaxRequests - include Kill - - def initialize(app, max_requests = 1000) - @app = app - @max_requests = max_requests - end - - def call(env) - @process_start ||= Time.now - quit if (@max_requests -= 1) == 0 - @app.call env - end - end -end diff --git a/public/javascripts/custom-mobile-scripting.js b/public/javascripts/custom-mobile-scripting.js deleted file mode 100644 index 900347dd608bb8bc2d49b460f79eed292c1c86f1..0000000000000000000000000000000000000000 --- a/public/javascripts/custom-mobile-scripting.js +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (c) 2010-2011, Diaspora Inc. This file is -* licensed under the Affero General Public License version 3 or later. See -* the COPYRIGHT file. -*/ - - -$(document).bind("mobileinit", function() { - $.extend($.mobile, { - ajaxLinksEnabled: false, - ajaxEnabled: false, - ajaxFormsEnabled: false - - }); - $.mobile.selectmenu.prototype.options.nativeMenu = false; -}); - - -$(document).ready(function(){ - $(".like_action.inactive").bind('tap', function(evt){ - evt.preventDefault(); - var target = $(this), - postId = target.data('post-id'); - - $.ajax({ - url: '/posts/'+postId+'/likes.json', - type: 'POST', - complete: function(data){ - target.addClass('inactive') - .removeClass('active') - .data('post-id', postId); - } - }); - }); - - $(".like_action.active").bind('tap', function(evt){ - evt.preventDefault(); - var target = $(this), - postId = $(this).data('post-id'), - likeId = $(this).data('like-id'); - - - $.ajax({ - url: '/posts/'+postId+'/likes/'+likeId+'.json', - type: 'DELETE', - complete: function(data){ - target.addClass('inactive') - .removeClass('active') - .data('like-id', ''); - } - }); - }); -}); diff --git a/script/ci/build.sh b/script/ci/build.sh index 1278742874e7536302022cf09309e5d9bd2df1c7..7a129f2118109a21d50aad47d2fcbe27b4cf8e93 100755 --- a/script/ci/build.sh +++ b/script/ci/build.sh @@ -4,8 +4,8 @@ # Create a database.yml for the right database echo "Setting up database.yml for $DB" cp config/database.yml.example config/database.yml -if [ "$DB" = "postgres" ]; then - sed -i 's/*common/*postgres_travis/' config/database.yml +if [ "$DB" = "mysql" ]; then + sed -i 's/*common/*mysql/' config/database.yml fi command="bundle exec rake --trace ci:travis:${BUILD_TYPE}" diff --git a/script/server b/script/server index 7b66ba22e2d0bf19723b4ae72d6c15bae9152668..d8d35aad8a3540547763e3a4cf833b3517cc5e50 100755 --- a/script/server +++ b/script/server @@ -103,7 +103,6 @@ fi os=$(uname -s) vars=$(bin/bundle exec ruby ./script/get_config.rb \ - port=server.port \ single_process_mode=environment.single_process_mode? \ embed_sidekiq_worker=server.embed_sidekiq_worker \ workers=server.sidekiq_workers \ @@ -114,17 +113,6 @@ vars=$(bin/bundle exec ruby ./script/get_config.rb \ on_failure "Couldn't parse config/diaspora.yml!" eval "$vars" -if [ -n "$DB" ] -then - export DB -fi - -if [ -z "$PORT" -a -n "$port" ] -then - warning "Setting port via configuration is deprecated, set listen instead. See the updated config/diaspora.yml.example." - PORT="$port" -fi - args="$@" for arg in $(echo $args | awk '{ for (i = 1; i <= NF; i++) print $i}') do @@ -139,7 +127,7 @@ then services=$(chk_service $PORT) if [ -n "$services" ] then - fatal "Port $port is already in use.\n\t$services" + fatal "Port $PORT is already in use.\n\t$services" fi fi @@ -214,4 +202,4 @@ else fi echo "" -exec bin/bundle exec loader_eye -st -c config/eye.rb +exec bin/bundle exec loader_eye --stop_all -c config/eye.rb diff --git a/spec/controllers/admin/pods_controller_spec.rb b/spec/controllers/admin/pods_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..cd4e198b3cee983ca5350bcd7977a4f2383f6e60 --- /dev/null +++ b/spec/controllers/admin/pods_controller_spec.rb @@ -0,0 +1,53 @@ + +require "spec_helper" + +describe Admin::PodsController, type: :controller do + before do + @user = FactoryGirl.create :user + Role.add_admin(@user.person) + + sign_in @user, scope: :user + end + + describe "#index" do + it "renders the pod list template" do + get :index + expect(response).to render_template("admins/pods") + expect(response.body).to match(/id='pod-alerts'/im) + expect(response.body).to match(/id='pod-list'/im) + end + + it "contains the preloads" do + get :index + expect(response.body).to match(/uncheckedCount=/im) + expect(response.body).to match(/errorCount=/im) + expect(response.body).to match(/preloads.*"pods"\s?\:/im) + end + + it "returns the json data" do + 3.times { FactoryGirl.create(:pod) } + + get :index, format: :json + + expect(response.body).to eql(PodPresenter.as_collection(Pod.all).to_json) + end + end + + describe "#recheck" do + before do + @pod = FactoryGirl.create(:pod).reload + allow(Pod).to receive(:find) { @pod } + expect(@pod).to receive(:test_connection!) + end + + it "performs a connection test" do + post :recheck, pod_id: 1 + expect(response).to be_redirect + end + + it "performs a connection test (format: json)" do + post :recheck, pod_id: 1, format: :json + expect(response.body).to eql(PodPresenter.new(@pod).to_json) + end + end +end diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index c2653685378946d28dc28a66503004427689f762..d9f9dd9110492dd5de8dd3cd881a1ec8fc80d492 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -6,7 +6,7 @@ describe Admin::UsersController, :type => :controller do @user = FactoryGirl.create :user Role.add_admin(@user.person) - sign_in :user, @user + sign_in @user, scope: :user end describe '#close_account' do diff --git a/spec/controllers/admins_controller_spec.rb b/spec/controllers/admins_controller_spec.rb index 3bab4f38a114bddc38b0e7396b81bd7901481d5e..e56fc5fb7dd9a68ec9de1213b1331818b4f2ea26 100644 --- a/spec/controllers/admins_controller_spec.rb +++ b/spec/controllers/admins_controller_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' describe AdminsController, :type => :controller do before do @user = FactoryGirl.create :user - sign_in :user, @user + sign_in @user, scope: :user end describe '#user_search' do @@ -86,6 +86,12 @@ describe AdminsController, :type => :controller do expect(response).to redirect_to user_search_path expect(flash.notice).to include("invitation sent") end + + it "doesn't invite an existing user" do + get :admin_inviter, identifier: bob.email + expect(response).to redirect_to user_search_path + expect(flash.notice).to include("error sending invite") + end end end @@ -94,10 +100,27 @@ describe AdminsController, :type => :controller do Role.add_admin(@user.person) end - it 'succeeds and renders stats' do + it "succeeds and renders stats" do get :stats expect(response).to be_success expect(response).to render_template(:stats) + expect(response.body).to include( + I18n.translate("admins.stats.display_results", segment: I18n.translate("admins.stats.daily")) + ) + end + + it "succeeds and renders stats for different ranges" do + %w(week 2weeks month).each do |range| + get :stats, range: range + expect(response).to be_success + expect(response).to render_template(:stats) + expect(response.body).not_to include( + I18n.translate("admins.stats.display_results", segment: I18n.translate("admins.stats.daily")) + ) + expect(response.body).to include( + I18n.translate("admins.stats.display_results", segment: I18n.translate("admins.stats.#{range}")) + ) + end end end end diff --git a/spec/controllers/api/openid_connect/authorizations_controller_spec.rb b/spec/controllers/api/openid_connect/authorizations_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..9a0631e63a74c97b2cfab6f76f1fb8121224c40a --- /dev/null +++ b/spec/controllers/api/openid_connect/authorizations_controller_spec.rb @@ -0,0 +1,382 @@ +require "spec_helper" + +describe Api::OpenidConnect::AuthorizationsController, type: :controller do + let!(:client) { FactoryGirl.create(:o_auth_application) } + let!(:client_with_xss) { FactoryGirl.create(:o_auth_application_with_xss) } + let!(:client_with_multiple_redirects) { FactoryGirl.create(:o_auth_application_with_multiple_redirects) } + + before do + sign_in alice, scope: :user + end + + describe "#new" do + context "when not yet authorized" do + context "when valid parameters are passed" do + render_views + context "as GET request" do + it "should return a form page" do + get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token", + scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16) + expect(response.body).to match("Diaspora Test Client") + end + end + + context "using claims" do + it "should return a form page" do + get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token", + scope: "openid", claims: "{\"userinfo\": {\"name\": {\"essential\": true}}}", + nonce: SecureRandom.hex(16), state: SecureRandom.hex(16) + expect(response.body).to match("Diaspora Test Client") + end + end + + context "as a request object" do + it "should return a form page" do + header = JWT.encoded_header("none") + payload_hash = {client_id: client.client_id, redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", nonce: "hello", state: "hello", + claims: {userinfo: {name: {essential: true}}}} + payload = JWT.encoded_payload(JSON.parse(payload_hash.to_json)) + request_object = header + "." + payload + "." + get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token", + scope: "openid", nonce: "hello", state: "hello", request: request_object + expect(response.body).to match("Diaspora Test Client") + end + end + + context "as a request object with no claims" do + it "should return a form page" do + header = JWT.encoded_header("none") + payload_hash = {client_id: client.client_id, redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", nonce: "hello", state: "hello"} + payload = JWT.encoded_payload(JSON.parse(payload_hash.to_json)) + request_object = header + "." + payload + "." + get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token", + scope: "openid", nonce: "hello", state: "hello", request: request_object + expect(response.body).to match("Diaspora Test Client") + end + end + + context "as POST request" do + it "should return a form page" do + post :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token", + scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16) + expect(response.body).to match("Diaspora Test Client") + end + end + end + + context "when client id is missing" do + it "should return an bad request error" do + post :new, redirect_uri: "http://localhost:3000/", response_type: "id_token", + scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16) + expect(response.body).to include("The request was malformed") + end + end + + context "when redirect uri is missing" do + context "when only one redirect URL is pre-registered" do + it "should return a form page" do + # Note this intentionally behavior diverts from OIDC spec http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + # When client has only one redirect uri registered, only that redirect uri can be used. Hence, + # we should implicitly assume the client wants to use that registered URI. + # See https://github.com/nov/rack-oauth2/blob/master/lib/rack/oauth2/server/authorize.rb#L63 + post :new, client_id: client.client_id, response_type: "id_token", + scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16) + expect(response.body).to match("Diaspora Test Client") + end + end + end + + context "when multiple redirect URLs are pre-registered" do + it "should return an invalid request error" do + post :new, client_id: client_with_multiple_redirects.client_id, response_type: "id_token", + scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16) + expect(response.body).to include("The request was malformed") + end + end + + context "when redirect URI does not match pre-registered URIs" do + it "should return an invalid request error" do + post :new, client_id: client.client_id, redirect_uri: "http://localhost:2000/", + response_type: "id_token", scope: "openid", nonce: SecureRandom.hex(16) + expect(response.body).to include("Invalid client id or redirect uri") + end + end + + context "when an unsupported scope is passed in" do + it "should return an invalid scope error" do + post :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token", + scope: "random", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16) + expect(response.body).to match("error=invalid_scope") + end + end + + context "when nonce is missing" do + it "should return an invalid request error" do + post :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", state: SecureRandom.hex(16) + expect(response.location).to match("error=invalid_request") + end + end + + context "when prompt is none" do + it "should return an interaction required error" do + post :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none" + expect(response.body).to include("User must already be authorized when `prompt` is `none`") + end + end + + context "when prompt is none and user not signed in" do + before do + sign_out :user + end + + it "should return an interaction required error" do + post :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none" + expect(response.body).to include("User must already be logged in when `prompt` is `none`") + end + end + + context "when prompt is none and consent" do + it "should return an interaction required error" do + post :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none consent" + expect(response.location).to match("error=invalid_request") + end + end + + context "when prompt is select_account" do + it "should return an account_selection_required error" do + post :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "select_account" + expect(response.location).to match("error=account_selection_required") + expect(response.location).to match("state=1234") + end + end + + context "when prompt is none and client ID is invalid" do + it "should return an account_selection_required error" do + post :new, client_id: "random", redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none" + expect(response.body).to include("Invalid client id or redirect uri") + end + end + + context "when prompt is none and redirect URI does not match pre-registered URIs" do + it "should return an account_selection_required error" do + post :new, client_id: client.client_id, redirect_uri: "http://randomuri:3000/", + response_type: "id_token", scope: "openid", state: 1234, display: "page", prompt: "none" + expect(response.body).to include("Invalid client id or redirect uri") + end + end + + context "when XSS script is passed as name" do + it "should escape html" do + post :new, client_id: client_with_xss.client_id, redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", nonce: SecureRandom.hex(16), state: SecureRandom.hex(16) + expect(response.body).to_not include("<script>alert(0);</script>") + end + end + end + + context "when already authorized" do + before do + Api::OpenidConnect::Authorization.create!( + o_auth_application: client, user: alice, redirect_uri: "http://localhost:3000/", scopes: ["openid"]) + end + + context "when valid parameters are passed" do + before do + get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token", + scope: "openid", nonce: 413_093_098_3, state: 413_093_098_3 + end + + it "should return the id token in a fragment" do + expect(response.location).to have_content("id_token=") + encoded_id_token = response.location[/(?<=id_token=)[^&]+/] + decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, + Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY + expect(decoded_token.nonce).to eq("4130930983") + expect(decoded_token.exp).to be > Time.zone.now.utc.to_i + end + + it "should return the passed in state" do + expect(response.location).to have_content("state=4130930983") + end + end + + context "when prompt is none" do + it "should return the id token in a fragment" do + post :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", nonce: 413_093_098_3, state: 413_093_098_3, + display: "page", prompt: "none" + expect(response.location).to have_content("id_token=") + encoded_id_token = response.location[/(?<=id_token=)[^&]+/] + decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, + Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY + expect(decoded_token.nonce).to eq("4130930983") + expect(decoded_token.exp).to be > Time.zone.now.utc.to_i + end + end + + context "when prompt contains consent" do + it "should return a consent form page" do + get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", + response_type: "id_token", scope: "openid", nonce: 413_093_098_3, state: 413_093_098_3, + display: "page", prompt: "consent" + expect(response.body).to match("Diaspora Test Client") + end + end + + context "when scopes are escalated" do + before do + get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token", + scope: "openid read", nonce: 413_093_098_3, state: 413_093_098_3 + end + + it "should receive another authorization request" do + expect(response.body).to match("Diaspora Test Client") + end + + it "should overwrite old authorization scope after approval" do + post :create, approve: "true" + authorization_with_old_scope = + Api::OpenidConnect::Authorization.find_by_client_id_user_and_scopes(client.client_id, alice, ["openid"]) + expect(authorization_with_old_scope).to be_nil + end + end + end + end + + describe "#create" do + context "when id_token token" do + before do + get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token token", + scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3 + end + + context "when authorization is approved" do + before do + post :create, approve: "true" + end + + it "should return the id token in a fragment" do + encoded_id_token = response.location[/(?<=id_token=)[^&]+/] + decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, + Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY + expect(decoded_token.nonce).to eq("4180930983") + expect(decoded_token.exp).to be > Time.zone.now.utc.to_i + end + + it "should return a valid access token in a fragment" do + encoded_id_token = response.location[/(?<=id_token=)[^&]+/] + decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, + Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY + access_token = response.location[/(?<=access_token=)[^&]+/] + access_token_check_num = UrlSafeBase64.encode64(OpenSSL::Digest::SHA256.digest(access_token)[0, 128 / 8]) + expect(decoded_token.at_hash).to eq(access_token_check_num) + end + end + end + + context "when id_token" do + before do + get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token", + scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3 + end + + context "when authorization is approved" do + before do + post :create, approve: "true" + end + + it "should return the id token in a fragment" do + expect(response.location).to have_content("id_token=") + encoded_id_token = response.location[/(?<=id_token=)[^&]+/] + decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, + Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY + expect(decoded_token.nonce).to eq("4180930983") + expect(decoded_token.exp).to be > Time.zone.now.utc.to_i + end + + it "should return the passed in state" do + expect(response.location).to have_content("state=4180930983") + end + end + + context "when authorization is denied" do + before do + post :create, approve: "false" + end + + it "should return an error in the fragment" do + expect(response.location).to have_content("error=") + end + + it "should NOT contain a id token in the fragment" do + expect(response.location).to_not have_content("id_token=") + end + end + end + + context "when code" do + before do + get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "code", + scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3 + end + + context "when authorization is approved" do + before do + post :create, approve: "true" + end + + it "should return the code" do + expect(response.location).to have_content("code") + end + + it "should return the passed in state" do + expect(response.location).to have_content("state=4180930983") + end + end + + context "when authorization is denied" do + before do + post :create, approve: "false" + end + + it "should return an error" do + expect(response.location).to have_content("error") + end + + it "should NOT contain code" do + expect(response.location).to_not have_content("code") + end + end + end + end + + describe "#destroy" do + let!(:auth_with_read) { FactoryGirl.create(:auth_with_read) } + + context "with existent authorization" do + before do + delete :destroy, id: auth_with_read.id + end + + it "removes the authorization" do + expect(Api::OpenidConnect::Authorization.find_by(id: auth_with_read.id)).to be_nil + end + end + + context "with non-existent authorization" do + it "raises an error" do + delete :destroy, id: 123_456_789 + expect(response).to redirect_to(api_openid_connect_user_applications_url) + expect(flash[:error]).to eq("The attempt to revoke the authorization with ID 123456789 failed") + end + end + end +end diff --git a/spec/controllers/api/openid_connect/clients_controller_spec.rb b/spec/controllers/api/openid_connect/clients_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..164c82bce6c4bf8e386ef16713fb2016133de58b --- /dev/null +++ b/spec/controllers/api/openid_connect/clients_controller_spec.rb @@ -0,0 +1,141 @@ +require "spec_helper" + +describe Api::OpenidConnect::ClientsController, type: :controller do + describe "#create" do + context "when valid parameters are passed" do + it "should return a client id" do + stub_request(:get, "http://example.com/uris") + .with(headers: { + "Accept" => "*/*", + "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3", + "User-Agent" => "Faraday v0.9.2" + }) + .to_return(status: 200, body: "[\"http://localhost\"]", headers: {}) + post :create, redirect_uris: ["http://localhost"], client_name: "diaspora client", + response_types: [], grant_types: [], application_type: "web", contacts: [], + logo_uri: "http://example.com/logo.png", client_uri: "http://example.com/client", + policy_uri: "http://example.com/policy", tos_uri: "http://example.com/tos", + sector_identifier_uri: "http://example.com/uris", subject_type: "pairwise" + client_json = JSON.parse(response.body) + expect(client_json["client_id"].length).to eq(32) + expect(client_json["ppid"]).to eq(true) + end + end + + context "when valid parameters with jwks is passed" do + it "should return a client id" do + stub_request(:get, "http://example.com/uris") + .with(headers: { + "Accept" => "*/*", + "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3", + "User-Agent" => "Faraday v0.9.2"}) + .to_return(status: 200, body: "[\"http://localhost\"]", headers: {}) + post :create, redirect_uris: ["http://localhost"], client_name: "diaspora client", + response_types: [], grant_types: [], application_type: "web", contacts: [], + logo_uri: "http://example.com/logo.png", client_uri: "http://example.com/client", + policy_uri: "http://example.com/policy", tos_uri: "http://example.com/tos", + sector_identifier_uri: "http://example.com/uris", subject_type: "pairwise", + token_endpoint_auth_method: "private_key_jwt", + jwks: { + keys: + [ + { + use: "enc", + e: "AQAB", + d: "-lTBWkI-----lvCO6tuiDsR4qgJnUwnndQFwEI_4mLmD3iNWXrc8N--5Cjq55eLtuJjtvuQ", + n: "--zYRQNDvIVsBDLQQIgrbctuGqj6lrXb31Jj3JIEYqH_4h5X9d0Q", + q: "1q-r----pFtyTz_JksYYaotc_Z3Zy-Szw6a39IDbuYGy1qL-15oQuc", + p: "-BfRjdgYouy4c6xAnGDgSMTip1YnPRyvbMaoYT9E_tEcBW5wOeoc", + kid: "a0", + kty: "RSA" + }, + { + use: "sig", + e: "AQAB", + d: "--x-gW---LRPowKrdvTuTo2p--HMI0pIEeFs7H_u5OW3jihjvoFClGPynHQhgWmQzlQRvWRXh6FhDVqFeGQ", + n: "---TyeadDqQPWgbqX69UzcGq5irhzN8cpZ_JaTk3Y_uV6owanTZLVvCgdjaAnMYeZhb0KFw", + q: "5E5XKK5njT--Hx3nF5sne5fleVfU-sZy6Za4B2U75PcE62oZgCPauOTAEm9Xuvrt5aMMovyzR8ecJZhm9bw7naU", + p: "-BUGA-", + kid: "a1", + kty: "RSA"}, + { + use: "sig", + crv: "P-256", + kty: "EC", + y: "Yg4IRzHBMIsuQK2Oz0Uukp1aNDnpdoyk6QBMtmfGHQQ", + x: "L0WUeVlc9r6YJd6ie9duvOU1RHwxSkJKA37IK9B4Bpc", + kid: "a2" + }, + { + use: "enc", + crv: "P-256", + kty: "EC", + y: "E6E6g5_ziIZvfdAoACctnwOhuQYMvQzA259aftPn59M", + x: "Yu8_BQE2L0f1MqnK0GumZOaj_77Tx70-LoudyRUnLM4", + kid: "a3" + } + ] + } + client_json = JSON.parse(response.body) + expect(client_json["client_id"].length).to eq(32) + expect(client_json["ppid"]).to eq(true) + end + end + + context "when valid parameters with jwks_uri is passed" do + it "should return a client id" do + stub_request(:get, "http://example.com/uris") + .with(headers: {"Accept" => "*/*", + "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3", + "User-Agent" => "Faraday v0.9.2"}) + .to_return(status: 200, body: "[\"http://localhost\"]", headers: {}) + stub_request(:get, "https://kentshikama.com/api/openid_connect/jwks.json") + .with(headers: {"Accept" => "*/*", + "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3", + "User-Agent" => "Faraday v0.9.2"}) + .to_return(status: 200, + body: "{\"keys\":[{\"kty\":\"RSA\",\"e\":\"AQAB\",\"n\":\"qpW\",\"use\":\"sig\"}]}", headers: {}) + post :create, redirect_uris: ["http://localhost"], client_name: "diaspora client", + response_types: [], grant_types: [], application_type: "web", contacts: [], + logo_uri: "http://example.com/logo.png", client_uri: "http://example.com/client", + policy_uri: "http://example.com/policy", tos_uri: "http://example.com/tos", + sector_identifier_uri: "http://example.com/uris", subject_type: "pairwise", + token_endpoint_auth_method: "private_key_jwt", + jwks_uri: "https://kentshikama.com/api/openid_connect/jwks.json" + client_json = JSON.parse(response.body) + expect(client_json["client_id"].length).to eq(32) + expect(client_json["ppid"]).to eq(true) + end + end + + context "when redirect uri is missing" do + it "should return a invalid_client_metadata error" do + post :create, response_types: [], grant_types: [], application_type: "web", contacts: [], + logo_uri: "http://example.com/logo.png", client_uri: "http://example.com/client", + policy_uri: "http://example.com/policy", tos_uri: "http://example.com/tos" + client_json = JSON.parse(response.body) + expect(client_json["error"]).to have_content("invalid_client_metadata") + end + end + end + + describe "#find" do + let!(:client) { FactoryGirl.create(:o_auth_application) } + + context "when an OIDC client already exists" do + it "should return a client id" do + get :find, client_name: client.client_name + client_id_json = JSON.parse(response.body) + expect(client_id_json["client_id"]).to eq(client.client_id) + end + end + + context "when an OIDC client doesn't already exist" do + it "should return the appropriate error" do + get :find, client_name: "random_name" + client_id_json = JSON.parse(response.body) + expect(client_id_json["error"]).to eq("Client with name random_name does not exist") + end + end + end +end diff --git a/spec/controllers/api/openid_connect/discovery_controller_spec.rb b/spec/controllers/api/openid_connect/discovery_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..19b90d6c5b26435d8d4f25c4aadd619385c61eed --- /dev/null +++ b/spec/controllers/api/openid_connect/discovery_controller_spec.rb @@ -0,0 +1,35 @@ +require "spec_helper" + +describe Api::OpenidConnect::DiscoveryController, type: :controller do + describe "#webfinger" do + before do + get :webfinger, resource: "http://example.com/bob" + end + + it "should return a url to the openid-configuration" do + json_body = JSON.parse(response.body) + expect(json_body["links"].first["href"]).to eq(root_url) + end + + it "should return the resource in the subject" do + json_body = JSON.parse(response.body) + expect(json_body["subject"]).to eq("http://example.com/bob") + end + end + + describe "#configuration" do + before do + get :configuration + end + + it "should have the issuer as the root url" do + json_body = JSON.parse(response.body) + expect(json_body["issuer"]).to eq(root_url) + end + + it "should have the appropriate user info endpoint" do + json_body = JSON.parse(response.body) + expect(json_body["userinfo_endpoint"]).to eq(api_openid_connect_user_info_url) + end + end +end diff --git a/spec/controllers/api/openid_connect/id_tokens_controller_spec.rb b/spec/controllers/api/openid_connect/id_tokens_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..ec8ab8643dc4e510a4b5fdf0502d28707532f510 --- /dev/null +++ b/spec/controllers/api/openid_connect/id_tokens_controller_spec.rb @@ -0,0 +1,19 @@ +require "spec_helper" + +describe Api::OpenidConnect::IdTokensController, type: :controller do + describe "#jwks" do + before do + get :jwks + end + + it "should contain a public key that matches the internal private key" do + json = JSON.parse(response.body).with_indifferent_access + jwks = JSON::JWK::Set.new json[:keys] + public_keys = jwks.map do |jwk| + JSON::JWK.new(jwk).to_key + end + public_key = public_keys.first + expect(Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY.to_s).to eq(public_key.to_s) + end + end +end diff --git a/spec/controllers/api/openid_connect/user_applications_spec.rb b/spec/controllers/api/openid_connect/user_applications_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..588384159ce55199e64897d311c76fa89461f2c2 --- /dev/null +++ b/spec/controllers/api/openid_connect/user_applications_spec.rb @@ -0,0 +1,17 @@ +require "spec_helper" + +describe Api::OpenidConnect::UserApplicationsController, type: :controller do + before do + @app = FactoryGirl.create(:o_auth_application_with_xss) + @user = FactoryGirl.create :user + FactoryGirl.create :auth_with_read, user: @user, o_auth_application: @app + sign_in @user, scope: :user + end + + context "when try to XSS" do + it "should not include XSS script" do + get :index + expect(response.body).to_not include("<script>alert(0);</script>") + end + end +end diff --git a/spec/controllers/aspect_memberships_controller_spec.rb b/spec/controllers/aspect_memberships_controller_spec.rb index 848560381e275d6974854b2c30f18b79ceafb0fd..78c0adfd656db89d28e6ac71e633c478692517d1 100644 --- a/spec/controllers/aspect_memberships_controller_spec.rb +++ b/spec/controllers/aspect_memberships_controller_spec.rb @@ -13,7 +13,7 @@ describe AspectMembershipsController, type: :controller do @contact = alice.contact_for(bob.person) alice.getting_started = false alice.save - sign_in :user, alice + sign_in alice, scope: :user allow(@controller).to receive(:current_user).and_return(alice) request.env["HTTP_REFERER"] = "http://" + request.host end diff --git a/spec/controllers/aspects_controller_spec.rb b/spec/controllers/aspects_controller_spec.rb index 779e510dee0f50f2078f64464f16043b10b949ca..c8f971ae10f7e4038b425c6be3fc1814bf5cb825 100644 --- a/spec/controllers/aspects_controller_spec.rb +++ b/spec/controllers/aspects_controller_spec.rb @@ -8,7 +8,7 @@ describe AspectsController, :type => :controller do before do alice.getting_started = false alice.save - sign_in :user, alice + sign_in alice, scope: :user @alices_aspect_1 = alice.aspects.where(:name => "generic").first @alices_aspect_2 = alice.aspects.create(:name => "another aspect") diff --git a/spec/controllers/blocks_controller_spec.rb b/spec/controllers/blocks_controller_spec.rb index fe733cf8d41787d16f1f98908e5bdc5b6e2a267a..1937c1e2d6a013046955052b67baffa312aba969 100644 --- a/spec/controllers/blocks_controller_spec.rb +++ b/spec/controllers/blocks_controller_spec.rb @@ -55,7 +55,7 @@ describe BlocksController, :type => :controller do it "calls disconnect with the force option if there is a contact for a given user" do contact = alice.contact_for(bob.person) allow(alice).to receive(:contact_for).and_return(contact) - expect(alice).to receive(:disconnect).with(contact, hash_including(:force => true)) + expect(alice).to receive(:disconnect).with(contact) @controller.send(:disconnect_if_contact, bob.person) end diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb index adb2ec1ec16d3e6295c27a0ce32048856ccc8fea..39492d19198718c88cd9fcc3ac6d7fb2e238b6fd 100644 --- a/spec/controllers/comments_controller_spec.rb +++ b/spec/controllers/comments_controller_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' describe CommentsController, :type => :controller do before do allow(@controller).to receive(:current_user).and_return(alice) - sign_in :user, alice + sign_in alice, scope: :user end describe '#create' do @@ -79,7 +79,7 @@ describe CommentsController, :type => :controller do context 'your post' do before do allow(@controller).to receive(:current_user).and_return(bob) - sign_in :user, bob + sign_in bob, scope: :user end it 'lets the user delete his comment' do @@ -140,7 +140,7 @@ describe CommentsController, :type => :controller do comments = [alice, bob, eve].map{ |u| u.comment!(@message, "hey") } get :index, :post_id => @message.id, :format => :json - expect(assigns[:comments].map(&:id)).to match_array(comments.map(&:id)) + expect(JSON.parse(response.body).map {|comment| comment["id"] }).to match_array(comments.map(&:id)) end it 'returns a 404 on a nonexistent post' do diff --git a/spec/controllers/contacts_controller_spec.rb b/spec/controllers/contacts_controller_spec.rb index 5b70a00147d5f963baf47a0cd37054b29d33e0df..7a8ab7a13c80cc47602f9c4022383c8f6b5462dc 100644 --- a/spec/controllers/contacts_controller_spec.rb +++ b/spec/controllers/contacts_controller_spec.rb @@ -6,7 +6,7 @@ require 'spec_helper' describe ContactsController, :type => :controller do before do - sign_in :user, bob + sign_in bob, scope: :user allow(@controller).to receive(:current_user).and_return(bob) end @@ -24,50 +24,97 @@ describe ContactsController, :type => :controller do expect(response).to be_success end - it "assigns contacts" do + it "doesn't assign contacts" do get :index contacts = assigns(:contacts) - expect(contacts.to_set).to eq(bob.contacts.to_set) + expect(contacts).to be_nil end + end - it "shows only contacts a user is sharing with" do - contact = bob.contacts.first - contact.update_attributes(:sharing => false) + context "format json" do + context "for the contacts search" do + before do + @person1 = FactoryGirl.create(:person) + bob.share_with(@person1, bob.aspects.first) + @person2 = FactoryGirl.create(:person) + end - get :index - contacts = assigns(:contacts) - expect(contacts.to_set).to eq(bob.contacts.receiving.to_set) - end + it "succeeds" do + get :index, q: @person1.first_name, format: "json" + expect(response).to be_success + end - it "shows all contacts (sharing and receiving)" do - contact = bob.contacts.first - contact.update_attributes(:sharing => false) + it "responds with json" do + get :index, q: @person1.first_name, format: "json" + expect(response.body).to eq([@person1].to_json) + end - get :index, :set => "all" - contacts = assigns(:contacts) - expect(contacts.to_set).to eq(bob.contacts.to_set) + it "only returns contacts" do + get :index, q: @person2.first_name, format: "json" + expect(response.body).to eq([].to_json) + end end - end - context 'format json' do - it 'assumes all aspects if none are specified' do - get :index, :format => 'json' - expect(assigns[:people].map(&:id)).to match_array(bob.contacts.map { |c| c.person.id }) - expect(response).to be_success - end + context "for pagination on the contacts page" do + context "without parameters" do + it "returns contacts" do + get :index, format: "json", page: "1" + contact_ids = JSON.parse(response.body).map {|c| c["id"] } + expect(contact_ids.to_set).to eq(bob.contacts.map(&:id).to_set) + end - it 'returns the contacts for multiple aspects' do - get :index, :aspect_ids => bob.aspect_ids, :format => 'json' - expect(assigns[:people].map(&:id)).to match_array(bob.contacts.map { |c| c.person.id }) - expect(response).to be_success - end + it "returns only contacts which are receiving (the user is sharing with them)" do + contact = bob.contacts.first + contact.update_attributes(receiving: false) + + get :index, format: "json", page: "1" + contact_ids = JSON.parse(response.body).map {|c| c["id"] } + expect(contact_ids.to_set).to eq(bob.contacts.receiving.map(&:id).to_set) + expect(contact_ids).not_to include(contact.id) + end + end + + context "set: all" do + before do + contact = bob.contacts.first + contact.update_attributes(receiving: false) + end + + it "returns all contacts (sharing and receiving)" do + get :index, format: "json", page: "1", set: "all" + contact_ids = JSON.parse(response.body).map {|c| c["id"] } + expect(contact_ids.to_set).to eq(bob.contacts.map(&:id).to_set) + end + + it "sorts contacts by receiving status" do + get :index, format: "json", page: "1", set: "all" + contact_ids = JSON.parse(response.body).map {|c| c["id"] } + expect(contact_ids).to eq(bob.contacts.order("receiving DESC").map(&:id)) + expect(contact_ids.last).to eq(bob.contacts.first.id) + end + end + + context "with an aspect id" do + before do + @aspect = bob.aspects.create(name: "awesome contacts") + @person = FactoryGirl.create(:person) + bob.share_with(@person, @aspect) + end + + it "returns all contacts" do + get :index, format: "json", a_id: @aspect.id, page: "1" + contact_ids = JSON.parse(response.body).map {|c| c["id"] } + expect(contact_ids.to_set).to eq(bob.contacts.map(&:id).to_set) + end + + it "sorts contacts by aspect memberships" do + get :index, format: "json", a_id: @aspect.id, page: "1" + expect(JSON.parse(response.body).first["person"]["id"]).to eq(@person.id) - it 'does not return duplicate contacts' do - aspect = bob.aspects.create(:name => 'hilarious people') - aspect.contacts << bob.contact_for(eve.person) - get :index, :format => 'json', :aspect_ids => bob.aspect_ids - expect(assigns[:people].map { |p| p.id }.uniq).to eq(assigns[:people].map { |p| p.id }) - expect(assigns[:people].map(&:id)).to match_array(bob.contacts.map { |c| c.person.id }) + get :index, format: "json", a_id: bob.aspects.first.id, page: "1" + expect(JSON.parse(response.body).first["person"]["id"]).not_to eq(@person.id) + end + end end end end diff --git a/spec/controllers/conversation_visibilities_controller_spec.rb b/spec/controllers/conversation_visibilities_controller_spec.rb index 24d60addaf28fa33784930d8a2204073f2037aac..f9dc655bd2546068183620de5cacbaf2291c1d10 100644 --- a/spec/controllers/conversation_visibilities_controller_spec.rb +++ b/spec/controllers/conversation_visibilities_controller_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' describe ConversationVisibilitiesController, :type => :controller do before do @user1 = alice - sign_in :user, @user1 + sign_in @user1, scope: :user hash = { :author => @user1.person, @@ -27,22 +27,22 @@ describe ConversationVisibilitiesController, :type => :controller do it 'does not let a user destroy a visibility that is not theirs' do user2 = eve - sign_in :user, user2 + sign_in user2, scope: :user expect { delete :destroy, :conversation_id => @conversation.id }.not_to change(ConversationVisibility, :count) end - + it 'returns "hidden"' do get :destroy, :conversation_id => @conversation.id expect(flash.notice).to include("hidden") end - + it 'returns "deleted" when last participant' do get :destroy, :conversation_id => @conversation.id sign_out :user - sign_in :user, bob + sign_in bob, scope: :user get :destroy, :conversation_id => @conversation.id expect(flash.notice).to include("deleted") end diff --git a/spec/controllers/conversations_controller_spec.rb b/spec/controllers/conversations_controller_spec.rb index 868649c629ab5dab2443bb2b344cb032043a7ff4..2dd8681c9702091222b5f18730a7607eb83a5220 100644 --- a/spec/controllers/conversations_controller_spec.rb +++ b/spec/controllers/conversations_controller_spec.rb @@ -6,7 +6,7 @@ require 'spec_helper' describe ConversationsController, :type => :controller do before do - sign_in :user, alice + sign_in alice, scope: :user end describe '#new' do @@ -23,10 +23,13 @@ describe ConversationsController, :type => :controller do end it "assigns a json list of contacts that are sharing with the person" do + sharing_user = FactoryGirl.create(:user_with_aspect) + sharing_user.share_with(alice.person, sharing_user.aspects.first) get :new, :modal => true - expect(assigns(:contacts_json)).to include(alice.contacts.where(:sharing => true).first.person.name) + expect(assigns(:contacts_json)).to include(alice.contacts.where(sharing: true, receiving: true).first.person.name) alice.contacts << Contact.new(:person_id => eve.person.id, :user_id => alice.id, :sharing => false, :receiving => true) - expect(assigns(:contacts_json)).not_to include(alice.contacts.where(:sharing => false).first.person.name) + expect(assigns(:contacts_json)).not_to include(alice.contacts.where(sharing: false).first.person.name) + expect(assigns(:contacts_json)).not_to include(alice.contacts.where(receiving: false).first.person.name) end it "assigns a contact if passed a contact id" do @@ -64,7 +67,7 @@ describe ConversationsController, :type => :controller do author: alice.person, participant_ids: [alice.contacts.first.person.id, alice.person.id], subject: "not spam", - messages_attributes: [{author: alice.person, text: "cool stuff"}] + messages_attributes: [{author: alice.person, text: "**cool stuff**"}] } @conversations = Array.new(3) { Conversation.create(hash) } @visibilities = @conversations.map {|conversation| @@ -98,10 +101,18 @@ describe ConversationsController, :type => :controller do end it "does not let you access conversations where you are not a recipient" do - sign_in :user, eve + sign_in eve, scope: :user get :index, conversation_id: @conversations.first.id expect(assigns[:conversation]).to be_nil end + + it "retrieves a conversation message with out markdown content " do + get :index + @conversation = @conversations.first + expect(response).to be_success + expect(response.body).to match(/cool stuff/) + expect(response.body).not_to match(%r{<strong>cool stuff</strong>}) + end end describe '#create' do @@ -153,9 +164,7 @@ describe ConversationsController, :type => :controller do } ) - p = Postzord::Dispatcher.build(alice, cnv) - allow(p.class).to receive(:new).and_return(p) - expect(p).to receive(:post) + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch) post :create, @hash end end diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..4d012e4eb958932c588f0e73ab6b93224ff7f77a --- /dev/null +++ b/spec/controllers/help_controller_spec.rb @@ -0,0 +1,16 @@ +require "spec_helper" + +describe HelpController, type: :controller do + describe "#faq" do + it "succeeds" do + get :faq + expect(response).to be_success + end + + it "fails on mobile" do + expect { + get :faq, format: :mobile + }.to raise_error ActionView::MissingTemplate + end + end +end diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb index 79ed02869b3ed20c87e21c4474a61d9049277890..95cc5c40d03af51b52a97580aebbd981ddf6db01 100644 --- a/spec/controllers/home_controller_spec.rb +++ b/spec/controllers/home_controller_spec.rb @@ -6,25 +6,56 @@ require "spec_helper" describe HomeController, type: :controller do describe "#show" do - it "does not redirect for :html" do + it "does not redirect for :html if there are at least 2 users and an admin" do + allow(User).to receive(:count).and_return(2) + allow(Role).to receive_message_chain(:where, :any?).and_return(true) + allow(Role).to receive_message_chain(:where, :exists?).and_return(true) get :show expect(response).not_to be_redirect end - it "redirects for :mobile" do + it "redirects to the podmin page for :html if there are less than 2 users" do + allow(User).to receive(:count).and_return(1) + allow(Role).to receive_message_chain(:where, :any?).and_return(true) + get :show + expect(response).to redirect_to(podmin_path) + end + + it "redirects to the podmin page for :html if there is no admin" do + allow(User).to receive(:count).and_return(2) + allow(Role).to receive_message_chain(:where, :any?).and_return(false) + get :show + expect(response).to redirect_to(podmin_path) + end + + it "redirects to the podmin page for :html if there are less than 2 users and no admin" do + allow(User).to receive(:count).and_return(0) + allow(Role).to receive_message_chain(:where, :any?).and_return(false) + get :show + expect(response).to redirect_to(podmin_path) + end + + it "redirects to the sign in page for :mobile" do get :show, format: :mobile expect(response).to redirect_to(user_session_path) end - context "redirection" do - before do - sign_in alice - end + it "redirects to the stream if the user is signed in" do + sign_in alice + get :show, home: true + expect(response).to redirect_to(stream_path) + end + end - it "points to the stream if a user has contacts" do - get :show, home: true - expect(response).to redirect_to(stream_path) - end + describe "#podmin" do + it "succeeds" do + get :podmin + expect(response).to be_success + end + + it "succeeds on mobile" do + get :podmin, format: :mobile + expect(response).to be_success end end @@ -41,4 +72,18 @@ describe HomeController, type: :controller do expect(session[:mobile_view]).to be true end end + + describe "#force_mobile" do + it "changes :html to :mobile" do + session[:mobile_view] = nil + get :force_mobile + expect(session[:mobile_view]).to be true + end + + it "keeps :mobile" do + session[:mobile_view] = true + get :force_mobile + expect(session[:mobile_view]).to be true + end + end end diff --git a/spec/controllers/invitations_controller_spec.rb b/spec/controllers/invitations_controller_spec.rb index c0a0bee6845a679aef4a2940e70057ad27ba26e0..00e6b2e8c1ced79e98e30e3a8798507ceb68e8e8 100644 --- a/spec/controllers/invitations_controller_spec.rb +++ b/spec/controllers/invitations_controller_spec.rb @@ -2,164 +2,142 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' - -describe InvitationsController, :type => :controller do - - before do - AppConfig.settings.invitations.open = true - @user = alice - @invite = {'email_inviter' => {'message' => "test", 'emails' => "abc@example.com"}} - end +require "spec_helper" +describe InvitationsController, type: :controller do describe "#create" do + let(:referer) { "http://test.host/cats/foo" } + let(:invite_params) { {email_inviter: {emails: "abc@example.com"}} } + before do - sign_in :user, @user - allow(@controller).to receive(:current_user).and_return(@user) - @referer = 'http://test.host/cats/foo' - request.env["HTTP_REFERER"] = @referer + sign_in alice, scope: :user + request.env["HTTP_REFERER"] = referer end context "no emails" do - before do - @invite = {'email_inviter' => {'message' => "test", 'emails' => ""}} - end + let(:invite_params) { {email_inviter: {emails: ""}} } - it 'does not create an EmailInviter' do + it "does not create an EmailInviter" do expect(Workers::Mail::InviteEmail).not_to receive(:perform_async) - post :create, @invite + post :create, invite_params end - it 'returns to the previous page' do - post :create, @invite - expect(response).to redirect_to @referer + it "returns to the previous page" do + post :create, invite_params + expect(response).to redirect_to referer end - it 'flashes an error' do - post :create, @invite + it "flashes an error" do + post :create, invite_params expect(flash[:error]).to eq(I18n.t("invitations.create.empty")) end end - context 'only valid emails' do - before do - @emails = 'mbs@gmail.com' - @invite = {'email_inviter' => {'message' => "test", 'emails' => @emails}} - end + context "only valid emails" do + let(:emails) { "mbs@gmail.com" } + let(:invite_params) { {email_inviter: {emails: emails}} } - it 'creates an InviteEmail worker' do - inviter = double(:emails => [@emails], :send! => true) - expect(Workers::Mail::InviteEmail).to receive(:perform_async).with(@invite['email_inviter']['emails'], @user.id, @invite['email_inviter']) - post :create, @invite + it "creates an InviteEmail worker" do + expect(Workers::Mail::InviteEmail).to receive(:perform_async).with( + emails, alice.id, invite_params[:email_inviter] + ) + post :create, invite_params end - it 'returns to the previous page on success' do - post :create, @invite - expect(response).to redirect_to @referer + it "returns to the previous page on success" do + post :create, invite_params + expect(response).to redirect_to referer end - it 'flashes a notice' do - post :create, @invite - expected = I18n.t('invitations.create.sent', :emails => @emails.split(',').join(', ')) + it "flashes a notice" do + post :create, invite_params + expected = I18n.t("invitations.create.sent", emails: emails) expect(flash[:notice]).to eq(expected) end end - context 'only invalid emails' do - before do - @emails = 'invalid_email' - @invite = {'email_inviter' => {'message' => "test", 'emails' => @emails}} - end + context "only invalid emails" do + let(:emails) { "invalid_email" } + let(:invite_params) { {email_inviter: {emails: emails}} } - it 'does not create an InviteEmail worker' do + it "does not create an InviteEmail worker" do expect(Workers::Mail::InviteEmail).not_to receive(:perform_async) - post :create, @invite + post :create, invite_params end - it 'returns to the previous page' do - post :create, @invite - expect(response).to redirect_to @referer + it "returns to the previous page" do + post :create, invite_params + expect(response).to redirect_to referer end - it 'flashes an error' do - post :create, @invite + it "flashes an error" do + post :create, invite_params - expected = I18n.t('invitations.create.rejected') + @emails.split(',').join(', ') + expected = I18n.t("invitations.create.rejected", emails: emails) expect(flash[:error]).to eq(expected) end end - context 'mixed valid and invalid emails' do - before do - @valid_emails = 'foo@bar.com,mbs@gmail.com' - @invalid_emails = 'invalid' - @invite = {'email_inviter' => {'message' => "test", 'emails' => - @valid_emails + ',' + @invalid_emails}} - end + context "mixed valid and invalid emails" do + let(:valid_emails) { "foo@bar.com,mbs@gmail.com" } + let(:invalid_emails) { "invalid_email" } + let(:invite_params) { {email_inviter: {emails: valid_emails + "," + invalid_emails}} } - it 'creates an InviteEmail worker' do - inviter = double(:emails => [@emails], :send! => true) - expect(Workers::Mail::InviteEmail).to receive(:perform_async).with(@valid_emails, @user.id, @invite['email_inviter']) - post :create, @invite + it "creates an InviteEmail worker" do + expect(Workers::Mail::InviteEmail).to receive(:perform_async).with( + valid_emails, alice.id, invite_params[:email_inviter] + ) + post :create, invite_params end - it 'returns to the previous page' do - post :create, @invite - expect(response).to redirect_to @referer + it "returns to the previous page" do + post :create, invite_params + expect(response).to redirect_to referer end - it 'flashes a notice' do - post :create, @invite - expected = I18n.t('invitations.create.sent', :emails => - @valid_emails.split(',').join(', ')) + - '. ' + I18n.t('invitations.create.rejected') + - @invalid_emails.split(',').join(', ') + it "flashes a notice" do + post :create, invite_params + expected = I18n.t("invitations.create.sent", emails: valid_emails.split(",").join(", ")) + ". " + + I18n.t("invitations.create.rejected", emails: invalid_emails) expect(flash[:error]).to eq(expected) end end - it 'redirects if invitations are closed' do - AppConfig.settings.invitations.open = false + context "with registration disabled" do + before do + AppConfig.settings.enable_registrations = false + end - post :create, @invite - expect(response).to be_redirect - end - end + it "displays an error if invitations are closed" do + AppConfig.settings.invitations.open = false - describe '#email' do + post :create, invite_params - it 'succeeds' do - get :email, :invitation_code => "anycode" - expect(response).to be_success - end - - context 'legacy invite tokens' do - def get_email - get :email, :invitation_token => @invitation_token + expect(flash[:error]).to eq(I18n.t("invitations.create.closed")) end - context 'invalid token' do - @invitation_token = "invalidtoken" + it "displays an error when no invitations are left" do + alice.invitation_code.update_attributes(count: 0) - it 'redirects and flashes if the invitation token is invalid' do - get_email + post :create, invite_params - expect(response).to be_redirect - expect(response).to redirect_to root_url - end + expect(flash[:error]).to eq(I18n.t("invitations.create.no_more")) + end + end - it 'flashes an error if the invitation token is invalid' do - get_email + it "does not display an error when registration is open" do + AppConfig.settings.invitations.open = false + alice.invitation_code.update_attributes(count: 0) - expect(flash[:error]).to eq(I18n.t("invitations.check_token.not_found")) - end - end + post :create, invite_params + + expect(flash[:error]).to be_nil end end describe '#new' do it 'renders' do - sign_in :user, @user + sign_in alice, scope: :user get :new end end diff --git a/spec/controllers/jasmine_fixtures/admins_spec.rb b/spec/controllers/jasmine_fixtures/admins_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..af4784d221de2664fab9138d01f6bab0f123981b --- /dev/null +++ b/spec/controllers/jasmine_fixtures/admins_spec.rb @@ -0,0 +1,18 @@ +require "spec_helper" + +describe AdminsController, type: :controller do + describe "#dashboard" do + before do + @user = FactoryGirl.create :user + Role.add_admin(@user.person) + sign_in @user, scope: :user + end + + context "jasmine fixtures" do + it "generates a jasmine fixture", fixture: true do + get :dashboard + save_fixture(html_for("body"), "admin_dashboard") + end + end + end +end diff --git a/spec/controllers/jasmine_fixtures/aspects_spec.rb b/spec/controllers/jasmine_fixtures/aspects_spec.rb index 315326f7a7a2c285fa7d66e6e8e249b4676d8404..f3ea2b5bab6454bb4a530fcaa540439670b3b863 100644 --- a/spec/controllers/jasmine_fixtures/aspects_spec.rb +++ b/spec/controllers/jasmine_fixtures/aspects_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' describe StreamsController, :type => :controller do describe '#aspects' do before do - sign_in :user, alice + sign_in alice, scope: :user @alices_aspect_2 = alice.aspects.create(:name => "another aspect") request.env["HTTP_REFERER"] = 'http://' + request.host @@ -58,6 +58,27 @@ describe StreamsController, :type => :controller do save_fixture(html_for("body"), "aspects_index_post_with_comments") end + it "generates a mobile jasmine fixture with a post with comments", fixture: true do + message = bob.post(:status_message, text: "HALO WHIRLED", to: @bob.aspects.where(name: "generic").first.id) + 5.times { bob.comment!(message, "what") } + get :aspects, format: :mobile + save_fixture(html_for("body"), "aspects_index_mobile_post_with_comments") + end + + it "generates a mobile jasmine fixture with a public post", fixture: true do + message = bob.post(:status_message, text: "HALO WHIRLED", public: true) + 5.times { bob.comment!(message, "what") } + get :aspects, format: :mobile + save_fixture(html_for("body"), "aspects_index_mobile_public_post") + end + + it "generates a mobile jasmine fixture with an NSFW post", fixture: true do + message = bob.post(:status_message, text: "#NSFW", to: @bob.aspects.where(name: "generic").first.id) + 5.times { bob.comment!(message, "what") } + get :aspects, format: :mobile + save_fixture(html_for("body"), "aspects_index_mobile_nsfw_post") + end + it 'generates a jasmine fixture with a followed tag', :fixture => true do @tag = ActsAsTaggableOn::Tag.create!(:name => "partytimeexcellent") TagFollowing.create!(:tag => @tag, :user => alice) diff --git a/spec/controllers/jasmine_fixtures/contacts_spec.rb b/spec/controllers/jasmine_fixtures/contacts_spec.rb index 6311c3b34385006c5076909071a6feeeb16f32da..3e6cb3c85e1b3872fd802799c0b5708214a7ff26 100644 --- a/spec/controllers/jasmine_fixtures/contacts_spec.rb +++ b/spec/controllers/jasmine_fixtures/contacts_spec.rb @@ -11,7 +11,7 @@ describe ContactsController, :type => :controller do @aspect = bob.aspects.create(:name => "another aspect") bob.share_with alice.person, @aspect bob.share_with eve.person, @aspect - sign_in :user, bob + sign_in bob, scope: :user end it "generates the aspects_manage fixture", :fixture => true do @@ -19,6 +19,11 @@ describe ContactsController, :type => :controller do save_fixture(html_for("body"), "aspects_manage") end + it "generates the aspects_manage_contacts_json fixture", fixture: true do + get :index, format: :json, a_id: @aspect.id, page: "1" + save_fixture(response.body, "aspects_manage_contacts_json") + end + it "generates the contacts_json fixture", :fixture => true do json = bob.contacts.map { |c| ContactPresenter.new(c, bob).full_hash_with_person diff --git a/spec/controllers/jasmine_fixtures/conversations_spec.rb b/spec/controllers/jasmine_fixtures/conversations_spec.rb index b5d86e66c9a72b53002fbcf37026553456e8b8fd..4c4d317b7186155e6cc566317fa037a5d8fd1a8c 100644 --- a/spec/controllers/jasmine_fixtures/conversations_spec.rb +++ b/spec/controllers/jasmine_fixtures/conversations_spec.rb @@ -20,7 +20,7 @@ describe ConversationsController, :type => :controller do Message.create(:author => @person, :created_at => Time.now + 100, :text => "message", :conversation_id => @conv2.id) .increase_unread(alice) - sign_in :user, alice + sign_in alice, scope: :user end it "generates a jasmine fixture", :fixture => true do diff --git a/spec/controllers/jasmine_fixtures/notifications_spec.rb b/spec/controllers/jasmine_fixtures/notifications_spec.rb index 771d99ec549f7060e9cfd98c5c84a45efeef6def..75f95bc801689465ae95f0851d09e8f87e8eca50 100644 --- a/spec/controllers/jasmine_fixtures/notifications_spec.rb +++ b/spec/controllers/jasmine_fixtures/notifications_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe NotificationsController, :type => :controller do describe '#index' do before do - sign_in :user, alice + sign_in alice, scope: :user @post = FactoryGirl.create(:status_message) FactoryGirl.create(:notification, :recipient => alice, :target => @post) get :read_all diff --git a/spec/controllers/jasmine_fixtures/people_spec.rb b/spec/controllers/jasmine_fixtures/people_spec.rb index 36e66fe0bda0540397ff0ce20c2a0f0db5b47954..eb387f06e724f726ad72bd3b52102a27e43fbcb8 100644 --- a/spec/controllers/jasmine_fixtures/people_spec.rb +++ b/spec/controllers/jasmine_fixtures/people_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' describe PeopleController, :type => :controller do describe '#index' do before do - sign_in :user, bob + sign_in bob, scope: :user end it "generates a jasmine fixture with no query", :fixture => true do @@ -20,17 +20,4 @@ describe PeopleController, :type => :controller do save_fixture(html_for("body"), "pending_external_people_search") end end - - describe '#aspect_membership_dropdown' do - before do - aspect = bob.aspects.create name: 'Testing' - bob.share_with alice.person, aspect - sign_in :user, bob - end - - it "generates a jasmine fixture", :fixture => true do - get :aspect_membership_dropdown, :person_id => alice.person.guid - save_fixture(html_for("body"), "aspect_membership_dropdown") - end - end end diff --git a/spec/controllers/jasmine_fixtures/photos_spec.rb b/spec/controllers/jasmine_fixtures/photos_spec.rb index 79e6868ee5477c30e533538f6940109c8ee7ff2d..cde36c7b205b5f2bff4708525f47f1470a5e28db 100644 --- a/spec/controllers/jasmine_fixtures/photos_spec.rb +++ b/spec/controllers/jasmine_fixtures/photos_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' describe PhotosController, :type => :controller do before do @alices_photo = alice.post(:photo, :user_file => uploaded_photo, :to => alice.aspects.first.id, :public => false) - sign_in :user, alice + sign_in alice, scope: :user end describe '#index' do diff --git a/spec/controllers/jasmine_fixtures/status_messages_spec.rb b/spec/controllers/jasmine_fixtures/status_messages_spec.rb index 66730dfade0dfd7d7154e672e7aca6d670dee782..0787327fff2940fc699b81bd982582ea47627bec 100644 --- a/spec/controllers/jasmine_fixtures/status_messages_spec.rb +++ b/spec/controllers/jasmine_fixtures/status_messages_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' describe StatusMessagesController, :type => :controller do describe '#bookmarklet' do before do - sign_in :user, bob + sign_in bob, scope: :user end it "generates a jasmine fixture", :fixture => true do @@ -19,7 +19,7 @@ describe StatusMessagesController, :type => :controller do describe '#new' do before do - sign_in :user, alice + sign_in alice, scope: :user end it 'generates a jasmine fixture', :fixture => true do diff --git a/spec/controllers/jasmine_fixtures/streams_spec.rb b/spec/controllers/jasmine_fixtures/streams_spec.rb index 94e0cbb032137c8a686f404737f1f7ea6dddc7da..485343c186d2a9e4d4fd9b09977f37c3abc845be 100644 --- a/spec/controllers/jasmine_fixtures/streams_spec.rb +++ b/spec/controllers/jasmine_fixtures/streams_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' describe StreamsController, :type => :controller do describe '#multi' do before do - sign_in :user, alice + sign_in alice, scope: :user end it 'generates the stream_json fixture', :fixture => true do diff --git a/spec/controllers/jasmine_fixtures/users_spec.rb b/spec/controllers/jasmine_fixtures/users_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..9eb2e17b9e765f4f78254065ad22ad2ad02443df --- /dev/null +++ b/spec/controllers/jasmine_fixtures/users_spec.rb @@ -0,0 +1,19 @@ +require "spec_helper" + +describe UsersController, type: :controller do + before do + sign_in alice, scope: :user + end + + describe "#getting_started" do + before do + alice.invited_by = bob + alice.save! + end + + it "generates a jasmine fixture with no query", fixture: true do + get :getting_started + save_fixture(html_for("body"), "getting_started") + end + end +end diff --git a/spec/controllers/likes_controller_spec.rb b/spec/controllers/likes_controller_spec.rb index 725c7f1a8217f30ff274cf642fb03f933723d2bb..066bdc01ae07383bee99dc0858f6adc995b50542 100644 --- a/spec/controllers/likes_controller_spec.rb +++ b/spec/controllers/likes_controller_spec.rb @@ -9,7 +9,7 @@ describe LikesController, :type => :controller do @alices_aspect = alice.aspects.where(:name => "generic").first @bobs_aspect = bob.aspects.where(:name => "generic").first - sign_in :user, alice + sign_in(alice, scope: :user) end [Comment, Post].each do |class_const| diff --git a/spec/controllers/messages_controller_spec.rb b/spec/controllers/messages_controller_spec.rb index c4364ef9e0c5886a736dd31989e4fd5ab2f00320..27e8bfe4fe132fadefcfe4133c8d953002f6c869 100644 --- a/spec/controllers/messages_controller_spec.rb +++ b/spec/controllers/messages_controller_spec.rb @@ -6,7 +6,7 @@ require 'spec_helper' describe MessagesController, :type => :controller do before do - sign_in :user, alice + sign_in(alice, scope: :user) end describe '#create' do @@ -39,6 +39,11 @@ describe MessagesController, :type => :controller do expect(response.status).to eq(302) expect(response).to redirect_to(conversations_path(:conversation_id => @conversation)) end + + it "dispatches the message" do + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, instance_of(Message)) + post :create, @message_params + end end context "with an empty message" do @@ -94,6 +99,24 @@ describe MessagesController, :type => :controller do post :create, @message_params expect(old_message.reload.text).to eq('hello') end + + it "dispatches the message" do + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, instance_of(Message)) + post :create, @message_params + end + + it "dispatches the message twice if the conversation author is local and it has remote users" do + @conversation_params[:participant_ids] = [bob.person.id, alice.person.id, remote_raphael.id] + conversation = Conversation.create!(@conversation_params) + @message_params[:conversation_id] = conversation.id + + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, instance_of(Message)) + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with( + bob, instance_of(Message), subscriber_ids: [remote_raphael.id] + ) + + post :create, @message_params + end end context 'on a post from a stranger' do diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb index c8ef2dc22675629886f192acfec437f478583201..b5e32bb9ef0541fcde1afc253df08ae3a4011859 100644 --- a/spec/controllers/notifications_controller_spec.rb +++ b/spec/controllers/notifications_controller_spec.rb @@ -6,7 +6,7 @@ require 'spec_helper' describe NotificationsController, :type => :controller do before do - sign_in :user, alice + sign_in alice, scope: :user end describe '#update' do @@ -111,7 +111,7 @@ describe NotificationsController, :type => :controller do eve.share_with(alice.person, eve.aspects.first) get :index, "per_page" => 5 - expect(Nokogiri(response.body).css('.aspect_membership')).not_to be_empty + expect(Nokogiri(response.body).css(".aspect_membership_dropdown")).not_to be_empty end it 'succeeds on mobile' do diff --git a/spec/controllers/participations_controller_spec.rb b/spec/controllers/participations_controller_spec.rb index 4262ae5805cdb5eca2b3b4774d1cfd62f21e441c..576c66a7cd87967f9ffcf512b82e7177c12f59fc 100644 --- a/spec/controllers/participations_controller_spec.rb +++ b/spec/controllers/participations_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe ParticipationsController, :type => :controller do before do allow(@controller).to receive(:current_user).and_return(alice) - sign_in :user, alice + sign_in alice, scope: :user end describe '#create' do diff --git a/spec/controllers/passwords_controller_spec.rb b/spec/controllers/passwords_controller_spec.rb index 30794cc07ea7f10c7db40f0641c4af4710dc8aa6..45a55e28b3bef75f6f8578182c285894654fa306 100644 --- a/spec/controllers/passwords_controller_spec.rb +++ b/spec/controllers/passwords_controller_spec.rb @@ -5,8 +5,6 @@ require "spec_helper" describe Devise::PasswordsController, type: :controller do - include Devise::TestHelpers - before do @request.env["devise.mapping"] = Devise.mappings[:user] end diff --git a/spec/controllers/people_controller_spec.rb b/spec/controllers/people_controller_spec.rb index b18751233ef76c9ceb3ea23712a76e8d8b41d68b..977a70475f12d89b2390fc1190dd1ec789cf9a66 100644 --- a/spec/controllers/people_controller_spec.rb +++ b/spec/controllers/people_controller_spec.rb @@ -5,10 +5,12 @@ require 'spec_helper' describe PeopleController, :type => :controller do + include_context :gon + before do @user = alice @aspect = @user.aspects.first - sign_in :user, @user + sign_in @user, scope: :user end describe '#index (search)' do @@ -116,21 +118,6 @@ describe PeopleController, :type => :controller do end end - describe '#tag_index' do - it 'works for js' do - xhr :get, :tag_index, :name => 'jellybeans', :format => :js - expect(response).to be_success - end - - it 'returns awesome people who have that tag' do - f = FactoryGirl.create(:person) - f.profile.tag_string = "#seeded" - f.profile.save - xhr :get, :tag_index, :name => 'seeded', :format => :js - expect(assigns[:people].count).to eq(1) - end - end - describe "#show performance", :performance => true do before do require 'benchmark' @@ -159,6 +146,11 @@ describe PeopleController, :type => :controller do end describe '#show' do + before do + @person = FactoryGirl.create(:user).person + @presenter = PersonPresenter.new(@person, @user) + end + it "404s if the id is invalid" do get :show, :id => 'delicious' expect(response.code).to eq("404") @@ -174,9 +166,15 @@ describe PeopleController, :type => :controller do expect(response.code).to eq("404") end + it "returns a person presenter" do + expect(PersonPresenter).to receive(:new).with(@person, @user).and_return(@presenter) + get :show, username: @person.username + expect(assigns(:presenter).to_json).to eq(@presenter.to_json) + end + it 'finds a person via username' do - get :show, username: @user.username - expect(assigns(:person)).to eq(@user.person) + get :show, username: @person.username + expect(assigns(:presenter).to_json).to eq(@presenter.to_json) end it "404s if no person is found via diaspora handle" do @@ -185,8 +183,8 @@ describe PeopleController, :type => :controller do end it 'finds a person via diaspora handle' do - get :show, username: @user.diaspora_handle - expect(assigns(:person)).to eq(@user.person) + get :show, username: @person.diaspora_handle + expect(assigns(:presenter).to_json).to eq(@presenter.to_json) end it 'redirects home for closed account' do @@ -210,11 +208,11 @@ describe PeopleController, :type => :controller do eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => true) end get :show, :id => eve.person.to_param - expect(response.body).to include '"photos":{"count":16}' + expect(response.body).to include ',"photos_count":16' eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => false) get :show, :id => eve.person.to_param - expect(response.body).to include '"photos":{"count":16}' # eve is not sharing with alice + expect(response.body).to include ',"photos_count":16' # eve is not sharing with alice end context "when the person is the current user" do @@ -229,8 +227,8 @@ describe PeopleController, :type => :controller do end it "assigns the right person" do - get :show, :id => @user.person.to_param - expect(assigns(:person)).to eq(@user.person) + get :show, id: @person.to_param + expect(assigns(:presenter).id).to eq(@presenter.id) end end @@ -262,6 +260,27 @@ describe PeopleController, :type => :controller do get :show, id: @person.to_param expect(response.body).not_to include(@person.profile.bio) end + + it "includes the correct meta tags" do + presenter = PersonPresenter.new(@person) + methods_properties = { + comma_separated_tags: {html_attribute: "name", name: "keywords"}, + url: {html_attribute: "property", name: "og:url"}, + title: {html_attribute: "property", name: "og:title"}, + image_url: {html_attribute: "property", name: "og:image"}, + first_name: {html_attribute: "property", name: "og:profile:first_name"}, + last_name: {html_attribute: "property", name: "og:profile:last_name"} + } + + get :show, id: @person.to_param + + methods_properties.each do |method, property| + value = presenter.send(method) + expect(response.body).to include( + "<meta #{property[:html_attribute]}=\"#{property[:name]}\" content=\"#{value}\" />" + ) + end + end end context "when the person is a contact of the current user" do @@ -292,6 +311,11 @@ describe PeopleController, :type => :controller do get :show, id: @person.to_param expect(response.body).to include(@person.profile.bio) end + + it "preloads data using gon for the aspect memberships dropdown" do + get :show, id: @person.to_param + expect_gon_preloads_for_aspect_membership_dropdown(:person, true) + end end context "when the person is not a contact of the current user" do @@ -313,12 +337,17 @@ describe PeopleController, :type => :controller do get :show, id: @person.to_param expect(response.body).not_to include(@person.profile.bio) end + + it "preloads data using gon for the aspect memberships dropdown" do + get :show, id: @person.to_param + expect_gon_preloads_for_aspect_membership_dropdown(:person, false) + end end context "when the user is following the person" do before do sign_out :user - sign_in :user, peter + sign_in peter, scope: :user @person = alice.person end @@ -456,7 +485,32 @@ describe PeopleController, :type => :controller do it 'returns json with profile stuff' do get :hovercard, :person_id => @hover_test.guid, :format => 'json' - expect(JSON.parse( response.body )['handle']).to eq(@hover_test.diaspora_handle) + expect(JSON.parse(response.body)["diaspora_id"]).to eq(@hover_test.diaspora_handle) + end + + it "returns contact when sharing" do + alice.share_with(@hover_test, alice.aspects.first) + expect(@controller).to receive(:current_user).at_least(:once).and_return(alice) + get :hovercard, person_id: @hover_test.guid, format: "json" + expect(JSON.parse(response.body)["contact"]).not_to be_falsy + end + + context "with no user signed in" do + before do + sign_out :user + end + + it "succeeds with local person" do + get :hovercard, person_id: bob.person.guid, format: :json + expect(response.status).to eq(200) + expect(JSON.parse(response.body)["diaspora_id"]).to eq(bob.diaspora_handle) + end + + it "succeeds with remote person" do + get :hovercard, person_id: remote_raphael.guid, format: :json + expect(response.status).to eq(200) + expect(JSON.parse(response.body)["diaspora_id"]).to eq(remote_raphael.diaspora_handle) + end end end @@ -468,19 +522,20 @@ describe PeopleController, :type => :controller do :profile => FactoryGirl.build(:profile, :first_name => "Evan", :last_name => "Korth")) end - describe 'via json' do - it 'returns a zero count when a search fails' do - get :refresh_search, :q => "weweweKorth", :format => 'json' - expect(response.body).to eq({:search_count=>0, :search_html=>""}.to_json) + describe "via json" do + it "returns no data when a search fails" do + get :refresh_search, q: "weweweKorth", format: "json" + expect(response.body).to eq({search_html: "", contacts: nil}.to_json) end - it 'returns with a zero count unless a fully composed name is sent' do - get :refresh_search, :q => "Korth" - expect(response.body).to eq({:search_count=>0, :search_html=>""}.to_json) + it "returns no data unless a fully composed name is sent" do + get :refresh_search, q: "Korth" + expect(response.body).to eq({search_html: "", contacts: nil}.to_json) end - it 'returns with a found name' do - get :refresh_search, :q => @korth.diaspora_handle - expect(JSON.parse( response.body )["search_count"]).to eq(1) + + it "returns with a found name" do + get :refresh_search, q: @korth.diaspora_handle + expect(JSON.parse(response.body)["contacts"].size).to eq(1) end end end @@ -506,11 +561,11 @@ describe PeopleController, :type => :controller do eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => true) end get :contacts, :person_id => eve.person.to_param - expect(response.body).to include '"photos":{"count":16}' + expect(response.body).to include ',"photos_count":16' eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => false) get :contacts, :person_id => eve.person.to_param - expect(response.body).to include '"photos":{"count":16}' # eve is not sharing with alice + expect(response.body).to include ',"photos_count":16' # eve is not sharing with alice end it "returns a 406 for json format" do diff --git a/spec/controllers/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb index 630735b674bf080fb0f010d11ce2b0e3594df97d..5cad2566b2ccbb7dba880470501ea1c5776095aa 100644 --- a/spec/controllers/photos_controller_spec.rb +++ b/spec/controllers/photos_controller_spec.rb @@ -9,7 +9,7 @@ describe PhotosController, :type => :controller do @alices_photo = alice.post(:photo, :user_file => uploaded_photo, :to => alice.aspects.first.id, :public => false) @bobs_photo = bob.post(:photo, :user_file => uploaded_photo, :to => bob.aspects.first.id, :public => true) - sign_in :user, alice + sign_in alice, scope: :user request.env["HTTP_REFERER"] = '' end @@ -109,11 +109,11 @@ describe PhotosController, :type => :controller do eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => true) end get :index, :person_id => eve.person.to_param - expect(response.body).to include '"photos":{"count":16}' + expect(response.body).to include ',"photos_count":16' eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => false) get :index, :person_id => eve.person.to_param - expect(response.body).to include '"photos":{"count":16}' # eve is not sharing with alice + expect(response.body).to include ',"photos_count":16' # eve is not sharing with alice end it "returns json when requested" do @@ -160,11 +160,11 @@ describe PhotosController, :type => :controller do eve.post(:photo, user_file: uploaded_photo, to: eve.aspects.first.id, public: true) end get :index, person_id: eve.person.to_param - expect(response.body).to include '"photos":{"count":16}' + expect(response.body).to include ',"photos_count":16' eve.post(:photo, user_file: uploaded_photo, to: eve.aspects.first.id, public: false) get :index, person_id: eve.person.to_param - expect(response.body).to include '"photos":{"count":16}' + expect(response.body).to include ',"photos_count":16' end it "displays a person's pictures" do @@ -175,18 +175,6 @@ describe PhotosController, :type => :controller do end end - describe '#edit' do - it "succeeds when user owns the photo" do - get :edit, :id => @alices_photo.id - expect(response).to be_success - end - - it "redirects when the user does not own the photo" do - get :edit, :id => @bobs_photo.id - expect(response).to redirect_to(:action => :index, :person_id => alice.person.guid.to_s) - end - end - describe '#destroy' do it 'let a user delete his message' do delete :destroy, :id => @alices_photo.id @@ -217,33 +205,6 @@ describe PhotosController, :type => :controller do end end - describe "#update" do - it "updates the caption of a photo" do - put :update, :id => @alices_photo.id, :photo => { :text => "now with lasers!" }, :format => :js - expect(@alices_photo.reload.text).to eq("now with lasers!") - end - - it "doesn't allow mass assignment of person" do - new_user = FactoryGirl.create(:user) - params = { :text => "now with lasers!", :author => new_user } - put :update, :id => @alices_photo.id, :photo => params, :format => :js - expect(@alices_photo.reload.author).to eq(alice.person) - end - - it "doesn't allow mass assignment of person_id" do - new_user = FactoryGirl.create(:user) - params = { :text => "now with lasers!", :author_id => new_user.id } - put :update, :id => @alices_photo.id, :photo => params, :format => :js - expect(@alices_photo.reload.author_id).to eq(alice.person.id) - end - - it 'redirects if you do not have access to the post' do - params = { :text => "now with lasers!" } - put :update, :id => @bobs_photo.id, :photo => params - expect(response).to redirect_to(:action => :index, :person_id => alice.person.guid.to_s) - end - end - describe "#make_profile_photo" do it 'should return a 201 on a js success' do xhr :get, :make_profile_photo, :photo_id => @alices_photo.id, :format => 'js' diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb index 8da4502f3dcda0d456f58d4820500648b8f57aab..7c3bb4384852412aa0ee8a44f650197c99f28b09 100644 --- a/spec/controllers/posts_controller_spec.rb +++ b/spec/controllers/posts_controller_spec.rb @@ -5,104 +5,117 @@ require "spec_helper" describe PostsController, type: :controller do - let!(:post_service_double) { double("post_service") } - - before do - aspect = alice.aspects.first - @message = alice.build_post :status_message, text: "ohai", to: aspect.id - @message.save! - - alice.add_to_streams(@message, [aspect]) - alice.dispatch_post @message, to: aspect.id - - allow(PostService).to receive(:new).and_return(post_service_double) - end + let(:post) { alice.post(:status_message, text: "ohai", to: alice.aspects.first) } describe "#show" do - before do - expect(post_service_double).to receive(:mark_user_notifications) - allow(post_service_double).to receive(:present_json) - end - context "user signed in" do context "given a post that the user is allowed to see" do before do - sign_in :user, alice - expect(post_service_double).to receive(:post).and_return(@message) + sign_in alice, scope: :user end it "succeeds" do - get :show, id: @message.id + expect_any_instance_of(PostService).to receive(:mark_user_notifications).with(post.id) + + get :show, id: post.id expect(response).to be_success end - it 'succeeds after removing a mention when closing the mentioned user\'s account' do + it "succeeds after removing a mention when closing the mentioned user's account" do user = FactoryGirl.create(:user, username: "user") alice.share_with(user.person, alice.aspects.first) - msg = alice.build_post :status_message, - text: "Mention @{User ; #{user.diaspora_handle}}", public: true, to: "all" - msg.save! + + msg = alice.post(:status_message, text: "Mention @{User ; #{user.diaspora_handle}}", public: true) + expect(msg.mentioned_people.count).to eq(1) user.destroy + get :show, id: msg.id expect(response).to be_success end it "renders the application layout on mobile" do - get :show, id: @message.id, format: :mobile + get :show, id: post.id, format: :mobile expect(response).to render_template("layouts/application") end it "succeeds on mobile with a reshare" do - get :show, id: FactoryGirl.create(:reshare, author: alice.person).id, format: :mobile + reshare_id = FactoryGirl.create(:reshare, author: alice.person).id + expect_any_instance_of(PostService).to receive(:mark_user_notifications).with(reshare_id) + + get :show, id: reshare_id, format: :mobile expect(response).to be_success end end context "given a post that the user is not allowed to see" do before do - sign_in :user, alice - expect(post_service_double).to receive(:post).and_raise(Diaspora::NonPublic) + sign_in eve, scope: :user end it "returns a 404" do - get :show, id: @message.id - expect(response.code).to eq("404") + expect { + get :show, id: post.id + }.to raise_error ActiveRecord::RecordNotFound end end end context "user not signed in" do context "given a public post" do - before :each do - @status = alice.post(:status_message, text: "hello", public: true, to: "all") - expect(post_service_double).to receive(:post).and_return(@status) - end + let(:public) { alice.post(:status_message, text: "hello", public: true) } + let(:public_with_tags) { alice.post(:status_message, text: "#hi #howareyou", public: true) } it "shows a public post" do - get :show, id: @status.id + get :show, id: public.id expect(response.body).to match "hello" end it "succeeds for statusnet" do @request.env["HTTP_ACCEPT"] = "application/html+xml,text/html" - get :show, id: @status.id + get :show, id: public.id expect(response.body).to match "hello" end it "responds with diaspora xml if format is xml" do - get :show, id: @status.guid, format: :xml - expect(response.body).to eq(@status.to_diaspora_xml) + get :show, id: public.guid, format: :xml + expected_xml = DiasporaFederation::Salmon::XmlPayload.pack(Diaspora::Federation::Entities.post(public)).to_xml + expect(response.body).to eq(expected_xml) end - end - context "given a limited post" do - before do - expect(post_service_double).to receive(:post).and_raise(Diaspora::NonPublic) + it "includes the correct uniques meta tags" do + presenter = PostPresenter.new(public) + methods_properties = { + comma_separated_tags: {html_attribute: "name", name: "keywords"}, + description: {html_attribute: "name", name: "description"}, + url: {html_attribute: "property", name: "og:url"}, + title: {html_attribute: "property", name: "og:title"}, + published_time_iso8601: {html_attribute: "property", name: "og:article:published_time"}, + modified_time_iso8601: {html_attribute: "property", name: "og:article:modified_time"}, + author_name: {html_attribute: "property", name: "og:article:author"} + } + + get :show, id: public.id, format: :html + + methods_properties.each do |method, property| + value = presenter.send(method) + expect(response.body).to include( + "<meta #{property[:html_attribute]}=\"#{property[:name]}\" content=\"#{value}\" />" + ) + end end + it "includes the correct multiple meta tags" do + get :show, id: public_with_tags.id, format: :html + + expect(response.body).to include('<meta property="og:article:tag" content="hi" />') + expect(response.body).to include('<meta property="og:article:tag" content="howareyou" />') + end + end + + context "given a limited post" do it "forces the user to sign" do - get :show, id: @message.id + get :show, id: post.id expect(response).to be_redirect expect(response).to redirect_to new_user_session_path end @@ -110,40 +123,55 @@ describe PostsController, type: :controller do end end - describe "iframe" do - it "contains an iframe" do - get :iframe, id: @message.id + describe "oembed" do + it "works when you can see it" do + sign_in alice + get :oembed, url: "/posts/#{post.id}" expect(response.body).to match /iframe/ end - end - describe "oembed" do - it "receives a present oembed" do - expect(post_service_double).to receive(:present_oembed) - get :oembed, url: "/posts/#{@message.id}" + it "returns a 404 response when the post is not found" do + get :oembed, url: "/posts/#{post.id}" + expect(response.status).to eq(404) end end describe "#destroy" do - before do - sign_in alice - end + context "own post" do + before do + sign_in alice + end - it "will receive a retract post" do - expect(post_service_double).to receive(:retract_post) - expect(post_service_double).to receive(:post).and_return(@message) - message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id) - delete :destroy, format: :js, id: message.id + it "works when it is your post" do + expect_any_instance_of(PostService).to receive(:destroy).with(post.id.to_s) + + delete :destroy, format: :json, id: post.id + expect(response.status).to eq(204) + end + + it "redirects to stream on mobile" do + delete :destroy, format: :mobile, id: post.id + expect(response).to be_redirect + expect(response).to redirect_to stream_path + end end - context "when Diaspora::NotMine is raised by retract post" do + context "post of another user" do it "will respond with a 403" do - expect(post_service_double).to receive(:retract_post).and_raise(Diaspora::NotMine) - message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id) - delete :destroy, format: :js, id: message.id + sign_in bob, scope: :user + + delete :destroy, format: :json, id: post.id expect(response.body).to eq("You are not allowed to do that") expect(response.status).to eq(403) end + + it "will respond with a 404 if the post is not visible" do + sign_in eve, scope: :user + + expect { + delete :destroy, format: :json, id: post.id + }.to raise_error ActiveRecord::RecordNotFound + end end end end diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb index c32878c6ed3c36a6e2214cfe7a51b9e91aa23579..88b082d235aacbe081ad7ea757fe25d4badd4f5b 100644 --- a/spec/controllers/profiles_controller_spec.rb +++ b/spec/controllers/profiles_controller_spec.rb @@ -6,7 +6,7 @@ require 'spec_helper' describe ProfilesController, :type => :controller do before do - sign_in :user, eve + sign_in eve, scope: :user end describe '#show' do diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index 6866b712e5d88189d55f1fed6dc452181a42e35f..49e07fa192f7f1573ac20f0f95c64149148d8545 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -2,49 +2,76 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' - -describe RegistrationsController, :type => :controller do - include Devise::TestHelpers +require "spec_helper" +describe RegistrationsController, type: :controller do before do request.env["devise.mapping"] = Devise.mappings[:user] - @valid_params = {:user => { - :username => "jdoe", - :email => "jdoe@example.com", - :password => "password", - :password_confirmation => "password" + end + + let(:valid_params) { + { + user: { + username: "jdoe", + email: "jdoe@example.com", + password: "password", + password_confirmation: "password" } } - allow(Person).to receive(:find_or_fetch_by_identifier).and_return(FactoryGirl.create(:person)) - end + } - describe '#check_registrations_open!' do + describe "#check_registrations_open_or_valid_invite!" do before do AppConfig.settings.enable_registrations = false end - it 'redirects #new to the login page' do + it "redirects #new to the login page" do get :new - expect(flash[:error]).to eq(I18n.t('registrations.closed')) + expect(flash[:error]).to eq(I18n.t("registrations.closed")) expect(response).to redirect_to new_user_session_path end - it 'redirects #create to the login page' do - post :create, @valid_params - expect(flash[:error]).to eq(I18n.t('registrations.closed')) + it "redirects #create to the login page" do + post :create, valid_params + expect(flash[:error]).to eq(I18n.t("registrations.closed")) expect(response).to redirect_to new_user_session_path end - it 'does not redirect if there is a valid invite token' do - i = InvitationCode.create(:user => bob) - get :new, :invite => {:token => i.token} + it "does not redirect if there is a valid invite token" do + code = InvitationCode.create(user: bob) + get :new, invite: {token: code.token} expect(response).not_to be_redirect end - it 'does redirect if there is an invalid invite token' do - get :new, :invite => {:token => 'fssdfsd'} - expect(response).to be_redirect + it "does redirect if there is an invalid invite token" do + get :new, invite: {token: "fssdfsd"} + expect(response).to redirect_to new_user_session_path + end + + it "does redirect if there are no invites available with this code" do + code = InvitationCode.create(user: bob) + code.update_attributes(count: 0) + + get :new, invite: {token: code.token} + expect(response).to redirect_to new_user_session_path + end + + it "does redirect when invitations are closed now" do + code = InvitationCode.create(user: bob) + AppConfig.settings.invitations.open = false + + get :new, invite: {token: code.token} + expect(response).to redirect_to new_user_session_path + end + + it "does not redirect when the registration is open" do + AppConfig.settings.enable_registrations = true + + code = InvitationCode.create(user: bob) + code.update_attributes(count: 0) + + get :new, invite: {token: code.token} + expect(response).not_to be_redirect end end @@ -52,66 +79,95 @@ describe RegistrationsController, :type => :controller do render_views context "with valid parameters" do - before do - AppConfig.settings.enable_registrations = true - user = FactoryGirl.build(:user) - allow(User).to receive(:build).and_return(user) - end - it "creates a user" do expect { - get :create, @valid_params + get :create, valid_params }.to change(User, :count).by(1) end it "assigns @user" do - get :create, @valid_params + get :create, valid_params expect(assigns(:user)).to be_truthy end it "sets the flash" do - get :create, @valid_params + get :create, valid_params expect(flash[:notice]).not_to be_blank end it "redirects to the home path" do - get :create, @valid_params + get :create, valid_params expect(response).to be_redirect - expect(response.location).to match /^#{stream_url}\??$/ + expect(response.location).to match(/^#{getting_started_url}$/) + end + + context "with invite code" do + it "reduces number of available invites when the registration is closed" do + AppConfig.settings.enable_registrations = false + + code = InvitationCode.create(user: bob) + + expect { + get :create, valid_params.merge(invite: {token: code.token}) + }.to change { code.reload.count }.by(-1) + end + + it "doesn't reduce number of available invites when the registration is open" do + code = InvitationCode.create(user: bob) + + expect { + get :create, valid_params.merge(invite: {token: code.token}) + }.not_to change { code.reload.count } + end + + it "links inviter with the user" do + code = InvitationCode.create(user: bob) + + post :create, valid_params.merge(invite: {token: code.token}) + + expect(User.find_by(username: "jdoe").invited_by).to eq(bob) + end end end context "with invalid parameters" do - before do - @invalid_params = @valid_params - @invalid_params[:user][:password_confirmation] = "baddword" - end + let(:invalid_params) { valid_params.deep_merge(user: {password_confirmation: "baddword"}) } it "does not create a user" do - expect { get :create, @invalid_params }.not_to change(User, :count) + expect { get :create, invalid_params }.not_to change(User, :count) end it "does not create a person" do - expect { get :create, @invalid_params }.not_to change(Person, :count) + expect { get :create, invalid_params }.not_to change(Person, :count) end it "assigns @user" do - get :create, @invalid_params + get :create, invalid_params expect(assigns(:user)).not_to be_nil end it "sets the flash error" do - get :create, @invalid_params + get :create, invalid_params expect(flash[:error]).not_to be_blank end + it "doesn't reduce number of available invites" do + AppConfig.settings.enable_registrations = false + + code = InvitationCode.create(user: bob) + + expect { + get :create, invalid_params.merge(invite: {token: code.token}) + }.not_to change { code.reload.count } + end + it "renders new" do - get :create, @invalid_params + get :create, invalid_params expect(response).to render_template("registrations/new") end it "keeps invalid params in form" do - get :create, @invalid_params + get :create, invalid_params expect(response.body).to match /jdoe@example.com/m end end diff --git a/spec/controllers/report_controller_spec.rb b/spec/controllers/report_controller_spec.rb index e5d5a49eb2cd7e063a50d6b634dad05a80ce0e9c..fc64d36dd04c96e1194af60040ff4e5bf7aa8d81 100644 --- a/spec/controllers/report_controller_spec.rb +++ b/spec/controllers/report_controller_spec.rb @@ -49,16 +49,16 @@ describe ReportController, type: :controller do context "report offensive post" do it "succeeds" do - put :create, report: {item_id: @message.id, item_type: "post", text: "offensive content"} + put :create, report: {item_id: @message.id, item_type: "Post", text: "offensive content"} expect(response.status).to eq(200) - expect(Report.exists?(item_id: @message.id, item_type: "post")).to be true + expect(Report.exists?(item_id: @message.id, item_type: "Post")).to be true end end context "report offensive comment" do it "succeeds" do - put :create, report: {item_id: @comment.id, item_type: "comment", text: "offensive content"} + put :create, report: {item_id: @comment.id, item_type: "Comment", text: "offensive content"} expect(response.status).to eq(200) - expect(Report.exists?(item_id: @comment.id, item_type: "comment")).to be true + expect(Report.exists?(item_id: @comment.id, item_type: "Comment")).to be true end end end @@ -68,14 +68,14 @@ describe ReportController, type: :controller do it "is behind redirect_unless_admin_or_moderator" do put :update, id: @message.id, type: "post" expect(response).to redirect_to stream_path - expect(Report.where(reviewed: false, item_id: @message.id, item_type: "post")).to be_truthy + expect(Report.where(reviewed: false, item_id: @message.id, item_type: "Post")).to be_truthy end end context "mark comment report as user" do it "is behind redirect_unless_admin_or_moderator" do put :update, id: @comment.id, type: "comment" expect(response).to redirect_to stream_path - expect(Report.where(reviewed: false, item_id: @comment.id, item_type: "comment")).to be_truthy + expect(Report.where(reviewed: false, item_id: @comment.id, item_type: "Comment")).to be_truthy end end @@ -86,7 +86,7 @@ describe ReportController, type: :controller do it "succeeds" do put :update, id: @message.id, type: "post" expect(response.status).to eq(302) - expect(Report.where(reviewed: true, item_id: @message.id, item_type: "post")).to be_truthy + expect(Report.where(reviewed: true, item_id: @message.id, item_type: "Post")).to be_truthy end end context "mark comment report as admin" do @@ -96,7 +96,7 @@ describe ReportController, type: :controller do it "succeeds" do put :update, id: @comment.id, type: "comment" expect(response.status).to eq(302) - expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "comment")).to be_truthy + expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "Comment")).to be_truthy end end @@ -108,7 +108,7 @@ describe ReportController, type: :controller do it "succeeds" do put :update, id: @message.id, type: "post" expect(response.status).to eq(302) - expect(Report.where(reviewed: true, item_id: @message.id, item_type: "post")).to be_truthy + expect(Report.where(reviewed: true, item_id: @message.id, item_type: "Post")).to be_truthy end end @@ -119,7 +119,7 @@ describe ReportController, type: :controller do it "succeeds" do put :update, id: @comment.id, type: "comment" expect(response.status).to eq(302) - expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "comment")).to be_truthy + expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "Comment")).to be_truthy end end end @@ -129,14 +129,14 @@ describe ReportController, type: :controller do it "is behind redirect_unless_admin_or_moderator" do delete :destroy, id: @message.id, type: "post" expect(response).to redirect_to stream_path - expect(Report.where(reviewed: false, item_id: @message.id, item_type: "post")).to be_truthy + expect(Report.where(reviewed: false, item_id: @message.id, item_type: "Post")).to be_truthy end end context "destroy comment as user" do it "is behind redirect_unless_admin_or_moderator" do delete :destroy, id: @comment.id, type: "comment" expect(response).to redirect_to stream_path - expect(Report.where(reviewed: false, item_id: @comment.id, item_type: "comment")).to be_truthy + expect(Report.where(reviewed: false, item_id: @comment.id, item_type: "Comment")).to be_truthy end end @@ -147,7 +147,7 @@ describe ReportController, type: :controller do it "succeeds" do delete :destroy, id: @message.id, type: "post" expect(response.status).to eq(302) - expect(Report.where(reviewed: true, item_id: @message.id, item_type: "post")).to be_truthy + expect(Report.where(reviewed: true, item_id: @message.id, item_type: "Post")).to be_truthy end end context "destroy comment as admin" do @@ -157,7 +157,7 @@ describe ReportController, type: :controller do it "succeeds" do delete :destroy, id: @comment.id, type: "comment" expect(response.status).to eq(302) - expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "comment")).to be_truthy + expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "Comment")).to be_truthy end end @@ -168,7 +168,7 @@ describe ReportController, type: :controller do it "succeeds" do delete :destroy, id: @message.id, type: "post" expect(response.status).to eq(302) - expect(Report.where(reviewed: true, item_id: @message.id, item_type: "post")).to be_truthy + expect(Report.where(reviewed: true, item_id: @message.id, item_type: "Post")).to be_truthy end end context "destroy comment as moderator" do @@ -178,7 +178,7 @@ describe ReportController, type: :controller do it "succeeds" do delete :destroy, id: @comment.id, type: "comment" expect(response.status).to eq(302) - expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "comment")).to be_truthy + expect(Report.where(reviewed: true, item_id: @comment.id, item_type: "Comment")).to be_truthy end end end diff --git a/spec/controllers/reshares_controller_spec.rb b/spec/controllers/reshares_controller_spec.rb index 8f90907844ad5609399b089c95d23ed6e3f31edc..cc4b7e9ecbf7a9311840b86b75d79724be4dfc50 100644 --- a/spec/controllers/reshares_controller_spec.rb +++ b/spec/controllers/reshares_controller_spec.rb @@ -18,7 +18,7 @@ describe ResharesController, :type => :controller do context 'with an authenticated user' do before do - sign_in :user, bob + sign_in(bob, scope: :user) allow(@controller).to receive(:current_user).and_return(bob) end @@ -33,13 +33,8 @@ describe ResharesController, :type => :controller do }.to change(Reshare, :count).by(1) end - it 'after save, calls add to streams' do - expect(bob).to receive(:add_to_streams) - post_request! - end - it 'calls dispatch' do - expect(bob).to receive(:dispatch_post).with(anything, hash_including(:additional_subscribers)) + expect(bob).to receive(:dispatch_post) post_request! end diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb index bc07db4ae131daeb96a07e61f5b16dbfbf859f20..58a62ba71bbe82f36da659fafeacbc17cb633715 100644 --- a/spec/controllers/search_controller_spec.rb +++ b/spec/controllers/search_controller_spec.rb @@ -4,7 +4,7 @@ describe SearchController, :type => :controller do before do @user = alice @aspect = @user.aspects.first - sign_in :user, @user + sign_in @user, scope: :user end describe 'query is a person' do @@ -23,7 +23,7 @@ describe SearchController, :type => :controller do get :search, :q => '#cats' expect(response).to redirect_to(tag_path('cats')) end - + it 'removes dots from the query' do get :search, :q => '#cat.s' expect(response).to redirect_to(tag_path('cats')) diff --git a/spec/controllers/services_controller_spec.rb b/spec/controllers/services_controller_spec.rb index d7bd50e92d5959cace3ef03d2afe9a4979b712d7..5c0c2f51fc77ec16dba9b36425ff0923c2a9ae20 100644 --- a/spec/controllers/services_controller_spec.rb +++ b/spec/controllers/services_controller_spec.rb @@ -14,7 +14,7 @@ describe ServicesController, :type => :controller do let(:user) { alice } before do - sign_in :user, user + sign_in user, scope: :user allow(@controller).to receive(:current_user).and_return(user) end @@ -75,11 +75,11 @@ describe ServicesController, :type => :controller do context 'when the access-level is read-only' do let(:header) { { 'x-access-level' => 'read' } } - let(:access_token) { double('access_token') } + let(:access_token) { double("access_token") } let(:extra) { {'extra' => { 'access_token' => access_token }} } let(:provider) { {'provider' => 'twitter'} } - before do + before do allow(access_token).to receive_message_chain(:response, :header).and_return header request.env['omniauth.auth'] = omniauth_auth.merge!( provider).merge!( extra ) end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 4ba846ed1ff77b47c6273f2d93c9220178705700..51e7361830d627fd3a90324292f7857f9455bd72 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -5,8 +5,6 @@ require "spec_helper" describe SessionsController, type: :controller do - include Devise::TestHelpers - let(:mock_access_token) { Object.new } before do @@ -34,7 +32,7 @@ describe SessionsController, type: :controller do describe "#destroy" do before do - sign_in :user, @user + sign_in @user, scope: :user end it "redirects to / for a non-mobile user" do delete :destroy @@ -51,7 +49,7 @@ describe SessionsController, type: :controller do describe "#reset_authentication_token" do context "for a logged in user" do before do - sign_in :user, @user + sign_in @user, scope: :user end it "succeeds" do diff --git a/spec/controllers/share_visibilities_controller_spec.rb b/spec/controllers/share_visibilities_controller_spec.rb index 5fe1bb11b79ff5e691d2b5e66f8bed0a5e9d356d..6215de699bdd639da0d95b9c29cc813da47d2576 100644 --- a/spec/controllers/share_visibilities_controller_spec.rb +++ b/spec/controllers/share_visibilities_controller_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' describe ShareVisibilitiesController, :type => :controller do before do @status = alice.post(:status_message, :text => "hello", :to => alice.aspects.first) - sign_in :user, bob + sign_in(bob, scope: :user) end describe '#update' do diff --git a/spec/controllers/social_relay_controller_spec.rb b/spec/controllers/social_relay_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..9b2f10be7c1a0ae35c5ab3bde92e645c36c32c72 --- /dev/null +++ b/spec/controllers/social_relay_controller_spec.rb @@ -0,0 +1,16 @@ +require "spec_helper" + +describe SocialRelayController, type: :controller do + describe "#well_known" do + it "responds to format json" do + get :well_known, format: "json" + expect(response.code).to eq("200") + end + + it "contains json" do + get :well_known, format: "json" + json = JSON.parse(response.body) + expect(json["scope"]).to be_present + end + end +end diff --git a/spec/controllers/status_messages_controller_spec.rb b/spec/controllers/status_messages_controller_spec.rb index 24b8787b8226bd23ceb5fcc1ddb122b3cba772f3..0c5ad604eb8a175d4c1efd86f324f09400135af8 100644 --- a/spec/controllers/status_messages_controller_spec.rb +++ b/spec/controllers/status_messages_controller_spec.rb @@ -9,7 +9,7 @@ describe StatusMessagesController, :type => :controller do @aspect1 = alice.aspects.first request.env["HTTP_REFERER"] = "" - sign_in :user, alice + sign_in alice, scope: :user allow(@controller).to receive(:current_user).and_return(alice) alice.reload end @@ -49,12 +49,12 @@ describe StatusMessagesController, :type => :controller do end describe '#create' do + let(:text) { "facebook, is that you?" } let(:status_message_hash) { - { :status_message => { - :public => "true", - :text => "facebook, is that you?", - }, - :aspect_ids => [@aspect1.id.to_s] } + { + status_message: {text: text}, + aspect_ids: [@aspect1.id.to_s] + } } it 'creates with valid html' do @@ -96,14 +96,52 @@ describe StatusMessagesController, :type => :controller do post :create, status_message_hash end - it 'takes public in aspect ids' do - post :create, status_message_hash.merge(:aspect_ids => ['public']) - expect(response.status).to eq(302) - end + context "with aspect_ids" do + before do + @aspect2 = alice.aspects.create(name: "another aspect") + end - it 'takes all_aspects in aspect ids' do - post :create, status_message_hash.merge(:aspect_ids => ['all_aspects']) - expect(response.status).to eq(302) + it "takes one aspect as array in aspect_ids" do + post :create, status_message_hash + expect(response.status).to eq(302) + status_message = StatusMessage.find_by_text(text) + expect(status_message.aspect_visibilities.map(&:aspect)).to eq([@aspect1]) + end + + it "takes one aspect as string in aspect_ids" do + post :create, status_message_hash.merge(aspect_ids: @aspect1.id.to_s) + expect(response.status).to eq(302) + status_message = StatusMessage.find_by_text(text) + expect(status_message.aspect_visibilities.map(&:aspect)).to eq([@aspect1]) + end + + it "takes public as array in aspect_ids" do + post :create, status_message_hash.merge(aspect_ids: ["public"]) + expect(response.status).to eq(302) + status_message = StatusMessage.find_by_text(text) + expect(status_message.public).to be_truthy + end + + it "takes public as string in aspect_ids" do + post :create, status_message_hash.merge(aspect_ids: "public") + expect(response.status).to eq(302) + status_message = StatusMessage.find_by_text(text) + expect(status_message.public).to be_truthy + end + + it "takes all_aspects as array in aspect_ids" do + post :create, status_message_hash.merge(aspect_ids: ["all_aspects"]) + expect(response.status).to eq(302) + status_message = StatusMessage.find_by_text(text) + expect(status_message.aspect_visibilities.map(&:aspect)).to match_array([@aspect1, @aspect2]) + end + + it "takes all_aspects as string in aspect_ids" do + post :create, status_message_hash.merge(aspect_ids: "all_aspects") + expect(response.status).to eq(302) + status_message = StatusMessage.find_by_text(text) + expect(status_message.aspect_visibilities.map(&:aspect)).to match_array([@aspect1, @aspect2]) + end end it "dispatches the post to the specified services" do @@ -127,7 +165,7 @@ describe StatusMessagesController, :type => :controller do it "doesn't overwrite author_id" do status_message_hash[:status_message][:author_id] = bob.person.id post :create, status_message_hash - new_message = StatusMessage.find_by_text(status_message_hash[:status_message][:text]) + new_message = StatusMessage.find_by_text(text) expect(new_message.author_id).to eq(alice.person.id) end @@ -138,9 +176,9 @@ describe StatusMessagesController, :type => :controller do expect(old_status_message.reload.text).to eq('hello') end - it 'calls dispatch post once subscribers is set' do - expect(alice).to receive(:dispatch_post){|post, opts| - expect(post.subscribers(alice)).to eq([bob.person]) + it "calls dispatch post once subscribers is set" do + expect(alice).to receive(:dispatch_post) {|post, _opts| + expect(post.subscribers).to eq([bob.person]) } post :create, status_message_hash end @@ -152,11 +190,11 @@ describe StatusMessagesController, :type => :controller do expect(StatusMessage.first.provider_display_name).to eq('mobile') end -# disabled to fix federation -# it 'sends the errors in the body on js' do -# post :create, status_message_hash.merge!(:format => 'js', :status_message => {:text => ''}) -# response.body.should include('Status message requires a message or at least one photo') -# end + it "has no participation" do + post :create, status_message_hash + new_message = StatusMessage.find_by_text(text) + expect(new_message.participations.count).to eq(0) + end context 'with photos' do before do @@ -178,7 +216,8 @@ describe StatusMessagesController, :type => :controller do it "attaches all referenced photos" do post :create, @hash - expect(assigns[:status_message].photos.map(&:id)).to match_array([@photo1, @photo2].map(&:id)) + status_message = StatusMessage.find_by_text(text) + expect(status_message.photos.map(&:id)).to match_array([@photo1, @photo2].map(&:id)) end it "sets the pending bit of referenced photos" do diff --git a/spec/controllers/tag_followings_controller_spec.rb b/spec/controllers/tag_followings_controller_spec.rb index 95ad774c4413a73d12f27658e0cc39f08cb50567..46546dd224bb0474c3a57ac3433ec684fb6cb24a 100644 --- a/spec/controllers/tag_followings_controller_spec.rb +++ b/spec/controllers/tag_followings_controller_spec.rb @@ -15,7 +15,7 @@ describe TagFollowingsController, type: :controller do end context "signed in" do before do - sign_in :user, alice + sign_in alice, scope: :user end it "redirects html requests" do diff --git a/spec/controllers/tags_controller_spec.rb b/spec/controllers/tags_controller_spec.rb index 06ccdf6eab71edc96e7b4933a43f8a2efae8807e..3d60feb2e792abf2237a608751f2282b5d2efa5a 100644 --- a/spec/controllers/tags_controller_spec.rb +++ b/spec/controllers/tags_controller_spec.rb @@ -7,7 +7,7 @@ require 'spec_helper' describe TagsController, :type => :controller do describe '#index (search)' do before do - sign_in :user, alice + sign_in alice, scope: :user bob.profile.tag_string = "#cats #diaspora #rad" bob.profile.build_tags bob.profile.save! @@ -38,7 +38,7 @@ describe TagsController, :type => :controller do describe '#show' do context 'tag with capital letters' do before do - sign_in :user, alice + sign_in alice, scope: :user end it 'redirect to the downcase tag uri' do @@ -67,7 +67,7 @@ describe TagsController, :type => :controller do context 'signed in' do before do - sign_in :user, alice + sign_in alice, scope: :user end it 'assigns a Stream::Tag object with the current_user' do @@ -107,6 +107,38 @@ describe TagsController, :type => :controller do get :show, :name => 'foo', :format => :mobile expect(response).to be_success end + + it "returns the post with the correct age" do + post2 = eve.post( + :status_message, + text: "#what #yes #hellyes #foo tagged second post", + public: true, + created_at: @post.created_at - 1.day + ) + get :show, name: "what", max_time: @post.created_at, format: :json + expect(JSON.parse(response.body).size).to be(1) + expect(JSON.parse(response.body).first["guid"]).to eq(post2.guid) + end + end + + it "includes the correct meta tags" do + tag_url = tag_url "yes", host: AppConfig.pod_uri.host, port: AppConfig.pod_uri.port + + get :show, name: "yes" + + expect(response.body).to include('<meta name="keywords" content="yes" />') + expect(response.body).to include( + %(<meta property="og:url" content="#{tag_url}" />) + ) + expect(response.body).to include( + '<meta property="og:title" content="#yes" />' + ) + expect(response.body).to include( + %(<meta name="description" content="#{I18n.t('streams.tags.title', tags: 'yes')}" />) + ) + expect(response.body).to include( + %(<meta property="og:description" content=\"#{I18n.t('streams.tags.title', tags: 'yes')}" />) + ) end end end diff --git a/spec/controllers/terms_controller_spec.rb b/spec/controllers/terms_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..78eb0f048c85b69b61998c4abaa86279f042eff9 --- /dev/null +++ b/spec/controllers/terms_controller_spec.rb @@ -0,0 +1,15 @@ +require "spec_helper" + +describe TermsController, type: :controller do + describe "#index" do + it "succeeds" do + get :index + expect(response).to be_success + end + + it "succeeds on mobile" do + get :index, format: :mobile + expect(response).to be_success + end + end +end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 40006a3af7b1a41634be7a992918fd83eaf089ef..6413ac45725f6b8d17cf025e105a3077b8c1fd8d 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -5,9 +5,11 @@ require 'spec_helper' describe UsersController, :type => :controller do + include_context :gon + before do @user = alice - sign_in :user, @user + sign_in @user, scope: :user allow(@controller).to receive(:current_user).and_return(@user) end @@ -61,7 +63,7 @@ describe UsersController, :type => :controller do it 'renders xml if atom is requested' do sm = FactoryGirl.create(:status_message, :public => true, :author => @user.person) get :public, :username => @user.username, :format => :atom - expect(response.body).to include(sm.raw_message) + expect(response.body).to include(sm.text) end it 'renders xml if atom is requested with clickalbe urls' do @@ -77,7 +79,7 @@ describe UsersController, :type => :controller do it 'includes reshares in the atom feed' do reshare = FactoryGirl.create(:reshare, :author => @user.person) get :public, :username => @user.username, :format => :atom - expect(response.body).to include reshare.root.raw_message + expect(response.body).to include reshare.root.text end it 'do not show reshares in atom feed if origin post is deleted' do @@ -116,11 +118,6 @@ describe UsersController, :type => :controller do expect(response).to render_template('edit') end - it 'responds with a 204 on a js request' do - put :update, @params.merge(:format => :js) - expect(response.status).to eq(204) - end - describe 'password updates' do let(:password_params) do {:current_password => 'bluepin7', @@ -152,6 +149,17 @@ describe UsersController, :type => :controller do end end + describe "color_theme" do + it "allow the user to change his color theme" do + old_color_theme = "original" + @user.color_theme = old_color_theme + @user.save + put(:update, id: @user.id, user: {color_theme: "dark_green"}) + @user.reload + expect(@user.color_theme).not_to eq(old_color_theme) + end + end + describe 'email' do it 'disallow the user to change his new (unconfirmed) mail when it is the same as the old' do @user.email = "my@newemail.com" @@ -173,7 +181,7 @@ describe UsersController, :type => :controller do end it 'informs the user about failure' do - put(:update, :id => @user.id, :user => { :email => "my@newemailcom"}) + put(:update, id: @user.id, user: {email: "mynewemailcom"}) expect(request.flash[:error]).to eql(I18n.t('users.update.unconfirmed_email_not_changed')) expect(request.flash[:notice]).to be_blank end @@ -308,5 +316,19 @@ describe UsersController, :type => :controller do get :getting_started, :format => :mobile expect(response).to be_success end + + context "with inviter" do + [bob, eve].each do |inviter| + sharing = !alice.contact_for(inviter.person).nil? + + context sharing ? "when sharing" : "when don't share" do + it "preloads data using gon for the aspect memberships dropdown" do + alice.invited_by = inviter + get :getting_started + expect_gon_preloads_for_aspect_membership_dropdown(:inviter, sharing) + end + end + end + end end end diff --git a/spec/factories.rb b/spec/factories.rb index 0d95a96067a35a26d3fee8647bcd1393c2cae4db..4b5363f70663fbf47d5a622b249ad7c8b3487bba 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -21,6 +21,8 @@ FactoryGirl.define do gender "robot" location "Earth" birthday Date.today + tag_string "#one #two" + association :person end factory :profile_with_image_url, :parent => :profile do @@ -31,7 +33,7 @@ FactoryGirl.define do factory(:person, aliases: %i(author)) do sequence(:diaspora_handle) {|n| "bob-person-#{n}#{r_str}@example.net" } - url AppConfig.pod_uri.to_s + pod { Pod.find_or_create_by(url: "http://example.net") } serialized_public_key OpenSSL::PKey::RSA.generate(1024).public_key.export after(:build) do |person| unless person.profile.first_name.present? @@ -50,12 +52,6 @@ FactoryGirl.define do end end - factory :searchable_person, :parent => :person do - after(:build) do |person| - person.profile = FactoryGirl.build(:profile, :person => person, :searchable => true) - end - end - factory :like do association :author, :factory => :person association :target, :factory => :status_message @@ -69,10 +65,10 @@ FactoryGirl.define do password_confirmation { |u| u.password } serialized_private_key OpenSSL::PKey::RSA.generate(1024).export after(:build) do |u| - u.person = FactoryGirl.build(:person, :profile => FactoryGirl.build(:profile), - :owner_id => u.id, - :serialized_public_key => u.encryption_key.public_key.export, - :diaspora_handle => "#{u.username}#{User.diaspora_id_host}") + u.person = FactoryGirl.build(:person, + pod: nil, + serialized_public_key: u.encryption_key.public_key.export, + diaspora_handle: "#{u.username}#{User.diaspora_id_host}") end after(:create) do |u| u.person.save @@ -92,9 +88,6 @@ FactoryGirl.define do factory(:status_message, aliases: %i(status_message_without_participation)) do sequence(:text) {|n| "jimmy's #{n} whales" } author - after(:build) do |sm| - sm.diaspora_handle = sm.author.diaspora_handle - end factory(:status_message_with_poll) do after(:build) do |sm| @@ -102,6 +95,12 @@ FactoryGirl.define do end end + factory(:status_message_with_location) do + after(:build) do |sm| + FactoryGirl.create(:location, status_message: sm) + end + end + factory(:status_message_with_photo) do sequence(:text) {|n| "There are #{n} ninjas in this photo." } after(:build) do |sm| @@ -137,25 +136,41 @@ FactoryGirl.define do end factory(:location) do - lat 1 - lng 2 + address "Fernsehturm Berlin, Berlin, Germany" + lat 52.520645 + lng 13.409779 + end + + factory :participation do + association :author, factory: :person + association :target, factory: :status_message end factory(:poll) do - sequence(:question) { |n| "What do you think about #{n} ninjas?" } + sequence(:question) {|n| "What do you think about #{n} ninjas?" } + association :status_message after(:build) do |p| - p.poll_answers << FactoryGirl.build(:poll_answer) - p.poll_answers << FactoryGirl.build(:poll_answer) + p.poll_answers << FactoryGirl.build(:poll_answer, poll: p) + p.poll_answers << FactoryGirl.build(:poll_answer, poll: p) end end factory(:poll_answer) do - sequence(:answer) { |n| "#{n} questionmarks" } + sequence(:answer) {|n| "#{n} questionmarks" } + association :poll + end + + factory :poll_participation do + association :author, factory: :person + association :poll_answer + after(:build) {|p| p.poll = p.poll_answer.poll } end factory(:photo) do sequence(:random_string) {|n| SecureRandom.hex(10) } association :author, :factory => :person + height 42 + width 23 after(:build) do |p| p.unprocessed_image.store! File.open(File.join(File.dirname(__FILE__), 'fixtures', 'button.png')) p.update_remote_path @@ -206,6 +221,11 @@ FactoryGirl.define do photo_url "/assets/user/adams.jpg" end + factory :pod do + sequence(:host) {|n| "pod#{n}.example#{r_str}.com" } + ssl true + end + factory(:comment) do sequence(:text) {|n| "#{n} cats"} association(:author, :factory => :person) @@ -256,7 +276,7 @@ FactoryGirl.define do factory(:conversation) do association(:author, factory: :person) - sequence(:subject) { |n| "conversation ##{n}" } + sequence(:subject) {|n| "conversation ##{n}" } after(:build) do |c| c.participants << c.author @@ -264,25 +284,40 @@ FactoryGirl.define do end factory(:conversation_with_message, parent: :conversation) do - after(:build) do |c| - msg = FactoryGirl.build(:message) + after(:create) do |c| + msg = FactoryGirl.build(:message, author: c.author) msg.conversation_id = c.id - c.participants << msg.author msg.save end end factory(:message) do - association(:author, factory: :person) - sequence(:text) { |n| "message text ##{n}" } + association :author, factory: :person + association :conversation + sequence(:text) {|n| "message text ##{n}" } + after(:build) {|m| m.conversation.participants << m.author } end - factory(:message_with_conversation, parent: :message) do - after(:build) do |msg| - c = FactoryGirl.build(:conversation) - c.participants << msg.author - msg.conversation_id = c.id - end + factory(:signature_order) do + order "guid parent_guid text author" + end + + factory(:comment_signature) do + author_signature "some signature" + association :signature_order, order: "guid parent_guid text author new_property" + additional_data { {"new_property" => "some text"} } + end + + factory(:like_signature) do + author_signature "some signature" + association :signature_order, order: "positive guid parent_type parent_guid author new_property" + additional_data { {"new_property" => "some text"} } + end + + factory(:poll_participation_signature) do + author_signature "some signature" + association :signature_order, order: "guid parent_guid author poll_answer_guid new_property" + additional_data { {"new_property" => "some text"} } end #templates @@ -298,12 +333,65 @@ FactoryGirl.define do factory(:status, :parent => :status_message) + factory :o_auth_application, class: Api::OpenidConnect::OAuthApplication do + client_name "Diaspora Test Client" + redirect_uris %w(http://localhost:3000/) + end + + factory :o_auth_application_with_image, class: Api::OpenidConnect::OAuthApplication do + client_name "Diaspora Test Client" + redirect_uris %w(http://localhost:3000/) + logo_uri "/assets/user/default.png" + end + + factory :o_auth_application_with_ppid, class: Api::OpenidConnect::OAuthApplication do + client_name "Diaspora Test Client" + redirect_uris %w(http://localhost:3000/) + ppid true + sector_identifier_uri "https://example.com/uri" + end + + factory :o_auth_application_with_ppid_with_specific_id, class: Api::OpenidConnect::OAuthApplication do + client_name "Diaspora Test Client" + redirect_uris %w(http://localhost:3000/) + ppid true + sector_identifier_uri "https://example.com/uri" + end + + factory :o_auth_application_with_multiple_redirects, class: Api::OpenidConnect::OAuthApplication do + client_name "Diaspora Test Client" + redirect_uris %w(http://localhost:3000/ http://localhost/) + end + + factory :o_auth_application_with_xss, class: Api::OpenidConnect::OAuthApplication do + client_name "<script>alert(0);</script>" + redirect_uris %w(http://localhost:3000/) + end + + factory :auth_with_read, class: Api::OpenidConnect::Authorization do + o_auth_application + user + scopes %w(openid sub aud profile picture nickname name read) + end + + factory :auth_with_read_and_ppid, class: Api::OpenidConnect::Authorization do + association :o_auth_application, factory: :o_auth_application_with_ppid + user + scopes %w(openid sub aud profile picture nickname name read) + end + + factory :auth_with_read_and_write, class: Api::OpenidConnect::Authorization do + o_auth_application + user + scopes %w(openid sub aud profile picture nickname name read write) + end + # Factories for the DiasporaFederation-gem factory(:federation_person_from_webfinger, class: DiasporaFederation::Entities::Person) do sequence(:guid) { UUID.generate :compact } sequence(:diaspora_id) {|n| "bob-person-#{n}#{r_str}@example.net" } - url AppConfig.pod_uri.to_s + url "https://example.net/" exported_key OpenSSL::PKey::RSA.generate(1024).public_key.export profile { DiasporaFederation::Entities::Profile.new( diff --git a/spec/federation_callbacks_spec.rb b/spec/federation_callbacks_spec.rb index febfcfc687633b106086cf4f1d325c8e115a9d36..4c6a631d0478e4ae988a76f25baac24e06e2c959 100644 --- a/spec/federation_callbacks_spec.rb +++ b/spec/federation_callbacks_spec.rb @@ -22,6 +22,19 @@ describe "diaspora federation callbacks" do wf = DiasporaFederation.callbacks.trigger(:fetch_person_for_webfinger, "unknown@example.com") expect(wf).to be_nil end + + it "returns nil for a remote person" do + person = FactoryGirl.create(:person) + wf = DiasporaFederation.callbacks.trigger(:fetch_person_for_webfinger, person.diaspora_handle) + expect(wf).to be_nil + end + + it "returns nil for a closed account" do + user = FactoryGirl.create(:user) + user.person.lock_access! + wf = DiasporaFederation.callbacks.trigger(:fetch_person_for_webfinger, user.diaspora_handle) + expect(wf).to be_nil + end end describe ":fetch_person_for_hcard" do @@ -54,6 +67,19 @@ describe "diaspora federation callbacks" do hcard = DiasporaFederation.callbacks.trigger(:fetch_person_for_hcard, "1234567890abcdef") expect(hcard).to be_nil end + + it "returns nil for a remote person" do + person = FactoryGirl.create(:person) + hcard = DiasporaFederation.callbacks.trigger(:fetch_person_for_hcard, person.guid) + expect(hcard).to be_nil + end + + it "returns nil for a closed account" do + user = FactoryGirl.create(:user) + user.person.lock_access! + hcard = DiasporaFederation.callbacks.trigger(:fetch_person_for_hcard, user.guid) + expect(hcard).to be_nil + end end describe ":save_person_after_webfinger" do @@ -83,7 +109,8 @@ describe "diaspora federation callbacks" do FactoryGirl.attributes_for( :federation_person_from_webfinger, profile: DiasporaFederation::Entities::Profile.new( - FactoryGirl.attributes_for(:federation_profile_from_hcard_with_image_url)) + FactoryGirl.attributes_for(:federation_profile_from_hcard_with_image_url) + ) ) ) @@ -103,6 +130,15 @@ describe "diaspora federation callbacks" do expect(profile_entity.image_url_small).to eq(profile.image_url_small) expect(profile_entity.searchable).to eq(profile.searchable) end + + it "raises an error if a person with the same GUID already exists" do + person_data = FactoryGirl.attributes_for(:federation_person_from_webfinger).merge(guid: alice.guid) + person = DiasporaFederation::Entities::Person.new(person_data) + + expect { + DiasporaFederation.callbacks.trigger(:save_person_after_webfinger, person) + }.to raise_error ActiveRecord::RecordInvalid, /Person with same GUID already exists: #{alice.diaspora_handle}/ + end end context "update profile" do @@ -152,151 +188,203 @@ describe "diaspora federation callbacks" do let(:local_person) { FactoryGirl.create(:user).person } let(:remote_person) { FactoryGirl.create(:person) } - let(:post_by_a_local_person) { FactoryGirl.create(:status_message, author: local_person) } - let(:post_by_a_remote_person) { FactoryGirl.create(:status_message, author: remote_person) } - describe ":fetch_private_key_by_diaspora_id" do + describe ":fetch_private_key" do it "returns a private key for a local user" do - key = DiasporaFederation.callbacks.trigger(:fetch_private_key_by_diaspora_id, local_person.diaspora_handle) + key = DiasporaFederation.callbacks.trigger(:fetch_private_key, local_person.diaspora_handle) expect(key).to be_a(OpenSSL::PKey::RSA) expect(key.to_s).to eq(local_person.owner.serialized_private_key) end it "returns nil for a remote user" do expect( - DiasporaFederation.callbacks.trigger(:fetch_private_key_by_diaspora_id, remote_person.diaspora_handle) + DiasporaFederation.callbacks.trigger(:fetch_private_key, remote_person.diaspora_handle) ).to be_nil end it "returns nil for an unknown id" do expect( - DiasporaFederation.callbacks.trigger(:fetch_private_key_by_diaspora_id, FactoryGirl.generate(:diaspora_id)) - ).to be_nil - end - end - - describe ":fetch_author_private_key_by_entity_guid" do - it "returns a private key for a post by a local user" do - key = DiasporaFederation.callbacks.trigger(:fetch_author_private_key_by_entity_guid, - "Post", post_by_a_local_person.guid) - expect(key).to be_a(OpenSSL::PKey::RSA) - expect(key.to_s).to eq(post_by_a_local_person.author.owner.serialized_private_key) - end - - it "returns nil for a post by a remote user" do - expect( - DiasporaFederation.callbacks.trigger(:fetch_author_private_key_by_entity_guid, - "Post", post_by_a_remote_person.guid) - ).to be_nil - end - - it "returns nil for an unknown post" do - expect( - DiasporaFederation.callbacks.trigger(:fetch_author_private_key_by_entity_guid, - "Post", FactoryGirl.generate(:guid)) + DiasporaFederation.callbacks.trigger(:fetch_private_key, FactoryGirl.generate(:diaspora_id)) ).to be_nil end end - describe ":fetch_public_key_by_diaspora_id" do + describe ":fetch_public_key" do it "returns a public key for a person" do - key = DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, remote_person.diaspora_handle) + key = DiasporaFederation.callbacks.trigger(:fetch_public_key, remote_person.diaspora_handle) expect(key).to be_a(OpenSSL::PKey::RSA) expect(key.to_s).to eq(remote_person.serialized_public_key) end - it "returns nil for an unknown person" do - expect( - DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, FactoryGirl.generate(:diaspora_id)) - ).to be_nil - end - end + it "fetches an unknown user" do + person = FactoryGirl.build(:person) + expect(Person).to receive(:find_or_fetch_by_identifier).with(person.diaspora_handle).and_return(person) - describe ":fetch_author_public_key_by_entity_guid" do - it "returns a public key for a known post" do - key = DiasporaFederation.callbacks.trigger(:fetch_author_public_key_by_entity_guid, - "Post", post_by_a_remote_person.guid) + key = DiasporaFederation.callbacks.trigger(:fetch_public_key, person.diaspora_handle) expect(key).to be_a(OpenSSL::PKey::RSA) - expect(key.to_s).to eq(post_by_a_remote_person.author.serialized_public_key) + expect(key.to_s).to eq(person.serialized_public_key) end - it "returns nil for an unknown post" do - expect( - DiasporaFederation.callbacks.trigger(:fetch_author_public_key_by_entity_guid, - "Post", FactoryGirl.generate(:guid)) - ).to be_nil + it "returns nil for an unknown person" do + diaspora_id = FactoryGirl.generate(:diaspora_id) + expect(Person).to receive(:find_or_fetch_by_identifier).with(diaspora_id) + .and_raise(DiasporaFederation::Discovery::DiscoveryError) + + expect { + DiasporaFederation.callbacks.trigger(:fetch_public_key, diaspora_id) + }.to raise_error DiasporaFederation::Discovery::DiscoveryError end end - describe ":entity_author_is_local?" do - it "returns true for a post by a local user" do - expect( - DiasporaFederation.callbacks.trigger(:entity_author_is_local?, "Post", post_by_a_local_person.guid) - ).to be_truthy + describe ":fetch_related_entity" do + it "returns related entity for an existing local post" do + post = FactoryGirl.create(:status_message, author: local_person) + entity = DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Post", post.guid) + expect(entity.author).to eq(post.diaspora_handle) + expect(entity.local).to be_truthy + expect(entity.public).to be_falsey + expect(entity.parent).to be_nil + end + + it "returns related entity for an existing remote post" do + post = FactoryGirl.create(:status_message, author: remote_person) + entity = DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Post", post.guid) + expect(entity.author).to eq(post.diaspora_handle) + expect(entity.local).to be_falsey + expect(entity.public).to be_falsey + expect(entity.parent).to be_nil + end + + it "returns related entity for an existing public post" do + post = FactoryGirl.create(:status_message, author: local_person, public: true) + entity = DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Post", post.guid) + expect(entity.author).to eq(post.diaspora_handle) + expect(entity.local).to be_truthy + expect(entity.public).to be_truthy + expect(entity.parent).to be_nil end - it "returns false for a post by a remote user" do - expect( - DiasporaFederation.callbacks.trigger(:entity_author_is_local?, "Post", post_by_a_remote_person.guid) - ).to be_falsey + it "returns related entity for an existing comment" do + post = FactoryGirl.create(:status_message, author: local_person, public: true) + comment = FactoryGirl.create(:comment, author: remote_person, parent: post) + entity = DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Comment", comment.guid) + expect(entity.author).to eq(comment.diaspora_handle) + expect(entity.local).to be_falsey + expect(entity.public).to be_truthy + expect(entity.parent.author).to eq(post.diaspora_handle) + expect(entity.parent.local).to be_truthy + expect(entity.parent.public).to be_truthy + expect(entity.parent.parent).to be_nil end - it "returns false for a unknown post" do - expect( - DiasporaFederation.callbacks.trigger(:entity_author_is_local?, "Post", FactoryGirl.generate(:diaspora_id)) - ).to be_falsey + it "returns related entity for an existing conversation" do + conversation = FactoryGirl.create(:conversation, author: local_person) + entity = DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Conversation", conversation.guid) + expect(entity.author).to eq(local_person.diaspora_handle) + expect(entity.local).to be_truthy + expect(entity.public).to be_falsey + expect(entity.parent).to be_nil end - end - describe ":fetch_entity_author_id_by_guid" do - it "returns id for a existing guid" do - expect( - DiasporaFederation.callbacks.trigger(:fetch_entity_author_id_by_guid, "Post", post_by_a_remote_person.guid) - ).not_to eq(post_by_a_remote_person.author_id) + it "returns related entity for an existing person" do + entity = DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Person", remote_person.guid) + expect(entity.author).to eq(remote_person.diaspora_handle) + expect(entity.local).to be_falsey + expect(entity.public).to be_falsey + expect(entity.parent).to be_nil end it "returns nil for a non-existing guid" do expect( - DiasporaFederation.callbacks.trigger(:fetch_entity_author_id_by_guid, "Post", FactoryGirl.generate(:guid)) + DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Post", FactoryGirl.generate(:guid)) ).to be_nil end end describe ":queue_public_receive" do - it "enqueues a ReceiveUnencryptedSalmon job" do - xml = "<diaspora/>" - expect(Workers::ReceiveUnencryptedSalmon).to receive(:perform_async).with(xml) + it "enqueues a ReceivePublic job" do + data = "<diaspora/>" + expect(Workers::ReceivePublic).to receive(:perform_async).with(data, true) - DiasporaFederation.callbacks.trigger(:queue_public_receive, xml) + DiasporaFederation.callbacks.trigger(:queue_public_receive, data, true) end end describe ":queue_private_receive" do - let(:xml) { "<diaspora/>" } + let(:data) { "<diaspora/>" } it "returns true if the user is found" do - result = DiasporaFederation.callbacks.trigger(:queue_private_receive, alice.person.guid, xml) + result = DiasporaFederation.callbacks.trigger(:queue_private_receive, alice.person.guid, data) expect(result).to be_truthy end - it "enqueues a ReceiveEncryptedSalmon job" do - expect(Workers::ReceiveEncryptedSalmon).to receive(:perform_async).with(alice.id, xml) + it "enqueues a ReceivePrivate job" do + expect(Workers::ReceivePrivate).to receive(:perform_async).with(alice.id, data, true) - DiasporaFederation.callbacks.trigger(:queue_private_receive, alice.person.guid, xml) + DiasporaFederation.callbacks.trigger(:queue_private_receive, alice.person.guid, data, true) end it "returns false if the no user is found" do person = FactoryGirl.create(:person) - result = DiasporaFederation.callbacks.trigger(:queue_private_receive, person.guid, xml) + result = DiasporaFederation.callbacks.trigger(:queue_private_receive, person.guid, data, true) expect(result).to be_falsey end it "returns false if the no person is found" do - result = DiasporaFederation.callbacks.trigger(:queue_private_receive, "2398rq3948yftn", xml) + result = DiasporaFederation.callbacks.trigger(:queue_private_receive, "2398rq3948yftn", data, true) expect(result).to be_falsey end end + describe ":receive_entity" do + it "receives an AccountDeletion" do + account_deletion = FactoryGirl.build(:account_deletion_entity) + + expect(Diaspora::Federation::Receive).to receive(:account_deletion).with(account_deletion) + expect(Workers::ReceiveLocal).not_to receive(:perform_async) + + DiasporaFederation.callbacks.trigger(:receive_entity, account_deletion, nil) + end + + it "receives a Retraction" do + retraction = FactoryGirl.build(:retraction_entity) + + expect(Diaspora::Federation::Receive).to receive(:retraction).with(retraction, 42) + expect(Workers::ReceiveLocal).not_to receive(:perform_async) + + DiasporaFederation.callbacks.trigger(:receive_entity, retraction, 42) + end + + it "receives a entity" do + received = FactoryGirl.build(:status_message_entity) + persisted = FactoryGirl.create(:status_message) + + expect(Diaspora::Federation::Receive).to receive(:perform).with(received).and_return(persisted) + expect(Workers::ReceiveLocal).to receive(:perform_async).with(persisted.class.to_s, persisted.id, []) + + DiasporaFederation.callbacks.trigger(:receive_entity, received, nil) + end + + it "receives a entity for a recipient" do + received = FactoryGirl.build(:status_message_entity) + persisted = FactoryGirl.create(:status_message) + + expect(Diaspora::Federation::Receive).to receive(:perform).with(received).and_return(persisted) + expect(Workers::ReceiveLocal).to receive(:perform_async).with(persisted.class.to_s, persisted.id, [42]) + + DiasporaFederation.callbacks.trigger(:receive_entity, received, 42) + end + + it "does not trigger a ReceiveLocal job if Receive.perform returned nil" do + received = FactoryGirl.build(:status_message_entity) + + expect(Diaspora::Federation::Receive).to receive(:perform).with(received).and_return(nil) + expect(Workers::ReceiveLocal).not_to receive(:perform_async) + + DiasporaFederation.callbacks.trigger(:receive_entity, received, nil) + end + end + describe ":fetch_public_entity" do it "fetches a Post" do post = FactoryGirl.create(:status_message, author: alice.person, public: true) @@ -342,11 +430,75 @@ describe "diaspora federation callbacks" do describe ":fetch_person_url_to" do it "returns the url with with the pod of the person" do - person = FactoryGirl.create(:person, url: "https://example.org") + pod = FactoryGirl.create(:pod) + person = FactoryGirl.create(:person, pod: pod) expect( DiasporaFederation.callbacks.trigger(:fetch_person_url_to, person.diaspora_handle, "/path/on/pod") - ).to eq("https://example.org/path/on/pod") + ).to eq("https://#{pod.host}/path/on/pod") + end + + it "fetches an unknown user" do + pod = FactoryGirl.build(:pod) + person = FactoryGirl.build(:person, pod: pod) + expect(Person).to receive(:find_or_fetch_by_identifier).with(person.diaspora_handle).and_return(person) + + expect( + DiasporaFederation.callbacks.trigger(:fetch_person_url_to, person.diaspora_handle, "/path/on/pod") + ).to eq("https://#{pod.host}/path/on/pod") + end + + it "forwards the DiscoveryError" do + diaspora_id = FactoryGirl.generate(:diaspora_id) + expect(Person).to receive(:find_or_fetch_by_identifier).with(diaspora_id) + .and_raise(DiasporaFederation::Discovery::DiscoveryError) + + expect { + DiasporaFederation.callbacks.trigger(:fetch_person_url_to, diaspora_id, "/path/on/pod") + }.to raise_error DiasporaFederation::Discovery::DiscoveryError + end + end + + describe ":update_pod" do + let(:pod) { FactoryGirl.create(:pod) } + let(:pod_url) { pod.url_to("/") } + + it "sets the correct error for curl-errors" do + pod = FactoryGirl.create(:pod) + + DiasporaFederation.callbacks.trigger(:update_pod, pod.url_to("/"), :ssl_cacert) + + updated_pod = Pod.find_or_create_by(url: pod.url_to("/")) + expect(Pod.statuses[updated_pod.status]).to eq(Pod.statuses[:ssl_failed]) + expect(updated_pod.error).to eq("FederationError: ssl_cacert") + end + + it "sets :no_errors to a pod that was down but up now and return code 202" do + pod = FactoryGirl.create(:pod, status: :unknown_error) + + DiasporaFederation.callbacks.trigger(:update_pod, pod.url_to("/"), 202) + + updated_pod = Pod.find_or_create_by(url: pod.url_to("/")) + expect(Pod.statuses[updated_pod.status]).to eq(Pod.statuses[:no_errors]) + end + + it "does not change a pod that has status :version_failed and was successful" do + pod = FactoryGirl.create(:pod, status: :version_failed) + + DiasporaFederation.callbacks.trigger(:update_pod, pod.url_to("/"), 202) + + updated_pod = Pod.find_or_create_by(url: pod.url_to("/")) + expect(Pod.statuses[updated_pod.status]).to eq(Pod.statuses[:version_failed]) + end + + it "sets :http_failed if it has an unsuccessful http status code" do + pod = FactoryGirl.create(:pod) + + DiasporaFederation.callbacks.trigger(:update_pod, pod.url_to("/"), 404) + + updated_pod = Pod.find_or_create_by(url: pod.url_to("/")) + expect(Pod.statuses[updated_pod.status]).to eq(Pod.statuses[:http_failed]) + expect(updated_pod.error).to eq("FederationError: HTTP status code was: 404") end end end diff --git a/spec/fixtures/client_assertion_with_nonexistent_client_id.txt b/spec/fixtures/client_assertion_with_nonexistent_client_id.txt new file mode 100644 index 0000000000000000000000000000000000000000..3bcabb07898a7e53a629707f8c6a6a10e5d806bb --- /dev/null +++ b/spec/fixtures/client_assertion_with_nonexistent_client_id.txt @@ -0,0 +1 @@ +eyJhbGciOiJSUzI1NiIsImtpZCI6ImExIn0.ewogIGF1ZDogWwogICAgaHR0cHM6Ly9rZW50c2hpa2FtYS5jb20vYXBpL29wZW5pZF9jb25uZWN0L2FjY2Vzc190b2tlbnMKICBdLAogIGlzczogMTRkNjkyY2Q1M2Q5YzFhOWY0NmZkNjllMGU1NzQ0M2QsCiAganRpOiAwbWNycmVZSCwKICBleHA6IDE0NDMxNzA4OTEuMzk3NDU2LAogIGlhdDogMTQ0MzE3MDI5MS4zOTc0NTYsCiAgc3ViOiAxNGQ2OTJjZDUzZDljMWE5ZjQ2ZmQ2OWUwZTU3NDQzZAp9Cg.QJUR3SYFrEIlbfOKjO0NYInddklytbJ2LSWNpkQ1aNThgneDCVCjIYGCaL2C9Sw-GR8j7QSUsKOwBbjZMUmVPFTjsfB4wdgObbxVt1QAXwDjAXc5w1smOerRsoahZ4yKI1an6PTaFxMwnoXUQcBZTsOS6RgXOCPPPoxibxohxoehPLieM0l7LYcF5DQKg7fTxZYOpmtiP--nibJxomXdVQNLSnZuQwnyWtlp_gYmqrYMMN1LPSmNCgZMZZZIYttaaAIA96SylglqubowJRShtDO9rSvUz_sgeCo7qo5Bfb0B5n9_PtIlr1CZSVoHyYj2lVqQldx7fnGuqqQJCfDQog diff --git a/spec/fixtures/client_assertion_with_nonexistent_kid.txt b/spec/fixtures/client_assertion_with_nonexistent_kid.txt new file mode 100644 index 0000000000000000000000000000000000000000..3419d02c165f02b02c7d7164934477d1929aaa62 --- /dev/null +++ b/spec/fixtures/client_assertion_with_nonexistent_kid.txt @@ -0,0 +1 @@ +ewogIGFsZzogUlMyNTYsCiAga2lkOiBpbnZhbGlkX2tpZAp9Cg.eyJhdWQiOiBbImh0dHBzOi8va2VudHNoaWthbWEuY29tL2FwaS9vcGVuaWRfY29ubmVjdC9hY2Nlc3NfdG9rZW5zIl0sICJpc3MiOiAiMTRkNjkyY2Q1M2Q5YzFhOWY0NmZkNjllMGU1NzQ0M2UiLCAianRpIjogIjBtY3JyZVlIIiwgImV4cCI6IDE0NDMxNzA4OTEuMzk3NDU2LCAiaWF0IjogMTQ0MzE3MDI5MS4zOTc0NTYsICJzdWIiOiAiMTRkNjkyY2Q1M2Q5YzFhOWY0NmZkNjllMGU1NzQ0M2UifQ. \ No newline at end of file diff --git a/spec/fixtures/client_assertion_with_tampered_sig.txt b/spec/fixtures/client_assertion_with_tampered_sig.txt new file mode 100644 index 0000000000000000000000000000000000000000..ff225126e0400572b41405b6f94740f03f87bce6 --- /dev/null +++ b/spec/fixtures/client_assertion_with_tampered_sig.txt @@ -0,0 +1 @@ +eyJhbGciOiJSUzI1NiIsImtpZCI6ImExIn0.eyJhdWQiOiBbImh0dHBzOi8va2VudHNoaWthbWEuY29tL2FwaS9vcGVuaWRfY29ubmVjdC9hY2Nlc3NfdG9rZW5zIl0sICJpc3MiOiAiMTRkNjkyY2Q1M2Q5YzFhOWY0NmZkNjllMGU1NzQ0M2UiLCAianRpIjogIjBtY3JyZVlIIiwgImV4cCI6IDE0NDMxNzA4OTEuMzk3NDU2LCAiaWF0IjogMTQ0MzE3MDI5MS4zOTc0NTYsICJzdWIiOiAiMTRkNjkyY2Q1M2Q5YzFhOWY0NmZkNjllMGU1NzQ0M2UifQ.QJUR3SYFrEIlbfOKjO0NYInddklytbJ2LSWNpkQ1aNThgneDCVCjIYGCaL2C9Sw-GR8j7QSUsKOwBbjZMUmVPFTjsfB4wdgObbxVt1QAXwDjAXc5w1smOerRsoahZ4yKI1an6PTaFxMwnoXUQcBZTsOS6RgXOCPPPoxibxohxoehPLieM0l7LYcF5DQKg7fTxZYOpmtiP--nibJxomXdVQNLSnZuQwnyWtlp_gYmqrYMMN1LPSmNCgZMZZZIYttaaAIA96SylglqubowJRShtDO9rSvUz_sgeCo7qo5Bfb0B5n9_PtIlr1CZSVoHyYj2lVqQldx7fnGuqqQJCfDQoe \ No newline at end of file diff --git a/spec/fixtures/data_conversion/aspect_memberships.csv b/spec/fixtures/data_conversion/aspect_memberships.csv deleted file mode 100644 index ff9d5859b9de19f6cd8fd2f474df4cee1dc9787f..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/aspect_memberships.csv +++ /dev/null @@ -1,7 +0,0 @@ -contact_mongo_id,aspect_mongo_id -4d2b6eb7cc8cb43cc200000f,4d2b6eb6cc8cb43cc2000008 -4d2b6eb7cc8cb43cc2000010,4d2b6eb7cc8cb43cc200000c -4d2b6eb7cc8cb43cc2000013,4d2b6eb7cc8cb43cc200000c -4d2b6eb7cc8cb43cc200001c,4d2b6eb7cc8cb43cc2000015 -4d2b6eb8cc8cb43cc2000022,4d2b6eb7cc8cb43cc2000015 -4d2b6ec2cc8cb43cc2000035,4d2b6eb7cc8cb43cc2000019 diff --git a/spec/fixtures/data_conversion/aspects.csv b/spec/fixtures/data_conversion/aspects.csv deleted file mode 100644 index e6fb9e99e9b709fb67774d94486c482e0fa634cc..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/aspects.csv +++ /dev/null @@ -1,5 +0,0 @@ -mongo_id,name,user_mongo_id,created_at,updated_at -4d2b6eb6cc8cb43cc2000008,generic,4d2b6eb6cc8cb43cc2000007,1294692022000,1294692033000 -4d2b6eb7cc8cb43cc200000c,generic,4d2b6eb6cc8cb43cc200000b,1294692023000,1294692033000 -4d2b6eb7cc8cb43cc2000015,generic,4d2b6eb7cc8cb43cc2000014,1294692023000,1294692034000 -4d2b6eb7cc8cb43cc2000019,generic,4d2b6eb7cc8cb43cc2000018,1294692023000,1294692036000 diff --git a/spec/fixtures/data_conversion/comments.csv b/spec/fixtures/data_conversion/comments.csv deleted file mode 100644 index e896127797a889a04d420b829cc28b4324b0ebfd..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/comments.csv +++ /dev/null @@ -1,3 +0,0 @@ -mongo_id,post_mongo_id,person_mongo_id,diaspora_handle,text,youtube_titles -4d2b6ebfcc8cb43cc200002b,4d2b6ebecc8cb43cc2000029,4d2b6eb7cc8cb43cc2000017,bob3c6c46f@localhost,Hey me!,"" -4d2b6ebfcc8cb43cc200002c,4d2b6ebecc8cb43cc2000027,4d2b6eb7cc8cb43cc200000e,bob2f66ee4@localhost,Hey you!,"" diff --git a/spec/fixtures/data_conversion/contacts.csv b/spec/fixtures/data_conversion/contacts.csv deleted file mode 100644 index 234a3da99e6e0ccd3c95a767e1289095cc8a471b..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/contacts.csv +++ /dev/null @@ -1,7 +0,0 @@ -mongo_id,user_mongo_id,person_mongo_id,pending,created_at,updated_at -4d2b6eb7cc8cb43cc200000f,4d2b6eb6cc8cb43cc2000007,4d2b6eb7cc8cb43cc200000e,false,, -4d2b6eb7cc8cb43cc2000010,4d2b6eb6cc8cb43cc200000b,4d2b6eb6cc8cb43cc200000a,false,, -4d2b6eb7cc8cb43cc2000013,4d2b6eb6cc8cb43cc200000b,4d2b6eb7cc8cb43cc2000011,false,, -4d2b6eb7cc8cb43cc200001c,4d2b6eb7cc8cb43cc2000014,4d2b6eb7cc8cb43cc200001b,true,, -4d2b6eb8cc8cb43cc2000022,4d2b6eb7cc8cb43cc2000014,4d2b6eb8cc8cb43cc2000020,true,, -4d2b6ec2cc8cb43cc2000035,4d2b6eb7cc8cb43cc2000018,4d2b6ec2cc8cb43cc2000034,false,, diff --git a/spec/fixtures/data_conversion/invitations.csv b/spec/fixtures/data_conversion/invitations.csv deleted file mode 100644 index 0c15e5db696b6cde4d1315390c545139481c2d31..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/invitations.csv +++ /dev/null @@ -1,2 +0,0 @@ -mongo_id,recipient_mongo_id,sender_mongo_id,aspect_mongo_id,message -4d2b6ebecc8cb43cc2000026,4d2b6ebccc8cb43cc2000025,4d2b6eb6cc8cb43cc2000007,4d2b6eb6cc8cb43cc2000008,Hello! diff --git a/spec/fixtures/data_conversion/notifications.csv b/spec/fixtures/data_conversion/notifications.csv deleted file mode 100644 index 4a2585e1bb52935bd28cda99dd6aa6d21f25e825..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/notifications.csv +++ /dev/null @@ -1,3 +0,0 @@ -mongo_id,target_mongo_id,recipient_mongo_id,actor_mongo_id,action,target_type,unread -4d2b6eb8cc8cb43cc200001f,4d2b6eb8cc8cb43cc200001e,4d2b6eb7cc8cb43cc2000018,4d2b6eb7cc8cb43cc2000017,,new_request,true -4d2b6ec4cc8cb43cc200003b,4d2b6ec4cc8cb43cc200003a,4d2b6eb6cc8cb43cc200000b,4d2b6ec2cc8cb43cc2000034,,new_request,true diff --git a/spec/fixtures/data_conversion/people.csv b/spec/fixtures/data_conversion/people.csv deleted file mode 100644 index ab45de84e7ca1f1c2b780c288f57c5a1dc67ccb5..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/people.csv +++ /dev/null @@ -1,61 +0,0 @@ -created_at,updated_at,serialized_public_key,url,mongo_id,owner_mongo_id,diaspora_handle -1294692022000,1294692022000,"-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBAKuK2doYFmBhcymlxKTII8fmFUXQtgk+NxSoJqCRWds/Uhsg/S/97Kzp -DJjzYWWDKNRfHXnrKsQ5wgcis+rIuvVrB6uVVe2pWjVRZoDxC/4qy5TghwnBsf5O -9/mfN1YhZLRzHCbGL5GBDwk5+emP7Re6l4hqNZRxZB5bpssoTShdAgMBAAE= ------END RSA PUBLIC KEY----- -",http://google-1b05052.com/,4d2b6eb6cc8cb43cc2000001,,bob-person-1fe12fb@aol.com -1294692022000,1294692022000,"-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBAKuK2doYFmBhcymlxKTII8fmFUXQtgk+NxSoJqCRWds/Uhsg/S/97Kzp -DJjzYWWDKNRfHXnrKsQ5wgcis+rIuvVrB6uVVe2pWjVRZoDxC/4qy5TghwnBsf5O -9/mfN1YhZLRzHCbGL5GBDwk5+emP7Re6l4hqNZRxZB5bpssoTShdAgMBAAE= ------END RSA PUBLIC KEY----- -",http://google-287b15e.com/,4d2b6eb6cc8cb43cc2000003,,bob-person-2281475@aol.com -1294692022000,1294692022000,"-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBAKuK2doYFmBhcymlxKTII8fmFUXQtgk+NxSoJqCRWds/Uhsg/S/97Kzp -DJjzYWWDKNRfHXnrKsQ5wgcis+rIuvVrB6uVVe2pWjVRZoDxC/4qy5TghwnBsf5O -9/mfN1YhZLRzHCbGL5GBDwk5+emP7Re6l4hqNZRxZB5bpssoTShdAgMBAAE= ------END RSA PUBLIC KEY----- -",http://google-37bb582.com/,4d2b6eb6cc8cb43cc2000005,,bob-person-34e6e33@aol.com -1294692022000,1294692033000,"-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBANLXsDZWFFy/SyjfTcykyCZVd5raI7G+EF+2kM3yF8UAAHf3FdinP0xv -mB9LsL86PZMiVfKSYU/pwPaIDO/XccnMspd6KxHORX+SbB9F3HC5auiYeekqNxPu -GqmsgBGFLjz8FZ3pbJbuu44XLf0cP1qfBqxKaDSOpwRH8bxvaUXLAgMBAAE= ------END RSA PUBLIC KEY----- -",http://google-4e2e53f.com/,4d2b6eb6cc8cb43cc200000a,4d2b6eb6cc8cb43cc2000007,bob1d2f837@localhost -1294692023000,1294692032000,"-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBANLXsDZWFFy/SyjfTcykyCZVd5raI7G+EF+2kM3yF8UAAHf3FdinP0xv -mB9LsL86PZMiVfKSYU/pwPaIDO/XccnMspd6KxHORX+SbB9F3HC5auiYeekqNxPu -GqmsgBGFLjz8FZ3pbJbuu44XLf0cP1qfBqxKaDSOpwRH8bxvaUXLAgMBAAE= ------END RSA PUBLIC KEY----- -",http://google-57834ac.com/,4d2b6eb7cc8cb43cc200000e,4d2b6eb6cc8cb43cc200000b,bob2f66ee4@localhost -1294692023000,1294692023000,"-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBAKuK2doYFmBhcymlxKTII8fmFUXQtgk+NxSoJqCRWds/Uhsg/S/97Kzp -DJjzYWWDKNRfHXnrKsQ5wgcis+rIuvVrB6uVVe2pWjVRZoDxC/4qy5TghwnBsf5O -9/mfN1YhZLRzHCbGL5GBDwk5+emP7Re6l4hqNZRxZB5bpssoTShdAgMBAAE= ------END RSA PUBLIC KEY----- -",http://google-6be752e.com/,4d2b6eb7cc8cb43cc2000011,,bob-person-46c7362@aol.com -1294692023000,1294692034000,"-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBANLXsDZWFFy/SyjfTcykyCZVd5raI7G+EF+2kM3yF8UAAHf3FdinP0xv -mB9LsL86PZMiVfKSYU/pwPaIDO/XccnMspd6KxHORX+SbB9F3HC5auiYeekqNxPu -GqmsgBGFLjz8FZ3pbJbuu44XLf0cP1qfBqxKaDSOpwRH8bxvaUXLAgMBAAE= ------END RSA PUBLIC KEY----- -",http://google-732b7c0.com/,4d2b6eb7cc8cb43cc2000017,4d2b6eb7cc8cb43cc2000014,bob3c6c46f@localhost -1294692023000,1294692036000,"-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBANLXsDZWFFy/SyjfTcykyCZVd5raI7G+EF+2kM3yF8UAAHf3FdinP0xv -mB9LsL86PZMiVfKSYU/pwPaIDO/XccnMspd6KxHORX+SbB9F3HC5auiYeekqNxPu -GqmsgBGFLjz8FZ3pbJbuu44XLf0cP1qfBqxKaDSOpwRH8bxvaUXLAgMBAAE= ------END RSA PUBLIC KEY----- -",http://google-8b1c74b.com/,4d2b6eb7cc8cb43cc200001b,4d2b6eb7cc8cb43cc2000018,bob457b189@localhost -1294692024000,1294692024000,"-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBAKuK2doYFmBhcymlxKTII8fmFUXQtgk+NxSoJqCRWds/Uhsg/S/97Kzp -DJjzYWWDKNRfHXnrKsQ5wgcis+rIuvVrB6uVVe2pWjVRZoDxC/4qy5TghwnBsf5O -9/mfN1YhZLRzHCbGL5GBDwk5+emP7Re6l4hqNZRxZB5bpssoTShdAgMBAAE= ------END RSA PUBLIC KEY----- -",http://google-934e10b.com/,4d2b6eb8cc8cb43cc2000020,,bob-person-5e2a1d1@aol.com -1294692034000,1294692036000,"-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBANLXsDZWFFy/SyjfTcykyCZVd5raI7G+EF+2kM3yF8UAAHf3FdinP0xv -mB9LsL86PZMiVfKSYU/pwPaIDO/XccnMspd6KxHORX+SbB9F3HC5auiYeekqNxPu -GqmsgBGFLjz8FZ3pbJbuu44XLf0cP1qfBqxKaDSOpwRH8bxvaUXLAgMBAAE= ------END RSA PUBLIC KEY----- -",http://google-105a8ed8.com/,4d2b6ec2cc8cb43cc2000034,,bob5aa0fd5@localhost diff --git a/spec/fixtures/data_conversion/post_visibilities.csv b/spec/fixtures/data_conversion/post_visibilities.csv deleted file mode 100644 index 2279143d90fc30026608d5bf9c0e19f172e4a77c..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/post_visibilities.csv +++ /dev/null @@ -1,9 +0,0 @@ -aspect_mongo_id,post_mongo_id -4d2b6eb6cc8cb43cc2000008,4d2b6ebecc8cb43cc2000027 -4d2b6eb6cc8cb43cc2000008,4d2b6ebfcc8cb43cc200002d -4d2b6eb7cc8cb43cc200000c,4d2b6ebecc8cb43cc2000027 -4d2b6eb7cc8cb43cc200000c,4d2b6ebfcc8cb43cc200002d -4d2b6eb7cc8cb43cc2000015,4d2b6ebecc8cb43cc2000029 -4d2b6eb7cc8cb43cc2000015,4d2b6ec1cc8cb43cc200002f -4d2b6eb7cc8cb43cc2000019,4d2b6ec2cc8cb43cc2000036 -4d2b6eb7cc8cb43cc2000019,4d2b6ec4cc8cb43cc2000037 diff --git a/spec/fixtures/data_conversion/posts.csv b/spec/fixtures/data_conversion/posts.csv deleted file mode 100644 index 9999d9c979319e6673ee3fcbf1d26faa78efacfe..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/posts.csv +++ /dev/null @@ -1,7 +0,0 @@ -youtube_titles,pending,created_at,public,updated_at,status_message_mongo_id,caption,remote_photo_path,remote_photo_name,random_string,image,mongo_id,type,diaspora_handle,person_mongo_id,message -"",false,1294692030000,false,1294692030000,,,,,,,4d2b6ebecc8cb43cc2000027,StatusMessage,bob1d2f837@localhost,4d2b6eb6cc8cb43cc200000a,User2 can see this -"",false,1294692030000,false,1294692030000,,,,,,,4d2b6ebecc8cb43cc2000029,StatusMessage,bob3c6c46f@localhost,4d2b6eb7cc8cb43cc2000017,User3 can see this -,false,1294692030000,false,1294692030000,4d2b6ebecc8cb43cc2000027,,,,mUKUIxkYlV,mUKUIxkYlV4d2b6ebfcc8cb43cc200002d.png,4d2b6ebfcc8cb43cc200002d,Photo,bob2f66ee4@localhost,4d2b6eb7cc8cb43cc200000e, -,false,1294692034000,false,1294692034000,,,,,AtwSOhcrt0,AtwSOhcrt04d2b6ec1cc8cb43cc200002f.png,4d2b6ec1cc8cb43cc200002f,Photo,bob3c6c46f@localhost,4d2b6eb7cc8cb43cc2000017, -,false,1294692036000,false,1294692036000,,,/uploads/images,3jcOyI5M444d2b6ec2cc8cb43cc2000036.png,,,4d2b6ec2cc8cb43cc2000036,Photo,bob5aa0fd5@localhost,4d2b6ec2cc8cb43cc2000034, -"",false,1294692036000,false,1294692036000,,,,,,,4d2b6ec4cc8cb43cc2000037,StatusMessage,bob5aa0fd5@localhost,4d2b6ec2cc8cb43cc2000034,from another server! diff --git a/spec/fixtures/data_conversion/profiles.csv b/spec/fixtures/data_conversion/profiles.csv deleted file mode 100644 index 2f57f9ae36ddccfd0216c97b7bd1973c04e9ede5..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/profiles.csv +++ /dev/null @@ -1,11 +0,0 @@ -image_url_medium,searchable,image_url,person_mongo_id,gender,diaspora_handle,birthday,last_name,bio,image_url_small,first_name -,true,,4d2b6eb6cc8cb43cc2000001,,,,weinstien,,,eugene -,true,,4d2b6eb6cc8cb43cc2000003,,,,weinstien,,,eugene -,true,,4d2b6eb6cc8cb43cc2000005,,,,weinstien,,,eugene -,true,,4d2b6eb6cc8cb43cc200000a,,,,Grimm12dfa3a,,,Robert1742367 -,true,,4d2b6eb7cc8cb43cc200000e,,,,Grimm2527144,,,Robert27d6c2c -,true,,4d2b6eb7cc8cb43cc2000011,,,,weinstien,,,eugene -,true,,4d2b6eb7cc8cb43cc2000017,,,,Grimm3089db2,,,Robert39365a5 -,true,,4d2b6eb7cc8cb43cc200001b,,,,Grimm49fb290,,,Robert405fcf8 -,true,,4d2b6eb8cc8cb43cc2000020,,,,weinstien,,,eugene -,true,,4d2b6ec2cc8cb43cc2000034,,,,Grimm50990f2,,,Robert5501643 diff --git a/spec/fixtures/data_conversion/requests.csv b/spec/fixtures/data_conversion/requests.csv deleted file mode 100644 index f20d6152776cd20d1196fa1a2ee72d073b39d51c..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/requests.csv +++ /dev/null @@ -1,3 +0,0 @@ -mongo_id,recipient_mongo_id,sender_mongo_id,aspect_mongo_id -4d2b6eb8cc8cb43cc200001e,4d2b6eb7cc8cb43cc200001b,4d2b6eb7cc8cb43cc2000017, -4d2b6ec4cc8cb43cc200003a,4d2b6eb7cc8cb43cc200000e,4d2b6ec2cc8cb43cc2000034, diff --git a/spec/fixtures/data_conversion/services.csv b/spec/fixtures/data_conversion/services.csv deleted file mode 100644 index d27bc37d0d34b11d36b13c075468154e108867c9..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/services.csv +++ /dev/null @@ -1,3 +0,0 @@ -mongo_id,type,user_mongo_id,provider,uid,access_token,access_secret,nickname -4d2b6ec4cc8cb43cc200003e,Services::Facebook,4d2b6eb7cc8cb43cc2000014,,,yeah,, -4d2b6ec4cc8cb43cc200003f,Services::Twitter,4d2b6eb6cc8cb43cc200000b,,,yeah,foobar, diff --git a/spec/fixtures/data_conversion/users.csv b/spec/fixtures/data_conversion/users.csv deleted file mode 100644 index 0eafc2198d5c1d4c599abbe69f3d23029ff75fa6..0000000000000000000000000000000000000000 --- a/spec/fixtures/data_conversion/users.csv +++ /dev/null @@ -1,169 +0,0 @@ -mongo_id,email,username,serialized_private_key,encrypted_password,invites,invitation_token,invitation_sent_at,getting_started,disable_mail,language,last_sign_in_ip,last_sign_in_at,reset_password_token,password_salt -4d2b6eb6cc8cb43cc2000007,bob1a25dee@pivotallabs.com,bob1d2f837,"-----BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDS17A2VhRcv0so303MpMgmVXea2iOxvhBftpDN8hfFAAB39xXY -pz9Mb5gfS7C/Oj2TIlXykmFP6cD2iAzv13HJzLKXeisRzkV/kmwfRdxwuWromHnp -KjcT7hqprIARhS48/BWd6WyW7ruOFy39HD9anwasSmg0jqcER/G8b2lFywIDAQAB -AoGALGz4GyreFYDVJGKQ8QrThYhCsGVAWiZTKue78TkOmxrZ/m0YtFLhOojVA9sd -/d0WtlboxzjiukTlvMyD9VFvDxVZMIS1/bSqVjTCKAetN3q2LPEfFwaHi3Uj+D66 -ulZYaf9VOd0wXREsKQB8Ri0uzlT+zTydbtr6Dnky14IfhuECQQDvGXktxLP9ywSz -avTpNHhwj0Q8aBHSJU7Ms8MCzAHATzjjxZfJCZz5xuocyrpGT18zmmQ6XJS7s8fM -WG5ykmUxAkEA4b7nDh6AxBzFAV5TdxZwThee9ZsndN4tYQmDyI1aCI9xG1lKIxbL -4N/DRyHv7CWkVCxM5L7Kn0QcqnCsYxRLuwJAMCLGvKofOncG6UAdMl336WFOcYLa -I56TMK74EbYUnCzW3TRIjJa83aRoOYeu3LzaA7+Pchh1cRyOmtsq0TIb4QJAQJ6s -9VW19m1l12Zw7f32V+RbFGM9gC65PrXCi34q75hgADwnBLRZ2B01gP8t9qMvzwh/ -WltjFQQiUIfAUPxWUQJBAMyoY38x2AP7WclMtNELAF2lUJ270uq3cxlzrGy9wJP9 -bf3qTUrqURMKgZezWW3iZke1h3vW+regHB2RBgdGmwk= ------END RSA PRIVATE KEY----- -",$2a$10$n1LF9/RgYmytvu5GYGj/Q.XhoquuQv55tdU6NrFSSxyeJabZbvk1y,4,,,true,false,en,,,,$2a$10$n1LF9/RgYmytvu5GYGj/Q. -4d2b6eb6cc8cb43cc200000b,bob21f51ad@pivotallabs.com,bob2f66ee4,"-----BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDS17A2VhRcv0so303MpMgmVXea2iOxvhBftpDN8hfFAAB39xXY -pz9Mb5gfS7C/Oj2TIlXykmFP6cD2iAzv13HJzLKXeisRzkV/kmwfRdxwuWromHnp -KjcT7hqprIARhS48/BWd6WyW7ruOFy39HD9anwasSmg0jqcER/G8b2lFywIDAQAB -AoGALGz4GyreFYDVJGKQ8QrThYhCsGVAWiZTKue78TkOmxrZ/m0YtFLhOojVA9sd -/d0WtlboxzjiukTlvMyD9VFvDxVZMIS1/bSqVjTCKAetN3q2LPEfFwaHi3Uj+D66 -ulZYaf9VOd0wXREsKQB8Ri0uzlT+zTydbtr6Dnky14IfhuECQQDvGXktxLP9ywSz -avTpNHhwj0Q8aBHSJU7Ms8MCzAHATzjjxZfJCZz5xuocyrpGT18zmmQ6XJS7s8fM -WG5ykmUxAkEA4b7nDh6AxBzFAV5TdxZwThee9ZsndN4tYQmDyI1aCI9xG1lKIxbL -4N/DRyHv7CWkVCxM5L7Kn0QcqnCsYxRLuwJAMCLGvKofOncG6UAdMl336WFOcYLa -I56TMK74EbYUnCzW3TRIjJa83aRoOYeu3LzaA7+Pchh1cRyOmtsq0TIb4QJAQJ6s -9VW19m1l12Zw7f32V+RbFGM9gC65PrXCi34q75hgADwnBLRZ2B01gP8t9qMvzwh/ -WltjFQQiUIfAUPxWUQJBAMyoY38x2AP7WclMtNELAF2lUJ270uq3cxlzrGy9wJP9 -bf3qTUrqURMKgZezWW3iZke1h3vW+regHB2RBgdGmwk= ------END RSA PRIVATE KEY----- -",$2a$10$zq/w8.JTL9VxSlwjFI/Pe.ffWpzmmmRhJ9GXPS48KBTQar5l5CIQi,5,,,true,false,en,,,,$2a$10$zq/w8.JTL9VxSlwjFI/Pe. -4d2b6eb7cc8cb43cc2000014,bob3a2252c@pivotallabs.com,bob3c6c46f,"-----BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDS17A2VhRcv0so303MpMgmVXea2iOxvhBftpDN8hfFAAB39xXY -pz9Mb5gfS7C/Oj2TIlXykmFP6cD2iAzv13HJzLKXeisRzkV/kmwfRdxwuWromHnp -KjcT7hqprIARhS48/BWd6WyW7ruOFy39HD9anwasSmg0jqcER/G8b2lFywIDAQAB -AoGALGz4GyreFYDVJGKQ8QrThYhCsGVAWiZTKue78TkOmxrZ/m0YtFLhOojVA9sd -/d0WtlboxzjiukTlvMyD9VFvDxVZMIS1/bSqVjTCKAetN3q2LPEfFwaHi3Uj+D66 -ulZYaf9VOd0wXREsKQB8Ri0uzlT+zTydbtr6Dnky14IfhuECQQDvGXktxLP9ywSz -avTpNHhwj0Q8aBHSJU7Ms8MCzAHATzjjxZfJCZz5xuocyrpGT18zmmQ6XJS7s8fM -WG5ykmUxAkEA4b7nDh6AxBzFAV5TdxZwThee9ZsndN4tYQmDyI1aCI9xG1lKIxbL -4N/DRyHv7CWkVCxM5L7Kn0QcqnCsYxRLuwJAMCLGvKofOncG6UAdMl336WFOcYLa -I56TMK74EbYUnCzW3TRIjJa83aRoOYeu3LzaA7+Pchh1cRyOmtsq0TIb4QJAQJ6s -9VW19m1l12Zw7f32V+RbFGM9gC65PrXCi34q75hgADwnBLRZ2B01gP8t9qMvzwh/ -WltjFQQiUIfAUPxWUQJBAMyoY38x2AP7WclMtNELAF2lUJ270uq3cxlzrGy9wJP9 -bf3qTUrqURMKgZezWW3iZke1h3vW+regHB2RBgdGmwk= ------END RSA PRIVATE KEY----- -",$2a$10$qGnZ/GODnmZVukDf9UC49uNgmYk9hRrtomisb0GTs559E1yxMQgvu,5,,,true,false,en,,,,$2a$10$qGnZ/GODnmZVukDf9UC49u -4d2b6eb7cc8cb43cc2000018,bob438d5bc@pivotallabs.com,bob457b189,"-----BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDS17A2VhRcv0so303MpMgmVXea2iOxvhBftpDN8hfFAAB39xXY -pz9Mb5gfS7C/Oj2TIlXykmFP6cD2iAzv13HJzLKXeisRzkV/kmwfRdxwuWromHnp -KjcT7hqprIARhS48/BWd6WyW7ruOFy39HD9anwasSmg0jqcER/G8b2lFywIDAQAB -AoGALGz4GyreFYDVJGKQ8QrThYhCsGVAWiZTKue78TkOmxrZ/m0YtFLhOojVA9sd -/d0WtlboxzjiukTlvMyD9VFvDxVZMIS1/bSqVjTCKAetN3q2LPEfFwaHi3Uj+D66 -ulZYaf9VOd0wXREsKQB8Ri0uzlT+zTydbtr6Dnky14IfhuECQQDvGXktxLP9ywSz -avTpNHhwj0Q8aBHSJU7Ms8MCzAHATzjjxZfJCZz5xuocyrpGT18zmmQ6XJS7s8fM -WG5ykmUxAkEA4b7nDh6AxBzFAV5TdxZwThee9ZsndN4tYQmDyI1aCI9xG1lKIxbL -4N/DRyHv7CWkVCxM5L7Kn0QcqnCsYxRLuwJAMCLGvKofOncG6UAdMl336WFOcYLa -I56TMK74EbYUnCzW3TRIjJa83aRoOYeu3LzaA7+Pchh1cRyOmtsq0TIb4QJAQJ6s -9VW19m1l12Zw7f32V+RbFGM9gC65PrXCi34q75hgADwnBLRZ2B01gP8t9qMvzwh/ -WltjFQQiUIfAUPxWUQJBAMyoY38x2AP7WclMtNELAF2lUJ270uq3cxlzrGy9wJP9 -bf3qTUrqURMKgZezWW3iZke1h3vW+regHB2RBgdGmwk= ------END RSA PRIVATE KEY----- -",$2a$10$35yqJfo2RHCZIDrkNSWvYebxt7Ac5HULdn0ZVNS/4onPqEWmdsDKm,5,,,true,false,en,,,,$2a$10$35yqJfo2RHCZIDrkNSWvYe -4d2b6eb8cc8cb43cc2000024,random@example.com,,"-----BEGIN RSA PRIVATE KEY----- -MIIJJwIBAAKCAgEAr6Zg031vZaArv+1W6WjTKg2Kg2ifuK2dh+fmM/vWJxwnaJpB -WWDUkdUx8dG9jN1E2DQKApYzhxToP2XTZg9fsd7J322Ah3AjXJ7GSycHsJpXUdDZ -GCf16iDgvGq4SKd+UreZxhLFybjl91yeH0oKB2Lv9aFJS079zjKUU4IEDNWbgw7D -mqiVjRA1E7osVX40eD/nkmjBuPMoZyTa9ibN2TldQCqWGxwztHrFW+ap54hpghw6 -ilRWsBt38b3ORTdJgHo3jQWZz5d7llFHKakyylLais0KSmQ5j3c+gXQYJ74Qw/yR -aW2DhEYxOcRc9sxDvHS0fQqLfx6+0ijaaWKZCFqYqoylOWf+CyQHZG5NmgI6wj29 -Aj01a9cpzwswb51yO23/TITC4siC4i5HKDTcnnUQIzuX/uoLW1jsyN4Ot6/qaMYa -B6nmP750DVqMO5BXFr6H33/ga309b71ipIxONLXW0cK8ugns4/L4jV3GarzXWaXG -eoMebwDK6FhQnMyR+/+HKpMiqvwALPCVbfgUgqhKJQ+vvQ8utNwrvnA0X0YiP2EB -eEz0Ie1VSwL1Y0DCfs/WbKCq+EdfstMlpDhRVn3yTfR7lu1yiOG++wKQ/Hx9lzQ5 -2REgfNcNR8pRzLfdA4JjHwW95vK1qhNgGPc3mvLs1VBZ6xQcJw9VG1vNJhECAwEA -AQKCAgAzBmQOS9v2a6cJ5AphV6AwESrxrYzoexbOCiGnbDrztYwFKPpe2nAlxQbz -NniX2RdMryFRSwzA6uPkttHITiMAarW9//NcZMkA+OalojrrpIpFLCREjicz0kU2 -ttG92Voq8UbscTufs+SqDO+qKznql2UZt7aw98tnAO5xq809ZTf9xGYyIVMAXXrt -tiF23GilnfrJX0EXVxufiudIplEaDz31i+l7CqBCh3+ZiNJGfiwYLdcbpBBirDgV -s4ueM8dYWSiWANCDq3+tVQMVKR+mApeVxqZ8oczOzlcMCAuUT/RS2qXrOHMCE9ns -7AwNbZ0nu8dKo6uOTAImztNT1d6aQVT5XF4OxWyim73h2lp2udckUpmArdtpDqWJ -x341PjbrQuRpg89ovwENJLz6c58S5uI8lFUOA5cVYkC8j0GJglXA5keF9GnDi+eF -ITAzv9dCT6LJfweNX9lPLFKujIr7jTvnaNaRc6R8lacJbFY1WpxhrjyT/OI40586 -72SpsQBjwyHaErCixpZxW1lEhrLnv3s7K7YJWL4xWiwEwqtrIui7btG9eJ1G/dzY -adxQKGtdYmWqSBKun9ADZhzwx5DLdgshc8SRG8VqfkktepaoRV0IkkCpsNM/Om3+ -qoLau03LCLnP5FjV99+TtbMMeH+EF3dkysGVgd7xxDYYtTHNGQKCAQEA3ZtGdajy -h+lTEj32jZKXvuSJhBkXlwazFCtOfWo5xoj0w+0EH2V00o9GeaDKpvkHymkReXjG -YiTaXk3INwiY0zA8vmPwigFdOJnQrfn0cCBWHsvUiPDVFWsdJZmHYd4c6eKiU2Sg -j+o/Nyl+KUrzDhITERlhBvxuBZxiAMisG8gKAUhUjVcxrMfbSdzR+I673GSls1tw -vXfXVgZdeAwD9HslSXdwK3GIXw+V355nLIXn2at9r7s5wOJ2aRoUz3rc1r9ctHgo -xq+rVmaRif3qFmwyXAa4fFyoLB+T9UXiY7nB2XfZ/vCDQ7L/V906hQwL2zBXT4t5 -HUMuS8SxOpoP6wKCAQEAyukvQLSJTzaT3ZtP6kzkWnCuw7pNP+eu+L8U1MYDHM4z -hMY/yXoyvEtjCzEX6zBxgBCUgdnpUhJTx6EW3dvOgYOdfmMREwrwl7jtySQwlqPA -BTBzLf/11QAU7k3gNVzqo7OUCKoswafZA0wL2gtMbULrKUJ9iUftfEUpY6pZchJp -yJkTHhjamA7uM5uzULjQhtj00bQbEQqcVD1vnfsmtfDQCHaHrrD/HhMQMLI1HEjG -bpVC7u70d5vFU+g8prLhleYBsmQ8Ql+0iR4cINGkROriGPhCCyov3kB+OfwO7b8u -UP4WOsceczSIgbTqZI/q+ZGRCrK9wff8IxCoXvee8wKCAQAnbjJ6SwZkcnqqe0X8 -aMIBYE6rp39QCwwgIZiErjr7fXD3z5t1Lqs7r+ydRaPpU9Q0Cr/mOjwqSF5mezaN -vETdBu83/TZWh+mbYZsE6b25mbdZIXF+sENp3TZBc3DoVAoW/5Fcf0ImeUqoOQTO -uhxHO6YS284s3QuCihHSC+K7yrslAUayI3qeQK1fFiByNotsqqflIvcLb2BsWROW -gaTOgn7e9JaL1Fase2xybo/zFxxq2Z2ygADFtkXVa6OaS0UyHLiVD/BJcgZtiDCL -OhfFx5iqUTPQRPhTaYb9FGM01V+Nn0q1lvv0NsxCSQXZmIwfgxl1+N4i+8ooByZ1 -w+XjAoIBADVLK6MGB+5rOkkBKusyCOQMJoq32uRG+LjSjykXXOfq7LMZ0tUbKEo2 -Tqw417xo+9aUBD1au6JXt/N9xuC8g6+Wnv38DRcAT5K5+pJS1AQsvBlg0U+qo6mv -HNA+Wf4KCoK2ftILyDeQ2zm3doFtaERmSBeNJCWzY5e5HpbTvixs06XhNpk4E+nO -OhgJ8/3mnLZeM2cEs/s02zxw6mkG9vLgbfNbFmX2jPscLKttku972cpfn7Xbww/L -NPfFznBGGWPihl2RYBZaxrMg2mhwR4HmYz4Frmr6SJpKPB0Eq/MbvJF/Ot1zQPcn -PBc9KjcBacjkx8CUk6xncqzPCjnvNasCggEAfwocA/YL8iZWFaOLmVLhuyN9dLvP -MsMyx51b9eeg8ux95+MUwPZEBovqsI6ziCWDgTbkVttx+SxYdcDA5ckHbAC8MYNK -4xEpyDTT8rwQpCW7+42iNdqsSGnH4TVLC2u4Pbk3mvpX1wDcrqMmJN/G3mKIj6YY -u4azxx/SEPCWI3qZt/laBixhSM5jdyWq6y0ht/DFpdWQJ1hKR8vpnVi+ZSFZmUkO -S/KiO2fMmKF6aOQgGVBHSdQTUxPAc5sD+O6CpRj/VedGQko2x8kGNpm53LIox/nU -gO38qEEvOx0uymkh7LriH9NkMxkdCghw4mwCUvyrOTymFnOGs2OMR1bmsQ== ------END RSA PRIVATE KEY----- -","",3,wY567RLhNsA8pp4SnnFa,1294617600000,true,false,en,,,,"" -4d2b6ebccc8cb43cc2000025,random2@example.net,,"-----BEGIN RSA PRIVATE KEY----- -MIIJJwIBAAKCAgEAmq6rTmlfmjfXSMCUcTQ55JUT180G6ZP3KUsHY5bmQm9F7cc6 -W+RvpuAqnFgq8tEuqWz8bpzPmYpy9uFh+kY7LJfi4mW+aBFRNYsfsKPy8ckhItVl -HYsAOCBABwxRAeXDgKMabAhkMMYHvJn2tDgWeEoctjf89eovcCWXjm0HAmiDY50s -F0VhRFZ3YpaNBEMCuC/icj1w0c2Cx72MWPxIMdm4Do2Mhv5lmaK5Br/URtcG00Yz -B7xqsG3/YVpvL5jL1LSGJnuCiOYKZ6rfXwJy57jm0MEXpNh1YeemI/PtSsp7x00i -dqjsqh3FOE9NWZAoS+GwnmIRoL0VCR2ly4pVDBa8lNUwydz8JUXPDVU7xVxM4ams -MPBOK1e7Yb0Ev5tObVjmAY/hhwrawga413zVddkejxiMR1RktORywjJrDBV1tQgv -1eohQON+MAknFR5N7Q8w+/oeAwnSo5BL+qomL2kxvclAAdvMD8hJ1H2ZuqWsI5Ex -lfSsPdErJ2KElhVbM9Zh8wSpizDB2HdKCkjQglpsX8MgeyXA1EWiiRvNd2b6OoPn -WX12QGUFkUFSPW6cW0lUmg7g26+jGwoC0NPV9lvg/yJccLXqYbRMGiNZze1bHt9J -K5LTmDxIvyyxjxDhzwUifqOfIHSpSpHvjLobsuMUV40f2H5LrD+aP4249rUCAwEA -AQKCAgBlCMg+LFfUzLqi+586HineY32VjIcCVLKxVx+ZbjwykqnzeRlmYlyHfI54 -lqJe/kFjSxvLSEPVf3g+R9MOfYczRnZc+KYZJY6M0bW+VChgw8YQEaC9XkijYHVR -5TqYabJ8OI0OmaCPtxngmBRrfOM4aPg+EW36Vp/rubI3xoE4knmXvFbLUHcLAwtx -6vJrITYKhsR7aCRj9b+Bpg6hJRAm95Xgc5ahqlNEuePvQ6dtKhB8ObMlT23EleSk -e0R6q2wgIFYrlqsZrmCHfDXwwhG5x62EF0vRUc3CSGPdwftxybZ15K0pIoeLSmzC -rhHQ+XdIsT8DBP2Mp1SxIptjypRnkBAFyTju8vAMQg+vsbysD6AdSmC5PEdiEMAE -FOqdqKsxqlK0E/NY5TdYL3aVvoTTHq/gW5mumhoNdfpn9LuzdRxeF+jIYUk6Hy21 -2feyey3npXBn/3DlV6RmLjLXad/XvMwXh9pAN6eXp3tmNVk7G8w2z19E5+ZJuXYt -+EXWLZo1vGw0pV/Ud+3mJYMcQcH1WvCXmImvuQdMqmX6brCTPbrrQl8ABUw2q524 -kLlnnJJ4Rzc896QwQxT1XdDqot1rIO2GgE2yIu6KKxJWfLlGagcStzj/AkR65vIM -miZkCj7p6qUvVl1eQ2xviaTb8PvQK0gz7KjpQCuRvuEEd+Hl1QKCAQEAx/QrCztG -ydX8fwCu1b6F4f53L78BCW+20A+jSVGr5hPByQrgNBbxd+ddHXPBrTr7ivIYTJ3y -jiH1kbDiIA876U0kglPXFsZ3vnCNefC7cYRMlRLhGNMeemrddau/DejwSjo96jP+ -DaqXXRaLTnFKd80KxouLzhuYxaPR9g1DR9dMsWqU5dx17M8Q7n48GBu4GcTAC6uY -3xV2vmYfN8jULyfl7EcSkNegSFhfMnZqqUaXN5PYlN8ImnKYFwLyM2Pr6s1GvhtT -VNphnylNUE3a9jQ/G42f6tBT+XXl05edJcOrqPDK/Ab1WWPPeAfADKS/Njg4Q/mS -B3gWLeSTneWlJwKCAQEAxgoDK8NWBQ82Knf6juRzpHRisutB/gh3B2kFvOaL1s9C -7U7y73FyyHeg/Bpxt07UKCIBEinq/uP6zCcg7vyu08nE5BeX+biGY85NmUq3dAgu -oiZNKeBfWeCBfPRRkNhd37zfUtt6Y8WOjS+s9KA3KyR7pJhkEFvgY6xeBtTghaQt -PfbjibuIIAW2c7ta3EG1uopLC9x8TqELjTyELR2bGdXUOQcVIuI9Pwf84l8GFpPL -doGn/Th6tz5Aa10o+0MvWCEQ2QNdfxqH9T7sGF25Kep8ejTHA/ahEr336Y5noaZP -LLc3/v+qjHHqOiq+7gSPJrsUY/E/idhUQMIh73DGwwKCAQAdZ9Uks7T3XdbiPpF3 -sasyzx9sECTw5FL4SjRzReWH0oP/MvBB+NXOEmJpQGrNNQ1lI7FbIydWq7vXjzHS -ESt4ZfXmjLnnCYz2nsrPkg2e5hv1GG+uHO4whqLG+VkBjK453FLarIbCL8JO2E/o -W1TeRXM+O6t1xi0zc6IfE1g/qnQG62u2WjOlfdY5nKrtyLXMZFjx3mx+8kMiQRZ6 -N7isrqtrkhAy6OMTgJuPakbJWi5G6CFD04EKZavkRnSkBh/dyg6LSq14nx0YMRTD -qI95Abn+LVfFSpnu593CvltIAHywPak8YzGV0c3jExC1S00rhh0QMhW9r3Vjjmf/ -IpSlAoIBAE7+HWeuYbhg6e0ksEeg7lOxrNDLMCaA/+Fvzb8cgrjrMTnxHMvPh8ZY -mVkVvzgr9EoRzjWNjNOg4h/el69cEOwfdi65DoCoTsqutpsnh2d8AAXjmzHR8paq -C1xpI8PP2hntf3LQYtA7M/IzCx0Ebx0BT2RG+Nrhmu6HCXZWITyNURJ/USFWMST8 -wlsFZ2elujQvB2Iyz06ZxD7Q3bQVNBGpDh61KYQhk+Z5bDBrUMVerHCXpQdHKQPA -i/eHUFpw4QiZH9xAEGIrlgGH2Kqbb8k9Y+tm898r1/He3m1FxSZgbQJcDrTjDAc7 -RP9wn3nXTbZYNvjqeLqmFG1EQj78z/sCggEAObB/itRxT0G3PtNGoAymW7/l/dhs -8H0BSQKjSQyrP8l4eUIWu4e92jdklOmEzba1+RdMr7sAbBeFn9DfUON3/cBVLV4u -l++D+DbL0abIel07SwsyGkCsajxXazF/6lMrYIiMBCV2sE/13CRIxBHcMRM84XCt -00VwoxJpwEVhkiGTK/ckSj3+QzP2u2FF1WpqmHLOH7iYxnhO8JyypI92eM2TKxi8 -tKWyjWisXwQmbigurNXqBFmMz+kSBpsskjgHxLRu/JQogl6avKMQ/jTBZLSKF0Ds -KbFEI6SXfIxjp0engFRaf0EdVenig52hS4dml+GaagOh71VzljLOTEKUUw== ------END RSA PRIVATE KEY----- -","",5,aA1hEEz6V7btITaZUJKT,1294617600000,true,false,en,,,,"" diff --git a/spec/fixtures/jwks.json b/spec/fixtures/jwks.json new file mode 100644 index 0000000000000000000000000000000000000000..be157aeec7c8fc65f1e7858309583968a72d7d3e --- /dev/null +++ b/spec/fixtures/jwks.json @@ -0,0 +1 @@ +{"keys": [{"use": "enc", "e": "AQAB", "d": "lZQv0_81euRLeUYU84Aodh0ar7ymDlzWP5NMra4Jklkb-lTBWkI-u4RMsPqGYyW3KHRoL_pgzZXSzQx8RLQfER6timRWb--NxMMKllZubByU3RqH2ooNuocJurspYiXkznPW1Mg9DaNXL0C2hwWPQHTeUVISpjgi5TCOV1ccWVyksFruya_VNL1CIByB-L0GL1rqbKv32cDwi2A3_jJa61cpzfLSIBe-lvCO6tuiDsR4qgJnUwnndQFwEI_4mLmD3iNWXrc8N-poleV8mBfMqBB5fWwy_ZTFCpmQ5AywGmctaik_wNhMoWuA4tUfY6_1LdKld-5Cjq55eLtuJjtvuQ", "n": "tx3Hjdbc19lkTiohbJrNj4jf2_90MEE122CRrwtFu6saDywKcG7Bi7w2FMAK2oTkuWfqhWRb5BEGmnSXdiCEPO5d-ytqP3nwlZXHaCDYscpP8bB4YLhvCn7R8Efw6gwQle24QPRP3lYoFeuUbDUq7GKA5SfaZUvWoeWjqyLIaBspKQsC26_Umx1E4IXLrMSL6nkRnrYcVZBAXrYCeTP1XtsV38_lZVJfHSaJaUy4PKaj3yvgm93EV2CXybPti7CCMXZ34VqqWiF64pQjZsPu3ZTr7ha_TTQq499-zYRQNDvIVsBDLQQIgrbctuGqj6lrXb31Jj3JIEYqH_4h5X9d0Q", "q": "1q-r-bmMFbIzrLK2U3elksZq8CqUqZxlSfkGMZuVkxgYMS-e4FPzEp2iirG-eO11aa0cpMMoBdTnVdGJ_ZUR93w0lGf9XnQAJqxP7eOsrUoiW4VWlWH4WfOiLgpO-pFtyTz_JksYYaotc_Z3Zy-Szw6a39IDbuYGy1qL-15oQuc", "p": "2lrYPppRbcQWu4LtWN6tOVUrtCOPv1eLTKTc7q8vCMcem1Ox5QFB7KnUtNZ5Ni7wnZUeVDfimNebtjNsGvDSrpgIlo9dEnFBQsQIkzZ2SkoYfgmF8hNdi6P-BfRjdgYouy4c6xAnGDgSMTip1YnPRyvbMaoYT9E_tEcBW5wOeoc", "kid": "a0", "kty": "RSA"}, {"use": "sig", "e": "AQAB", "d": "DodXDEtkovWWGsMEXYy_nEEMCWyROMOebCnCv0ey3i4M4bh2dmwqgz0e-IKQAFlGiMkidGL1lNbq0uFS04FbuRAR06dYw1cbrNbDdhrWFxKTd1L5D9p-x-gW-YDWhpI8rUGRa76JXkOSxZUbg09_QyUd99CXAHh-FXi_ZkIKD8hK6FrAs68qhLf8MNkUv63DTduw7QgeFfQivdopePxyGuMk5n8veqwsUZsklQkhNlTYQqeM1xb2698ZQcNYkl0OssEsSJKRjXt-LRPowKrdvTuTo2p--HMI0pIEeFs7H_u5OW3jihjvoFClGPynHQhgWmQzlQRvWRXh6FhDVqFeGQ", "n": "zfZzttF7HmnTYwSMPdxKs5AoczbNS2mOPz-tN1g4ljqI_F1DG8cgQDcN_VDufxoFGRERo2FK6WEN41LhbGEyP6uL6wW6Cy29qE9QZcvY5mXrncndRSOkNcMizvuEJes_fMYrmP_lPiC6kWiqItTk9QBWqJfiYKhCx9cSDXsBmJXn3KWQCVHvj1ANFWW0CWLMKlWN-_NMNLIWJN_pEAocTZMzxSFBK1b5_5J8ZS7hfWRF6MQmjsJcz2jzA21SQZNpre3kwnTGRSwo05sAS-TyeadDqQPWgbqX69UzcGq5irhzN8cpZ_JaTk3Y_uV6owanTZLVvCgdjaAnMYeZhb0KFw", "q": "5E5XKK5njT-zzRqqTeY2tgP9PJBACeaH_xQRHZ_1ydE7tVd7HdgdaEHfQ1jvKIHFkknWWOBAY1mlBc4YDirLShB_voShD8C-Hx3nF5sne5fleVfU-sZy6Za4B2U75PcE62oZgCPauOTAEm9Xuvrt5aMMovyzR8ecJZhm9bw7naU", "p": "5vJHCSM3H3q4RltYzENC9RyZZV8EUmpkv9moyguT5t-BUGA-T4W_FGIxzOPXRWOckIplKkoDKhavUeNmTZMCUcue0nkICSJpvNE4Nb2p5PZk_QqSdQNvCasQtdojEG0AmfVD85SU551CYxJdLdDFOqyK2entpMr8lhokem189As", "kid": "a1", "kty": "RSA"}, {"use": "sig", "crv": "P-256", "kty": "EC", "y": "Yg4IRzHBMIsuQK2Oz0Uukp1aNDnpdoyk6QBMtmfGHQQ", "x": "L0WUeVlc9r6YJd6ie9duvOU1RHwxSkJKA37IK9B4Bpc", "kid": "a2"}, {"use": "enc", "crv": "P-256", "kty": "EC", "y": "E6E6g5_ziIZvfdAoACctnwOhuQYMvQzA259aftPn59M", "x": "Yu8_BQE2L0f1MqnK0GumZOaj_77Tx70-LoudyRUnLM4", "kid": "a3"}]} \ No newline at end of file diff --git a/spec/fixtures/public_posts.json b/spec/fixtures/public_posts.json index 4d4cc1812f5795a2d7e9385d772f7a3e6cb28796..a8aff71124b66f82bbfd569fdde2484343776b34 100644 --- a/spec/fixtures/public_posts.json +++ b/spec/fixtures/public_posts.json @@ -1 +1 @@ -[{"id":15086,"guid":"198095988ad26f21","text":"test of #left4dead on #linux results in \"faster zombies\" http://is.gd/uHeUC6 with linux outperforming windows","public":true,"created_at":"2012-08-02T22:13:16Z","interacted_at":"2012-08-03T15:02:59Z","provider_display_name":null,"post_type":"Reshare","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":{"id":15028,"guid":"1b2a98db23582947","text":"test of #left4dead on #linux results in \"faster zombies\" http://is.gd/uHeUC6 with linux outperforming windows","public":true,"created_at":"2012-08-02T14:25:56Z","interacted_at":"2012-08-02T21:54:53Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":1769,"guid":"a2f9a3a7cb3dcd5a","name":"el [spare pope] olmo","diaspora_id":"el_olmo@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_343f6520778765c4b3f9.jpg","medium":"https://pod.fulll.name/uploads/images/thumb_medium_343f6520778765c4b3f9.jpg","large":"https://pod.fulll.name/uploads/images/thumb_large_343f6520778765c4b3f9.jpg"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":null,"title":"test of #left4dead on #linux results in \"faster zombies\" http://is.gd/uHeUC6 with linux outperforming windows","next_post":"/posts/15028/next","previous_post":"/posts/15028/previous","interactions":{"likes":[{"id":32638,"guid":"b2c1e789b1eec9ea","author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"created_at":"2012-08-02T21:54:53Z"}],"reshares":[{"reshare":{"actor_url":null,"author_id":2,"comments_count":0,"created_at":"2012-08-02T22:13:16Z","diaspora_handle":"raven24@pod.fulll.name","favorite":false,"frame_name":null,"guid":"198095988ad26f21","id":15086,"image_height":null,"image_url":null,"image_width":null,"interacted_at":"2012-08-03T15:02:59Z","likes_count":2,"o_embed_cache_id":null,"objectId":null,"object_url":null,"pending":false,"processed_image":null,"provider_display_name":null,"public":true,"random_string":null,"remote_photo_name":null,"remote_photo_path":null,"reshares_count":0,"root_guid":"1b2a98db23582947","status_message_guid":null,"text":null,"unprocessed_image":null,"updated_at":"2012-08-03T15:02:59Z"}}],"comments_count":0,"likes_count":6,"reshares_count":1}},"title":"A post from Florian Staudacher","next_post":"/posts/15086/next","previous_post":"/posts/15086/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":2,"reshares_count":0,"comments":[]}},{"id":14755,"guid":"0ffef04549e81bfa","text":"... in case you ever need the network device name, ip and mac address, here you go: \r\nhttps://gist.github.com/3202188\r\n\r\n(uses ifconfig, grep and sed with some regular expression magic) \r\n#bash #script #network #ip #grep #sed #regexp #linux","public":true,"created_at":"2012-07-29T22:28:17Z","interacted_at":"2012-08-01T18:01:49Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"note","root":null,"title":"... in case you ever need the network device name, ip and mac address, here you go: \r\nhttps://gist.github.com/3202188\r\n\r\n(uses ifconfig, grep and sed with some regular expression magic) \r\n#bash #script #network #ip #grep #sed #regexp #linux","next_post":"/posts/14755/next","previous_post":"/posts/14755/previous","interactions":{"likes":[],"reshares":[],"comments_count":8,"likes_count":4,"reshares_count":0,"comments":[{"id":20912,"guid":"ba86c52ca4d293c4","text":"It only shows network devices named eth* and doesn't work with localized versions of ifconfig in non-english language environments","author":{"id":6243,"guid":"c7bf295dae900b7a","name":"Florian Diesch","diaspora_id":"diesch@joindiaspora.com","avatar":{"small":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_small_7f090bd1002004896464.png","medium":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_medium_7f090bd1002004896464.png","large":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_7f090bd1002004896464.png"}},"created_at":"2012-07-30T02:33:06Z"},{"id":21012,"guid":"81fc5d869de5ea05","text":"For now, I only need it just the way it is (in my collection of VM management scripts), but feel free to change it to work with whatever version or language of `ifconfig` you need. I leave that \"as an exercise to the reader\" ... it's always a good time to start learning `sed` regular expressions \n;)","author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"created_at":"2012-07-31T01:51:24Z"},{"id":21164,"guid":"d74aac53420cd66f","text":"[inxi](https://code.google.com/p/inxi/)","author":{"id":3920,"guid":"b636315dc6f90ece","name":"Kiridesce","diaspora_id":"iridesce@kosmospora.net","avatar":{"small":"https://kosmospora.net/uploads/images/thumb_small_7b3c16e2107449bf9717.jpeg","medium":"https://kosmospora.net/uploads/images/thumb_medium_7b3c16e2107449bf9717.jpeg","large":"https://kosmospora.net/uploads/images/thumb_large_7b3c16e2107449bf9717.jpeg"}},"created_at":"2012-08-01T18:01:49Z"}]}},{"id":14514,"guid":"c6b5e0a20421d719","text":"lol! \r\nhttp://youtu.be/6RrpGgaT5kk\r\n\r\n#acapella #movie #dub","public":true,"created_at":"2012-07-27T14:09:31Z","interacted_at":"2012-07-28T21:25:56Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":{"data":{"provider_url":"http://www.youtube.com/","thumbnail_url":"http://i3.ytimg.com/vi/6RrpGgaT5kk/hqdefault.jpg","title":"'The Matrix' Lobby Scene with A capella Multitrack - Matt Mulholland","html":"<iframe width=\"420\" height=\"236\" src=\"http://www.youtube.com/embed/6RrpGgaT5kk?fs=1&feature=oembed\" frameborder=\"0\" allowfullscreen></iframe>","author_name":"mattmulholland26","height":236,"thumbnail_width":480,"width":420,"version":"1.0","author_url":"http://www.youtube.com/user/mattmulholland26","provider_name":"YouTube","type":"video","thumbnail_height":360,"trusted_endpoint_url":"http://www.youtube.com/oembed"}},"mentioned_people":[],"photos":[],"frame_name":"status","root":null,"title":"lol! \r\nhttp://youtu.be/6RrpGgaT5kk\r\n\r\n#acapella #movie #dub","next_post":"/posts/14514/next","previous_post":"/posts/14514/previous","interactions":{"likes":[],"reshares":[],"comments_count":1,"likes_count":2,"reshares_count":0,"comments":[{"id":20833,"guid":"3c2d21708b6cfa29","text":"Inception Trailer A Capella Re-Dub: http://www.youtube.com/watch?v=d2yD4yDsiP4","author":{"id":2896,"guid":"24e82915d58368fe","name":"Alexey Andreyev","diaspora_id":"yetanotherandreyev@diasp.org","avatar":{"small":"https://diasp.org/uploads/images/thumb_small_9f29c5326741a32889fa.jpg","medium":"https://diasp.org/uploads/images/thumb_medium_9f29c5326741a32889fa.jpg","large":"https://diasp.org/uploads/images/thumb_large_9f29c5326741a32889fa.jpg"}},"created_at":"2012-07-28T21:25:56Z"}]}},{"id":14113,"guid":"4404d1bb88d36735","text":"Keep Calm and use #Linux <br> [  ](http://goo.gl/HSS18) <br>","public":true,"created_at":"2012-07-23T15:50:00Z","interacted_at":"2012-07-24T15:16:25Z","provider_display_name":null,"post_type":"Reshare","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":{"id":14099,"guid":"d1970bb173aae310","text":"Keep Calm and use #Linux <br> [  ](http://goo.gl/HSS18) <br>","public":true,"created_at":"2012-07-23T13:12:51Z","interacted_at":"2012-07-23T13:37:24Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":175,"guid":"4d11bd252c174338f2002a4c","name":"\u24b6\u24c5\u24c4\u24c1\u24c4\u24c3\u24be\u24c8 \u2301 \u24b6\u24c5\u24bd\u24c7\u24c4\u24b9\u24be\u24c8\u24be\u24b6","diaspora_id":"apolonisaphrodisia@joindiaspora.com","avatar":{"small":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_small_8107d3419ac23bd16253.gif","medium":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_medium_8107d3419ac23bd16253.gif","large":"https://pod.fulll.name/images/user/default.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":null,"title":"Keep Calm and use #Linux <br> [  ](http://goo.gl/HSS18) <br>","next_post":"/posts/14099/next","previous_post":"/posts/14099/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":2}},"title":"A post from Florian Staudacher","next_post":"/posts/14113/next","previous_post":"/posts/14113/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":2,"reshares_count":1,"comments":[]}},{"id":14110,"guid":"bb89c419e60fd801","text":"awesome #youtube #video \r\nhttp://youtu.be/daVDrGsaDME\r\n\r\n#car #engine #stopmotion","public":true,"created_at":"2012-07-23T15:05:36Z","interacted_at":"2012-07-24T12:48:48Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":{"data":{"provider_url":"http://www.youtube.com/","thumbnail_url":"http://i1.ytimg.com/vi/daVDrGsaDME/hqdefault.jpg","title":"11 Months, 3000 pictures and a lot of coffee.","html":"<iframe width=\"420\" height=\"315\" src=\"http://www.youtube.com/embed/daVDrGsaDME?fs=1&feature=oembed\" frameborder=\"0\" allowfullscreen></iframe>","author_name":"nothinghereok","height":315,"thumbnail_width":480,"width":420,"version":"1.0","author_url":"http://www.youtube.com/user/nothinghereok","provider_name":"YouTube","type":"video","thumbnail_height":360,"trusted_endpoint_url":"http://www.youtube.com/oembed"}},"mentioned_people":[],"photos":[],"frame_name":"status","root":null,"title":"awesome #youtube #video \r\nhttp://youtu.be/daVDrGsaDME\r\n\r\n#car #engine #stopmotion","next_post":"/posts/14110/next","previous_post":"/posts/14110/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":1,"reshares_count":0,"comments":[]}},{"id":12830,"guid":"5a4089375be2db14","text":"jQuery Core: Version 1.9 and Beyond - http://blog.jquery.com/2012/06/28/jquery-core-version-1-9-and-beyond/ - \r\n_jQuery 2.0: This version will support the same APIs as jQuery 1.9 does, but removes support for IE 6/7/8 oddities such as borked event model, IE7 \u201cattroperties\u201d, HTML5 shims, etc. \r\nOur goal is for 1.9 and 2.0 to be interchangeable as far as the API set they support. When 2.0 comes out, your decision on which version to choose should be as simple as this: If you need IE 6/7/8 support, choose 1.9; otherwise you can use either 1.9 or 2.0._ \r\nI hope IE dies a quick but painfull death... \r\n#jquery #ie #browser #web","public":true,"created_at":"2012-07-13T20:36:35Z","interacted_at":"2012-07-13T20:36:35Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"note","root":null,"title":"jQuery Core: Version 1.9 and Beyond - http://blog.jquery.com/2012/06/28/jquery-core-version-1-9-and-beyond/ - \r\n_jQuery 2.0: This version will support the same APIs as jQuery 1.9 does, but removes support for IE 6/7/8 oddities such as borked event model, IE7 \u201cattroperties\u201d, HTML5 shims, etc. \r\nOur goal is for 1.9 and 2.0 to be interchangeable as far as the API set they support. When 2.0 comes out, your decision on which version to choose should be as simple as this: If you need IE 6/7/8 support, choose 1.9; otherwise you can use either 1.9 or 2.0._ \r\nI hope IE dies a quick but painfull death... \r\n#jquery #ie #browser #web","next_post":"/posts/12830/next","previous_post":"/posts/12830/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":0,"comments":[]}},{"id":12763,"guid":"82adaf03843115e8","text":"http://www.evolutionoftheweb.com\r\n\r\n\r\n\r\n#www #web #ITNews #Browser #Internet #technology #IT","public":true,"created_at":"2012-07-13T09:30:02Z","interacted_at":"2012-07-29T23:46:30Z","provider_display_name":null,"post_type":"Reshare","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":{"id":12751,"guid":"389f84ae16581df6","text":"http://www.evolutionoftheweb.com\r\n\r\n\r\n\r\n#www #web #ITNews #Browser #Internet #technology #IT","public":true,"created_at":"2012-07-12T17:34:10Z","interacted_at":"2012-07-13T05:49:09Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":4079,"guid":"bfe281001b5a8561","name":"Anonymiss","diaspora_id":"anonymiss@despora.de","avatar":{"small":"https://despora.de/uploads/images/thumb_small_d25c7b27e7bbf307a8cc.jpg","medium":"https://despora.de/uploads/images/thumb_medium_d25c7b27e7bbf307a8cc.jpg","large":"https://despora.de/uploads/images/thumb_large_d25c7b27e7bbf307a8cc.jpg"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":null,"title":"http://www.evolutionoftheweb.com\r\n\r\n\r\n\r\n#www #web #ITNews #Browser #Internet #technology #IT","next_post":"/posts/12751/next","previous_post":"/posts/12751/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":1}},"title":"A post from Florian Staudacher","next_post":"/posts/12763/next","previous_post":"/posts/12763/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":2,"reshares_count":0,"comments":[]}},{"id":12463,"guid":"cb0a304194c719d8","text":"Relativistic Baseball - http://what-if.xkcd.com/1/ - \r\nWhat would happen if you tried to hit a baseball pitched at 90% the speed of light? \r\n#xkcd #whatif","public":true,"created_at":"2012-07-10T09:31:54Z","interacted_at":"2012-07-29T23:52:08Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":null,"title":"Relativistic Baseball - http://what-if.xkcd.com/1/ - \r\nWhat would happen if you tried to hit a baseball pitched at 90% the speed of light? \r\n#xkcd #whatif","next_post":"/posts/12463/next","previous_post":"/posts/12463/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":3,"reshares_count":1,"comments":[]}},{"id":12349,"guid":"b16efb0fc6427338","text":"yay, new \"simon's cat\"! \r\n \r\nhttp://youtu.be/XrivBjlv6Mw \r\n#simonscat #cat","public":true,"created_at":"2012-07-09T12:03:38Z","interacted_at":"2012-07-10T21:59:32Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":{"data":{"provider_url":"http://www.youtube.com/","thumbnail_url":"http://i1.ytimg.com/vi/XrivBjlv6Mw/hqdefault.jpg","title":"Simon's Cat in 'Window Pain'","html":"<iframe width=\"420\" height=\"236\" src=\"http://www.youtube.com/embed/XrivBjlv6Mw?fs=1&feature=oembed\" frameborder=\"0\" allowfullscreen></iframe>","author_name":"simonscat","height":236,"thumbnail_width":480,"width":420,"version":"1.0","author_url":"http://www.youtube.com/user/simonscat","provider_name":"YouTube","type":"video","thumbnail_height":360,"trusted_endpoint_url":"http://www.youtube.com/oembed"}},"mentioned_people":[],"photos":[],"frame_name":"status","root":null,"title":"yay, new \"simon's cat\"! \r\n \r\nhttp://youtu.be/XrivBjlv6Mw \r\n#simonscat #cat","next_post":"/posts/12349/next","previous_post":"/posts/12349/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":2,"reshares_count":1,"comments":[]}},{"id":12172,"guid":"198034364c7226a1","text":"Ex-Nokia staff to build MeeGo-based smartphones - http://www.theverge.com/2012/7/7/3143099/jolla-meego-startup-ex-nokia-employees - \r\n_A group of ex-Nokia staff and MeeGo enthusiasts has formed Jolla (Finnish for \"dinghy\"), a mobile startup with the aim of bringing new MeeGo devices to the market._ \r\nThank you, thank you so much!\r\n#nokia #meego #maemo #mer #linux #smartphone","public":true,"created_at":"2012-07-07T22:16:11Z","interacted_at":"2012-07-09T11:02:08Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"note","root":null,"title":"Ex-Nokia staff to build MeeGo-based smartphones - http://www.theverge.com/2012/7/7/3143099/jolla-meego-startup-ex-nokia-employees - \r\n_A group of ex-Nokia staff and MeeGo enthusiasts has formed Jolla (Finnish for \"dinghy\"), a mobile startup with the aim of bringing new MeeGo devices to the market._ \r\nThank you, thank you so much!\r\n#nokia #meego #maemo #mer #linux #smartphone","next_post":"/posts/12172/next","previous_post":"/posts/12172/previous","interactions":{"likes":[],"reshares":[],"comments_count":5,"likes_count":9,"reshares_count":3,"comments":[{"id":18837,"guid":"e70d7b0bbb779547","text":"Can they join efforts with Mer and PlasmaActive? I don't really see a need to reinvent the wheel.","author":{"id":1864,"guid":"6d48d8a46633e586","name":"Shmerl","diaspora_id":"bahaltener@joindiaspora.com","avatar":{"small":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_small_7d3b625db04eca524c67.png","medium":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_medium_7d3b625db04eca524c67.png","large":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_7d3b625db04eca524c67.png"}},"created_at":"2012-07-08T02:30:40Z"},{"id":18842,"guid":"421e799bef69f18b","text":"Looks like they do work with Mer. Good news!","author":{"id":1864,"guid":"6d48d8a46633e586","name":"Shmerl","diaspora_id":"bahaltener@joindiaspora.com","avatar":{"small":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_small_7d3b625db04eca524c67.png","medium":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_medium_7d3b625db04eca524c67.png","large":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_7d3b625db04eca524c67.png"}},"created_at":"2012-07-08T06:02:18Z"},{"id":18944,"guid":"16320b7c377ebb5a","text":"Tizen has normal Linux stack (X.org or Wayland based), so if you build all the dependencies, you can run Qt based programs there. The downside will be, that Qt isn't included in Tizen by default so far. They promote using EFL.","author":{"id":1864,"guid":"6d48d8a46633e586","name":"Shmerl","diaspora_id":"bahaltener@joindiaspora.com","avatar":{"small":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_small_7d3b625db04eca524c67.png","medium":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_medium_7d3b625db04eca524c67.png","large":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_7d3b625db04eca524c67.png"}},"created_at":"2012-07-09T02:59:06Z"}]}},{"id":11937,"guid":"2aad765debb1e80e","text":"to all podmins: \r\nplease read this announcement: https://groups.google.com/d/msg/diaspora-dev/kMOuJk5h_v4/5Gx1Dsib6EQJ \r\nthis hopefully provides the solution to clean the database from even the most stubborn mixed-case hashtags. \r\n#diaspora #podmin #hashtags #actionrequired","public":true,"created_at":"2012-07-06T11:56:30Z","interacted_at":"2012-07-06T16:32:38Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"note","root":null,"title":"to all podmins: \r\nplease read this announcement: https://groups.google.com/d/msg/diaspora-dev/kMOuJk5h_v4/5Gx1Dsib6EQJ \r\nthis hopefully provides the solution to clean the database from even the most stubborn mixed-case hashtags. \r\n#diaspora #podmin #hashtags #actionrequired","next_post":"/posts/11937/next","previous_post":"/posts/11937/previous","interactions":{"likes":[],"reshares":[],"comments_count":3,"likes_count":2,"reshares_count":1,"comments":[{"id":18691,"guid":"8a907544696e4faf","text":"thanks!","author":{"id":365,"guid":"dfc51824b3a76b71","name":"Sven Fischer","diaspora_id":"strubbl@sxspora.de","avatar":{"small":"http://sxspora.de/uploads/images/thumb_small_5c105bceab19eff9b0a3.jpg","medium":"http://sxspora.de/uploads/images/thumb_medium_5c105bceab19eff9b0a3.jpg","large":"http://sxspora.de/uploads/images/thumb_large_5c105bceab19eff9b0a3.jpg"}},"created_at":"2012-07-06T14:53:56Z"},{"id":18695,"guid":"8547aa6d2738ecb4","text":"before 2589. now of course 0. I prepended the bundle command with RAILS_ENV=production DB=\"mysql\". Otherwise it didn't work because a diaspora_development does not exist.","author":{"id":365,"guid":"dfc51824b3a76b71","name":"Sven Fischer","diaspora_id":"strubbl@sxspora.de","avatar":{"small":"http://sxspora.de/uploads/images/thumb_small_5c105bceab19eff9b0a3.jpg","medium":"http://sxspora.de/uploads/images/thumb_medium_5c105bceab19eff9b0a3.jpg","large":"http://sxspora.de/uploads/images/thumb_large_5c105bceab19eff9b0a3.jpg"}},"created_at":"2012-07-06T15:10:44Z"},{"id":18704,"guid":"247b0520a7824450","text":"oh, sorry ... yeah I thought that was implied","author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"created_at":"2012-07-06T16:32:38Z"}]}},{"id":11934,"guid":"e75e4e4719bf9405","text":"qtruby is intriguing ... I think I'll need to build something with it ;) \r\n(writing this from a QWebView created by a ruby script ^^) \r\n#ruby #qt #programming","public":true,"created_at":"2012-07-06T11:15:04Z","interacted_at":"2012-07-06T11:15:05Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":null,"title":"qtruby is intriguing ... I think I'll need to build something with it ;) \r\n(writing this from a QWebView created by a ruby script ^^) \r\n#ruby #qt #programming","next_post":"/posts/11934/next","previous_post":"/posts/11934/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":0,"comments":[]}},{"id":11782,"guid":"23416f5cd259bfcc","text":"can one or more podmins please test this pull request on a *copy* of their database? -> https://github.com/diaspora/diaspora/pull/3434 \r\nit's about hashtags mit mixed-case letters in them, and the PR ccontains some changes to the rake task that is supposed to clean those up, which should hopefully eliminate mixed-case hashtags one and for all. \r\nto verify the successful run, the rake task should complete and in your database there should be no more mixed-case hashtags. You can check this by running this statement before and after the rake task ran: \r\n\r\n SELECT * FROM tags WHERE LOWER(name) != name\r\n\r\nBefore, you should see a list of all hashtags that will be processed, and after, the query shoud return an empty result. \r\n\r\n#diaspora #podmin #pleasetest #hashtags","public":true,"created_at":"2012-07-05T10:01:50Z","interacted_at":"2012-07-08T19:18:00Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"note","root":null,"title":"can one or more podmins please test this pull request on a *copy* of their database? -> https://github.com/diaspora/diaspora/pull/3434 \r\nit's about hashtags mit mixed-case letters in them, and the PR ccontains some changes to the rake task that is supposed to clean those up, which should hopefully eliminate mixed-case hashtags one and for all. \r\nto verify the successful run, the rake task should complete and in your database there should be no more mixed-case hashtags. You can check this by running this statement before and after the rake task ran: \r\n\r\n SELECT * FROM tags WHERE LOWER(name) != name\r\n\r\nBefore, you should see a list of all hashtags that will be processed, and after, the query shoud return an empty result. \r\n\r\n#diaspora #podmin #pleasetest #hashtags","next_post":"/posts/11782/next","previous_post":"/posts/11782/previous","interactions":{"likes":[],"reshares":[],"comments_count":6,"likes_count":2,"reshares_count":0,"comments":[{"id":18584,"guid":"217ad7b7ab5fa869","text":"Oh! Duhh! Sorry, let me merge that and try again.","author":{"id":5653,"guid":"7410329c39e6810f","name":"Hans","diaspora_id":"hans@hfase.com","avatar":{"small":"https://hfase.com/uploads/images/thumb_small_f2b2d6b041732c5f91eb.jpg","medium":"https://hfase.com/uploads/images/thumb_medium_f2b2d6b041732c5f91eb.jpg","large":"https://hfase.com/uploads/images/thumb_large_f2b2d6b041732c5f91eb.jpg"}},"created_at":"2012-07-05T10:36:46Z"},{"id":18586,"guid":"0268792e018c3ec3","text":"\"MySQL returned an empty result set (i.e. zero rows). ( Query took 0.0003 sec )\"\n\nMuch better! :D Thanks!!","author":{"id":5653,"guid":"7410329c39e6810f","name":"Hans","diaspora_id":"hans@hfase.com","avatar":{"small":"https://hfase.com/uploads/images/thumb_small_f2b2d6b041732c5f91eb.jpg","medium":"https://hfase.com/uploads/images/thumb_medium_f2b2d6b041732c5f91eb.jpg","large":"https://hfase.com/uploads/images/thumb_large_f2b2d6b041732c5f91eb.jpg"}},"created_at":"2012-07-05T10:39:12Z"},{"id":18587,"guid":"8b39d807abd7302e","text":"yeah, that looks good!","author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"created_at":"2012-07-05T10:44:19Z"}]}},{"id":11774,"guid":"dbcb53c18a1c40bc","text":"# Intro To Using Diaspora\\*\r\n\r\n## Federated Social Networking\r\n\r\nDiaspora\\* is a social network (socnet), similar in many ways to Facebook, #MySpace, #Orkut, and Google Plus ( #GPlus). In fact, those of us who were already using D\\* when GPlus came out were quite familiar with its layout and functionality. It was almost as if they had started developing by grabbing D\\* code and stripping out federation.\r\n\r\nWhen I say federated, I mean that there is not one central Diaspora\\* server (or server cluster) that all users belong to. Instead, there are many [Diaspora\\* servers](http://podupti.me/) to choose from, with different operators ( #podmin), privacy policies, terms of service, and so on. Federation works much like when you decide to mail someone. It doesn't matter to me whether you use Gmail, Hotmail, Ymail, or GMX. I can send messages to you because electronic mail is federated. It is the same way with Diaspora\\*. You may be on [JoinDiaspora](http://joindiaspora.com/), [Calispora](http://calispora.org/), [Diasp.org](http://diasp.org/), [Diasp.eu](http://diasp.eu/), [Serendipitous](http://ser.endipito.us/) or another pod. You can still connect to people whose accounts are on other pods.\r\n\r\nI have written before about [federation](https://joindiaspora.com/posts/1679098).\r\n\r\nThis is an advantage, because it means that you're not beholden to a single organization's policies. If you decide that you dislike the _podmin_ on Pod X, you can open an account on Pod Y instead or even set up your own pod. (_**Moving** your account is not yet implemented_, but I believe you can export your contacts and use the export to help you repopulate that list on your new pod.) If podmin X decides to shut down pod X, again you can open an account on another pod or host your own.\r\n\r\n## @ mentions\r\n\r\nHit the at-sign and the first few letters of the person's display name (it used to be the first few of the person's username, but then they decided to hide that ... personally, I wish they'd switch back)\r\n\r\nWhen you mention someone, make sure you set the privacy to include the group that person is in. There was a bug (possibly fixed) where you could mention someone in a post they weren't allowed to see. I do not believe that @ mentions work in comments yet.\r\n\r\nTwitter, where at-mentions were invented (by users and 3rd-party clients) doesn't have the problem of at-mentions affecting groups simply because it does not have any form of privacy groups.\r\n\r\n## Hashtags\r\n\r\nDiaspora\\* supports #hashtags. Because your pod intercepts them, being on a bigger pod means that clicking a hashtag will give a larger results set than if you clicked on the hashtag from a smaller pod. It is a known problem of the current federation mechanism, and is being fixed.\r\n\r\nTwitter, where hashtags were invented (by users and 3rd-party clients), doesn't have this problem only because everyone is one the same instance of T. #StatusNet, which is like a federated clone of #Twitter, also has the same issue to some degree.\r\n\r\n## Aspects\r\n\r\nPrivacy groups for posts; these were the obvious inspiration for #GPlus's circles, and they work similarly. For example, you may wish to place your boss and others that you know from work into a work aspect. You may also wish to place people you know from college, church, or other such activities into aspects specific to their roles in your life, and to place family members into aspects specific to people in that role.\r\n\r\nIf you didn't already understand aspects, consider this: if posts are wide-open, anyone who becomes a contact can see them. So if you have your boss as a contact, and you post a photo of your trip to the beach won a day you called in sick, _you may get fired for stupidity_. What you do is you put your boss into a work aspect, and only post things into that aspect that are acceptable in a work context.\r\n\r\n## Posting syntax\r\n\r\nDiaspora\\* uses something called [Markdown](http://www.simpleeditions.com/59001/markdown-an-introduction) for its posts. Most of the time, you can just post in plain text and not worry about it, but every once in a while, Markdown will distort what you've posted.\r\n\r\nMarkdown does give you the ability to _italicize_, **bold**, and otherwise decorate text and to embed links and images using a fairly simple syntax. I find, however, that I have to look up embedding every time I use it.\r\n\r\n(I personally prefer [Textile](http://textile.thresholdstate.com/). You still have to learn to use it effectively, but it more closely matches what experienced net users have grown to expect from applications like Outlook and Thunderbird. For instance, if I want bold text, surround it with single asterisks [\\*] rather than the double asterisks [\\*\\*] that Markdown requires.)\r\n\r\n## Pods\r\n\r\nA Diaspora\\* pod is the server or server cluster where your account resides. There are dozens or even hundreds of pods out there. Most of them are pretty similar in what they offer. A few offer experimental features, such as post previews, pod-only posts, or encrypted messaging. It is my hope that many of these features will be picked up by the main codebase, so that all pods will have them.\r\n\r\nYou'll rarely need to know this, but every Diaspora\\* account has an address that looks like username@podname.com. If you want people to be able to add you as a contact, publish your Diaspora\\* address. They'll be able to add you that way.\r\n\r\n## Facebook\r\n\r\nAll of the pods I have used have the ability to connect to certain external accounts, such as Twitter and #Facebook. This means that you can post from D\\* to FB or T. You don't have to abandon your \"friends\" on other #socnets because you join D\\*.\r\n\r\nIf you read many online articles, you will come across some that seem to believe that Diaspora\\*'s purpose is to become a Facebook-killer. Do not believe them. If and when people tire of Facebook, it will be because of something that FB does, not because socnet X is better. If you look at D\\* as a substitute for Facebook, it will be like a meat-eater who tries to replace meat with soy-based meat substitutes. You won't like it. Instead, I recommend that you get to know people who are on D\\* and that you invite your existing contacts, but that you **enjoy D\\* for its own value**. If you find that it then makes FB unnecessary, that is good. If, on the other hand, you still want to keep your FB account, that is also good.\r\n\r\n## Controversies\r\n\r\nThere are occasional squabbles over the directions the project is taking. Unlike the squabbles at Twitter, which took place behind closed doors and resulted in a number of highly-skilled people leaving and the recently announced restrictions on how client applications can display Twitter-sourced content, Diaspora\\*'s squabbles tend to happen in public. My advice is simple: stay out of the squabbles, find your own philosophical point of view, and support this and any other project that agrees with that point of view. If the time comes when this or any other project no longer fits your POV, leave quietly.\r\n\r\nWhen I felt that GPlus was hostile to my POV, I closed my accounts. When I felt that Facebook was hostile to my POV, I closed my account. I do not go around trash-talking either project, or assuming that anyone in said projects is intentionally \"evil,\" and I would not recommend doing that to D\\* or any other project.\r\n\r\n## Future\r\n\r\nAt some point in the future, the Diaspora\\* developers will be changing the federation protocol. Federation is what enables a user on Pod X to interact with users on pods Y, Z, etc. They are working to improve scalability (ability to handle more content posted from more users in the same period of time) and content dispersion (ability for content to travel between a wider number of pods seamlessly). It is a tough task. If you are interested in #Ruby programming or Ruby on Rails ( #RoR ), I would encourage you to get involved.\r\n\r\nThey are also planning to make D\\* a far more visual-oriented socnet. That means that posts with images, graphics, and video will be far more interesting, and will be displayed in a manner that caters to those things. There is an experimental pod where they test out many of the visual designs that may make it into the D* codebase. I will not link it here, because people may misunderstand that it is experimental and not really intended to be your home pod.\r\n\r\nIf you're interested in the technical side and the future directions, they have a moderated and directed code-chat on IRC every (other?) Thursday at 10AM Pacific in the room #diaspora-meeting on Freenode. Sean can jump in on the comments to correct me on this.\r\n\r\n## Conclusion\r\n\r\nThis is long, but I think this is a good intro to Diaspora\\*. I wish there had been someone who could write something like this when I joined. I should also put in a disclaimer. This is my personal opinion, and not the official stance of any podmin or of the Diaspora\\* developers. You are free to disagree, but please start a new thread for it. This is posted in the hope that people who newly join Diaspora\\* will get a head start.\r\n\r\nThere are a number of tutorials at [Diasporal](http://diasporial.com/). I would encourage you to visit the site and check them out. If you are a blogger, or if you write for a magazine (online or dead-tree), I would encourage you to write about Diaspora\\* once you've taken some time to get to know the place.","public":true,"created_at":"2012-07-05T09:37:15Z","interacted_at":"2012-07-05T09:37:15Z","provider_display_name":null,"post_type":"Reshare","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":{"id":11730,"guid":"57288b4adf721900","text":"# Intro To Using Diaspora\\*\r\n\r\n## Federated Social Networking\r\n\r\nDiaspora\\* is a social network (socnet), similar in many ways to Facebook, #MySpace, #Orkut, and Google Plus ( #GPlus). In fact, those of us who were already using D\\* when GPlus came out were quite familiar with its layout and functionality. It was almost as if they had started developing by grabbing D\\* code and stripping out federation.\r\n\r\nWhen I say federated, I mean that there is not one central Diaspora\\* server (or server cluster) that all users belong to. Instead, there are many [Diaspora\\* servers](http://podupti.me/) to choose from, with different operators ( #podmin), privacy policies, terms of service, and so on. Federation works much like when you decide to mail someone. It doesn't matter to me whether you use Gmail, Hotmail, Ymail, or GMX. I can send messages to you because electronic mail is federated. It is the same way with Diaspora\\*. You may be on [JoinDiaspora](http://joindiaspora.com/), [Calispora](http://calispora.org/), [Diasp.org](http://diasp.org/), [Diasp.eu](http://diasp.eu/), [Serendipitous](http://ser.endipito.us/) or another pod. You can still connect to people whose accounts are on other pods.\r\n\r\nI have written before about [federation](https://joindiaspora.com/posts/1679098).\r\n\r\nThis is an advantage, because it means that you're not beholden to a single organization's policies. If you decide that you dislike the _podmin_ on Pod X, you can open an account on Pod Y instead or even set up your own pod. (_**Moving** your account is not yet implemented_, but I believe you can export your contacts and use the export to help you repopulate that list on your new pod.) If podmin X decides to shut down pod X, again you can open an account on another pod or host your own.\r\n\r\n## @ mentions\r\n\r\nHit the at-sign and the first few letters of the person's display name (it used to be the first few of the person's username, but then they decided to hide that ... personally, I wish they'd switch back)\r\n\r\nWhen you mention someone, make sure you set the privacy to include the group that person is in. There was a bug (possibly fixed) where you could mention someone in a post they weren't allowed to see. I do not believe that @ mentions work in comments yet.\r\n\r\nTwitter, where at-mentions were invented (by users and 3rd-party clients) doesn't have the problem of at-mentions affecting groups simply because it does not have any form of privacy groups.\r\n\r\n## Hashtags\r\n\r\nDiaspora\\* supports #hashtags. Because your pod intercepts them, being on a bigger pod means that clicking a hashtag will give a larger results set than if you clicked on the hashtag from a smaller pod. It is a known problem of the current federation mechanism, and is being fixed.\r\n\r\nTwitter, where hashtags were invented (by users and 3rd-party clients), doesn't have this problem only because everyone is one the same instance of T. #StatusNet, which is like a federated clone of #Twitter, also has the same issue to some degree.\r\n\r\n## Aspects\r\n\r\nPrivacy groups for posts; these were the obvious inspiration for #GPlus's circles, and they work similarly. For example, you may wish to place your boss and others that you know from work into a work aspect. You may also wish to place people you know from college, church, or other such activities into aspects specific to their roles in your life, and to place family members into aspects specific to people in that role.\r\n\r\nIf you didn't already understand aspects, consider this: if posts are wide-open, anyone who becomes a contact can see them. So if you have your boss as a contact, and you post a photo of your trip to the beach won a day you called in sick, _you may get fired for stupidity_. What you do is you put your boss into a work aspect, and only post things into that aspect that are acceptable in a work context.\r\n\r\n## Posting syntax\r\n\r\nDiaspora\\* uses something called [Markdown](http://www.simpleeditions.com/59001/markdown-an-introduction) for its posts. Most of the time, you can just post in plain text and not worry about it, but every once in a while, Markdown will distort what you've posted.\r\n\r\nMarkdown does give you the ability to _italicize_, **bold**, and otherwise decorate text and to embed links and images using a fairly simple syntax. I find, however, that I have to look up embedding every time I use it.\r\n\r\n(I personally prefer [Textile](http://textile.thresholdstate.com/). You still have to learn to use it effectively, but it more closely matches what experienced net users have grown to expect from applications like Outlook and Thunderbird. For instance, if I want bold text, surround it with single asterisks [\\*] rather than the double asterisks [\\*\\*] that Markdown requires.)\r\n\r\n## Pods\r\n\r\nA Diaspora\\* pod is the server or server cluster where your account resides. There are dozens or even hundreds of pods out there. Most of them are pretty similar in what they offer. A few offer experimental features, such as post previews, pod-only posts, or encrypted messaging. It is my hope that many of these features will be picked up by the main codebase, so that all pods will have them.\r\n\r\nYou'll rarely need to know this, but every Diaspora\\* account has an address that looks like username@podname.com. If you want people to be able to add you as a contact, publish your Diaspora\\* address. They'll be able to add you that way.\r\n\r\n## Facebook\r\n\r\nAll of the pods I have used have the ability to connect to certain external accounts, such as Twitter and #Facebook. This means that you can post from D\\* to FB or T. You don't have to abandon your \"friends\" on other #socnets because you join D\\*.\r\n\r\nIf you read many online articles, you will come across some that seem to believe that Diaspora\\*'s purpose is to become a Facebook-killer. Do not believe them. If and when people tire of Facebook, it will be because of something that FB does, not because socnet X is better. If you look at D\\* as a substitute for Facebook, it will be like a meat-eater who tries to replace meat with soy-based meat substitutes. You won't like it. Instead, I recommend that you get to know people who are on D\\* and that you invite your existing contacts, but that you **enjoy D\\* for its own value**. If you find that it then makes FB unnecessary, that is good. If, on the other hand, you still want to keep your FB account, that is also good.\r\n\r\n## Controversies\r\n\r\nThere are occasional squabbles over the directions the project is taking. Unlike the squabbles at Twitter, which took place behind closed doors and resulted in a number of highly-skilled people leaving and the recently announced restrictions on how client applications can display Twitter-sourced content, Diaspora\\*'s squabbles tend to happen in public. My advice is simple: stay out of the squabbles, find your own philosophical point of view, and support this and any other project that agrees with that point of view. If the time comes when this or any other project no longer fits your POV, leave quietly.\r\n\r\nWhen I felt that GPlus was hostile to my POV, I closed my accounts. When I felt that Facebook was hostile to my POV, I closed my account. I do not go around trash-talking either project, or assuming that anyone in said projects is intentionally \"evil,\" and I would not recommend doing that to D\\* or any other project.\r\n\r\n## Future\r\n\r\nAt some point in the future, the Diaspora\\* developers will be changing the federation protocol. Federation is what enables a user on Pod X to interact with users on pods Y, Z, etc. They are working to improve scalability (ability to handle more content posted from more users in the same period of time) and content dispersion (ability for content to travel between a wider number of pods seamlessly). It is a tough task. If you are interested in #Ruby programming or Ruby on Rails ( #RoR ), I would encourage you to get involved.\r\n\r\nThey are also planning to make D\\* a far more visual-oriented socnet. That means that posts with images, graphics, and video will be far more interesting, and will be displayed in a manner that caters to those things. There is an experimental pod where they test out many of the visual designs that may make it into the D* codebase. I will not link it here, because people may misunderstand that it is experimental and not really intended to be your home pod.\r\n\r\nIf you're interested in the technical side and the future directions, they have a moderated and directed code-chat on IRC every (other?) Thursday at 10AM Pacific in the room #diaspora-meeting on Freenode. Sean can jump in on the comments to correct me on this.\r\n\r\n## Conclusion\r\n\r\nThis is long, but I think this is a good intro to Diaspora\\*. I wish there had been someone who could write something like this when I joined. I should also put in a disclaimer. This is my personal opinion, and not the official stance of any podmin or of the Diaspora\\* developers. You are free to disagree, but please start a new thread for it. This is posted in the hope that people who newly join Diaspora\\* will get a head start.\r\n\r\nThere are a number of tutorials at [Diasporal](http://diasporial.com/). I would encourage you to visit the site and check them out. If you are a blogger, or if you write for a magazine (online or dead-tree), I would encourage you to write about Diaspora\\* once you've taken some time to get to know the place.","public":true,"created_at":"2012-07-04T23:41:33Z","interacted_at":"2012-07-05T04:21:21Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":5508,"guid":"25d1ca8dd064f3dd","name":"lnxwalt@calispora.org","diaspora_id":"lnxwalt@calispora.org","avatar":{"small":"https://pod.fulll.name/images/user/default.png","medium":"https://pod.fulll.name/images/user/default.png","large":"https://pod.fulll.name/images/user/default.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"note","root":null,"title":"# Intro To Using Diaspora\\*\r\n\r\n## Federated Social Networking\r\n\r\nDiaspora\\* is a social network (socnet), similar in many ways to Facebook, #MySpace, #Orkut, and Google Plus ( #GPlus). In fact, those of us who were already using D\\* when GPlus came out were quite familiar with its layout and functionality. It was almost as if they had started developing by grabbing D\\* code and stripping out federation.\r\n\r\nWhen I say federated, I mean that there is not one central Diaspora\\* server (or server cluster) that all users belong to. Instead, there are many [Diaspora\\* servers](http://podupti.me/) to choose from, with different operators ( #podmin), privacy policies, terms of service, and so on. Federation works much like when you decide to mail someone. It doesn't matter to me whether you use Gmail, Hotmail, Ymail, or GMX. I can send messages to you because electronic mail is federated. It is the same way with Diaspora\\*. You may be on [JoinDiaspora](http://joindiaspora.com/), [Calispora](http://calispora.org/), [Diasp.org](http://diasp.org/), [Diasp.eu](http://diasp.eu/), [Serendipitous](http://ser.endipito.us/) or another pod. You can still connect to people whose accounts are on other pods.\r\n\r\nI have written before about [federation](https://joindiaspora.com/posts/1679098).\r\n\r\nThis is an advantage, because it means that you're not beholden to a single organization's policies. If you decide that you dislike the _podmin_ on Pod X, you can open an account on Pod Y instead or even set up your own pod. (_**Moving** your account is not yet implemented_, but I believe you can export your contacts and use the export to help you repopulate that list on your new pod.) If podmin X decides to shut down pod X, again you can open an account on another pod or host your own.\r\n\r\n## @ mentions\r\n\r\nHit the at-sign and the first few letters of the person's display name (it used to be the first few of the person's username, but then they decided to hide that ... personally, I wish they'd switch back)\r\n\r\nWhen you mention someone, make sure you set the privacy to include the group that person is in. There was a bug (possibly fixed) where you could mention someone in a post they weren't allowed to see. I do not believe that @ mentions work in comments yet.\r\n\r\nTwitter, where at-mentions were invented (by users and 3rd-party clients) doesn't have the problem of at-mentions affecting groups simply because it does not have any form of privacy groups.\r\n\r\n## Hashtags\r\n\r\nDiaspora\\* supports #hashtags. Because your pod intercepts them, being on a bigger pod means that clicking a hashtag will give a larger results set than if you clicked on the hashtag from a smaller pod. It is a known problem of the current federation mechanism, and is being fixed.\r\n\r\nTwitter, where hashtags were invented (by users and 3rd-party clients), doesn't have this problem only because everyone is one the same instance of T. #StatusNet, which is like a federated clone of #Twitter, also has the same issue to some degree.\r\n\r\n## Aspects\r\n\r\nPrivacy groups for posts; these were the obvious inspiration for #GPlus's circles, and they work similarly. For example, you may wish to place your boss and others that you know from work into a work aspect. You may also wish to place people you know from college, church, or other such activities into aspects specific to their roles in your life, and to place family members into aspects specific to people in that role.\r\n\r\nIf you didn't already understand aspects, consider this: if posts are wide-open, anyone who becomes a contact can see them. So if you have your boss as a contact, and you post a photo of your trip to the beach won a day you called in sick, _you may get fired for stupidity_. What you do is you put your boss into a work aspect, and only post things into that aspect that are acceptable in a work context.\r\n\r\n## Posting syntax\r\n\r\nDiaspora\\* uses something called [Markdown](http://www.simpleeditions.com/59001/markdown-an-introduction) for its posts. Most of the time, you can just post in plain text and not worry about it, but every once in a while, Markdown will distort what you've posted.\r\n\r\nMarkdown does give you the ability to _italicize_, **bold**, and otherwise decorate text and to embed links and images using a fairly simple syntax. I find, however, that I have to look up embedding every time I use it.\r\n\r\n(I personally prefer [Textile](http://textile.thresholdstate.com/). You still have to learn to use it effectively, but it more closely matches what experienced net users have grown to expect from applications like Outlook and Thunderbird. For instance, if I want bold text, surround it with single asterisks [\\*] rather than the double asterisks [\\*\\*] that Markdown requires.)\r\n\r\n## Pods\r\n\r\nA Diaspora\\* pod is the server or server cluster where your account resides. There are dozens or even hundreds of pods out there. Most of them are pretty similar in what they offer. A few offer experimental features, such as post previews, pod-only posts, or encrypted messaging. It is my hope that many of these features will be picked up by the main codebase, so that all pods will have them.\r\n\r\nYou'll rarely need to know this, but every Diaspora\\* account has an address that looks like username@podname.com. If you want people to be able to add you as a contact, publish your Diaspora\\* address. They'll be able to add you that way.\r\n\r\n## Facebook\r\n\r\nAll of the pods I have used have the ability to connect to certain external accounts, such as Twitter and #Facebook. This means that you can post from D\\* to FB or T. You don't have to abandon your \"friends\" on other #socnets because you join D\\*.\r\n\r\nIf you read many online articles, you will come across some that seem to believe that Diaspora\\*'s purpose is to become a Facebook-killer. Do not believe them. If and when people tire of Facebook, it will be because of something that FB does, not because socnet X is better. If you look at D\\* as a substitute for Facebook, it will be like a meat-eater who tries to replace meat with soy-based meat substitutes. You won't like it. Instead, I recommend that you get to know people who are on D\\* and that you invite your existing contacts, but that you **enjoy D\\* for its own value**. If you find that it then makes FB unnecessary, that is good. If, on the other hand, you still want to keep your FB account, that is also good.\r\n\r\n## Controversies\r\n\r\nThere are occasional squabbles over the directions the project is taking. Unlike the squabbles at Twitter, which took place behind closed doors and resulted in a number of highly-skilled people leaving and the recently announced restrictions on how client applications can display Twitter-sourced content, Diaspora\\*'s squabbles tend to happen in public. My advice is simple: stay out of the squabbles, find your own philosophical point of view, and support this and any other project that agrees with that point of view. If the time comes when this or any other project no longer fits your POV, leave quietly.\r\n\r\nWhen I felt that GPlus was hostile to my POV, I closed my accounts. When I felt that Facebook was hostile to my POV, I closed my account. I do not go around trash-talking either project, or assuming that anyone in said projects is intentionally \"evil,\" and I would not recommend doing that to D\\* or any other project.\r\n\r\n## Future\r\n\r\nAt some point in the future, the Diaspora\\* developers will be changing the federation protocol. Federation is what enables a user on Pod X to interact with users on pods Y, Z, etc. They are working to improve scalability (ability to handle more content posted from more users in the same period of time) and content dispersion (ability for content to travel between a wider number of pods seamlessly). It is a tough task. If you are interested in #Ruby programming or Ruby on Rails ( #RoR ), I would encourage you to get involved.\r\n\r\nThey are also planning to make D\\* a far more visual-oriented socnet. That means that posts with images, graphics, and video will be far more interesting, and will be displayed in a manner that caters to those things. There is an experimental pod where they test out many of the visual designs that may make it into the D* codebase. I will not link it here, because people may misunderstand that it is experimental and not really intended to be your home pod.\r\n\r\nIf you're interested in the technical side and the future directions, they have a moderated and directed code-chat on IRC every (other?) Thursday at 10AM Pacific in the room #diaspora-meeting on Freenode. Sean can jump in on the comments to correct me on this.\r\n\r\n## Conclusion\r\n\r\nThis is long, but I think this is a good intro to Diaspora\\*. I wish there had been someone who could write something like this when I joined. I should also put in a disclaimer. This is my personal opinion, and not the official stance of any podmin or of the Diaspora\\* developers. You are free to disagree, but please start a new thread for it. This is posted in the hope that people who newly join Diaspora\\* will get a head start.\r\n\r\nThere are a number of tutorials at [Diasporal](http://diasporial.com/). I would encourage you to visit the site and check them out. If you are a blogger, or if you write for a magazine (online or dead-tree), I would encourage you to write about Diaspora\\* once you've taken some time to get to know the place.","next_post":"/posts/11730/next","previous_post":"/posts/11730/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":4}},"title":"A post from Florian Staudacher","next_post":"/posts/11774/next","previous_post":"/posts/11774/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":0,"comments":[]}},{"id":11725,"guid":"909471c6070243be","text":"If you think you know of a #Diaspora #Bug please remember to be as specific as possible when describing it so we can help!!","public":true,"created_at":"2012-07-04T23:29:43Z","interacted_at":"2012-07-04T23:29:43Z","provider_display_name":null,"post_type":"Reshare","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":{"id":11718,"guid":"c1770c590b097c28","text":"If you think you know of a #Diaspora #Bug please remember to be as specific as possible when describing it so we can help!!","public":true,"created_at":"2012-07-04T22:00:49Z","interacted_at":"2012-07-05T08:19:07Z","provider_display_name":null,"post_type":"StatusMessage","image_url":null,"object_url":null,"favorite":false,"nsfw":false,"author":{"id":5653,"guid":"7410329c39e6810f","name":"Hans","diaspora_id":"hans@hfase.com","avatar":{"small":"https://hfase.com/uploads/images/thumb_small_f2b2d6b041732c5f91eb.jpg","medium":"https://hfase.com/uploads/images/thumb_medium_f2b2d6b041732c5f91eb.jpg","large":"https://hfase.com/uploads/images/thumb_large_f2b2d6b041732c5f91eb.jpg"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"frame_name":"status","root":null,"title":"If you think you know of a #Diaspora #Bug please remember to be as specific as possible when describing it so we can help!!","next_post":"/posts/11718/next","previous_post":"/posts/11718/previous","interactions":{"likes":[],"reshares":[{"reshare":{"actor_url":null,"author_id":2,"comments_count":0,"created_at":"2012-07-04T23:29:43Z","diaspora_handle":"raven24@pod.fulll.name","favorite":false,"frame_name":null,"guid":"909471c6070243be","id":11725,"image_height":null,"image_url":null,"image_width":null,"interacted_at":"2012-07-04T23:29:43Z","likes_count":0,"o_embed_cache_id":null,"objectId":null,"object_url":null,"pending":false,"processed_image":null,"provider_display_name":null,"public":true,"random_string":null,"remote_photo_name":null,"remote_photo_path":null,"reshares_count":0,"root_guid":"c1770c590b097c28","status_message_guid":null,"text":null,"unprocessed_image":null,"updated_at":"2012-07-04T23:29:43Z"}}],"comments_count":0,"likes_count":2,"reshares_count":2}},"title":"A post from Florian Staudacher","next_post":"/posts/11725/next","previous_post":"/posts/11725/previous","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":0,"comments":[]}}] \ No newline at end of file +[{"id":15086,"guid":"198095988ad26f21","text":"test of #left4dead on #linux results in \"faster zombies\" http://is.gd/uHeUC6 with linux outperforming windows","public":true,"created_at":"2012-08-02T22:13:16Z","interacted_at":"2012-08-03T15:02:59Z","provider_display_name":null,"post_type":"Reshare","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":{"id":15028,"guid":"1b2a98db23582947","text":"test of #left4dead on #linux results in \"faster zombies\" http://is.gd/uHeUC6 with linux outperforming windows","public":true,"created_at":"2012-08-02T14:25:56Z","interacted_at":"2012-08-02T21:54:53Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":1769,"guid":"a2f9a3a7cb3dcd5a","name":"el [spare pope] olmo","diaspora_id":"el_olmo@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_343f6520778765c4b3f9.jpg","medium":"https://pod.fulll.name/uploads/images/thumb_medium_343f6520778765c4b3f9.jpg","large":"https://pod.fulll.name/uploads/images/thumb_large_343f6520778765c4b3f9.jpg"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"test of #left4dead on #linux results in \"faster zombies\" http://is.gd/uHeUC6 with linux outperforming windows","interactions":{"likes":[{"id":32638,"guid":"b2c1e789b1eec9ea","author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"created_at":"2012-08-02T21:54:53Z"}],"reshares":[{"reshare":{"author_id":2,"comments_count":0,"created_at":"2012-08-02T22:13:16Z","diaspora_handle":"raven24@pod.fulll.name","guid":"198095988ad26f21","id":15086,"interacted_at":"2012-08-03T15:02:59Z","likes_count":2,"o_embed_cache_id":null,"provider_display_name":null,"public":true,"reshares_count":0,"root_guid":"1b2a98db23582947","text":null,"updated_at":"2012-08-03T15:02:59Z"}}],"comments_count":0,"likes_count":6,"reshares_count":1}},"title":"A post from Florian Staudacher","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":2,"reshares_count":0,"comments":[]}},{"id":14755,"guid":"0ffef04549e81bfa","text":"... in case you ever need the network device name, ip and mac address, here you go: \r\nhttps://gist.github.com/3202188\r\n\r\n(uses ifconfig, grep and sed with some regular expression magic) \r\n#bash #script #network #ip #grep #sed #regexp #linux","public":true,"created_at":"2012-07-29T22:28:17Z","interacted_at":"2012-08-01T18:01:49Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"... in case you ever need the network device name, ip and mac address, here you go: \r\nhttps://gist.github.com/3202188\r\n\r\n(uses ifconfig, grep and sed with some regular expression magic) \r\n#bash #script #network #ip #grep #sed #regexp #linux","interactions":{"likes":[],"reshares":[],"comments_count":8,"likes_count":4,"reshares_count":0,"comments":[{"id":20912,"guid":"ba86c52ca4d293c4","text":"It only shows network devices named eth* and doesn't work with localized versions of ifconfig in non-english language environments","author":{"id":6243,"guid":"c7bf295dae900b7a","name":"Florian Diesch","diaspora_id":"diesch@joindiaspora.com","avatar":{"small":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_small_7f090bd1002004896464.png","medium":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_medium_7f090bd1002004896464.png","large":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_7f090bd1002004896464.png"}},"created_at":"2012-07-30T02:33:06Z"},{"id":21012,"guid":"81fc5d869de5ea05","text":"For now, I only need it just the way it is (in my collection of VM management scripts), but feel free to change it to work with whatever version or language of `ifconfig` you need. I leave that \"as an exercise to the reader\" ... it's always a good time to start learning `sed` regular expressions \n;)","author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"created_at":"2012-07-31T01:51:24Z"},{"id":21164,"guid":"d74aac53420cd66f","text":"[inxi](https://code.google.com/p/inxi/)","author":{"id":3920,"guid":"b636315dc6f90ece","name":"Kiridesce","diaspora_id":"iridesce@kosmospora.net","avatar":{"small":"https://kosmospora.net/uploads/images/thumb_small_7b3c16e2107449bf9717.jpeg","medium":"https://kosmospora.net/uploads/images/thumb_medium_7b3c16e2107449bf9717.jpeg","large":"https://kosmospora.net/uploads/images/thumb_large_7b3c16e2107449bf9717.jpeg"}},"created_at":"2012-08-01T18:01:49Z"}]}},{"id":14514,"guid":"c6b5e0a20421d719","text":"lol! \r\nhttp://youtu.be/6RrpGgaT5kk\r\n\r\n#acapella #movie #dub","public":true,"created_at":"2012-07-27T14:09:31Z","interacted_at":"2012-07-28T21:25:56Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":{"data":{"provider_url":"http://www.youtube.com/","thumbnail_url":"http://i3.ytimg.com/vi/6RrpGgaT5kk/hqdefault.jpg","title":"'The Matrix' Lobby Scene with A capella Multitrack - Matt Mulholland","html":"<iframe width=\"420\" height=\"236\" src=\"http://www.youtube.com/embed/6RrpGgaT5kk?fs=1&feature=oembed\" frameborder=\"0\" allowfullscreen></iframe>","author_name":"mattmulholland26","height":236,"thumbnail_width":480,"width":420,"version":"1.0","author_url":"http://www.youtube.com/user/mattmulholland26","provider_name":"YouTube","type":"video","thumbnail_height":360,"trusted_endpoint_url":"http://www.youtube.com/oembed"}},"mentioned_people":[],"photos":[],"root":null,"title":"lol! \r\nhttp://youtu.be/6RrpGgaT5kk\r\n\r\n#acapella #movie #dub","interactions":{"likes":[],"reshares":[],"comments_count":1,"likes_count":2,"reshares_count":0,"comments":[{"id":20833,"guid":"3c2d21708b6cfa29","text":"Inception Trailer A Capella Re-Dub: http://www.youtube.com/watch?v=d2yD4yDsiP4","author":{"id":2896,"guid":"24e82915d58368fe","name":"Alexey Andreyev","diaspora_id":"yetanotherandreyev@diasp.org","avatar":{"small":"https://diasp.org/uploads/images/thumb_small_9f29c5326741a32889fa.jpg","medium":"https://diasp.org/uploads/images/thumb_medium_9f29c5326741a32889fa.jpg","large":"https://diasp.org/uploads/images/thumb_large_9f29c5326741a32889fa.jpg"}},"created_at":"2012-07-28T21:25:56Z"}]}},{"id":14113,"guid":"4404d1bb88d36735","text":"Keep Calm and use #Linux <br> [  ](http://goo.gl/HSS18) <br>","public":true,"created_at":"2012-07-23T15:50:00Z","interacted_at":"2012-07-24T15:16:25Z","provider_display_name":null,"post_type":"Reshare","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":{"id":14099,"guid":"d1970bb173aae310","text":"Keep Calm and use #Linux <br> [  ](http://goo.gl/HSS18) <br>","public":true,"created_at":"2012-07-23T13:12:51Z","interacted_at":"2012-07-23T13:37:24Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":175,"guid":"4d11bd252c174338f2002a4c","name":"\u24b6\u24c5\u24c4\u24c1\u24c4\u24c3\u24be\u24c8 \u2301 \u24b6\u24c5\u24bd\u24c7\u24c4\u24b9\u24be\u24c8\u24be\u24b6","diaspora_id":"apolonisaphrodisia@joindiaspora.com","avatar":{"small":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_small_8107d3419ac23bd16253.gif","medium":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_medium_8107d3419ac23bd16253.gif","large":"https://pod.fulll.name/images/user/default.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"Keep Calm and use #Linux <br> [  ](http://goo.gl/HSS18) <br>","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":2}},"title":"A post from Florian Staudacher","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":2,"reshares_count":1,"comments":[]}},{"id":14110,"guid":"bb89c419e60fd801","text":"awesome #youtube #video \r\nhttp://youtu.be/daVDrGsaDME\r\n\r\n#car #engine #stopmotion","public":true,"created_at":"2012-07-23T15:05:36Z","interacted_at":"2012-07-24T12:48:48Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":{"data":{"provider_url":"http://www.youtube.com/","thumbnail_url":"http://i1.ytimg.com/vi/daVDrGsaDME/hqdefault.jpg","title":"11 Months, 3000 pictures and a lot of coffee.","html":"<iframe width=\"420\" height=\"315\" src=\"http://www.youtube.com/embed/daVDrGsaDME?fs=1&feature=oembed\" frameborder=\"0\" allowfullscreen></iframe>","author_name":"nothinghereok","height":315,"thumbnail_width":480,"width":420,"version":"1.0","author_url":"http://www.youtube.com/user/nothinghereok","provider_name":"YouTube","type":"video","thumbnail_height":360,"trusted_endpoint_url":"http://www.youtube.com/oembed"}},"mentioned_people":[],"photos":[],"root":null,"title":"awesome #youtube #video \r\nhttp://youtu.be/daVDrGsaDME\r\n\r\n#car #engine #stopmotion","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":1,"reshares_count":0,"comments":[]}},{"id":12830,"guid":"5a4089375be2db14","text":"jQuery Core: Version 1.9 and Beyond - http://blog.jquery.com/2012/06/28/jquery-core-version-1-9-and-beyond/ - \r\n_jQuery 2.0: This version will support the same APIs as jQuery 1.9 does, but removes support for IE 6/7/8 oddities such as borked event model, IE7 \u201cattroperties\u201d, HTML5 shims, etc. \r\nOur goal is for 1.9 and 2.0 to be interchangeable as far as the API set they support. When 2.0 comes out, your decision on which version to choose should be as simple as this: If you need IE 6/7/8 support, choose 1.9; otherwise you can use either 1.9 or 2.0._ \r\nI hope IE dies a quick but painfull death... \r\n#jquery #ie #browser #web","public":true,"created_at":"2012-07-13T20:36:35Z","interacted_at":"2012-07-13T20:36:35Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"jQuery Core: Version 1.9 and Beyond - http://blog.jquery.com/2012/06/28/jquery-core-version-1-9-and-beyond/ - \r\n_jQuery 2.0: This version will support the same APIs as jQuery 1.9 does, but removes support for IE 6/7/8 oddities such as borked event model, IE7 \u201cattroperties\u201d, HTML5 shims, etc. \r\nOur goal is for 1.9 and 2.0 to be interchangeable as far as the API set they support. When 2.0 comes out, your decision on which version to choose should be as simple as this: If you need IE 6/7/8 support, choose 1.9; otherwise you can use either 1.9 or 2.0._ \r\nI hope IE dies a quick but painfull death... \r\n#jquery #ie #browser #web","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":0,"comments":[]}},{"id":12763,"guid":"82adaf03843115e8","text":"http://www.evolutionoftheweb.com\r\n\r\n\r\n\r\n#www #web #ITNews #Browser #Internet #technology #IT","public":true,"created_at":"2012-07-13T09:30:02Z","interacted_at":"2012-07-29T23:46:30Z","provider_display_name":null,"post_type":"Reshare","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":{"id":12751,"guid":"389f84ae16581df6","text":"http://www.evolutionoftheweb.com\r\n\r\n\r\n\r\n#www #web #ITNews #Browser #Internet #technology #IT","public":true,"created_at":"2012-07-12T17:34:10Z","interacted_at":"2012-07-13T05:49:09Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":4079,"guid":"bfe281001b5a8561","name":"Anonymiss","diaspora_id":"anonymiss@despora.de","avatar":{"small":"https://despora.de/uploads/images/thumb_small_d25c7b27e7bbf307a8cc.jpg","medium":"https://despora.de/uploads/images/thumb_medium_d25c7b27e7bbf307a8cc.jpg","large":"https://despora.de/uploads/images/thumb_large_d25c7b27e7bbf307a8cc.jpg"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"http://www.evolutionoftheweb.com\r\n\r\n\r\n\r\n#www #web #ITNews #Browser #Internet #technology #IT","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":1}},"title":"A post from Florian Staudacher","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":2,"reshares_count":0,"comments":[]}},{"id":12463,"guid":"cb0a304194c719d8","text":"Relativistic Baseball - http://what-if.xkcd.com/1/ - \r\nWhat would happen if you tried to hit a baseball pitched at 90% the speed of light? \r\n#xkcd #whatif","public":true,"created_at":"2012-07-10T09:31:54Z","interacted_at":"2012-07-29T23:52:08Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"Relativistic Baseball - http://what-if.xkcd.com/1/ - \r\nWhat would happen if you tried to hit a baseball pitched at 90% the speed of light? \r\n#xkcd #whatif","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":3,"reshares_count":1,"comments":[]}},{"id":12349,"guid":"b16efb0fc6427338","text":"yay, new \"simon's cat\"! \r\n \r\nhttp://youtu.be/XrivBjlv6Mw \r\n#simonscat #cat","public":true,"created_at":"2012-07-09T12:03:38Z","interacted_at":"2012-07-10T21:59:32Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":{"data":{"provider_url":"http://www.youtube.com/","thumbnail_url":"http://i1.ytimg.com/vi/XrivBjlv6Mw/hqdefault.jpg","title":"Simon's Cat in 'Window Pain'","html":"<iframe width=\"420\" height=\"236\" src=\"http://www.youtube.com/embed/XrivBjlv6Mw?fs=1&feature=oembed\" frameborder=\"0\" allowfullscreen></iframe>","author_name":"simonscat","height":236,"thumbnail_width":480,"width":420,"version":"1.0","author_url":"http://www.youtube.com/user/simonscat","provider_name":"YouTube","type":"video","thumbnail_height":360,"trusted_endpoint_url":"http://www.youtube.com/oembed"}},"mentioned_people":[],"photos":[],"root":null,"title":"yay, new \"simon's cat\"! \r\n \r\nhttp://youtu.be/XrivBjlv6Mw \r\n#simonscat #cat","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":2,"reshares_count":1,"comments":[]}},{"id":12172,"guid":"198034364c7226a1","text":"Ex-Nokia staff to build MeeGo-based smartphones - http://www.theverge.com/2012/7/7/3143099/jolla-meego-startup-ex-nokia-employees - \r\n_A group of ex-Nokia staff and MeeGo enthusiasts has formed Jolla (Finnish for \"dinghy\"), a mobile startup with the aim of bringing new MeeGo devices to the market._ \r\nThank you, thank you so much!\r\n#nokia #meego #maemo #mer #linux #smartphone","public":true,"created_at":"2012-07-07T22:16:11Z","interacted_at":"2012-07-09T11:02:08Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"Ex-Nokia staff to build MeeGo-based smartphones - http://www.theverge.com/2012/7/7/3143099/jolla-meego-startup-ex-nokia-employees - \r\n_A group of ex-Nokia staff and MeeGo enthusiasts has formed Jolla (Finnish for \"dinghy\"), a mobile startup with the aim of bringing new MeeGo devices to the market._ \r\nThank you, thank you so much!\r\n#nokia #meego #maemo #mer #linux #smartphone","interactions":{"likes":[],"reshares":[],"comments_count":5,"likes_count":9,"reshares_count":3,"comments":[{"id":18837,"guid":"e70d7b0bbb779547","text":"Can they join efforts with Mer and PlasmaActive? I don't really see a need to reinvent the wheel.","author":{"id":1864,"guid":"6d48d8a46633e586","name":"Shmerl","diaspora_id":"bahaltener@joindiaspora.com","avatar":{"small":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_small_7d3b625db04eca524c67.png","medium":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_medium_7d3b625db04eca524c67.png","large":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_7d3b625db04eca524c67.png"}},"created_at":"2012-07-08T02:30:40Z"},{"id":18842,"guid":"421e799bef69f18b","text":"Looks like they do work with Mer. Good news!","author":{"id":1864,"guid":"6d48d8a46633e586","name":"Shmerl","diaspora_id":"bahaltener@joindiaspora.com","avatar":{"small":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_small_7d3b625db04eca524c67.png","medium":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_medium_7d3b625db04eca524c67.png","large":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_7d3b625db04eca524c67.png"}},"created_at":"2012-07-08T06:02:18Z"},{"id":18944,"guid":"16320b7c377ebb5a","text":"Tizen has normal Linux stack (X.org or Wayland based), so if you build all the dependencies, you can run Qt based programs there. The downside will be, that Qt isn't included in Tizen by default so far. They promote using EFL.","author":{"id":1864,"guid":"6d48d8a46633e586","name":"Shmerl","diaspora_id":"bahaltener@joindiaspora.com","avatar":{"small":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_small_7d3b625db04eca524c67.png","medium":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_medium_7d3b625db04eca524c67.png","large":"https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_7d3b625db04eca524c67.png"}},"created_at":"2012-07-09T02:59:06Z"}]}},{"id":11937,"guid":"2aad765debb1e80e","text":"to all podmins: \r\nplease read this announcement: https://groups.google.com/d/msg/diaspora-dev/kMOuJk5h_v4/5Gx1Dsib6EQJ \r\nthis hopefully provides the solution to clean the database from even the most stubborn mixed-case hashtags. \r\n#diaspora #podmin #hashtags #actionrequired","public":true,"created_at":"2012-07-06T11:56:30Z","interacted_at":"2012-07-06T16:32:38Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"to all podmins: \r\nplease read this announcement: https://groups.google.com/d/msg/diaspora-dev/kMOuJk5h_v4/5Gx1Dsib6EQJ \r\nthis hopefully provides the solution to clean the database from even the most stubborn mixed-case hashtags. \r\n#diaspora #podmin #hashtags #actionrequired","interactions":{"likes":[],"reshares":[],"comments_count":3,"likes_count":2,"reshares_count":1,"comments":[{"id":18691,"guid":"8a907544696e4faf","text":"thanks!","author":{"id":365,"guid":"dfc51824b3a76b71","name":"Sven Fischer","diaspora_id":"strubbl@sxspora.de","avatar":{"small":"http://sxspora.de/uploads/images/thumb_small_5c105bceab19eff9b0a3.jpg","medium":"http://sxspora.de/uploads/images/thumb_medium_5c105bceab19eff9b0a3.jpg","large":"http://sxspora.de/uploads/images/thumb_large_5c105bceab19eff9b0a3.jpg"}},"created_at":"2012-07-06T14:53:56Z"},{"id":18695,"guid":"8547aa6d2738ecb4","text":"before 2589. now of course 0. I prepended the bundle command with RAILS_ENV=production DB=\"mysql\". Otherwise it didn't work because a diaspora_development does not exist.","author":{"id":365,"guid":"dfc51824b3a76b71","name":"Sven Fischer","diaspora_id":"strubbl@sxspora.de","avatar":{"small":"http://sxspora.de/uploads/images/thumb_small_5c105bceab19eff9b0a3.jpg","medium":"http://sxspora.de/uploads/images/thumb_medium_5c105bceab19eff9b0a3.jpg","large":"http://sxspora.de/uploads/images/thumb_large_5c105bceab19eff9b0a3.jpg"}},"created_at":"2012-07-06T15:10:44Z"},{"id":18704,"guid":"247b0520a7824450","text":"oh, sorry ... yeah I thought that was implied","author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"created_at":"2012-07-06T16:32:38Z"}]}},{"id":11934,"guid":"e75e4e4719bf9405","text":"qtruby is intriguing ... I think I'll need to build something with it ;) \r\n(writing this from a QWebView created by a ruby script ^^) \r\n#ruby #qt #programming","public":true,"created_at":"2012-07-06T11:15:04Z","interacted_at":"2012-07-06T11:15:05Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"qtruby is intriguing ... I think I'll need to build something with it ;) \r\n(writing this from a QWebView created by a ruby script ^^) \r\n#ruby #qt #programming","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":0,"comments":[]}},{"id":11782,"guid":"23416f5cd259bfcc","text":"can one or more podmins please test this pull request on a *copy* of their database? -> https://github.com/diaspora/diaspora/pull/3434 \r\nit's about hashtags mit mixed-case letters in them, and the PR ccontains some changes to the rake task that is supposed to clean those up, which should hopefully eliminate mixed-case hashtags one and for all. \r\nto verify the successful run, the rake task should complete and in your database there should be no more mixed-case hashtags. You can check this by running this statement before and after the rake task ran: \r\n\r\n SELECT * FROM tags WHERE LOWER(name) != name\r\n\r\nBefore, you should see a list of all hashtags that will be processed, and after, the query shoud return an empty result. \r\n\r\n#diaspora #podmin #pleasetest #hashtags","public":true,"created_at":"2012-07-05T10:01:50Z","interacted_at":"2012-07-08T19:18:00Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"can one or more podmins please test this pull request on a *copy* of their database? -> https://github.com/diaspora/diaspora/pull/3434 \r\nit's about hashtags mit mixed-case letters in them, and the PR ccontains some changes to the rake task that is supposed to clean those up, which should hopefully eliminate mixed-case hashtags one and for all. \r\nto verify the successful run, the rake task should complete and in your database there should be no more mixed-case hashtags. You can check this by running this statement before and after the rake task ran: \r\n\r\n SELECT * FROM tags WHERE LOWER(name) != name\r\n\r\nBefore, you should see a list of all hashtags that will be processed, and after, the query shoud return an empty result. \r\n\r\n#diaspora #podmin #pleasetest #hashtags","interactions":{"likes":[],"reshares":[],"comments_count":6,"likes_count":2,"reshares_count":0,"comments":[{"id":18584,"guid":"217ad7b7ab5fa869","text":"Oh! Duhh! Sorry, let me merge that and try again.","author":{"id":5653,"guid":"7410329c39e6810f","name":"Hans","diaspora_id":"hans@hfase.com","avatar":{"small":"https://hfase.com/uploads/images/thumb_small_f2b2d6b041732c5f91eb.jpg","medium":"https://hfase.com/uploads/images/thumb_medium_f2b2d6b041732c5f91eb.jpg","large":"https://hfase.com/uploads/images/thumb_large_f2b2d6b041732c5f91eb.jpg"}},"created_at":"2012-07-05T10:36:46Z"},{"id":18586,"guid":"0268792e018c3ec3","text":"\"MySQL returned an empty result set (i.e. zero rows). ( Query took 0.0003 sec )\"\n\nMuch better! :D Thanks!!","author":{"id":5653,"guid":"7410329c39e6810f","name":"Hans","diaspora_id":"hans@hfase.com","avatar":{"small":"https://hfase.com/uploads/images/thumb_small_f2b2d6b041732c5f91eb.jpg","medium":"https://hfase.com/uploads/images/thumb_medium_f2b2d6b041732c5f91eb.jpg","large":"https://hfase.com/uploads/images/thumb_large_f2b2d6b041732c5f91eb.jpg"}},"created_at":"2012-07-05T10:39:12Z"},{"id":18587,"guid":"8b39d807abd7302e","text":"yeah, that looks good!","author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"created_at":"2012-07-05T10:44:19Z"}]}},{"id":11774,"guid":"dbcb53c18a1c40bc","text":"# Intro To Using Diaspora\\*\r\n\r\n## Federated Social Networking\r\n\r\nDiaspora\\* is a social network (socnet), similar in many ways to Facebook, #MySpace, #Orkut, and Google Plus ( #GPlus). In fact, those of us who were already using D\\* when GPlus came out were quite familiar with its layout and functionality. It was almost as if they had started developing by grabbing D\\* code and stripping out federation.\r\n\r\nWhen I say federated, I mean that there is not one central Diaspora\\* server (or server cluster) that all users belong to. Instead, there are many [Diaspora\\* servers](http://podupti.me/) to choose from, with different operators ( #podmin), privacy policies, terms of service, and so on. Federation works much like when you decide to mail someone. It doesn't matter to me whether you use Gmail, Hotmail, Ymail, or GMX. I can send messages to you because electronic mail is federated. It is the same way with Diaspora\\*. You may be on [JoinDiaspora](http://joindiaspora.com/), [Calispora](http://calispora.org/), [Diasp.org](http://diasp.org/), [Diasp.eu](http://diasp.eu/), [Serendipitous](http://ser.endipito.us/) or another pod. You can still connect to people whose accounts are on other pods.\r\n\r\nI have written before about [federation](https://joindiaspora.com/posts/1679098).\r\n\r\nThis is an advantage, because it means that you're not beholden to a single organization's policies. If you decide that you dislike the _podmin_ on Pod X, you can open an account on Pod Y instead or even set up your own pod. (_**Moving** your account is not yet implemented_, but I believe you can export your contacts and use the export to help you repopulate that list on your new pod.) If podmin X decides to shut down pod X, again you can open an account on another pod or host your own.\r\n\r\n## @ mentions\r\n\r\nHit the at-sign and the first few letters of the person's display name (it used to be the first few of the person's username, but then they decided to hide that ... personally, I wish they'd switch back)\r\n\r\nWhen you mention someone, make sure you set the privacy to include the group that person is in. There was a bug (possibly fixed) where you could mention someone in a post they weren't allowed to see. I do not believe that @ mentions work in comments yet.\r\n\r\nTwitter, where at-mentions were invented (by users and 3rd-party clients) doesn't have the problem of at-mentions affecting groups simply because it does not have any form of privacy groups.\r\n\r\n## Hashtags\r\n\r\nDiaspora\\* supports #hashtags. Because your pod intercepts them, being on a bigger pod means that clicking a hashtag will give a larger results set than if you clicked on the hashtag from a smaller pod. It is a known problem of the current federation mechanism, and is being fixed.\r\n\r\nTwitter, where hashtags were invented (by users and 3rd-party clients), doesn't have this problem only because everyone is one the same instance of T. #StatusNet, which is like a federated clone of #Twitter, also has the same issue to some degree.\r\n\r\n## Aspects\r\n\r\nPrivacy groups for posts; these were the obvious inspiration for #GPlus's circles, and they work similarly. For example, you may wish to place your boss and others that you know from work into a work aspect. You may also wish to place people you know from college, church, or other such activities into aspects specific to their roles in your life, and to place family members into aspects specific to people in that role.\r\n\r\nIf you didn't already understand aspects, consider this: if posts are wide-open, anyone who becomes a contact can see them. So if you have your boss as a contact, and you post a photo of your trip to the beach won a day you called in sick, _you may get fired for stupidity_. What you do is you put your boss into a work aspect, and only post things into that aspect that are acceptable in a work context.\r\n\r\n## Posting syntax\r\n\r\nDiaspora\\* uses something called [Markdown](http://www.simpleeditions.com/59001/markdown-an-introduction) for its posts. Most of the time, you can just post in plain text and not worry about it, but every once in a while, Markdown will distort what you've posted.\r\n\r\nMarkdown does give you the ability to _italicize_, **bold**, and otherwise decorate text and to embed links and images using a fairly simple syntax. I find, however, that I have to look up embedding every time I use it.\r\n\r\n(I personally prefer [Textile](http://textile.thresholdstate.com/). You still have to learn to use it effectively, but it more closely matches what experienced net users have grown to expect from applications like Outlook and Thunderbird. For instance, if I want bold text, surround it with single asterisks [\\*] rather than the double asterisks [\\*\\*] that Markdown requires.)\r\n\r\n## Pods\r\n\r\nA Diaspora\\* pod is the server or server cluster where your account resides. There are dozens or even hundreds of pods out there. Most of them are pretty similar in what they offer. A few offer experimental features, such as post previews, pod-only posts, or encrypted messaging. It is my hope that many of these features will be picked up by the main codebase, so that all pods will have them.\r\n\r\nYou'll rarely need to know this, but every Diaspora\\* account has an address that looks like username@podname.com. If you want people to be able to add you as a contact, publish your Diaspora\\* address. They'll be able to add you that way.\r\n\r\n## Facebook\r\n\r\nAll of the pods I have used have the ability to connect to certain external accounts, such as Twitter and #Facebook. This means that you can post from D\\* to FB or T. You don't have to abandon your \"friends\" on other #socnets because you join D\\*.\r\n\r\nIf you read many online articles, you will come across some that seem to believe that Diaspora\\*'s purpose is to become a Facebook-killer. Do not believe them. If and when people tire of Facebook, it will be because of something that FB does, not because socnet X is better. If you look at D\\* as a substitute for Facebook, it will be like a meat-eater who tries to replace meat with soy-based meat substitutes. You won't like it. Instead, I recommend that you get to know people who are on D\\* and that you invite your existing contacts, but that you **enjoy D\\* for its own value**. If you find that it then makes FB unnecessary, that is good. If, on the other hand, you still want to keep your FB account, that is also good.\r\n\r\n## Controversies\r\n\r\nThere are occasional squabbles over the directions the project is taking. Unlike the squabbles at Twitter, which took place behind closed doors and resulted in a number of highly-skilled people leaving and the recently announced restrictions on how client applications can display Twitter-sourced content, Diaspora\\*'s squabbles tend to happen in public. My advice is simple: stay out of the squabbles, find your own philosophical point of view, and support this and any other project that agrees with that point of view. If the time comes when this or any other project no longer fits your POV, leave quietly.\r\n\r\nWhen I felt that GPlus was hostile to my POV, I closed my accounts. When I felt that Facebook was hostile to my POV, I closed my account. I do not go around trash-talking either project, or assuming that anyone in said projects is intentionally \"evil,\" and I would not recommend doing that to D\\* or any other project.\r\n\r\n## Future\r\n\r\nAt some point in the future, the Diaspora\\* developers will be changing the federation protocol. Federation is what enables a user on Pod X to interact with users on pods Y, Z, etc. They are working to improve scalability (ability to handle more content posted from more users in the same period of time) and content dispersion (ability for content to travel between a wider number of pods seamlessly). It is a tough task. If you are interested in #Ruby programming or Ruby on Rails ( #RoR ), I would encourage you to get involved.\r\n\r\nThey are also planning to make D\\* a far more visual-oriented socnet. That means that posts with images, graphics, and video will be far more interesting, and will be displayed in a manner that caters to those things. There is an experimental pod where they test out many of the visual designs that may make it into the D* codebase. I will not link it here, because people may misunderstand that it is experimental and not really intended to be your home pod.\r\n\r\nIf you're interested in the technical side and the future directions, they have a moderated and directed code-chat on IRC every (other?) Thursday at 10AM Pacific in the room #diaspora-meeting on Freenode. Sean can jump in on the comments to correct me on this.\r\n\r\n## Conclusion\r\n\r\nThis is long, but I think this is a good intro to Diaspora\\*. I wish there had been someone who could write something like this when I joined. I should also put in a disclaimer. This is my personal opinion, and not the official stance of any podmin or of the Diaspora\\* developers. You are free to disagree, but please start a new thread for it. This is posted in the hope that people who newly join Diaspora\\* will get a head start.\r\n\r\nThere are a number of tutorials at [Diasporal](http://diasporial.com/). I would encourage you to visit the site and check them out. If you are a blogger, or if you write for a magazine (online or dead-tree), I would encourage you to write about Diaspora\\* once you've taken some time to get to know the place.","public":true,"created_at":"2012-07-05T09:37:15Z","interacted_at":"2012-07-05T09:37:15Z","provider_display_name":null,"post_type":"Reshare","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":{"id":11730,"guid":"57288b4adf721900","text":"# Intro To Using Diaspora\\*\r\n\r\n## Federated Social Networking\r\n\r\nDiaspora\\* is a social network (socnet), similar in many ways to Facebook, #MySpace, #Orkut, and Google Plus ( #GPlus). In fact, those of us who were already using D\\* when GPlus came out were quite familiar with its layout and functionality. It was almost as if they had started developing by grabbing D\\* code and stripping out federation.\r\n\r\nWhen I say federated, I mean that there is not one central Diaspora\\* server (or server cluster) that all users belong to. Instead, there are many [Diaspora\\* servers](http://podupti.me/) to choose from, with different operators ( #podmin), privacy policies, terms of service, and so on. Federation works much like when you decide to mail someone. It doesn't matter to me whether you use Gmail, Hotmail, Ymail, or GMX. I can send messages to you because electronic mail is federated. It is the same way with Diaspora\\*. You may be on [JoinDiaspora](http://joindiaspora.com/), [Calispora](http://calispora.org/), [Diasp.org](http://diasp.org/), [Diasp.eu](http://diasp.eu/), [Serendipitous](http://ser.endipito.us/) or another pod. You can still connect to people whose accounts are on other pods.\r\n\r\nI have written before about [federation](https://joindiaspora.com/posts/1679098).\r\n\r\nThis is an advantage, because it means that you're not beholden to a single organization's policies. If you decide that you dislike the _podmin_ on Pod X, you can open an account on Pod Y instead or even set up your own pod. (_**Moving** your account is not yet implemented_, but I believe you can export your contacts and use the export to help you repopulate that list on your new pod.) If podmin X decides to shut down pod X, again you can open an account on another pod or host your own.\r\n\r\n## @ mentions\r\n\r\nHit the at-sign and the first few letters of the person's display name (it used to be the first few of the person's username, but then they decided to hide that ... personally, I wish they'd switch back)\r\n\r\nWhen you mention someone, make sure you set the privacy to include the group that person is in. There was a bug (possibly fixed) where you could mention someone in a post they weren't allowed to see. I do not believe that @ mentions work in comments yet.\r\n\r\nTwitter, where at-mentions were invented (by users and 3rd-party clients) doesn't have the problem of at-mentions affecting groups simply because it does not have any form of privacy groups.\r\n\r\n## Hashtags\r\n\r\nDiaspora\\* supports #hashtags. Because your pod intercepts them, being on a bigger pod means that clicking a hashtag will give a larger results set than if you clicked on the hashtag from a smaller pod. It is a known problem of the current federation mechanism, and is being fixed.\r\n\r\nTwitter, where hashtags were invented (by users and 3rd-party clients), doesn't have this problem only because everyone is one the same instance of T. #StatusNet, which is like a federated clone of #Twitter, also has the same issue to some degree.\r\n\r\n## Aspects\r\n\r\nPrivacy groups for posts; these were the obvious inspiration for #GPlus's circles, and they work similarly. For example, you may wish to place your boss and others that you know from work into a work aspect. You may also wish to place people you know from college, church, or other such activities into aspects specific to their roles in your life, and to place family members into aspects specific to people in that role.\r\n\r\nIf you didn't already understand aspects, consider this: if posts are wide-open, anyone who becomes a contact can see them. So if you have your boss as a contact, and you post a photo of your trip to the beach won a day you called in sick, _you may get fired for stupidity_. What you do is you put your boss into a work aspect, and only post things into that aspect that are acceptable in a work context.\r\n\r\n## Posting syntax\r\n\r\nDiaspora\\* uses something called [Markdown](http://www.simpleeditions.com/59001/markdown-an-introduction) for its posts. Most of the time, you can just post in plain text and not worry about it, but every once in a while, Markdown will distort what you've posted.\r\n\r\nMarkdown does give you the ability to _italicize_, **bold**, and otherwise decorate text and to embed links and images using a fairly simple syntax. I find, however, that I have to look up embedding every time I use it.\r\n\r\n(I personally prefer [Textile](http://textile.thresholdstate.com/). You still have to learn to use it effectively, but it more closely matches what experienced net users have grown to expect from applications like Outlook and Thunderbird. For instance, if I want bold text, surround it with single asterisks [\\*] rather than the double asterisks [\\*\\*] that Markdown requires.)\r\n\r\n## Pods\r\n\r\nA Diaspora\\* pod is the server or server cluster where your account resides. There are dozens or even hundreds of pods out there. Most of them are pretty similar in what they offer. A few offer experimental features, such as post previews, pod-only posts, or encrypted messaging. It is my hope that many of these features will be picked up by the main codebase, so that all pods will have them.\r\n\r\nYou'll rarely need to know this, but every Diaspora\\* account has an address that looks like username@podname.com. If you want people to be able to add you as a contact, publish your Diaspora\\* address. They'll be able to add you that way.\r\n\r\n## Facebook\r\n\r\nAll of the pods I have used have the ability to connect to certain external accounts, such as Twitter and #Facebook. This means that you can post from D\\* to FB or T. You don't have to abandon your \"friends\" on other #socnets because you join D\\*.\r\n\r\nIf you read many online articles, you will come across some that seem to believe that Diaspora\\*'s purpose is to become a Facebook-killer. Do not believe them. If and when people tire of Facebook, it will be because of something that FB does, not because socnet X is better. If you look at D\\* as a substitute for Facebook, it will be like a meat-eater who tries to replace meat with soy-based meat substitutes. You won't like it. Instead, I recommend that you get to know people who are on D\\* and that you invite your existing contacts, but that you **enjoy D\\* for its own value**. If you find that it then makes FB unnecessary, that is good. If, on the other hand, you still want to keep your FB account, that is also good.\r\n\r\n## Controversies\r\n\r\nThere are occasional squabbles over the directions the project is taking. Unlike the squabbles at Twitter, which took place behind closed doors and resulted in a number of highly-skilled people leaving and the recently announced restrictions on how client applications can display Twitter-sourced content, Diaspora\\*'s squabbles tend to happen in public. My advice is simple: stay out of the squabbles, find your own philosophical point of view, and support this and any other project that agrees with that point of view. If the time comes when this or any other project no longer fits your POV, leave quietly.\r\n\r\nWhen I felt that GPlus was hostile to my POV, I closed my accounts. When I felt that Facebook was hostile to my POV, I closed my account. I do not go around trash-talking either project, or assuming that anyone in said projects is intentionally \"evil,\" and I would not recommend doing that to D\\* or any other project.\r\n\r\n## Future\r\n\r\nAt some point in the future, the Diaspora\\* developers will be changing the federation protocol. Federation is what enables a user on Pod X to interact with users on pods Y, Z, etc. They are working to improve scalability (ability to handle more content posted from more users in the same period of time) and content dispersion (ability for content to travel between a wider number of pods seamlessly). It is a tough task. If you are interested in #Ruby programming or Ruby on Rails ( #RoR ), I would encourage you to get involved.\r\n\r\nThey are also planning to make D\\* a far more visual-oriented socnet. That means that posts with images, graphics, and video will be far more interesting, and will be displayed in a manner that caters to those things. There is an experimental pod where they test out many of the visual designs that may make it into the D* codebase. I will not link it here, because people may misunderstand that it is experimental and not really intended to be your home pod.\r\n\r\nIf you're interested in the technical side and the future directions, they have a moderated and directed code-chat on IRC every (other?) Thursday at 10AM Pacific in the room #diaspora-meeting on Freenode. Sean can jump in on the comments to correct me on this.\r\n\r\n## Conclusion\r\n\r\nThis is long, but I think this is a good intro to Diaspora\\*. I wish there had been someone who could write something like this when I joined. I should also put in a disclaimer. This is my personal opinion, and not the official stance of any podmin or of the Diaspora\\* developers. You are free to disagree, but please start a new thread for it. This is posted in the hope that people who newly join Diaspora\\* will get a head start.\r\n\r\nThere are a number of tutorials at [Diasporal](http://diasporial.com/). I would encourage you to visit the site and check them out. If you are a blogger, or if you write for a magazine (online or dead-tree), I would encourage you to write about Diaspora\\* once you've taken some time to get to know the place.","public":true,"created_at":"2012-07-04T23:41:33Z","interacted_at":"2012-07-05T04:21:21Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":5508,"guid":"25d1ca8dd064f3dd","name":"lnxwalt@calispora.org","diaspora_id":"lnxwalt@calispora.org","avatar":{"small":"https://pod.fulll.name/images/user/default.png","medium":"https://pod.fulll.name/images/user/default.png","large":"https://pod.fulll.name/images/user/default.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"# Intro To Using Diaspora\\*\r\n\r\n## Federated Social Networking\r\n\r\nDiaspora\\* is a social network (socnet), similar in many ways to Facebook, #MySpace, #Orkut, and Google Plus ( #GPlus). In fact, those of us who were already using D\\* when GPlus came out were quite familiar with its layout and functionality. It was almost as if they had started developing by grabbing D\\* code and stripping out federation.\r\n\r\nWhen I say federated, I mean that there is not one central Diaspora\\* server (or server cluster) that all users belong to. Instead, there are many [Diaspora\\* servers](http://podupti.me/) to choose from, with different operators ( #podmin), privacy policies, terms of service, and so on. Federation works much like when you decide to mail someone. It doesn't matter to me whether you use Gmail, Hotmail, Ymail, or GMX. I can send messages to you because electronic mail is federated. It is the same way with Diaspora\\*. You may be on [JoinDiaspora](http://joindiaspora.com/), [Calispora](http://calispora.org/), [Diasp.org](http://diasp.org/), [Diasp.eu](http://diasp.eu/), [Serendipitous](http://ser.endipito.us/) or another pod. You can still connect to people whose accounts are on other pods.\r\n\r\nI have written before about [federation](https://joindiaspora.com/posts/1679098).\r\n\r\nThis is an advantage, because it means that you're not beholden to a single organization's policies. If you decide that you dislike the _podmin_ on Pod X, you can open an account on Pod Y instead or even set up your own pod. (_**Moving** your account is not yet implemented_, but I believe you can export your contacts and use the export to help you repopulate that list on your new pod.) If podmin X decides to shut down pod X, again you can open an account on another pod or host your own.\r\n\r\n## @ mentions\r\n\r\nHit the at-sign and the first few letters of the person's display name (it used to be the first few of the person's username, but then they decided to hide that ... personally, I wish they'd switch back)\r\n\r\nWhen you mention someone, make sure you set the privacy to include the group that person is in. There was a bug (possibly fixed) where you could mention someone in a post they weren't allowed to see. I do not believe that @ mentions work in comments yet.\r\n\r\nTwitter, where at-mentions were invented (by users and 3rd-party clients) doesn't have the problem of at-mentions affecting groups simply because it does not have any form of privacy groups.\r\n\r\n## Hashtags\r\n\r\nDiaspora\\* supports #hashtags. Because your pod intercepts them, being on a bigger pod means that clicking a hashtag will give a larger results set than if you clicked on the hashtag from a smaller pod. It is a known problem of the current federation mechanism, and is being fixed.\r\n\r\nTwitter, where hashtags were invented (by users and 3rd-party clients), doesn't have this problem only because everyone is one the same instance of T. #StatusNet, which is like a federated clone of #Twitter, also has the same issue to some degree.\r\n\r\n## Aspects\r\n\r\nPrivacy groups for posts; these were the obvious inspiration for #GPlus's circles, and they work similarly. For example, you may wish to place your boss and others that you know from work into a work aspect. You may also wish to place people you know from college, church, or other such activities into aspects specific to their roles in your life, and to place family members into aspects specific to people in that role.\r\n\r\nIf you didn't already understand aspects, consider this: if posts are wide-open, anyone who becomes a contact can see them. So if you have your boss as a contact, and you post a photo of your trip to the beach won a day you called in sick, _you may get fired for stupidity_. What you do is you put your boss into a work aspect, and only post things into that aspect that are acceptable in a work context.\r\n\r\n## Posting syntax\r\n\r\nDiaspora\\* uses something called [Markdown](http://www.simpleeditions.com/59001/markdown-an-introduction) for its posts. Most of the time, you can just post in plain text and not worry about it, but every once in a while, Markdown will distort what you've posted.\r\n\r\nMarkdown does give you the ability to _italicize_, **bold**, and otherwise decorate text and to embed links and images using a fairly simple syntax. I find, however, that I have to look up embedding every time I use it.\r\n\r\n(I personally prefer [Textile](http://textile.thresholdstate.com/). You still have to learn to use it effectively, but it more closely matches what experienced net users have grown to expect from applications like Outlook and Thunderbird. For instance, if I want bold text, surround it with single asterisks [\\*] rather than the double asterisks [\\*\\*] that Markdown requires.)\r\n\r\n## Pods\r\n\r\nA Diaspora\\* pod is the server or server cluster where your account resides. There are dozens or even hundreds of pods out there. Most of them are pretty similar in what they offer. A few offer experimental features, such as post previews, pod-only posts, or encrypted messaging. It is my hope that many of these features will be picked up by the main codebase, so that all pods will have them.\r\n\r\nYou'll rarely need to know this, but every Diaspora\\* account has an address that looks like username@podname.com. If you want people to be able to add you as a contact, publish your Diaspora\\* address. They'll be able to add you that way.\r\n\r\n## Facebook\r\n\r\nAll of the pods I have used have the ability to connect to certain external accounts, such as Twitter and #Facebook. This means that you can post from D\\* to FB or T. You don't have to abandon your \"friends\" on other #socnets because you join D\\*.\r\n\r\nIf you read many online articles, you will come across some that seem to believe that Diaspora\\*'s purpose is to become a Facebook-killer. Do not believe them. If and when people tire of Facebook, it will be because of something that FB does, not because socnet X is better. If you look at D\\* as a substitute for Facebook, it will be like a meat-eater who tries to replace meat with soy-based meat substitutes. You won't like it. Instead, I recommend that you get to know people who are on D\\* and that you invite your existing contacts, but that you **enjoy D\\* for its own value**. If you find that it then makes FB unnecessary, that is good. If, on the other hand, you still want to keep your FB account, that is also good.\r\n\r\n## Controversies\r\n\r\nThere are occasional squabbles over the directions the project is taking. Unlike the squabbles at Twitter, which took place behind closed doors and resulted in a number of highly-skilled people leaving and the recently announced restrictions on how client applications can display Twitter-sourced content, Diaspora\\*'s squabbles tend to happen in public. My advice is simple: stay out of the squabbles, find your own philosophical point of view, and support this and any other project that agrees with that point of view. If the time comes when this or any other project no longer fits your POV, leave quietly.\r\n\r\nWhen I felt that GPlus was hostile to my POV, I closed my accounts. When I felt that Facebook was hostile to my POV, I closed my account. I do not go around trash-talking either project, or assuming that anyone in said projects is intentionally \"evil,\" and I would not recommend doing that to D\\* or any other project.\r\n\r\n## Future\r\n\r\nAt some point in the future, the Diaspora\\* developers will be changing the federation protocol. Federation is what enables a user on Pod X to interact with users on pods Y, Z, etc. They are working to improve scalability (ability to handle more content posted from more users in the same period of time) and content dispersion (ability for content to travel between a wider number of pods seamlessly). It is a tough task. If you are interested in #Ruby programming or Ruby on Rails ( #RoR ), I would encourage you to get involved.\r\n\r\nThey are also planning to make D\\* a far more visual-oriented socnet. That means that posts with images, graphics, and video will be far more interesting, and will be displayed in a manner that caters to those things. There is an experimental pod where they test out many of the visual designs that may make it into the D* codebase. I will not link it here, because people may misunderstand that it is experimental and not really intended to be your home pod.\r\n\r\nIf you're interested in the technical side and the future directions, they have a moderated and directed code-chat on IRC every (other?) Thursday at 10AM Pacific in the room #diaspora-meeting on Freenode. Sean can jump in on the comments to correct me on this.\r\n\r\n## Conclusion\r\n\r\nThis is long, but I think this is a good intro to Diaspora\\*. I wish there had been someone who could write something like this when I joined. I should also put in a disclaimer. This is my personal opinion, and not the official stance of any podmin or of the Diaspora\\* developers. You are free to disagree, but please start a new thread for it. This is posted in the hope that people who newly join Diaspora\\* will get a head start.\r\n\r\nThere are a number of tutorials at [Diasporal](http://diasporial.com/). I would encourage you to visit the site and check them out. If you are a blogger, or if you write for a magazine (online or dead-tree), I would encourage you to write about Diaspora\\* once you've taken some time to get to know the place.","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":4}},"title":"A post from Florian Staudacher","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":0,"comments":[]}},{"id":11725,"guid":"909471c6070243be","text":"If you think you know of a #Diaspora #Bug please remember to be as specific as possible when describing it so we can help!!","public":true,"created_at":"2012-07-04T23:29:43Z","interacted_at":"2012-07-04T23:29:43Z","provider_display_name":null,"post_type":"Reshare","nsfw":false,"author":{"id":2,"guid":"7445f9a0a6c28ebb","name":"Florian Staudacher","diaspora_id":"raven24@pod.fulll.name","avatar":{"small":"https://pod.fulll.name/uploads/images/thumb_small_5f612f44a0a026b119f8.png","medium":"https://pod.fulll.name/uploads/images/thumb_medium_5f612f44a0a026b119f8.png","large":"https://pod.fulll.name/uploads/images/thumb_large_5f612f44a0a026b119f8.png"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":{"id":11718,"guid":"c1770c590b097c28","text":"If you think you know of a #Diaspora #Bug please remember to be as specific as possible when describing it so we can help!!","public":true,"created_at":"2012-07-04T22:00:49Z","interacted_at":"2012-07-05T08:19:07Z","provider_display_name":null,"post_type":"StatusMessage","nsfw":false,"author":{"id":5653,"guid":"7410329c39e6810f","name":"Hans","diaspora_id":"hans@hfase.com","avatar":{"small":"https://hfase.com/uploads/images/thumb_small_f2b2d6b041732c5f91eb.jpg","medium":"https://hfase.com/uploads/images/thumb_medium_f2b2d6b041732c5f91eb.jpg","large":"https://hfase.com/uploads/images/thumb_large_f2b2d6b041732c5f91eb.jpg"}},"o_embed_cache":null,"mentioned_people":[],"photos":[],"root":null,"title":"If you think you know of a #Diaspora #Bug please remember to be as specific as possible when describing it so we can help!!","interactions":{"likes":[],"reshares":[{"reshare":{"author_id":2,"comments_count":0,"created_at":"2012-07-04T23:29:43Z","diaspora_handle":"raven24@pod.fulll.name","guid":"909471c6070243be","id":11725,"interacted_at":"2012-07-04T23:29:43Z","likes_count":0,"o_embed_cache_id":null,"provider_display_name":null,"public":true,"reshares_count":0,"root_guid":"c1770c590b097c28","text":null,"updated_at":"2012-07-04T23:29:43Z"}}],"comments_count":0,"likes_count":2,"reshares_count":2}},"title":"A post from Florian Staudacher","interactions":{"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":0,"comments":[]}}] diff --git a/spec/fixtures/valid_client_assertion.txt b/spec/fixtures/valid_client_assertion.txt new file mode 100644 index 0000000000000000000000000000000000000000..4a0ac9441f4f119908b50df6862143058cffd059 --- /dev/null +++ b/spec/fixtures/valid_client_assertion.txt @@ -0,0 +1 @@ +eyJhbGciOiJSUzI1NiIsImtpZCI6ImExIn0.eyJhdWQiOiBbImh0dHBzOi8va2VudHNoaWthbWEuY29tL2FwaS9vcGVuaWRfY29ubmVjdC9hY2Nlc3NfdG9rZW5zIl0sICJpc3MiOiAiMTRkNjkyY2Q1M2Q5YzFhOWY0NmZkNjllMGU1NzQ0M2UiLCAianRpIjogIjBtY3JyZVlIIiwgImV4cCI6IDE0NDMxNzA4OTEuMzk3NDU2LCAiaWF0IjogMTQ0MzE3MDI5MS4zOTc0NTYsICJzdWIiOiAiMTRkNjkyY2Q1M2Q5YzFhOWY0NmZkNjllMGU1NzQ0M2UifQ.QJUR3SYFrEIlbfOKjO0NYInddklytbJ2LSWNpkQ1aNThgneDCVCjIYGCaL2C9Sw-GR8j7QSUsKOwBbjZMUmVPFTjsfB4wdgObbxVt1QAXwDjAXc5w1smOerRsoahZ4yKI1an6PTaFxMwnoXUQcBZTsOS6RgXOCPPPoxibxohxoehPLieM0l7LYcF5DQKg7fTxZYOpmtiP--nibJxomXdVQNLSnZuQwnyWtlp_gYmqrYMMN1LPSmNCgZMZZZIYttaaAIA96SylglqubowJRShtDO9rSvUz_sgeCo7qo5Bfb0B5n9_PtIlr1CZSVoHyYj2lVqQldx7fnGuqqQJCfDQog \ No newline at end of file diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 8ce0ea39cac73d836d43f5abfa1cdd70419dfd3f..092b8f6a14a7fdfda0901a1c42efa4fa39572797 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -74,7 +74,7 @@ describe ApplicationHelper, :type => :helper do end it 'includes jquery.js from asset pipeline' do - expect(jquery_include_tag).to match(/jquery\.js/) + expect(jquery_include_tag).to match(/jquery2\.js/) expect(jquery_include_tag).not_to match(/jquery\.com/) end end @@ -88,17 +88,16 @@ describe ApplicationHelper, :type => :helper do end end - describe '#changelog_url' do - it 'defaults to master branch changleog' do - AppConfig.git_revision = nil - expect(changelog_url).to eq('https://github.com/diaspora/diaspora/blob/master/Changelog.md') + describe "#changelog_url" do + it "defaults to master branch changleog" do + expect(AppConfig).to receive(:git_revision).and_return(nil) + expect(changelog_url).to eq("https://github.com/diaspora/diaspora/blob/master/Changelog.md") end - it 'displays the changelog for the current git revision if set' do - AppConfig.git_revision = '123' - expect(changelog_url).to eq('https://github.com/diaspora/diaspora/blob/123/Changelog.md') + it "displays the changelog for the current git revision if set" do + expect(AppConfig).to receive(:git_revision).twice.and_return("123") + expect(changelog_url).to eq("https://github.com/diaspora/diaspora/blob/123/Changelog.md") end - end describe '#pod_name' do @@ -108,7 +107,6 @@ describe ApplicationHelper, :type => :helper do it 'displays the supplied pod_name if it is set' do AppConfig.settings.pod_name = "Catspora" - # require 'pry'; binding.pry expect(pod_name).to match "Catspora" end end diff --git a/spec/helpers/gon_helper_spec.rb b/spec/helpers/gon_helper_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..c449c91260c7b0975b7086f9f02a849ebfff19d3 --- /dev/null +++ b/spec/helpers/gon_helper_spec.rb @@ -0,0 +1,48 @@ +require "spec_helper" + +describe GonHelper, type: :helper do + include_context :gon + + describe "#gon_load_contact" do + let(:contact) { FactoryGirl.build(:contact) } + let(:current_user) { contact.user } + let(:another_contact) { FactoryGirl.build(:contact, user: current_user) } + + before do + RequestStore.store[:gon] = Gon::Request.new(controller.request.env) + Gon.preloads = {} + end + + it "calls appropriate presenter" do + expect_any_instance_of(ContactPresenter).to receive(:full_hash_with_person) + gon_load_contact(contact) + end + + shared_examples "contacts loading" do + it "loads contacts to gon" do + gon_load_contact(contact) + gon_load_contact(another_contact) + expect(Gon.preloads[:contacts].count).to eq(2) + end + + it "avoids duplicates" do + gon_load_contact(contact) + gon_load_contact(contact) + expect(Gon.preloads[:contacts].count).to eq(1) + end + end + + context "with non-persisted contacts" do + include_examples "contacts loading" + end + + context "with persisted contacts" do + before do + contact.save! + another_contact.save! + end + + include_examples "contacts loading" + end + end +end diff --git a/spec/helpers/interim_stream_hackiness_helper_spec.rb b/spec/helpers/interim_stream_hackiness_helper_spec.rb index c0cbb0ba576297f76c0b5c74e30f42dd35988bf7..31fcfc2e9ae7022ed8e7212780a4c3ae76d9da10 100644 --- a/spec/helpers/interim_stream_hackiness_helper_spec.rb +++ b/spec/helpers/interim_stream_hackiness_helper_spec.rb @@ -1,8 +1,9 @@ require 'spec_helper' -describe InterimStreamHackinessHelper, :type => :helper do - describe 'commenting_disabled?' do - include Devise::TestHelpers +describe InterimStreamHackinessHelper, type: :helper do + describe "commenting_disabled?" do + include Devise::Test::ControllerHelpers + before do sign_in alice def user_signed_in? diff --git a/spec/helpers/invitation_codes_helper_spec.rb b/spec/helpers/invitation_codes_helper_spec.rb deleted file mode 100644 index 5ebd8b1ef90e3f06893df82a59179d7fb84e16fc..0000000000000000000000000000000000000000 --- a/spec/helpers/invitation_codes_helper_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -# Specs in this file have access to a helper object that includes -# the InvitationCodesHelper. For example: -# -# describe InvitationCodesHelper do -# describe "string concat" do -# it "concats two strings with spaces" do -# helper.concat_strings("this","that").should == "this that" -# end -# end -# end -describe InvitationCodesHelper, :type => :helper do - skip "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/helpers/language_helper_spec.rb b/spec/helpers/language_helper_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..73d4df5f8f5c3dccfcfe0606b2e5248722fac10e --- /dev/null +++ b/spec/helpers/language_helper_spec.rb @@ -0,0 +1,10 @@ +require "spec_helper" + +describe LanguageHelper, type: :helper do + describe "#get_javascript_strings_for" do + it "generates a jasmine fixture", fixture: true do + save_fixture(get_javascript_strings_for("en", "javascripts").to_json, "locale_en_javascripts_json") + save_fixture(get_javascript_strings_for("en", "help").to_json, "locale_en_help_json") + end + end +end diff --git a/spec/helpers/meta_data_helper_spec.rb b/spec/helpers/meta_data_helper_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..7564dd04a43a1b9304f2c1284f51773048ce93bb --- /dev/null +++ b/spec/helpers/meta_data_helper_spec.rb @@ -0,0 +1,55 @@ +require "spec_helper" + +describe MetaDataHelper, type: :helper do + describe "#meta_tag" do + it "returns an empty string if passed an empty hash" do + expect(meta_tag({})).to eq("") + end + + it "returns a meta tag with the passed attributes" do + attributes = {name: "test", content: "foo"} + expect(meta_tag(attributes)).to eq('<meta name="test" content="foo" />') + end + + it "returns a list of the same meta type if the value for :content in the passed attribute is an array" do + attributes = {property: "og:tag", content: %w(tag_1 tag_2)} + expect(meta_tag(attributes)).to eq( + %(<meta property="og:tag" content="tag_1" />\n) + + %(<meta property="og:tag" content="tag_2" />) + ) + end + end + + describe '#metas_tags' do + before do + @attributes = { + description: {name: "description", content: "i am a test"}, + og_website: {property: "og:website", content: "http://www.test2.com"} + } + default_attributes = { + description: {name: "description", content: "default description"}, + og_url: {property: "og:url", content: "http://www.defaulturl.com"} + } + allow(helper).to receive(:general_metas).and_return(default_attributes) + end + + it "returns the default meta datas if passed nothing" do + metas_html = %(<meta name="description" content="default description" />\n) + + %(<meta property="og:url" content="http://www.defaulturl.com" />) + expect(helper.metas_tags).to eq(metas_html) + end + + it "combines by default the general meta datas with the passed attributes" do + metas_html = %(<meta name="description" content="i am a test" />\n) + + %(<meta property="og:url" content="http://www.defaulturl.com" />\n) + + %(<meta property="og:website" content="http://www.test2.com" />) + expect(helper.metas_tags(@attributes)).to eq(metas_html) + end + + it "does not combines the general meta datas with the passed attributes if option is disabled" do + default_metas_html = %(<meta name="description" content="default description" />\n) + + %(<meta property="og:url" content="http://www.defaulturl.com" />) + expect(helper.metas_tags(@attributes, false)).not_to include(default_metas_html) + end + end +end diff --git a/spec/helpers/mobile_helper_spec.rb b/spec/helpers/mobile_helper_spec.rb deleted file mode 100644 index c506b3b3ce6fdafc18bb8af09280e6908ba459a8..0000000000000000000000000000000000000000 --- a/spec/helpers/mobile_helper_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe MobileHelper, :type => :helper do - - describe "#aspect_select_options" do - it "adds an all option to the list of aspects" do - # options_from_collection_for_select(@aspects, "id", "name", @aspect.id) - - n = FactoryGirl.create(:aspect) - - options = aspect_select_options([n], n).split('\n') - expect(options.first).to match(/All/) - end - end -end \ No newline at end of file diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb index 3b9cefb1ea72126a18d0d01ae8a9c0ac1d338fcb..daf579b3c941b8634fb5037c6995746dd4700eb5 100644 --- a/spec/helpers/notifications_helper_spec.rb +++ b/spec/helpers/notifications_helper_spec.rb @@ -1,16 +1,17 @@ -require 'spec_helper' +require "spec_helper" - -describe NotificationsHelper, :type => :helper do +describe NotificationsHelper, type: :helper do include ApplicationHelper before do @user = FactoryGirl.create(:user) @person = FactoryGirl.create(:person) - @post = FactoryGirl.create(:status_message, :author => @user.person) + @post = FactoryGirl.create(:status_message, author: @user.person) @person2 = FactoryGirl.create(:person) - @notification = Notification.notify(@user, FactoryGirl.create(:like, :author => @person, :target => @post), @person) - @notification = Notification.notify(@user, FactoryGirl.create(:like, :author => @person2, :target => @post), @person2) + Notifications::Liked.notify(FactoryGirl.create(:like, author: @person, target: @post), []) + Notifications::Liked.notify(FactoryGirl.create(:like, author: @person2, target: @post), []) + + @notification = Notifications::Liked.find_by(target: @post, recipient: @user) end describe '#notification_people_link' do @@ -64,7 +65,6 @@ describe NotificationsHelper, :type => :helper do end end - describe '#object_link' do describe 'for a like' do it 'should include a link to the post' do diff --git a/spec/helpers/open_graph_helper_spec.rb b/spec/helpers/open_graph_helper_spec.rb index f2f3e6480234212df74d798d4fd9bb76f541e0e5..f727961517170a78f5a839aa7d9bb554ff791b5e 100644 --- a/spec/helpers/open_graph_helper_spec.rb +++ b/spec/helpers/open_graph_helper_spec.rb @@ -1,20 +1,6 @@ require 'spec_helper' describe OpenGraphHelper, :type => :helper do - describe 'og_page_post_tags' do - it 'handles a reshare of a deleted post' do - reshare = FactoryGirl.build(:reshare, root: nil, id: 123) - - expect { - helper.og_page_post_tags(reshare) - }.to_not raise_error - end - - it 'handles a normal post' do - post = FactoryGirl.create(:status_message) - expect(helper.og_page_post_tags(post)).to include helper.og_url(post_url(post)) - end - end describe 'og_html' do scenarios = { diff --git a/spec/helpers/people_helper_spec.rb b/spec/helpers/people_helper_spec.rb index 24f0bf4455d391ecd597ac160cb9b5cc9b17d2ee..d650a8714259a77ad225e1088a186660d868c926 100644 --- a/spec/helpers/people_helper_spec.rb +++ b/spec/helpers/people_helper_spec.rb @@ -77,6 +77,11 @@ describe PeopleHelper, :type => :helper do it 'links by id for a local user' do expect(person_link(@user.person)).to include "href='#{person_path(@user.person)}'" end + + it "recognizes the 'display_name' option" do + display_name = "string used as a name" + expect(person_link(@person, display_name: display_name)).to match(%r{<a [^>]+>#{display_name}</a>}) + end end describe '#local_or_remote_person_path' do @@ -86,10 +91,8 @@ describe PeopleHelper, :type => :helper do it "links by id if there is a period in the user's username" do @user.username = "invalid.username" - expect(@user.save(:validate => false)).to eq(true) - person = @user.person - person.diaspora_handle = "#{@user.username}@#{AppConfig.pod_uri.authority}" - person.save! + @user.person.diaspora_handle = "#{@user.username}@#{AppConfig.pod_uri.authority}" + expect(@user.save(validate: false)).to eq(true) expect(local_or_remote_person_path(@user.person)).to eq(person_path(@user.person)) end diff --git a/spec/helpers/posts_helper_spec.rb b/spec/helpers/posts_helper_spec.rb index d1624f8dcb74041296c80040db5b876e175cd159..a6ca72c0748ae73b4b52703efa8066a0d9910f8d 100644 --- a/spec/helpers/posts_helper_spec.rb +++ b/spec/helpers/posts_helper_spec.rb @@ -32,7 +32,7 @@ describe PostsHelper, :type => :helper do end it "returns an iframe containing the post" do - expect(post_iframe_url(@post.id)).to include "src='http://localhost:9887#{post_path(@post)}'" + expect(post_iframe_url(@post.id)).to include "src='#{AppConfig.url_to(post_path(@post))}'" end end end diff --git a/spec/helpers/report_helper_spec.rb b/spec/helpers/report_helper_spec.rb index 8cb003c42ce4f7c120ad1a94886d93b150df59d3..f7d6b2510755a49ccf0a0a3df4ba7d49c7a16927 100644 --- a/spec/helpers/report_helper_spec.rb +++ b/spec/helpers/report_helper_spec.rb @@ -1,17 +1,29 @@ -require 'spec_helper' +require "spec_helper" -describe ReportHelper, :type => :helper do +describe ReportHelper, type: :helper do before do - @comment = FactoryGirl.create(:comment) - @post = @comment.post + @user = bob + @post = @user.post(:status_message, text: "hello", to: @user.aspects.first.id) + @comment = @user.comment!(@post, "welcome") + + @post_report = @user.reports.create( + item_id: @post.id, item_type: "Post", + text: "offensive content" + ) + @comment_report = @user.reports.create( + item_id: @comment.id, item_type: "Comment", + text: "offensive content" + ) end describe "#report_content" do it "contains a link to the post" do - expect(helper.report_content(@post, 'post')).to include %Q(href="#{post_path(@post)}") + expect(helper.report_content(@post_report)) + .to include %(href="#{post_path(@post)}") end - it "contains an anchor to the comment" do - expect(helper.report_content(@comment, 'comment')).to include %Q(href="#{post_path(@post, anchor: @comment.guid)}") + it "contains an anchor to the comment" do + expect(helper.report_content(@comment_report)) + .to include %(href="#{post_path(@post, anchor: @comment.author.guid)}") end end end diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..c67789bf6701b78a9b4fabb81e66fb895534bf2e --- /dev/null +++ b/spec/helpers/users_helper_spec.rb @@ -0,0 +1,42 @@ +require "spec_helper" + +describe UsersHelper, type: :helper do + include Devise::Test::ControllerHelpers + + describe "#current_color_theme" do + describe "if user is not signed in" do + before do + def user_signed_in? + false + end + end + + it "returns the default color theme" do + expect(current_color_theme).to eq("color_themes/#{AppConfig.settings.default_color_theme}") + end + end + + describe "if user is signed in" do + before do + @user = User.new + def user_signed_in? + true + end + + def current_user + @user + end + end + + it "returns the default color theme if user has not selected any theme" do + expect(current_color_theme).to eq("color_themes/#{AppConfig.settings.default_color_theme}") + end + + it "returns the color theme selected by the user if there is a selected one" do + selected_theme = "test_theme" + @user.color_theme = selected_theme + expect(current_color_theme).to eq("color_themes/#{selected_theme}") + end + end + end +end diff --git a/spec/integration/account_deletion_spec.rb b/spec/integration/account_deletion_spec.rb index 71e52786e93a406317bd751d692e3a6d7d05bacb..abe3c4db285ddf6b18f42a716b92efa6d4fe0035 100644 --- a/spec/integration/account_deletion_spec.rb +++ b/spec/integration/account_deletion_spec.rb @@ -1,134 +1,130 @@ -require 'spec_helper' +require "spec_helper" -describe 'deleteing your account', :type => :request do +describe "deleteing your account", type: :request do context "user" do before do - @bob2 = bob - @person = @bob2.person - @alices_post = alice.post(:status_message, :text => "@{@bob2 Grimn; #{@bob2.person.diaspora_handle}} you are silly", :to => alice.aspects.find_by_name('generic')) + @person = bob.person + @alices_post = alice.post(:status_message, + text: "@{bob Grimn; #{bob.person.diaspora_handle}} you are silly", + to: alice.aspects.find_by_name("generic")) - @bobs_contact_ids = @bob2.contacts.map {|c| c.id} + # bob's own content + bob.post(:status_message, text: "asldkfjs", to: bob.aspects.first) + FactoryGirl.create(:photo, author: bob.person) - #@bob2's own content - @bob2.post(:status_message, :text => 'asldkfjs', :to => @bob2.aspects.first) - f = FactoryGirl.create(:photo, :author => @bob2.person) + @aspect_vis = AspectVisibility.where(aspect_id: bob.aspects.map(&:id)) - @aspect_vis = AspectVisibility.where(:aspect_id => @bob2.aspects.map(&:id)) + # objects on post + bob.like!(@alices_post) + bob.comment!(@alices_post, "here are some thoughts on your post") - #objects on post - @bob2.like!(@alices_post) - @bob2.comment!(@alices_post, "here are some thoughts on your post") + # conversations + create_conversation_with_message(alice, bob.person, "Subject", "Hey bob") - #conversations - create_conversation_with_message(alice, @bob2.person, "Subject", "Hey @bob2") + # join tables + @users_sv = ShareVisibility.where(user_id: bob.id).load + @persons_sv = ShareVisibility.where(shareable_id: bob.posts.map(&:id), shareable_type: "Post").load - #join tables - @users_sv = ShareVisibility.where(:contact_id => @bobs_contact_ids).load - @persons_sv = ShareVisibility.where(:contact_id => bob.person.contacts.map(&:id)).load - - #user associated objects + # user associated objects @prefs = [] - %w{mentioned liked reshared}.each do |pref| - @prefs << @bob2.user_preferences.create!(:email_type => pref) + %w(mentioned liked reshared).each do |pref| + @prefs << bob.user_preferences.create!(email_type: pref) end # notifications @notifications = [] - 3.times do |n| - @notifications << FactoryGirl.create(:notification, :recipient => @bob2) + 3.times do + @notifications << FactoryGirl.create(:notification, recipient: bob) end # services @services = [] - 3.times do |n| - @services << FactoryGirl.create(:service, :user => @bob2) + 3.times do + @services << FactoryGirl.create(:service, user: bob) end # block - @block = @bob2.blocks.create!(:person => eve.person) - - #authorization + @block = bob.blocks.create!(person: eve.person) - AccountDeleter.new(@bob2.person.diaspora_handle).perform! - @bob2.reload + AccountDeleter.new(bob.person.diaspora_handle).perform! + bob.reload end it "deletes all of the user's preferences" do - expect(UserPreference.where(:id => @prefs.map{|pref| pref.id})).to be_empty + expect(UserPreference.where(id: @prefs.map(&:id))).to be_empty end it "deletes all of the user's notifications" do - expect(Notification.where(:id => @notifications.map{|n| n.id})).to be_empty + expect(Notification.where(id: @notifications.map(&:id))).to be_empty end it "deletes all of the users's blocked users" do - expect(Block.where(:id => @block.id)).to be_empty + expect(Block.where(id: @block.id)).to be_empty end it "deletes all of the user's services" do - expect(Service.where(:id => @services.map{|s| s.id})).to be_empty + expect(Service.where(id: @services.map(&:id))).to be_empty end - it 'deletes all of @bob2s share visiblites' do - expect(ShareVisibility.where(:id => @users_sv.map{|sv| sv.id})).to be_empty - expect(ShareVisibility.where(:id => @persons_sv.map{|sv| sv.id})).to be_empty + it "deletes all of bobs share visiblites" do + expect(ShareVisibility.where(id: @users_sv.map(&:id))).to be_empty + expect(ShareVisibility.where(id: @persons_sv.map(&:id))).to be_empty end - it 'deletes all of @bob2s aspect visiblites' do - expect(AspectVisibility.where(:id => @aspect_vis.map(&:id))).to be_empty + it "deletes all of bobs aspect visiblites" do + expect(AspectVisibility.where(id: @aspect_vis.map(&:id))).to be_empty end - it 'deletes all aspects' do - expect(@bob2.aspects).to be_empty + it "deletes all aspects" do + expect(bob.aspects).to be_empty end - it 'deletes all user contacts' do - expect(@bob2.contacts).to be_empty + it "deletes all user contacts" do + expect(bob.contacts).to be_empty end - it "clears the account fields" do - @bob2.send(:clearable_fields).each do |field| - expect(@bob2.reload[field]).to be_blank + bob.send(:clearable_fields).each do |field| + expect(bob.reload[field]).to be_blank end end - it_should_behave_like 'it removes the person associations' + it_should_behave_like "it removes the person associations" end - context 'remote person' do + context "remote person" do before do @person = remote_raphael - #contacts + # contacts @contacts = @person.contacts - #posts + # posts @posts = (1..3).map do - FactoryGirl.create(:status_message, :author => @person) + FactoryGirl.create(:status_message, author: @person) end @persons_sv = @posts.each do |post| @contacts.each do |contact| - ShareVisibility.create!(:contact_id => contact.id, :shareable => post) + ShareVisibility.create!(user_id: contact.user.id, shareable: post) end end - #photos - @photo = FactoryGirl.create(:photo, :author => @person) + # photos + @photo = FactoryGirl.create(:photo, author: @person) - #mentions + # mentions @mentions = 3.times do - FactoryGirl.create(:mention, :person => @person) + FactoryGirl.create(:mention, person: @person) end - #conversations - create_conversation_with_message(alice, @person, "Subject", "Hey @bob2") + # conversations + create_conversation_with_message(alice, @person, "Subject", "Hey bob") AccountDeleter.new(@person.diaspora_handle).perform! @person.reload end - it_should_behave_like 'it removes the person associations' + it_should_behave_like "it removes the person associations" end end diff --git a/spec/integration/api/user_info_controller_spec.rb b/spec/integration/api/user_info_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..1f237a172fb526de67af6fd5a30d056464a2ea04 --- /dev/null +++ b/spec/integration/api/user_info_controller_spec.rb @@ -0,0 +1,21 @@ +require "spec_helper" +describe Api::OpenidConnect::UserInfoController do + let!(:auth_with_read_and_ppid) { FactoryGirl.create(:auth_with_read_and_ppid) } + let!(:access_token_with_read) { auth_with_read_and_ppid.create_access_token.to_s } + + describe "#show" do + before do + @user = auth_with_read_and_ppid.user + get api_openid_connect_user_info_path, access_token: access_token_with_read + end + + it "shows the info" do + json_body = JSON.parse(response.body) + expected_sub = + @user.pairwise_pseudonymous_identifiers.find_or_create_by(identifier: "https://example.com/uri").guid + expect(json_body["sub"]).to eq(expected_sub) + expect(json_body["nickname"]).to eq(@user.name) + expect(json_body["profile"]).to eq(File.join(AppConfig.environment.url, "people", @user.guid).to_s) + end + end +end diff --git a/spec/integration/attack_vectors_spec.rb b/spec/integration/attack_vectors_spec.rb deleted file mode 100644 index 284823f4ef60e1161adc783ea90baf8a26bf0620..0000000000000000000000000000000000000000 --- a/spec/integration/attack_vectors_spec.rb +++ /dev/null @@ -1,262 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - - -def receive_post(post, opts) - sender = opts.fetch(:from) - receiver = opts.fetch(:by) - salmon_xml = sender.salmon(post).xml_for(receiver.person) - zord = Postzord::Receiver::Private.new(receiver, :salmon_xml => salmon_xml) - zord.perform! -end - -def receive_public(post, opts) - sender = opts.fetch(:from) - salmon_xml = Salmon::Slap.create_by_user_and_activity(sender, post.to_diaspora_xml).xml_for(nil) - post.destroy - zord = Postzord::Receiver::Public.new(salmon_xml) - zord.perform! -end - -def temporary_user(&block) - user = FactoryGirl.create(:user) - block_return_value = yield user - user.delete - block_return_value -end - -def temporary_post(user, &block) - temp_post = user.post(:status_message, :text => 'hi') - block_return_value = yield temp_post - temp_post.delete - block_return_value -end - -def expect_error(partial_message, &block)# DOES NOT REQUIRE ERROR!! - begin - yield - rescue => e - expect(e.message).to match partial_message - - ensure - raise "no error occured where expected" unless e.present? - end -end - -def bogus_retraction(&block) - ret = Retraction.new - yield ret - ret -end - -def user_should_not_see_guid(user, guid) - expect(user.reload.visible_shareables(Post).where(:guid => guid)).to be_blank -end - #returns the message -def legit_post_from_user1_to_user2(user1, user2) - original_message = user1.post(:status_message, :text => 'store this!', :to => user1.aspects.find_by_name("generic").id) - receive_post(original_message, :from => user1, :by => user2) - original_message -end - -describe "attack vectors", :type => :request do - - let(:eves_aspect) { eve.aspects.find_by_name("generic") } - let(:alices_aspect) { alice.aspects.find_by_name("generic") } - - context "testing side effects of validation phase" do - - describe 'Contact Required Unless Request' do - #CUSTOM SETUP; cant use helpers here - it 'does not save a post from a non-contact as a side effect' do - salmon_xml = nil - bad_post_guid = nil - - temporary_user do |bad_user| - temporary_post(bad_user) do |post_from_non_contact| - bad_post_guid = post_from_non_contact.guid - salmon_xml = bad_user.salmon(post_from_non_contact).xml_for(bob.person) - end - end - - zord = Postzord::Receiver::Private.new(bob, :salmon_xml => salmon_xml) - - expect { - expect { - zord.perform! - }.to raise_error Diaspora::ContactRequiredUnlessRequest - }.to_not change(Post, :count) - - user_should_not_see_guid(bob, bad_post_guid) - end - - - #CUSTOM SETUP; cant use helpers here - it 'other users can not grant visiblity to another users posts by sending their friends post to themselves (even if they are contacts)' do - #setup: eve has a message. then, alice is connected to eve. - #(meaning alice can not see the old post, but it exists in the DB) - # bob takes eves message, changes the post author to himself - # bob trys to send a message to alice - original_message = eve.post(:status_message, :text => 'store this!', :to => eves_aspect.id) - original_message.diaspora_handle = bob.diaspora_handle - - alice.contacts.create(:person => eve.person, :aspects => [alice.aspects.first]) - - salmon_xml = bob.salmon(original_message).xml_for(alice.person) - - #bob sends it to himself????? - zord = Postzord::Receiver::Private.new(bob, :salmon_xml => salmon_xml) - - expect { - zord.perform! - }.to raise_error Diaspora::ContactRequiredUnlessRequest - - #alice still should not see eves original post, even though bob sent it to her - user_should_not_see_guid(alice, original_message.guid) - end - end - - describe 'author does not match xml author' do - it 'should not overwrite another persons profile profile' do - profile = eve.profile.clone - profile.first_name = "Not BOB" - - expect { - expect { - receive_post(profile, :from => alice, :by => bob) - }.to raise_error Diaspora::AuthorXMLAuthorMismatch - }.to_not change(eve.profile, :first_name) - end - end - - - it 'public stuff should not be spoofed from another author' do - post = FactoryGirl.build(:status_message, :public => true, :author => eve.person) - expect { - receive_public(post, :from => alice) - }.to raise_error Diaspora::AuthorXMLAuthorMismatch - end - end - - - - context 'malicious contact attack vector' do - describe 'mass assignment on id' do - it "does not save a message over an old message with a different author" do - #setup: A user has a message with a given guid and author - original_message = legit_post_from_user1_to_user2(eve, bob) - - #someone else tries to make a message with the same guid - malicious_message = FactoryGirl.build(:status_message, :id => original_message.id, :guid => original_message.guid, :author => alice.person) - - expect{ - receive_post(malicious_message, :from => alice, :by => bob) - }.to_not change(original_message, :author_id) - end - - it 'does not save a message over an old message with the same author' do - #setup: - # i have a legit message from eve - original_message = legit_post_from_user1_to_user2(eve, bob) - - #eve tries to send me another message with the same ID - malicious_message = FactoryGirl.build( :status_message, :id => original_message.id, :text => 'BAD!!!', :author => eve.person) - - expect { - receive_post(malicious_message, :from => eve, :by => bob) - }.to_not change(original_message, :text) - end - end - - - it "ignores retractions on a post not owned by the retraction's sender" do - original_message = legit_post_from_user1_to_user2(eve, bob) - - ret = bogus_retraction do |retraction| - retraction.post_guid = original_message.guid - retraction.diaspora_handle = alice.person.diaspora_handle - retraction.type = original_message.class.to_s - end - - expect { - receive_post(ret, :from => alice, :by => bob) - }.to_not change(StatusMessage, :count) - end - - it "silently disregards retractions for non-existent posts(that are from someone other than the post's author)" do - bogus_retraction = temporary_post(eve) do |original_message| - bogus_retraction do |ret| - ret.post_guid = original_message.guid - ret.diaspora_handle = alice.person.diaspora_handle - ret.type = original_message.class.to_s - end - end - expect{ - receive_post(bogus_retraction, :from => alice, :by => bob) - }.to_not raise_error - end - - it 'should not receive retractions where the retractor and the salmon author do not match' do - original_message = legit_post_from_user1_to_user2(eve, bob) - - retraction = bogus_retraction do |ret| - ret.post_guid = original_message.guid - ret.diaspora_handle = eve.person.diaspora_handle - ret.type = original_message.class.to_s - end - - expect { - expect { - receive_post(retraction, :from => alice, :by => bob) - }.to raise_error Diaspora::AuthorXMLAuthorMismatch - }.to_not change { bob.visible_shareables(Post).count(:all) } - - end - - it 'it should not allow you to send retractions for other people' do - #we are banking on bob being friends with alice and eve - #here, alice is trying to disconnect bob and eve - - retraction = bogus_retraction do |ret| - ret.post_guid = eve.person.guid - ret.diaspora_handle = alice.person.diaspora_handle - ret.type = eve.person.class.to_s - end - - expect{ - receive_post(retraction, :from => alice, :by => bob) - }.to_not change{bob.reload.contacts.count} - end - - it 'it should not allow you to send retractions with xml and salmon handle mismatch' do - retraction = bogus_retraction do |ret| - ret.post_guid = eve.person.guid - ret.diaspora_handle = eve.person.diaspora_handle - ret.type = eve.person.class.to_s - end - - expect{ - expect { - receive_post(retraction, :from => alice, :by => bob) - }.to raise_error Diaspora::AuthorXMLAuthorMismatch - }.to_not change(bob.contacts, :count) - end - - it 'does not let another user update other persons post' do - original_message = eve.post(:photo, :user_file => uploaded_photo, :text => "store this!", :to => eves_aspect.id) - receive_post(original_message, :from => eve, :by => bob) - - #is this testing two things? - new_message = original_message.dup - new_message.diaspora_handle = alice.diaspora_handle - new_message.text = "bad bad bad" - - expect{ - receive_post(new_message, :from => alice, :by => bob) - }.to_not change(original_message, :text) - end - end -end diff --git a/spec/integration/dispatching_spec.rb b/spec/integration/dispatching_spec.rb index 83d4f0e3226af71575b8b59ecca43a1dc1a8b67c..2a18e8e096cb35e3ac8b46a2a8681b4f9cbd09ef 100644 --- a/spec/integration/dispatching_spec.rb +++ b/spec/integration/dispatching_spec.rb @@ -1,19 +1,34 @@ -require 'spec_helper' +require "spec_helper" -describe "Dispatching", :type => :request do +describe "Dispatching", type: :request do context "a comment retraction on a public post" do - it "should trigger a private dispatch" do - luke, leia, raph = set_up_friends - # Luke has a public post and comments on it - post = FactoryGirl.create(:status_message, :public => true, :author => luke.person) + it "triggers a public dispatch" do + # Alice has a public post and comments on it + post = FactoryGirl.create(:status_message, public: true, author: alice.person) + + comment = alice.comment!(post, "awesomesauseum") + + inlined_jobs do + # Alice now retracts her comment + expect(Diaspora::Federation::Dispatcher::Public).to receive(:new).and_return(double(dispatch: true)) + expect(Diaspora::Federation::Dispatcher::Private).not_to receive(:new) + alice.retract(comment) + end + end + end + + context "a comment retraction on a private post" do + it "triggers a private dispatch" do + # Alice has a private post and comments on it + post = alice.post(:status_message, text: "hello", to: alice.aspects.first) + + comment = alice.comment!(post, "awesomesauseum") - comment = luke.comment!(post, "awesomesauseum") - inlined_jobs do - # Luke now retracts his comment - expect(Postzord::Dispatcher::Public).not_to receive(:new) - expect(Postzord::Dispatcher::Private).to receive(:new).and_return(double(:post => true)) - luke.retract(comment) + # Alice now retracts her comment + expect(Diaspora::Federation::Dispatcher::Public).not_to receive(:new) + expect(Diaspora::Federation::Dispatcher::Private).to receive(:new).and_return(double(dispatch: true)) + alice.retract(comment) end end end diff --git a/spec/integration/federation/attack_vectors_spec.rb b/spec/integration/federation/attack_vectors_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..541de7de5bda4598b147c11623153fa809dbbc5e --- /dev/null +++ b/spec/integration/federation/attack_vectors_spec.rb @@ -0,0 +1,129 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require "spec_helper" +require "integration/federation/federation_helper" + +describe "attack vectors", type: :request do + before do + allow_callbacks(%i(queue_public_receive queue_private_receive receive_entity fetch_related_entity fetch_public_key)) + end + + let(:eves_aspect) { eve.aspects.find_by_name("generic") } + let(:alices_aspect) { alice.aspects.find_by_name("generic") } + + it "other users can not grant visiblity to another users posts by sending their friends post to themselves" do + # setup: eve has a message. then, alice is connected to eve. + # (meaning alice can not see the old post, but it exists in the DB) + # bob takes eves message, changes the post author to himself + # bob trys to send a message to alice + + original_message = eve.post(:status_message, text: "store this!", to: eves_aspect.id) + original_message.author = bob.person + + alice.share_with(eve.person, alices_aspect) + + post_message(generate_xml(Diaspora::Federation::Entities.post(original_message), bob, alice), alice) + + # alice still should not see eves original post, even though bob sent it to her + expect(alice.reload.visible_shareables(Post).where(guid: original_message.guid)).to be_blank + end + + context "author does not match xml author" do + it "should not overwrite another persons profile" do + profile = eve.profile.clone + profile.first_name = "Not BOB" + + post_message(generate_xml(Diaspora::Federation::Entities.profile(profile), alice, bob), bob) + + expect(eve.profile(true).first_name).not_to eq("Not BOB") + end + + it "public post should not be spoofed from another author" do + post = FactoryGirl.build(:status_message, public: true, author: eve.person) + + post_message(generate_xml(Diaspora::Federation::Entities.post(post), alice)) + + expect(StatusMessage.exists?(guid: post.guid)).to be_falsey + end + + it "should not receive retractions where the retractor and the salmon author do not match" do + original_message = eve.post(:status_message, text: "store this!", to: eves_aspect.id) + + expect { + post_message(generate_xml(Diaspora::Federation::Entities.retraction(original_message), alice, bob), bob) + }.to_not change { bob.visible_shareables(Post).count(:all) } + end + + it "should not receive contact retractions from another person" do + # we are banking on bob being friends with alice and eve + # here, alice is trying to disconnect bob and eve + contact = bob.contacts(true).find_by(person_id: eve.person.id) + expect(contact).to be_sharing + + post_message(generate_xml(Diaspora::Federation::Entities.retraction(contact), alice, bob), bob) + + expect(bob.contacts(true).find_by(person_id: eve.person.id)).to be_sharing + end + end + + it "does not save a message over an old message with a different author" do + # setup: A user has a message with a given guid and author + original_message = eve.post(:status_message, text: "store this!", to: eves_aspect.id) + + # someone else tries to make a message with the same guid + malicious_message = FactoryGirl.build( + :status_message, + id: original_message.id, + guid: original_message.guid, + author: alice.person + ) + + post_message(generate_xml(Diaspora::Federation::Entities.post(malicious_message), alice, bob), bob) + + expect(original_message.reload.author_id).to eq(eve.person.id) + end + + it "does not save a message over an old message with the same author" do + # setup: + # I have a legit message from eve + original_message = eve.post(:status_message, text: "store this!", to: eves_aspect.id) + + # eve tries to send me another message with the same ID + malicious_message = FactoryGirl.build(:status_message, id: original_message.id, text: "BAD!!!", author: eve.person) + + post_message(generate_xml(Diaspora::Federation::Entities.post(malicious_message), eve, bob), bob) + + expect(original_message.reload.text).to eq("store this!") + end + + it "ignores retractions on a post not owned by the retraction's sender" do + original_message = eve.post(:status_message, text: "store this!", to: eves_aspect.id) + + retraction = DiasporaFederation::Entities::Retraction.new( + target_guid: original_message.guid, + target_type: original_message.class.to_s, + target: Diaspora::Federation::Entities.related_entity(original_message), + author: alice.person.diaspora_handle + ) + + expect { + post_message(generate_xml(retraction, alice, bob), bob) + }.to_not change(StatusMessage, :count) + end + + it "does not let another user update other persons post" do + original_message = eve.post(:photo, user_file: uploaded_photo, text: "store this!", to: eves_aspect.id) + + new_message = original_message.dup + new_message.author = alice.person + new_message.text = "bad bad bad" + new_message.height = 23 + new_message.width = 42 + + post_message(generate_xml(Diaspora::Federation::Entities.photo(new_message), alice, bob), bob) + + expect(original_message.reload.text).to eq("store this!") + end +end diff --git a/spec/integration/federation/federation_helper.rb b/spec/integration/federation/federation_helper.rb index f9340517b8cac671555a01772444b549c0397d92..afc880792ef2e470ffeaa5db51491982c6a21aaa 100644 --- a/spec/integration/federation/federation_helper.rb +++ b/spec/integration/federation/federation_helper.rb @@ -8,32 +8,41 @@ end def create_remote_user(pod) FactoryGirl.build(:user).tap do |user| - user.person = FactoryGirl.create(:person, - profile: FactoryGirl.build(:profile), - serialized_public_key: user.encryption_key.public_key.export, - diaspora_handle: "#{user.username}@#{pod}") - allow(DiasporaFederation.callbacks).to receive(:trigger) - .with(:fetch_private_key_by_diaspora_id, user.diaspora_handle) { - user.encryption_key - } + allow(user).to receive(:person).and_return( + FactoryGirl.create(:person, + profile: FactoryGirl.build(:profile), + serialized_public_key: user.encryption_key.public_key.export, + pod: Pod.find_or_create_by(url: "http://#{pod}"), + diaspora_handle: "#{user.username}@#{pod}") + ) + allow(DiasporaFederation.callbacks).to receive(:trigger).with( + :fetch_private_key, user.diaspora_handle + ) { user.encryption_key } + allow(DiasporaFederation.callbacks).to receive(:trigger).with( + :fetch_public_key, user.diaspora_handle + ) { OpenSSL::PKey::RSA.new(user.person.serialized_public_key) } + end +end + +def allow_callbacks(callbacks) + callbacks.each do |callback| + allow(DiasporaFederation.callbacks).to receive(:trigger).with(callback, any_args).and_call_original end end -def create_relayable_entity(entity_name, target, diaspora_id, parent_author_key) - expect(DiasporaFederation.callbacks).to receive(:trigger) - .with( - :fetch_author_private_key_by_entity_guid, - FactoryGirl.build(entity_name).parent_type, - target.guid - ) - .and_return(parent_author_key) +def create_relayable_entity(entity_name, parent, diaspora_id) + expect(DiasporaFederation.callbacks).to receive(:trigger).with( + :fetch_private_key, alice.diaspora_handle + ).at_least(1).times.and_return(nil) if parent == local_parent + parent_guid = parent.guid FactoryGirl.build( entity_name, - conversation_guid: target.guid, - parent_guid: target.guid, + conversation_guid: parent_guid, + parent_guid: parent_guid, author: diaspora_id, - poll_answer_guid: target.respond_to?(:poll_answers) ? target.poll_answers.first.guid : nil + poll_answer_guid: parent.respond_to?(:poll_answers) ? parent.poll_answers.first.guid : nil, + parent: Diaspora::Federation::Entities.related_entity(parent) ) end @@ -41,13 +50,13 @@ def generate_xml(entity, remote_user, recipient=nil) if recipient DiasporaFederation::Salmon::EncryptedSlap.prepare( remote_user.diaspora_handle, - OpenSSL::PKey::RSA.new(remote_user.encryption_key), + remote_user.encryption_key, entity - ).generate_xml(OpenSSL::PKey::RSA.new(recipient.encryption_key)) + ).generate_xml(recipient.encryption_key) else DiasporaFederation::Salmon::Slap.generate_xml( remote_user.diaspora_handle, - OpenSSL::PKey::RSA.new(remote_user.encryption_key), + remote_user.encryption_key, entity ) end diff --git a/spec/integration/federation/receive_federation_messages_spec.rb b/spec/integration/federation/receive_federation_messages_spec.rb index 3c5bc16050cf1fdbfaa41d56ad06608c8d577d37..b0139b8d8dfe5d8a2c263187fcb18757334876c5 100644 --- a/spec/integration/federation/receive_federation_messages_spec.rb +++ b/spec/integration/federation/receive_federation_messages_spec.rb @@ -6,10 +6,7 @@ require "integration/federation/shared_receive_stream_items" describe "Receive federation messages feature" do before do - allow(DiasporaFederation.callbacks).to receive(:trigger) - .with(:queue_public_receive, any_args).and_call_original - allow(DiasporaFederation.callbacks).to receive(:trigger) - .with(:queue_private_receive, any_args).and_call_original + allow_callbacks(%i(queue_public_receive queue_private_receive receive_entity fetch_related_entity)) end let(:sender) { remote_user_on_pod_b } @@ -37,9 +34,15 @@ describe "Receive federation messages feature" do post = FactoryGirl.create(:status_message, author: alice.person, public: true) reshare = FactoryGirl.build( :reshare_entity, root_author: alice.diaspora_handle, root_guid: post.guid, author: sender_id) + + expect(Participation::Generator).to receive(:new).with( + alice, instance_of(Reshare) + ).and_return(double(create!: true)) + post_message(generate_xml(reshare, sender)) - expect(Reshare.exists?(root_guid: post.guid, diaspora_handle: sender_id)).to be_truthy + expect(Reshare.exists?(root_guid: post.guid)).to be_truthy + expect(Reshare.where(root_guid: post.guid).last.diaspora_handle).to eq(sender_id) end it "reshare of private post fails" do @@ -50,7 +53,7 @@ describe "Receive federation messages feature" do post_message(generate_xml(reshare, sender)) }.to raise_error ActiveRecord::RecordInvalid, "Validation failed: Only posts which are public may be reshared." - expect(Reshare.exists?(root_guid: post.guid, diaspora_handle: sender_id)).to be_falsey + expect(Reshare.exists?(root_guid: post.guid)).to be_falsey end end @@ -72,17 +75,16 @@ describe "Receive federation messages feature" do let(:recipient) { alice } it "treats sharing request recive correctly" do - entity = FactoryGirl.build(:request_entity, recipient: alice.diaspora_handle) + entity = FactoryGirl.build(:request_entity, author: sender_id, recipient: alice.diaspora_handle) - expect(Diaspora::Fetcher::Public).to receive(:queue_for).exactly(1).times + expect(Workers::ReceiveLocal).to receive(:perform_async).and_call_original post_message(generate_xml(entity, sender, alice), alice) expect(alice.contacts.count).to eq(2) - new_contact = alice.contacts.order(created_at: :asc).last + new_contact = alice.contacts.find {|c| c.person.diaspora_handle == sender_id } expect(new_contact).not_to be_nil expect(new_contact.sharing).to eq(true) - expect(new_contact.person.diaspora_handle).to eq(sender_id) expect( Notifications::StartedSharing.exists?( @@ -93,13 +95,6 @@ describe "Receive federation messages feature" do ).to be_truthy end - it "doesn't save the private status message if there is no sharing" do - entity = FactoryGirl.build(:status_message_entity, author: sender_id, public: false) - post_message(generate_xml(entity, sender, alice), alice) - - expect(StatusMessage.exists?(guid: entity.guid)).to be_falsey - end - context "with sharing" do before do contact = alice.contacts.find_or_initialize_by(person_id: sender.person.id) @@ -114,7 +109,10 @@ describe "Receive federation messages feature" do entity = FactoryGirl.build(:profile_entity, author: sender_id) post_message(generate_xml(entity, sender, alice), alice) - expect(Profile.exists?(diaspora_handle: entity.diaspora_id)).to be_truthy + received_profile = sender.profile.reload + + expect(received_profile.first_name).to eq(entity.first_name) + expect(received_profile.bio).to eq(entity.bio) end it "receives conversation correctly" do @@ -129,14 +127,14 @@ describe "Receive federation messages feature" do end context "with message" do - let(:local_target) { + let(:local_parent) { FactoryGirl.build(:conversation, author: alice.person).tap do |target| target.participants << remote_user_on_pod_b.person target.participants << remote_user_on_pod_c.person target.save end } - let(:remote_target) { + let(:remote_parent) { FactoryGirl.build(:conversation, author: remote_user_on_pod_b.person).tap do |target| target.participants << alice.person target.participants << remote_user_on_pod_c.person diff --git a/spec/integration/federation/shared_receive_relayable.rb b/spec/integration/federation/shared_receive_relayable.rb index 71c67574335fd050a7efc1342d9598e9fc8f9acf..06e67c2479f53cabe3e15cb3c68fffa992c6be82 100644 --- a/spec/integration/federation/shared_receive_relayable.rb +++ b/spec/integration/federation/shared_receive_relayable.rb @@ -1,9 +1,9 @@ shared_examples_for "it deals correctly with a relayable" do context "local" do - let(:entity) { create_relayable_entity(entity_name, local_target, sender_id, nil) } + let(:entity) { create_relayable_entity(entity_name, local_parent, sender_id) } it "treats upstream receive correctly" do - expect(Postzord::Dispatcher).to receive(:build).with(alice, kind_of(klass)).and_call_original + expect(Workers::ReceiveLocal).to receive(:perform_async) post_message(generate_xml(entity, sender, recipient), recipient) received_entity = klass.find_by(guid: entity.guid) @@ -13,7 +13,7 @@ shared_examples_for "it deals correctly with a relayable" do # Checks when a remote pod wants to send us a relayable without having a key for declared diaspora ID it "rejects an upstream entity with a malformed author signature" do - expect(Postzord::Dispatcher).not_to receive(:build) + expect(Workers::ReceiveLocal).not_to receive(:perform_async) allow(remote_user_on_pod_b).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) post_message(generate_xml(entity, sender, recipient), recipient) @@ -23,11 +23,10 @@ shared_examples_for "it deals correctly with a relayable" do context "remote" do let(:author_id) { remote_user_on_pod_c.diaspora_handle } - let(:entity) { create_relayable_entity(entity_name, remote_target, author_id, sender.encryption_key) } + let(:entity) { create_relayable_entity(entity_name, remote_parent, author_id) } it "treats downstream receive correctly" do - expect(Postzord::Dispatcher).to receive(:build) - .with(alice, kind_of(klass)).and_call_original unless recipient.nil? + expect(Workers::ReceiveLocal).to receive(:perform_async) post_message(generate_xml(entity, sender, recipient), recipient) @@ -39,7 +38,7 @@ shared_examples_for "it deals correctly with a relayable" do # Checks when a remote pod B wants to send us a relayable with authorship from a remote pod C user # without having correct signature from him. it "rejects a downstream entity with a malformed author signature" do - expect(Postzord::Dispatcher).not_to receive(:build) + expect(Workers::ReceiveLocal).not_to receive(:perform_async) allow(remote_user_on_pod_c).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) post_message(generate_xml(entity, sender, recipient), recipient) @@ -49,7 +48,7 @@ shared_examples_for "it deals correctly with a relayable" do # Checks when a remote pod C wants to send us a relayable from its user, but bypassing the pod B where # remote status came from. it "declines downstream receive when sender signed with a wrong key" do - expect(Postzord::Dispatcher).not_to receive(:build) + expect(Workers::ReceiveLocal).not_to receive(:perform_async) allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) post_message(generate_xml(entity, sender, recipient), recipient) diff --git a/spec/integration/federation/shared_receive_retraction.rb b/spec/integration/federation/shared_receive_retraction.rb index e4e2612a7e9aad055a448e6354b6107fc438a34a..afa415993ae31438c28ce46e67fd7779c39ebd06 100644 --- a/spec/integration/federation/shared_receive_retraction.rb +++ b/spec/integration/federation/shared_receive_retraction.rb @@ -1,17 +1,10 @@ def retraction_entity(entity_name, target_object, sender) - allow(DiasporaFederation.callbacks).to receive(:trigger) - .with( - :fetch_entity_author_id_by_guid, - target_object.class.to_s, - target_object.guid - ) - .and_return(sender.encryption_key) - FactoryGirl.build( entity_name, author: sender.diaspora_handle, target_guid: target_object.guid, - target_type: target_object.class.to_s + target_type: target_object.class.to_s, + target: Diaspora::Federation::Entities.related_entity(target_object) ) end diff --git a/spec/integration/federation/shared_receive_stream_items.rb b/spec/integration/federation/shared_receive_stream_items.rb index 6d745683644283349730b3daceb6069772d3c977..391c194cf453a7ecfdb347d94d5f8b073ad90b32 100644 --- a/spec/integration/federation/shared_receive_stream_items.rb +++ b/spec/integration/federation/shared_receive_stream_items.rb @@ -21,38 +21,38 @@ shared_examples_for "messages which are indifferent about sharing fact" do end describe "with messages which require a status to operate on" do - let(:local_target) { FactoryGirl.create(:status_message, author: alice.person, public: public) } - let(:remote_target) { FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person, public: public) } + let(:local_parent) { FactoryGirl.create(:status_message, author: alice.person, public: public) } + let(:remote_parent) { FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person, public: public) } describe "notifications are sent where required" do it "for comment on local post" do - entity = create_relayable_entity(:comment_entity, local_target, remote_user_on_pod_b.diaspora_handle, nil) + entity = create_relayable_entity(:comment_entity, local_parent, remote_user_on_pod_b.diaspora_handle) post_message(generate_xml(entity, sender, recipient), recipient) expect( Notifications::CommentOnPost.exists?( recipient_id: alice.id, target_type: "Post", - target_id: local_target.id + target_id: local_parent.id ) ).to be_truthy end it "for like on local post" do - entity = create_relayable_entity(:like_entity, local_target, remote_user_on_pod_b.diaspora_handle, nil) + entity = create_relayable_entity(:like_entity, local_parent, remote_user_on_pod_b.diaspora_handle) post_message(generate_xml(entity, sender, recipient), recipient) expect( Notifications::Liked.exists?( recipient_id: alice.id, target_type: "Post", - target_id: local_target.id + target_id: local_parent.id ) ).to be_truthy end end - %w(comment like participation).each do |entity| + %w(comment like).each do |entity| context "with #{entity}" do let(:entity_name) { "#{entity}_entity".to_sym } let(:klass) { entity.camelize.constantize } @@ -61,14 +61,36 @@ shared_examples_for "messages which are indifferent about sharing fact" do end end + context "with participations" do + let(:entity) { create_relayable_entity(:participation_entity, local_parent, sender_id) } + + it "treats participation receive correctly" do + expect(Workers::ReceiveLocal).to receive(:perform_async) + post_message(generate_xml(entity, sender, recipient), recipient) + + received_entity = Participation.find_by(guid: entity.guid) + expect(received_entity).not_to be_nil + expect(received_entity.author.diaspora_handle).to eq(remote_user_on_pod_b.diaspora_handle) + end + + it "rejects a participations for a remote parent" do + expect(Workers::ReceiveLocal).not_to receive(:perform_async) + entity = create_relayable_entity(:participation_entity, remote_parent, sender_id) + + post_message(generate_xml(entity, sender, recipient), recipient) + + expect(Participation.exists?(guid: entity.guid)).to be_falsey + end + end + context "with poll_participation" do - let(:local_target) { + let(:local_parent) { FactoryGirl.create( :poll, status_message: FactoryGirl.create(:status_message, author: alice.person, public: public) ) } - let(:remote_target) { + let(:remote_parent) { FactoryGirl.create( :poll, status_message: FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person, public: public) @@ -102,22 +124,22 @@ shared_examples_for "messages which can't be send without sharing" do describe "with messages which require a status to operate on" do let(:public) { recipient.nil? } - let(:local_target) { FactoryGirl.create(:status_message, author: alice.person, public: public) } - let(:remote_target) { FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person, public: public) } + let(:local_parent) { FactoryGirl.create(:status_message, author: alice.person, public: public) } + let(:remote_parent) { FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person, public: public) } # this one shouldn't depend on the sharing fact. this must be fixed describe "notifications are sent where required" do it "for comment on remote post where we participate" do - alice.participate!(remote_target) + alice.participate!(remote_parent) author_id = remote_user_on_pod_c.diaspora_handle - entity = create_relayable_entity(:comment_entity, remote_target, author_id, sender.encryption_key) + entity = create_relayable_entity(:comment_entity, remote_parent, author_id) post_message(generate_xml(entity, sender, recipient), recipient) expect( Notifications::AlsoCommented.exists?( recipient_id: alice.id, target_type: "Post", - target_id: remote_target.id + target_id: remote_parent.id ) ).to be_truthy end @@ -128,18 +150,24 @@ shared_examples_for "messages which can't be send without sharing" do context "with #{retraction_entity_name}" do let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } + before do + allow(DiasporaFederation.callbacks).to receive(:trigger).with( + :fetch_private_key, alice.diaspora_handle + ) { alice.encryption_key } + end + context "with comment" do it_behaves_like "it retracts relayable object" do # case for to-upstream federation let(:target_object) { - FactoryGirl.create(:comment, author: remote_user_on_pod_b.person, post: local_target) + FactoryGirl.create(:comment, author: remote_user_on_pod_b.person, post: local_parent) } end it_behaves_like "it retracts relayable object" do # case for to-downsteam federation let(:target_object) { - FactoryGirl.create(:comment, author: remote_user_on_pod_c.person, post: remote_target) + FactoryGirl.create(:comment, author: remote_user_on_pod_c.person, post: remote_parent) } end end @@ -148,14 +176,14 @@ shared_examples_for "messages which can't be send without sharing" do it_behaves_like "it retracts relayable object" do # case for to-upstream federation let(:target_object) { - FactoryGirl.create(:like, author: remote_user_on_pod_b.person, target: local_target) + FactoryGirl.create(:like, author: remote_user_on_pod_b.person, target: local_parent) } end it_behaves_like "it retracts relayable object" do # case for to-downsteam federation let(:target_object) { - FactoryGirl.create(:like, author: remote_user_on_pod_c.person, target: remote_target) + FactoryGirl.create(:like, author: remote_user_on_pod_c.person, target: remote_parent) } end end diff --git a/spec/integration/mentioning_spec.rb b/spec/integration/mentioning_spec.rb index d8e851660823644c14b4a8ca91d8083bd12d45e8..78ee924049f5fb696c2fe05f27a7d6b43b4dc08a 100644 --- a/spec/integration/mentioning_spec.rb +++ b/spec/integration/mentioning_spec.rb @@ -1,18 +1,12 @@ - -require 'spec_helper' +require "spec_helper" module MentioningSpecHelpers def default_aspect - @user1.aspects.where(name: 'generic').first + @user1.aspects.where(name: "generic").first end def text_mentioning(user) - handle = user.diaspora_handle - "this is a text mentioning @{Mention User ; #{handle}} ... have fun testing!" - end - - def notifications_about_mentioning(user) - Notifications::Mentioned.where(recipient_id: user.id) + "this is a text mentioning @{#{user.name}; #{user.diaspora_handle}} ... have fun testing!" end def stream_for(user) @@ -20,13 +14,18 @@ module MentioningSpecHelpers stream.posts end + def mention_stream_for(user) + stream = Stream::Mention.new(user) + stream.posts + end + def users_connected?(user1, user2) user1.contacts.where(person_id: user2.person).count > 0 end end -describe 'mentioning', :type => :request do +describe "mentioning", type: :request do include MentioningSpecHelpers before do @@ -35,24 +34,62 @@ describe 'mentioning', :type => :request do @user3 = FactoryGirl.create :user @user1.share_with(@user2.person, default_aspect) + sign_in @user1 end # see: https://github.com/diaspora/diaspora/issues/4160 - it 'only mentions people that are in the target aspect' do - expect(users_connected?(@user1, @user2)).to be true + it "doesn't mention people that aren't in the target aspect" do expect(users_connected?(@user1, @user3)).to be false status_msg = nil - expect do - status_msg = @user1.post(:status_message, {text: text_mentioning(@user3), to: default_aspect}) - end.to change(Post, :count).by(1) + expect { + post "/status_messages.json", status_message: {text: text_mentioning(@user3)}, aspect_ids: default_aspect.id.to_s + status_msg = StatusMessage.find(JSON.parse(response.body)["id"]) + }.to change(Post, :count).by(1).and change(AspectVisibility, :count).by(1) expect(status_msg).not_to be_nil expect(status_msg.public?).to be false expect(status_msg.text).to include(@user3.name) + expect(status_msg.text).not_to include(@user3.diaspora_handle) + expect(status_msg.text).to include(user_profile_path(username: @user3.username)) + + expect(stream_for(@user3).map(&:id)).not_to include(status_msg.id) + expect(mention_stream_for(@user3).map(&:id)).not_to include(status_msg.id) + end + + it "mentions people in public posts" do + expect(users_connected?(@user1, @user3)).to be false + + status_msg = nil + expect { + post "/status_messages.json", status_message: {text: text_mentioning(@user3)}, aspect_ids: "public" + status_msg = StatusMessage.find(JSON.parse(response.body)["id"]) + }.to change(Post, :count).by(1) + + expect(status_msg).not_to be_nil + expect(status_msg.public?).to be true + expect(status_msg.text).to include(@user3.name) + expect(status_msg.text).to include(@user3.diaspora_handle) - expect(notifications_about_mentioning(@user3)).to be_empty - expect(stream_for(@user3).map { |item| item.id }).not_to include(status_msg.id) + expect(stream_for(@user3).map(&:id)).to include(status_msg.id) + expect(mention_stream_for(@user3).map(&:id)).to include(status_msg.id) end + it "mentions people that are in the target aspect" do + expect(users_connected?(@user1, @user2)).to be true + + status_msg = nil + expect { + post "/status_messages.json", status_message: {text: text_mentioning(@user2)}, aspect_ids: default_aspect.id.to_s + status_msg = StatusMessage.find(JSON.parse(response.body)["id"]) + }.to change(Post, :count).by(1).and change(AspectVisibility, :count).by(1) + + expect(status_msg).not_to be_nil + expect(status_msg.public?).to be false + expect(status_msg.text).to include(@user2.name) + expect(status_msg.text).to include(@user2.diaspora_handle) + + expect(stream_for(@user2).map(&:id)).to include(status_msg.id) + expect(mention_stream_for(@user2).map(&:id)).to include(status_msg.id) + end end diff --git a/spec/integration/mobile_posts_spec.rb b/spec/integration/mobile_posts_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..54cc2e60c884241ab277141dc5ddb6396c087d44 --- /dev/null +++ b/spec/integration/mobile_posts_spec.rb @@ -0,0 +1,36 @@ +require "spec_helper" + +describe PostsController, type: :request do + context "with a poll" do + let(:sm) { FactoryGirl.build(:status_message_with_poll, public: true) } + + it "displays the poll" do + get "/posts/#{sm.id}", format: :mobile + + expect(response.status).to eq(200) + expect(response.body).to match(/div class='poll'/) + expect(response.body).to match(/#{sm.poll.poll_answers.first.answer}/) + end + + it "displays the correct percentage for the answers" do + alice.participate_in_poll!(sm, sm.poll.poll_answers.first) + bob.participate_in_poll!(sm, sm.poll.poll_answers.last) + get "/posts/#{sm.id}", format: :mobile + + expect(response.status).to eq(200) + expect(response.body).to match(/div class='percentage pull-right'>\n50%/) + end + end + + context "with a location" do + let(:sm) { FactoryGirl.build(:status_message_with_location, public: true) } + + it "displays the location" do + get "/posts/#{sm.id}", format: :mobile + + expect(response.status).to eq(200) + expect(response.body).to match(/'location nsfw-hidden'/) + expect(response.body).to match(/#{I18n.t("posts.show.location", location: sm.location.address)}/) + end + end +end diff --git a/spec/integration/profile_spec.rb b/spec/integration/profile_spec.rb index 75dcca37d10ec67e6db528c40ecb0cc0b97755fd..1e61cdb122a9a6c53353f3a1846575e3fea033d4 100644 --- a/spec/integration/profile_spec.rb +++ b/spec/integration/profile_spec.rb @@ -1,10 +1,9 @@ require "spec_helper" -require "requests_helper" describe PeopleController, type: :request do context "for the current user" do before do - login alice + sign_in alice end it "displays the publisher for user profile path" do @@ -13,7 +12,7 @@ describe PeopleController, type: :request do expect(response.status).to eq(200) # make sure we are signed in expect(response.body).not_to match(/a class="login"/) - expect(response.body).to match(/div id='publisher_textarea_wrapper'/) + expect(response.body).to match(/div class='publisher-textarea-wrapper' id='publisher_textarea_wrapper'/) end it "displays the publisher for people path" do @@ -22,7 +21,7 @@ describe PeopleController, type: :request do expect(response.status).to eq(200) # make sure we are signed in expect(response.body).not_to match(/a class="login"/) - expect(response.body).to match(/div id='publisher_textarea_wrapper'/) + expect(response.body).to match(/div class='publisher-textarea-wrapper' id='publisher_textarea_wrapper'/) end it "doesn't display the publisher for people photos path" do @@ -37,7 +36,7 @@ describe PeopleController, type: :request do context "for another user" do before do - login bob + sign_in bob end it "doesn't display the publisher for user profile path" do @@ -46,7 +45,7 @@ describe PeopleController, type: :request do expect(response.status).to eq(200) # make sure we are signed in expect(response.body).not_to match(/a class="login"/) - expect(response.body).not_to match(/div id='publisher_textarea_wrapper'/) + expect(response.body).not_to match(/div class='publisher-textarea-wrapper' id='publisher_textarea_wrapper'/) end it "doesn't display the publisher for people path" do @@ -55,7 +54,7 @@ describe PeopleController, type: :request do expect(response.status).to eq(200) # make sure we are signed in expect(response.body).not_to match(/a class="login"/) - expect(response.body).not_to match(/div id='publisher_textarea_wrapper'/) + expect(response.body).not_to match(/div class='publisher-textarea-wrapper' id='publisher_textarea_wrapper'/) end end @@ -66,7 +65,7 @@ describe PeopleController, type: :request do expect(response.status).to eq(200) # make sure we aren't signed in expect(response.body).to match(/a class="login"/) - expect(response.body).not_to match(/div id='publisher_textarea_wrapper'/) + expect(response.body).not_to match(/div class='publisher-textarea-wrapper' id='publisher_textarea_wrapper'/) end it "doesn't display the publisher for people path" do @@ -75,7 +74,7 @@ describe PeopleController, type: :request do expect(response.status).to eq(200) # make sure we aren't signed in expect(response.body).to match(/a class="login"/) - expect(response.body).not_to match(/div id='publisher_textarea_wrapper'/) + expect(response.body).not_to match(/div class='publisher-textarea-wrapper' id='publisher_textarea_wrapper'/) end end end diff --git a/spec/integration/receiving_spec.rb b/spec/integration/receiving_spec.rb index c62241cf7a15db4f7e48af69ede4245eee259feb..c07a6d5091ba90c2f7a1096fd18afd6bde4b7ecd 100644 --- a/spec/integration/receiving_spec.rb +++ b/spec/integration/receiving_spec.rb @@ -5,30 +5,10 @@ require 'spec_helper' describe 'a user receives a post', :type => :request do - - def receive_with_zord(user, person, xml) - zord = Postzord::Receiver::Private.new(user, :person => person) - zord.parse_and_receive(xml) - end - before do @alices_aspect = alice.aspects.where(:name => "generic").first @bobs_aspect = bob.aspects.where(:name => "generic").first @eves_aspect = eve.aspects.where(:name => "generic").first - - @contact = alice.contact_for(bob.person) - end - - it 'should be able to parse and store a status message from xml' do - status_message = bob.post :status_message, :text => 'store this!', :to => @bobs_aspect.id - - xml = status_message.to_diaspora_xml - bob.delete - status_message.destroy - - expect { - receive_with_zord(alice, bob.person, xml) - }.to change(Post,:count).by(1) end it 'should not create new aspects on message receive' do @@ -54,319 +34,22 @@ describe 'a user receives a post', :type => :request do expect(alice.visible_shareables(Post).count(:all)).to eq(1) end - context 'with mentions, ' do - it 'adds the notifications for the mentioned users regardless of the order they are received' do - expect(Notification).to receive(:notify).with(alice, anything(), bob.person) - expect(Notification).to receive(:notify).with(eve, anything(), bob.person) - - @sm = bob.build_post(:status_message, :text => "@{#{alice.name}; #{alice.diaspora_handle}} stuff @{#{eve.name}; #{eve.diaspora_handle}}") - bob.add_to_streams(@sm, [bob.aspects.first]) - @sm.save - - zord = Postzord::Receiver::Private.new(alice, :object => @sm, :person => bob.person) - zord.receive_object - - zord = Postzord::Receiver::Private.new(eve, :object => @sm, :person => bob.person) - zord.receive_object - end - - it 'notifies local users who are mentioned' do - @remote_person = FactoryGirl.create(:person, :diaspora_handle => "foobar@foobar.com") - Contact.create!(:user => alice, :person => @remote_person, :aspects => [@alices_aspect]) - - expect(Notification).to receive(:notify).with(alice, anything(), @remote_person) - - @sm = FactoryGirl.create(:status_message, :text => "hello @{#{alice.name}; #{alice.diaspora_handle}}", :diaspora_handle => @remote_person.diaspora_handle, :author => @remote_person) - @sm.save - - zord = Postzord::Receiver::Private.new(alice, :object => @sm, :person => bob.person) - zord.receive_object - end - - it 'does not notify the mentioned user if the mentioned user is not friends with the post author' do - expect(Notification).not_to receive(:notify).with(alice, anything(), eve.person) - - @sm = eve.build_post(:status_message, :text => "should not notify @{#{alice.name}; #{alice.diaspora_handle}}") - eve.add_to_streams(@sm, [eve.aspects.first]) - @sm.save - - zord = Postzord::Receiver::Private.new(alice, :object => @sm, :person => bob.person) - zord.receive_object - end - end - - context 'update posts' do - it 'does not update posts not marked as mutable' do - status = alice.post :status_message, :text => "store this!", :to => @alices_aspect.id - status.text = 'foo' - xml = status.to_diaspora_xml - - receive_with_zord(bob, alice.person, xml) - - expect(status.reload.text).to eq('store this!') - end - - it 'updates posts marked as mutable' do - photo = alice.post(:photo, :user_file => uploaded_photo, :text => "Original", :to => @alices_aspect.id) - photo.text = 'foo' - xml = photo.to_diaspora_xml - bob.reload - - receive_with_zord(bob, alice.person, xml) - - expect(photo.reload.text).to match(/foo/) - end - end - - describe 'profiles' do - it 'federates tags' do - luke, leia, raph = set_up_friends - raph.profile.diaspora_handle = "raph@remote.net" - raph.profile.save! - p = raph.profile - - p.tag_string = "#big #rafi #style" - p.receive(luke, raph) - expect(p.tags(true).count).to eq(3) - end - end - describe 'post refs' do before do @status_message = bob.post(:status_message, :text => "hi", :to => @bobs_aspect.id) - alice.reload - @alices_aspect.reload - @contact = alice.contact_for(bob.person) end - it "adds a received post to the the contact" do + it "adds a received post to the the user" do expect(alice.visible_shareables(Post)).to include(@status_message) - expect(@contact.posts).to include(@status_message) - end - - it 'removes posts upon forceful removal' do - alice.remove_contact(@contact, :force => true) - alice.reload - expect(alice.visible_shareables(Post)).not_to include @status_message + expect(ShareVisibility.find_by(user_id: alice.id, shareable_id: @status_message.id)).not_to be_nil end - context 'dependent delete' do - it 'deletes share_visibilities on disconnected by' do - @person = FactoryGirl.create(:person) - alice.contacts.create(:person => @person, :aspects => [@alices_aspect]) - - @post = FactoryGirl.create(:status_message, :author => @person) - expect(@post.share_visibilities).to be_empty - receive_with_zord(alice, @person, @post.to_diaspora_xml) - @contact = alice.contact_for(@person) - @contact.share_visibilities.reset - expect(@contact.posts(true)).to include(@post) - @post.share_visibilities.reset + it "does not remove visibility on disconnect" do + contact = alice.contact_for(bob.person) + alice.disconnect(contact) + contact.destroy - expect { - alice.disconnected_by(@person) - }.to change{@post.share_visibilities(true).count}.by(-1) - end + expect(ShareVisibility.exists?(user_id: alice.id, shareable_id: @status_message.id)).to be_truthy end end - - describe 'comments' do - - context 'remote' do - before do - inlined_jobs do |queue| - connect_users(alice, @alices_aspect, eve, @eves_aspect) - @post = alice.post(:status_message, :text => "hello", :to => @alices_aspect.id) - - xml = @post.to_diaspora_xml - - receive_with_zord(bob, alice.person, xml) - receive_with_zord(eve, alice.person, xml) - - comment = eve.comment!(@post, 'tada') - queue.drain_all - # After Eve creates her comment, it gets sent to Alice, who signs it with her private key - # before relaying it out to the contacts on the top-level post - comment.parent_author_signature = comment.sign_with_key(alice.encryption_key) - @xml = comment.to_diaspora_xml - comment.delete - - comment_with_whitespace = alice.comment!(@post, ' I cannot lift my thumb from the spacebar ') - queue.drain_all - @xml_with_whitespace = comment_with_whitespace.to_diaspora_xml - @guid_with_whitespace = comment_with_whitespace.guid - comment_with_whitespace.delete - end - end - - it 'should receive a relayed comment with leading whitespace' do - expect(eve.reload.visible_shareables(Post).size).to eq(1) - post_in_db = StatusMessage.find(@post.id) - expect(post_in_db.comments).to eq([]) - receive_with_zord(eve, alice.person, @xml_with_whitespace) - - expect(post_in_db.comments(true).first.guid).to eq(@guid_with_whitespace) - end - - it 'should correctly attach the user already on the pod' do - expect(bob.reload.visible_shareables(Post).size).to eq(1) - post_in_db = StatusMessage.find(@post.id) - expect(post_in_db.comments).to eq([]) - receive_with_zord(bob, alice.person, @xml) - - expect(post_in_db.comments(true).first.author).to eq(eve.person) - end - - it 'should correctly marshal a stranger for the downstream user' do - remote_person = eve.person.dup - eve.person.delete - eve.delete - Person.where(:id => remote_person.id).delete_all - Profile.where(:person_id => remote_person.id).delete_all - remote_person.attributes.delete(:id) # leaving a nil id causes it to try to save with id set to NULL in postgres - - remote_person.save(:validate => false) - remote_person.profile = FactoryGirl.create(:profile, :person => remote_person) - expect(Person).to receive(:find_or_fetch_by_identifier).twice.with(eve.person.diaspora_handle) - .and_return(remote_person) - - expect(bob.reload.visible_shareables(Post).size).to eq(1) - post_in_db = StatusMessage.find(@post.id) - expect(post_in_db.comments).to eq([]) - - receive_with_zord(bob, alice.person, @xml) - - expect(post_in_db.comments(true).first.author).to eq(remote_person) - end - end - - context 'local' do - before do - @post = alice.post :status_message, :text => "hello", :to => @alices_aspect.id - - xml = @post.to_diaspora_xml - - alice.share_with(eve.person, alice.aspects.first) - - receive_with_zord(bob, alice.person, xml) - receive_with_zord(eve, alice.person, xml) - end - - it 'does not raise a `Mysql2::Error: Duplicate entry...` exception on save' do - inlined_jobs do - @comment = bob.comment!(@post, 'tada') - @xml = @comment.to_diaspora_xml - - expect { - receive_with_zord(alice, bob.person, @xml) - }.to_not raise_exception - end - end - end - end - - - describe 'receiving mulitple versions of the same post from a remote pod' do - before do - @local_luke, @local_leia, @remote_raphael = set_up_friends - @post = FactoryGirl.create(:status_message, :text => 'hey', :guid => '12313123', :author=> @remote_raphael, :created_at => 5.days.ago, :updated_at => 5.days.ago) - end - - it 'does not update created_at or updated_at when two people save the same post' do - @post = FactoryGirl.build(:status_message, :text => 'hey', :guid => '12313123', :author=> @remote_raphael, :created_at => 5.days.ago, :updated_at => 5.days.ago) - xml = @post.to_diaspora_xml - receive_with_zord(@local_luke, @remote_raphael, xml) - old_time = Time.now+1 - receive_with_zord(@local_leia, @remote_raphael, xml) - expect((Post.find_by_guid @post.guid).updated_at).to be < old_time - expect((Post.find_by_guid @post.guid).created_at).to be < old_time - end - - it 'does not update the post if a new one is sent with a new created_at' do - @post = FactoryGirl.build(:status_message, :text => 'hey', :guid => '12313123', :author => @remote_raphael, :created_at => 5.days.ago) - old_time = @post.created_at - xml = @post.to_diaspora_xml - receive_with_zord(@local_luke, @remote_raphael, xml) - @post = FactoryGirl.build(:status_message, :text => 'hey', :guid => '12313123', :author => @remote_raphael, :created_at => 2.days.ago) - receive_with_zord(@local_luke, @remote_raphael, xml) - expect((Post.find_by_guid @post.guid).created_at.day).to eq(old_time.day) - end - end - - - describe 'salmon' do - let(:post){alice.post :status_message, :text => "hello", :to => @alices_aspect.id} - let(:salmon){alice.salmon( post )} - - it 'processes a salmon for a post' do - salmon_xml = salmon.xml_for(bob.person) - - zord = Postzord::Receiver::Private.new(bob, :salmon_xml => salmon_xml) - zord.perform! - - expect(bob.visible_shareables(Post).include?(post)).to be true - end - end - - - context 'retractions' do - let(:message) { bob.post(:status_message, text: "cats", to: @bobs_aspect.id) } - let(:zord) { Postzord::Receiver::Private.new(alice, person: bob.person) } - - it 'should accept retractions' do - retraction = Retraction.for(message) - xml = retraction.to_diaspora_xml - - expect { - zord.parse_and_receive(xml) - }.to change(StatusMessage, :count).by(-1) - end - - it 'should accept relayable retractions' do - comment = bob.comment! message, "and dogs" - retraction = RelayableRetraction.build(bob, comment) - xml = retraction.to_diaspora_xml - - expect { - zord.parse_and_receive xml - }.to change(Comment, :count).by(-1) - end - - it 'should accept signed retractions for public posts' do - message = bob.post(:status_message, text: "cats", public: true) - retraction = SignedRetraction.build(bob, message) - salmon = Postzord::Dispatcher::Public.salmon bob, retraction.to_diaspora_xml - xml = salmon.xml_for alice.person - zord = Postzord::Receiver::Public.new xml - - expect { - zord.receive! - }.to change(Post, :count).by(-1) - end - end - - it 'should marshal a profile for a person' do - #Create person - person = bob.person - id = person.id - person.profile.delete - person.profile = Profile.new(:first_name => 'bob', :last_name => 'billytown', :image_url => "http://clown.com", :person_id => person.id) - person.save - - #Cache profile for checking against marshaled profile - new_profile = person.profile.dup - new_profile.first_name = 'boo!!!' - - #Build xml for profile - xml = new_profile.to_diaspora_xml - #Marshal profile - zord = Postzord::Receiver::Private.new(alice, :person => person) - zord.parse_and_receive(xml) - - #Check that marshaled profile is the same as old profile - person = Person.find(person.id) - expect(person.profile.first_name).to eq(new_profile.first_name) - expect(person.profile.last_name).to eq(new_profile.last_name) - expect(person.profile.image_url).to eq(new_profile.image_url) - end end diff --git a/spec/javascripts/app/app_spec.js b/spec/javascripts/app/app_spec.js index bbdcae351a9e13d44f8bd2600db4960d39b834a9..06f9a14b06113abf0acba9fdfa5f2c08279b0abe 100644 --- a/spec/javascripts/app/app_spec.js +++ b/spec/javascripts/app/app_spec.js @@ -45,6 +45,13 @@ describe("app", function() { expect($.fn.placeholder).toHaveBeenCalled(); expect($.fn.placeholder.calls.mostRecent().object.selector).toBe("input, textarea"); }); + + it("initializes autosize for textareas", function(){ + spyOn(window, "autosize"); + app.setupForms(); + expect(window.autosize).toHaveBeenCalled(); + expect(window.autosize.calls.mostRecent().args[0].selector).toBe("textarea"); + }); }); describe("setupAjaxErrorRedirect", function() { diff --git a/spec/javascripts/app/collections/aspect_memberships_spec.js b/spec/javascripts/app/collections/aspect_memberships_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..fccba68b32433bbdee834093b533132575895498 --- /dev/null +++ b/spec/javascripts/app/collections/aspect_memberships_spec.js @@ -0,0 +1,17 @@ +describe("app.collections.AspectMemberships", function() { + beforeEach(function() { + this.models = [factory.aspectMembershipAttrs(), factory.aspectMembershipAttrs(), factory.aspectMembershipAttrs()]; + this.collection = new app.collections.AspectMemberships(this.models); + }); + + describe("#findByAspectId", function() { + it("finds a model in collection", function() { + var model = this.collection.findByAspectId(this.models[1].aspect.id); + expect(model.get("id")).toEqual(this.models[1].id); + }); + + it("returns undefined when nothing found", function() { + expect(this.collection.findByAspectId(factory.id.next())).toEqual(undefined); + }); + }); +}); diff --git a/spec/javascripts/app/collections/aspect_selections_spec.js b/spec/javascripts/app/collections/aspect_selections_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..a2b232d138b1ea1f02190f9e27719b4ef750d3ce --- /dev/null +++ b/spec/javascripts/app/collections/aspect_selections_spec.js @@ -0,0 +1,82 @@ +describe("app.collections.AspectSelections", function() { + beforeEach(function() { + var myAspects = [ + {name: "Work", selected: true}, + {name: "Friends", selected: false}, + {name: "Acquaintances", selected: false} + ]; + this.aspects = new app.collections.AspectSelections(myAspects); + }); + + describe("#selectAll", function() { + it("selects every aspect in the collection", function() { + this.aspects.selectAll(); + this.aspects.each(function(aspect) { + expect(aspect.get("selected")).toBeTruthy(); + }); + }); + }); + + describe("#deselectAll", function() { + it("deselects every aspect in the collection", function() { + this.aspects.deselectAll(); + this.aspects.each(function(aspect) { + expect(aspect.get("selected")).toBeFalsy(); + }); + }); + }); + + describe("#allSelected", function() { + it("returns true if every aspect is selected", function() { + this.aspects.at(1).set("selected", true); + this.aspects.at(2).set("selected", true); + expect(this.aspects.allSelected()).toBeTruthy(); + }); + + it("returns false if at least one aspect is not selected", function() { + expect(this.aspects.allSelected()).toBeFalsy(); + }); + }); + + describe("#toSentence", function() { + describe("with one aspect", function() { + beforeEach(function() { + this.aspects = new app.collections.AspectSelections([{name: "Work", selected: false}]); + }); + + it("returns 'My aspects' when the apsect isn't selected", function() { + expect(this.aspects.toSentence()).toEqual("My aspects"); + }); + + it("returns the name of the aspect when the aspect is selected", function() { + this.aspects.at(0).set({selected: true}); + expect(this.aspects.toSentence()).toEqual("Work"); + }); + }); + + describe("with three aspect", function() { + it("returns the name of the selected aspect", function() { + expect(this.aspects.toSentence()).toEqual("Work"); + }); + + it("returns the names of the two selected aspects", function() { + this.aspects.at(1).set("selected", true); + expect(this.aspects.toSentence()).toEqual("Work and Friends"); + }); + + it("returns the names of the selected aspects in a comma-separated sentence", function() { + this.aspects.at(1).set("selected", true); + this.aspects.at(2).set("selected", true); + expect(this.aspects.toSentence()).toEqual("Work, Friends and Acquaintances"); + }); + }); + }); + + describe("#selectedGetAttribute", function() { + describe("by name", function() { + it("returns the names of the selected aspects", function() { + expect(this.aspects.selectedGetAttribute("name")).toEqual(["Work"]); + }); + }); + }); +}); diff --git a/spec/javascripts/app/collections/aspects_spec.js b/spec/javascripts/app/collections/aspects_spec.js deleted file mode 100644 index ab89a4206cf7c94849f618932e7e76848fabc5c2..0000000000000000000000000000000000000000 --- a/spec/javascripts/app/collections/aspects_spec.js +++ /dev/null @@ -1,94 +0,0 @@ -describe("app.collections.Aspects", function(){ - beforeEach(function(){ - var locale = { - and: 'and', - comma: ',', - my_aspects: 'My Aspects' - }; - var my_aspects = [ - { name: 'Work', selected: true }, - { name: 'Friends', selected: false }, - { name: 'Acquaintances', selected: false } - ]; - - Diaspora.I18n.load(locale); - this.aspects = new app.collections.Aspects(my_aspects); - }); - - describe("#selectAll", function(){ - it("selects every aspect in the collection", function(){ - this.aspects.selectAll(); - this.aspects.each(function(aspect){ - expect(aspect.get('selected')).toBeTruthy(); - }); - }); - }); - - describe("#deselectAll", function(){ - it("deselects every aspect in the collection", function(){ - this.aspects.deselectAll(); - this.aspects.each(function(aspect){ - expect(aspect.get('selected')).toBeFalsy(); - }); - }); - }); - - describe("#allSelected", function(){ - it("returns true if every aspect is selected", function(){ - this.aspects.at(1).set('selected', true); - this.aspects.at(2).set('selected', true); - expect(this.aspects.allSelected()).toBeTruthy(); - }); - - it("returns false if at least one aspect is not selected", function(){ - expect(this.aspects.allSelected()).toBeFalsy(); - }); - }); - - describe("#toSentence", function(){ - describe('without aspects', function(){ - beforeEach(function(){ - this.aspects = new app.collections.Aspects([{ name: 'Work', selected: false }]); - }); - - it("returns the name of the aspect", function(){ - expect(this.aspects.toSentence()).toEqual('My Aspects'); - }); - }); - - describe("with one aspect", function(){ - beforeEach(function(){ - this.aspects = new app.collections.Aspects([{ name: 'Work', selected: true }]); - }); - - it("returns the name of the aspect", function(){ - expect(this.aspects.toSentence()).toEqual('Work'); - }); - }); - - describe("with three aspect", function(){ - it("returns the name of the selected aspect", function(){ - expect(this.aspects.toSentence()).toEqual('Work'); - }); - - it("returns the names of the two selected aspects", function(){ - this.aspects.at(1).set('selected', true); - expect(this.aspects.toSentence()).toEqual('Work and Friends'); - }); - - it("returns the names of the selected aspects in a comma-separated sentence", function(){ - this.aspects.at(1).set('selected', true); - this.aspects.at(2).set('selected', true); - expect(this.aspects.toSentence()).toEqual('Work, Friends and Acquaintances'); - }); - }); - }); - - describe("#selectedAspects", function(){ - describe("by name", function(){ - it("returns the names of the selected aspects", function(){ - expect(this.aspects.selectedAspects('name')).toEqual(["Work"]); - }); - }); - }); -}); diff --git a/spec/javascripts/app/collections/pods_spec.js b/spec/javascripts/app/collections/pods_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..97bb296193e55ce06937e5235321d96bc56b28c8 --- /dev/null +++ b/spec/javascripts/app/collections/pods_spec.js @@ -0,0 +1,16 @@ + +describe("app.collections.Pods", function() { + describe("#comparator", function() { + it("should handle empty hostnames", function() { + var collection = new app.collections.Pods([ + {id: 1}, + {id: 2, host: "zzz.zz"}, + {id: 3, host: "aaa.aa"}, + {id: 4, host: ""} + ]); + expect(collection.length).toBe(4); + expect(collection.first().get("host")).toBeFalsy(); // also empty string + expect(collection.last().get("host")).toBe("zzz.zz"); + }); + }); +}); diff --git a/spec/javascripts/app/helpers/date_formatter_spec.js b/spec/javascripts/app/helpers/date_formatter_spec.js index 141cdbd6ec1785083edeccafd06e39b126be673a..7343aea9dede00b6efe70808ba01c33482e1df03 100644 --- a/spec/javascripts/app/helpers/date_formatter_spec.js +++ b/spec/javascripts/app/helpers/date_formatter_spec.js @@ -1,5 +1,4 @@ describe("app.helpers.dateFormatter", function(){ - beforeEach(function(){ this.statusMessage = factory.post(); this.formatter = app.helpers.dateFormatter; diff --git a/spec/javascripts/app/helpers/handlebars-helpers_spec.js b/spec/javascripts/app/helpers/handlebars-helpers_spec.js index 1ea73894fab192d785365b73191474c23b792556..9ff382cf45b9c617dc75042bab93167bcccd6a24 100644 --- a/spec/javascripts/app/helpers/handlebars-helpers_spec.js +++ b/spec/javascripts/app/helpers/handlebars-helpers_spec.js @@ -1,8 +1,4 @@ describe("Handlebars helpers", function() { - beforeEach(function() { - Diaspora.I18n.load({people: {helper: {"is_not_sharing": "<%= name %> is not sharing with you"}}}); - }); - describe("sharingMessage", function() { it("escapes the person's name", function() { var person = { name: "\"><script>alert(0)</script> \"><script>alert(0)</script>"}; diff --git a/spec/javascripts/app/helpers/locations_spec.js b/spec/javascripts/app/helpers/locations_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..f9848a7dca220b8957934c7f3e2def35e3e7f37f --- /dev/null +++ b/spec/javascripts/app/helpers/locations_spec.js @@ -0,0 +1,29 @@ +describe("app.helpers.locations", function() { + describe("getTiles", function() { + context("with mapbox disabled", function() { + beforeEach(function() { + gon.appConfig = {map: {mapbox: {enabled: false}}}; + }); + + it("returns tiles from the Heidelberg University", function() { + var tiles = app.helpers.locations.getTiles(); + expect(tiles._url).toMatch("http://korona.geog.uni-heidelberg.de/"); + expect(tiles._url).not.toMatch("https://api.tiles.mapbox.com/"); + }); + }); + + context("with mapbox enabled", function() { + beforeEach(function() { + /* eslint-disable camelcase */ + gon.appConfig = {map: {mapbox: {enabled: true, id: "yourID", access_token: "yourAccessToken"}}}; + /* eslint-enable camelcase */ + }); + + it("returns tiles from mapbox", function() { + var tiles = app.helpers.locations.getTiles(); + expect(tiles._url).toMatch("https://api.tiles.mapbox.com/"); + expect(tiles._url).not.toMatch("http://korona.geog.uni-heidelberg.de/"); + }); + }); + }); +}); diff --git a/spec/javascripts/app/helpers/text_formatter_spec.js b/spec/javascripts/app/helpers/text_formatter_spec.js index e0b72adcb90c377e08885daee33d70b5f5d1782b..eca62cb4d4fbfe424f0cc37b04b4b83590487f8e 100644 --- a/spec/javascripts/app/helpers/text_formatter_spec.js +++ b/spec/javascripts/app/helpers/text_formatter_spec.js @@ -132,8 +132,11 @@ describe("app.helpers.textFormatter", function(){ expect(linkElement.attr("target")).toContain("_blank"); }); - expect(this.formatter('<http://google.com>')).toContain('<a href'); - expect(this.formatter('<http://google.com>')).toContain('_blank'); + expect(this.formatter("<http://google.com>")).toContain("<a href"); + expect(this.formatter("<http://google.com>")).toContain("_blank"); + + expect(this.formatter("<http://google.com>")).toContain("noopener"); + expect(this.formatter("<http://google.com>")).toContain("noreferrer"); }); it("adds a missing http://", function() { @@ -147,6 +150,16 @@ describe("app.helpers.textFormatter", function(){ expect(wrapper.find('code').text()).toEqual('<unknown tag>'); }); + it("adds 'img-responsive' to the image class", function() { + var content = "]"; + var wrapper = $("<div>").html(this.formatter(content)); + expect(wrapper.find("img")).toHaveClass("img-responsive"); + + content = "<img src=\"http://google.com\">"; + wrapper = $("<div>").html(this.formatter(content)); + expect(wrapper.find("img")).toHaveClass("img-responsive"); + }); + context("symbol conversion", function() { beforeEach(function() { this.input_strings = [ @@ -285,12 +298,8 @@ describe("app.helpers.textFormatter", function(){ 'https://foo.com!', 'ftp://example.org:8080' ]; - var results = [ - '<p><a href="https://foo.com" target="_blank">https://foo.com</a>!</p>', - '<p><a href="ftp://example.org:8080" target="_blank">ftp://example.org:8080</a></p>' - ]; for (var i = 0; i < contents.length; i++) { - expect(this.formatter(contents[i])).toContain(results[i]); + expect(this.formatter(contents[i])).toContain("<a href"); } }); }); @@ -302,7 +311,7 @@ describe("app.helpers.textFormatter", function(){ 'oh, cool, nginx 1.7.9 supports json autoindexes: http://nginx.org/en/docs/http/ngx_http_autoindex_module.html#autoindex_format' ]; var results = [ - '<p>oh, cool, nginx 1.7.9 supports json autoindexes: <a href="http://nginx.org/en/docs/http/ngx_http_autoindex_module.html#autoindex_format" target="_blank">http://nginx.org/en/docs/http/ngx_http_autoindex_module.html#autoindex_format</a></p>' + '<p>oh, cool, nginx 1.7.9 supports json autoindexes: <a href="http://nginx.org/en/docs/http/ngx_http_autoindex_module.html#autoindex_format" target="_blank" rel="noopener noreferrer">http://nginx.org/en/docs/http/ngx_http_autoindex_module.html#autoindex_format</a></p>' ]; for (var i = 0; i < contents.length; i++) { expect(this.formatter(contents[i])).toContain(results[i]); diff --git a/spec/javascripts/app/models/contact_spec.js b/spec/javascripts/app/models/contact_spec.js index b5fda20c1ae06ce0dfa20a0f97d34e9dc1749bf4..a523cc038c68a94fa8250a9eaef8e28d55153563 100644 --- a/spec/javascripts/app/models/contact_spec.js +++ b/spec/javascripts/app/models/contact_spec.js @@ -8,6 +8,13 @@ describe("app.models.Contact", function() { }); }); + describe("initialize", function() { + it("sets person object with contact reference", function() { + expect(this.contact.person.get("name")).toEqual("aaa"); + expect(this.contact.person.contact).toEqual(this.contact); + }); + }); + describe("inAspect", function(){ it("returns true if the contact has been added to the aspect", function(){ expect(this.contact.inAspect(this.aspect.id)).toBeTruthy(); diff --git a/spec/javascripts/app/models/person_spec.js b/spec/javascripts/app/models/person_spec.js index 21f18d658c737cbd8e817208df9f140f962a00c9..d84afdd8f8bad3a9171e139a891ff126d16a0b9f 100644 --- a/spec/javascripts/app/models/person_spec.js +++ b/spec/javascripts/app/models/person_spec.js @@ -7,6 +7,15 @@ describe("app.models.Person", function() { this.blockedContact = factory.person({relationship: "blocked", block: {id: 1}}); }); + describe("initialize", function() { + it("sets contact object with person reference", function() { + var contact = {id: factory.id.next()}; + var person = factory.person({contact: contact}); + expect(person.contact.get("id")).toEqual(contact.id); + expect(person.contact.person).toEqual(person); + }); + }); + context("#isSharing", function() { it("indicates if the person is sharing", function() { expect(this.mutualContact.isSharing()).toBeTruthy(); diff --git a/spec/javascripts/app/models/pod_spec.js b/spec/javascripts/app/models/pod_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..a848d3225cb4e840df4b6102f4db4513b22b48ed --- /dev/null +++ b/spec/javascripts/app/models/pod_spec.js @@ -0,0 +1,45 @@ +describe("app.model.Pod", function() { + var podId = 123; + + beforeEach(function() { + this.pod = new app.models.Pod({ + id: podId, + host: "pod.example.com", + status: "unchecked", + /* jshint camelcase: false */ + checked_at: null + /* jshint camelcase: true */ + }); + }); + + describe("recheck", function() { + var newAttributes = { + id: podId, + status: "no_errors", + /* jshint camelcase: false */ + checked_at: new Date() + /* jshint camelcase: true */ + }; + var ajaxSuccess = { + status: 200, + responseText: JSON.stringify(newAttributes) + }; + + it("calls the recheck action on the server", function() { + var expected = Routes.adminPodRecheck(podId); + this.pod.recheck(); + expect(jasmine.Ajax.requests.mostRecent().url).toEqual(expected); + }); + + it("updates the model attributes from the response", function() { + spyOn(this.pod, "set").and.callThrough(); + expect(this.pod.get("status")).toEqual("unchecked"); + this.pod.recheck(); + jasmine.Ajax.requests.mostRecent().respondWith(ajaxSuccess); + + expect(this.pod.set).toHaveBeenCalled(); + expect(this.pod.get("status")).toEqual("no_errors"); + expect(this.pod.get("checked_at")).not.toEqual(null); + }); + }); +}); diff --git a/spec/javascripts/app/models/post/interacations_spec.js b/spec/javascripts/app/models/post/interacations_spec.js index 0536b3f1d85016e08a381b63461cec535a406f58..fe5eda94b615ee472909d28934e4c77395fb208d 100644 --- a/spec/javascripts/app/models/post/interacations_spec.js +++ b/spec/javascripts/app/models/post/interacations_spec.js @@ -82,4 +82,91 @@ describe("app.models.Post.Interactions", function(){ }); }); }); + + describe("userLike", function(){ + beforeEach(function() { + this.interactions.likes.reset([]); + }); + + it("returns false if no user liked the post", function() { + expect(this.interactions.userLike()).toBeFalsy(); + }); + + it("returns true if only the current user liked the post", function() { + this.interactions.likes.add(this.userLike); + expect(this.interactions.userLike()).toBeTruthy(); + }); + + it("returns false if only another user liked the post", function() { + var anotherAuthor = factory.author({guid: "anotherAuthor"}); + var anotherLike = new app.models.Like({author : anotherAuthor}); + this.interactions.likes.add(anotherLike); + expect(this.interactions.userLike()).toBeFalsy(); + }); + + it("returns true if the current user and another user liked the post", function() { + var anotherAuthor = factory.author({guid: "anotherAuthor"}); + var anotherLike = new app.models.Like({author : anotherAuthor}); + this.interactions.likes.add(anotherLike); + this.interactions.likes.add(this.userLike); + expect(this.interactions.userLike()).toBeTruthy(); + }); + + it("returns false if only a broken like exists", function() { + var brokenLike = new app.models.Like(); + this.interactions.likes.add(brokenLike); + expect(this.interactions.userLike()).toBeFalsy(); + }); + + it("returns true if the current user liked the post and there is a broken like", function() { + var brokenLike = new app.models.Like(); + this.interactions.likes.add(brokenLike); + this.interactions.likes.add(this.userLike); + expect(this.interactions.userLike()).toBeTruthy(); + }); + }); + + describe("userReshare", function(){ + beforeEach(function() { + this.interactions.reshares.reset([]); + this.userReshare = new app.models.Reshare({author : this.author}); + }); + + it("returns false if no user reshared the post", function() { + expect(this.interactions.userReshare()).toBeFalsy(); + }); + + it("returns true if only the current user reshared the post", function() { + this.interactions.reshares.add(this.userReshare); + expect(this.interactions.userReshare()).toBeTruthy(); + }); + + it("returns false if only another user reshared the post", function() { + var anotherAuthor = factory.author({guid: "anotherAuthor"}); + var anotherReshare = new app.models.Reshare({author : anotherAuthor}); + this.interactions.reshares.add(anotherReshare); + expect(this.interactions.userReshare()).toBeFalsy(); + }); + + it("returns true if the current user and another user reshared the post", function() { + var anotherAuthor = factory.author({guid: "anotherAuthor"}); + var anotherReshare = new app.models.Reshare({author : anotherAuthor}); + this.interactions.reshares.add(anotherReshare); + this.interactions.reshares.add(this.userReshare); + expect(this.interactions.userReshare()).toBeTruthy(); + }); + + it("returns false if only a broken reshare exists", function() { + var brokenReshare = new app.models.Reshare(); + this.interactions.reshares.add(brokenReshare); + expect(this.interactions.userReshare()).toBeFalsy(); + }); + + it("returns true if the current user reshared the post and there is a broken reshare", function() { + var brokenReshare = new app.models.Reshare(); + this.interactions.reshares.add(brokenReshare); + this.interactions.reshares.add(this.userReshare); + expect(this.interactions.userReshare()).toBeTruthy(); + }); + }); }); diff --git a/spec/javascripts/app/pages/admin_dashboard_spec.js b/spec/javascripts/app/pages/admin_dashboard_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..3b97a3fabd05e587f0728e63af6f84fb957df0f5 --- /dev/null +++ b/spec/javascripts/app/pages/admin_dashboard_spec.js @@ -0,0 +1,166 @@ +describe("app.pages.AdminDashboard", function(){ + beforeEach(function() { + spec.loadFixture("admin_dashboard"); + this.view = new app.pages.AdminDashboard(); + gon.podVersion = "0.5.1.2"; + }); + + describe("initialize" , function() { + it("calls updatePodStatus", function() { + spyOn(this.view, "updatePodStatus"); + this.view.initialize(); + expect(this.view.updatePodStatus).toHaveBeenCalled(); + }); + }); + + describe("updatePodStatus" , function() { + it("sends an ajax request to the github API", function() { + this.view.updatePodStatus(); + expect(jasmine.Ajax.requests.mostRecent().url).toBe( + "https://api.github.com/repos/diaspora/diaspora/releases/latest" + ); + }); + + it("calls updatePodStatusFail on a failed request", function() { + spyOn(this.view, "updatePodStatusFail"); + this.view.updatePodStatus(); + jasmine.Ajax.requests.mostRecent().respondWith({status: 400}); + expect(this.view.updatePodStatusFail).toHaveBeenCalled(); + }); + + it("calls updatePodStatusFail on a malformed response", function() { + spyOn(this.view, "updatePodStatusFail"); + spyOn(this.view, "podUpToDate").and.returnValue(true); + var responses = [ + // no object + "text", + // object without tag_name + "{\"tag\": 0}", + // tag_name not a string + "{\"tag_name\": 0}", + "{\"tag_name\": {\"id\": 0}}", + // tag_name doesn't start with "v" + "{\"tag_name\": \"0.5.1.2\"}" + ]; + + for(var i = 0; i < responses.length; i++) { + this.view.updatePodStatus(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: responses[i] + }); + expect(this.view.updatePodStatusFail.calls.count()).toEqual(i+1); + } + }); + + it("sets latestVersion on a correct response", function() { + this.view.updatePodStatus(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: "{\"tag_name\": \"v0.5.1.2\"}" + }); + expect(this.view.latestVersion).toEqual([0,5,1,2]); + }); + + it("calls podUpToDate on a correct response", function() { + spyOn(this.view, "podUpToDate"); + this.view.updatePodStatus(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: "{\"tag_name\": \"v0.5.1.2\"}" + }); + expect(this.view.podUpToDate).toHaveBeenCalled(); + }); + + it("calls updatePodStatusFail if podUpToDate returns null", function() { + spyOn(this.view, "updatePodStatusFail"); + spyOn(this.view, "podUpToDate").and.returnValue(null); + this.view.updatePodStatus(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: "{\"tag_name\": \"v0.5.1.2\"}" + }); + expect(this.view.updatePodStatusFail).toHaveBeenCalled(); + }); + + it("calls updatePodStatusSuccess if podUpToDate returns a Boolean", function() { + spyOn(this.view, "updatePodStatusSuccess"); + spyOn(this.view, "podUpToDate").and.returnValue(false); + this.view.updatePodStatus(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: "{\"tag_name\": \"v0.5.1.2\"}" + }); + expect(this.view.updatePodStatusSuccess).toHaveBeenCalled(); + }); + }); + + describe("podUpToDate" , function() { + it("returns null if latestVersion is not long enough", function() { + this.view.latestVersion = [0, 5, 1]; + expect(this.view.podUpToDate()).toBeNull(); + }); + + it("returns true if the pod is up to date", function() { + var self = this; + [ + {latest: "0.5.1.2", pod: "0.5.1.2"}, + {latest: "0.5.1.2", pod: "0.5.1.2-abcdefg"}, + {latest: "0.5.1.2", pod: "0.5.1.2-2"}, + {latest: "0.5.1.2", pod: "0.5.1.3"}, + {latest: "0.5.1.2", pod: "0.5.2.1"}, + {latest: "0.5.1.2", pod: "0.6.0.0"}, + {latest: "0.5.1.2", pod: "2.0.0.0"} + ].forEach(function(version) { + gon.podVersion = version.pod; + self.view.latestVersion = version.latest.split(".").map(Number); + expect(self.view.podUpToDate()).toBeTruthy(); + }); + }); + + it("returns false if the pod is outdated", function() { + var self = this; + [ + {latest: "0.5.1.2", pod: "0.5.1.1"}, + {latest: "0.5.1.2", pod: "0.5.1.1-abcdefg"}, + {latest: "0.5.1.2", pod: "0.5.1.1-2"}, + {latest: "0.5.1.2", pod: "0.4.99.4"}, + {latest: "2.0.3.5", pod: "1.99.2.1"} + ].forEach(function(version) { + gon.podVersion = version.pod; + self.view.latestVersion = version.latest.split(".").map(Number); + expect(self.view.podUpToDate()).toBeFalsy(); + }); + }); + }); + + describe("updatePodStatusSuccess", function() { + it("adds a 'success' alert if the pod is up to date", function() { + spyOn(this.view, "podUpToDate").and.returnValue(true); + this.view.latestVersion = [0, 5, 1, 1]; + this.view.updatePodStatusSuccess(); + expect($("#pod-status .alert")).toHaveClass("alert-success"); + expect($("#pod-status .alert").text()).toContain("up to date"); + expect($("#pod-status .alert").text()).toContain("release is v0.5.1.1"); + expect($("#pod-status .alert").text()).toContain("pod is running v0.5.1.2"); + }); + + it("adds a 'danger' alert if the pod is up to date", function() { + spyOn(this.view, "podUpToDate").and.returnValue(false); + this.view.latestVersion = [0, 5, 1, 3]; + this.view.updatePodStatusSuccess(); + expect($("#pod-status .alert")).toHaveClass("alert-danger"); + expect($("#pod-status .alert").text()).toContain("outdated"); + expect($("#pod-status .alert").text()).toContain("release is v0.5.1.3"); + expect($("#pod-status .alert").text()).toContain("pod is running v0.5.1.2"); + }); + }); + + describe("updatePodStatusFail", function() { + it("adds a 'warning' alert", function() { + this.view.updatePodStatusFail(); + expect($("#pod-status .alert")).toHaveClass("alert-warning"); + expect($("#pod-status .alert").text()).toContain("Unable to determine"); + }); + }); +}); diff --git a/spec/javascripts/app/pages/contacts_spec.js b/spec/javascripts/app/pages/contacts_spec.js index 052db4ac3acf4fdcc35049844414e8d941b3a802..a40b899d22eaacf9cf407af1a448ad311a1a5d44 100644 --- a/spec/javascripts/app/pages/contacts_spec.js +++ b/spec/javascripts/app/pages/contacts_spec.js @@ -1,70 +1,65 @@ describe("app.pages.Contacts", function(){ beforeEach(function() { spec.loadFixture("aspects_manage"); + var contactsData = spec.readFixture("aspects_manage_contacts_json"); + app.contacts = new app.collections.Contacts(JSON.parse(contactsData)); this.view = new app.pages.Contacts({ stream: { - render: function(){} - } - }); - Diaspora.I18n.load({ - contacts: { - aspect_list_is_visible: "Contacts in this aspect are able to see each other.", - aspect_list_is_not_visible: "Contacts in this aspect are not able to see each other.", - aspect_chat_is_enabled: "Contacts in this aspect are able to chat with you.", - aspect_chat_is_not_enabled: "Contacts in this aspect are not able to chat with you.", + render: function(){}, + collection: app.contacts } }); }); context('toggle chat privilege', function() { beforeEach(function() { - this.chat_toggle = $("#chat_privilege_toggle"); - this.chat_icon = $("#chat_privilege_toggle .entypo"); + this.chatToggle = $("#chat_privilege_toggle"); + this.chatIcon = $("#chat_privilege_toggle i"); }); it('updates the title for the tooltip', function() { - expect(this.chat_icon.attr('data-original-title')).toBe( + expect(this.chatIcon.attr("data-original-title")).toBe( Diaspora.I18n.t("contacts.aspect_chat_is_not_enabled") ); - this.chat_toggle.trigger('click'); - expect(this.chat_icon.attr('data-original-title')).toBe( + this.chatToggle.trigger("click"); + expect(this.chatIcon.attr("data-original-title")).toBe( Diaspora.I18n.t("contacts.aspect_chat_is_enabled") ); }); - it('toggles the chat icon', function() { - expect(this.chat_icon.hasClass('enabled')).toBeFalsy(); - this.chat_toggle.trigger('click'); - expect(this.chat_icon.hasClass('enabled')).toBeTruthy(); + it("toggles the chat icon", function() { + expect(this.chatIcon.hasClass("enabled")).toBeFalsy(); + this.chatToggle.trigger("click"); + expect(this.chatIcon.hasClass("enabled")).toBeTruthy(); }); }); context('toggle contacts visibility', function() { beforeEach(function() { - this.visibility_toggle = $("#contacts_visibility_toggle"); - this.lock_icon = $("#contacts_visibility_toggle .entypo"); + this.visibilityToggle = $("#contacts_visibility_toggle"); + this.lockIcon = $("#contacts_visibility_toggle i"); }); - it('updates the title for the tooltip', function() { - expect(this.lock_icon.attr('data-original-title')).toBe( + it("updates the title for the tooltip", function() { + expect(this.lockIcon.attr("data-original-title")).toBe( Diaspora.I18n.t("contacts.aspect_list_is_visible") ); - this.visibility_toggle.trigger('click'); + this.visibilityToggle.trigger("click"); - expect(this.lock_icon.attr('data-original-title')).toBe( + expect(this.lockIcon.attr("data-original-title")).toBe( Diaspora.I18n.t("contacts.aspect_list_is_not_visible") ); }); - it('toggles the lock icon', function() { - expect(this.lock_icon.hasClass('lock-open')).toBeTruthy(); - expect(this.lock_icon.hasClass('lock')).toBeFalsy(); + it("toggles the lock icon", function() { + expect(this.lockIcon.hasClass("entypo-lock-open")).toBeTruthy(); + expect(this.lockIcon.hasClass("entypo-lock")).toBeFalsy(); - this.visibility_toggle.trigger('click'); + this.visibilityToggle.trigger("click"); - expect(this.lock_icon.hasClass('lock')).toBeTruthy(); - expect(this.lock_icon.hasClass('lock-open')).toBeFalsy(); + expect(this.lockIcon.hasClass("entypo-lock")).toBeTruthy(); + expect(this.lockIcon.hasClass("entypo-lock-open")).toBeFalsy(); }); }); @@ -93,16 +88,193 @@ describe("app.pages.Contacts", function(){ }); }); - context('search contact list', function() { - beforeEach(function() { - this.searchinput = $('#contact_list_search'); + describe("updateBadgeCount", function() { + it("increases the badge count of an aspect", function() { + var aspect = $("#aspect_nav .aspect").eq(0); + $(".badge", aspect).text("15"); + this.view.updateBadgeCount("[data-aspect-id='" + aspect.data("aspect-id") + "']", 27); + expect($(".badge", aspect).text()).toBe("42"); + }); + + it("decreases the badge count of an aspect", function() { + var aspect = $("#aspect_nav .aspect").eq(1); + $(".badge", aspect).text("42"); + this.view.updateBadgeCount("[data-aspect-id='" + aspect.data("aspect-id") + "']", -15); + expect($(".badge", aspect).text()).toBe("27"); + }); + + it("increases the badge count of 'my aspects'", function() { + $("#aspect_nav .all_aspects .badge").text("15"); + this.view.updateBadgeCount(".all_aspects", 27); + expect($("#aspect_nav .all_aspects .badge").text()).toBe("42"); + }); + + it("decreases the badge count of 'my aspects'", function() { + $("#aspect_nav .all_aspects .badge").text("42"); + this.view.updateBadgeCount(".all_aspects", -15); + expect($("#aspect_nav .all_aspects .badge").text()).toBe("27"); + }); + }); + + describe("addAspectMembership", function() { + context("when the user starts sharing", function() { + beforeEach(function() { + this.contact = app.contacts.first(); + this.data = { + membership: { + aspectId: $("#aspect_nav .aspect").eq(1).data("aspect-id"), + personId: this.contact.person.id + }, + startSharing: true + }; + spyOn(this.view, "updateBadgeCount").and.callThrough(); + }); + + it("is called on aspect_membership:create", function() { + spyOn(app.pages.Contacts.prototype, "addAspectMembership"); + this.view = new app.pages.Contacts({stream: {render: function(){}, collection: app.contacts}}); + app.events.trigger("aspect_membership:create", this.data); + expect(app.pages.Contacts.prototype.addAspectMembership).toHaveBeenCalledWith(this.data); + }); + + it("calls updateContactCount for 'all aspects'", function() { + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".all_aspects", 1); + }); + + it("calls updateBadgeCount for the aspect", function() { + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith( + "[data-aspect-id='" + this.data.membership.aspectId + "']", 1 + ); + }); + + it("calls updateContactCount for 'all contacts' if there was no relationship before", function() { + this.contact.person.set({relationship: "not_sharing"}); + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".all_contacts", 1); + expect(this.contact.person.get("relationship")).toBe("receiving"); + }); + + it("calls updateContactCount for 'only sharing' if the relationship was 'sharing'", function() { + this.contact.person.set({relationship: "sharing"}); + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".only_sharing", -1); + expect(this.contact.person.get("relationship")).toBe("mutual"); + }); }); - it('calls stream.search', function() { - this.view.stream.search = jasmine.createSpy(); - this.searchinput.val("Username"); - this.searchinput.trigger('keyup'); - expect(this.view.stream.search).toHaveBeenCalledWith("Username"); + context("when the user doesn't start sharing", function() { + beforeEach(function() { + this.data = { + membership: { + aspectId: $("#aspect_nav .aspect").eq(1).data("aspect-id"), + personId: app.contacts.first().person.id + }, + startSharing: false + }; + spyOn(this.view, "updateBadgeCount").and.callThrough(); + }); + + it("is called on aspect_membership:create", function() { + spyOn(app.pages.Contacts.prototype, "addAspectMembership"); + this.view = new app.pages.Contacts({stream: {render: function(){}, collection: app.contacts}}); + app.events.trigger("aspect_membership:create", this.data); + expect(app.pages.Contacts.prototype.addAspectMembership).toHaveBeenCalledWith(this.data); + }); + + it("doesn't call updateBadgeCount for 'all aspects'", function() { + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).not.toHaveBeenCalledWith(".all_aspects", 1); + }); + + it("calls updateBadgeCount for the aspect", function() { + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith( + "[data-aspect-id='" + this.data.membership.aspectId + "']", 1 + ); + }); + }); + }); + + describe("removeAspectMembership", function() { + context("when the user stops sharing", function() { + beforeEach(function() { + this.contact = app.contacts.first(); + this.data = { + membership: { + aspectId: $("#aspect_nav .aspect").eq(0).data("aspect-id"), + personId: this.contact.person.id + }, + stopSharing: true + }; + spyOn(this.view, "updateBadgeCount").and.callThrough(); + }); + + it("is called on aspect_membership:destroy", function() { + spyOn(app.pages.Contacts.prototype, "removeAspectMembership"); + this.view = new app.pages.Contacts({stream: {render: function(){}, collection: app.contacts}}); + app.events.trigger("aspect_membership:destroy", this.data); + expect(app.pages.Contacts.prototype.removeAspectMembership).toHaveBeenCalledWith(this.data); + }); + + it("calls updateContactCount for 'all aspects'", function() { + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".all_aspects", -1); + }); + + it("calls updateBadgeCount for the aspect", function() { + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith( + "[data-aspect-id='" + this.data.membership.aspectId + "']", -1 + ); + }); + + it("calls updateContactCount for 'all contacts' if the relationship was 'receiving'", function() { + this.contact.person.set({relationship: "receiving"}); + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".all_contacts", -1); + expect(this.contact.person.get("relationship")).toBe("not_sharing"); + }); + + it("calls updateContactCount for 'only sharing' if the relationship was 'mutual'", function() { + this.contact.person.set({relationship: "mutual"}); + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".only_sharing", 1); + expect(this.contact.person.get("relationship")).toBe("sharing"); + }); + }); + + context("when the user doesn't stop sharing", function() { + beforeEach(function() { + this.data = { + membership: { + aspectId: $("#aspect_nav .aspect").eq(0).data("aspect-id"), + personId: app.contacts.first().person.id + }, + stopSharing: false + }; + spyOn(this.view, "updateBadgeCount").and.callThrough(); + }); + + it("is called on aspect_membership:destroy", function() { + spyOn(app.pages.Contacts.prototype, "removeAspectMembership"); + this.view = new app.pages.Contacts({stream: {render: function(){}, collection: app.contacts}}); + app.events.trigger("aspect_membership:destroy", this.data); + expect(app.pages.Contacts.prototype.removeAspectMembership).toHaveBeenCalledWith(this.data); + }); + + it("doesn't call updateBadgeCount for 'all aspects'", function() { + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).not.toHaveBeenCalledWith(".all_aspects", -1); + }); + + it("calls updateBadgeCount for the aspect", function() { + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith( + "[data-aspect-id='" + this.data.membership.aspectId + "']", -1 + ); + }); }); }); }); diff --git a/spec/javascripts/app/pages/getting_started_spec.js b/spec/javascripts/app/pages/getting_started_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..35e7f5aa4b732753dd246f6f1f6d7bad6ac7a2d3 --- /dev/null +++ b/spec/javascripts/app/pages/getting_started_spec.js @@ -0,0 +1,15 @@ +describe("app.pages.GettingStarted", function() { + beforeEach(function() { + spec.loadFixture("getting_started"); + app.aspects = new app.collections.Aspects([factory.aspect()]); + + this.view = new app.pages.GettingStarted({ + inviter: factory.person() + }); + }); + + it("renders aspect membership dropdown", function() { + this.view.render(); + expect($("ul.dropdown-menu.aspect_membership").length).toEqual(1); + }); +}); diff --git a/spec/javascripts/app/router_spec.js b/spec/javascripts/app/router_spec.js index 0dbe5b269e475f26c6e4349a98064780c81cc5e8..3b185a5f24dc320ce76bb834c6ca8386c31e9b3c 100644 --- a/spec/javascripts/app/router_spec.js +++ b/spec/javascripts/app/router_spec.js @@ -2,6 +2,7 @@ describe('app.Router', function () { describe('followed_tags', function() { beforeEach(function() { factory.preloads({tagFollowings: []}); + spec.loadFixture("aspects_index"); }); it('decodes name before passing it into TagFollowingAction', function () { @@ -38,7 +39,7 @@ describe('app.Router', function () { it('hides the aspects list', function(){ setFixtures('<div id="aspects_list" />'); - aspects = new app.collections.Aspects([ + aspects = new app.collections.AspectSelections([ factory.aspectAttrs({selected:true}), factory.aspectAttrs() ]); @@ -87,11 +88,24 @@ describe('app.Router', function () { }); }); + describe("gettingStarted", function() { + it("renders app.pages.GettingStarted", function() { + app.router.navigate("/getting_started", {trigger: true}); + expect(app.page.$el.selector).toEqual("#hello-there"); + }); + + it("renders app.pages.GettingStarted when the URL has a trailing slash", function() { + app.router.navigate("/getting_started/", {trigger: true}); + expect(app.page.$el.selector).toEqual("#hello-there"); + }); + }); + describe("_initializeStreamView", function() { beforeEach(function() { delete app.page; delete app.publisher; delete app.shortcuts; + spec.loadFixture("aspects_index"); }); it("sets app.page", function() { @@ -112,6 +126,12 @@ describe('app.Router', function () { expect(app.publisher.jasmineTestValue).toEqual(42); }); + it("doesn't set app.publisher if there is no publisher element in page", function() { + $("#publisher").remove(); + app.router._initializeStreamView(); + expect(app.publisher).toBeUndefined(); + }); + it("sets app.shortcuts", function() { expect(app.shortcuts).toBeUndefined(); app.router._initializeStreamView(); diff --git a/spec/javascripts/app/views/aspect_create_view_spec.js b/spec/javascripts/app/views/aspect_create_view_spec.js index bbd17446ff85f303c92b97429ff6534e5f52ecf9..bd1a38c4b753b06eaaabac27486e5b93ff3cfd89 100644 --- a/spec/javascripts/app/views/aspect_create_view_spec.js +++ b/spec/javascripts/app/views/aspect_create_view_spec.js @@ -1,23 +1,9 @@ describe("app.views.AspectCreate", function() { beforeEach(function() { app.events.off("aspect:create"); - // disable jshint camelcase for i18n - /* jshint camelcase: false */ - Diaspora.I18n.load({ - aspects: { - make_aspect_list_visible: "Make contacts in this aspect visible to each other?", - name: "Name", - create: { - add_a_new_aspect: "Add a new aspect", - success: "Your new aspect <%= name %> was created", - failure: "Aspect creation failed." - } - } - }); - /* jshint camelcase: true */ }); - context("without a person id", function() { + context("without a person", function() { beforeEach(function() { this.view = new app.views.AspectCreate(); }); @@ -32,7 +18,7 @@ describe("app.views.AspectCreate", function() { expect(this.view.$("#newAspectModal form").length).toBe(1); expect(this.view.$("#newAspectModal input#aspect_name").length).toBe(1); expect(this.view.$("#newAspectModal input#aspect_contacts_visible").length).toBe(1); - expect(this.view.$("#newAspectModal .btn.creation").length).toBe(1); + expect(this.view.$("#newAspectModal .btn-primary").length).toBe(1); }); it("shouldn't show a hidden person id input", function() { @@ -40,10 +26,31 @@ describe("app.views.AspectCreate", function() { }); }); + describe("#inputKeypress", function() { + beforeEach(function() { + this.view.render(); + spyOn(this.view, "createAspect"); + }); + + it("should call createAspect if the enter key was pressed", function() { + var e = $.Event("keypress", { which: Keycodes.ENTER }); + this.view.inputKeypress(e); + expect(this.view.createAspect).toHaveBeenCalled(); + }); + + it("shouldn't call createAspect if another key was pressed", function() { + var e = $.Event("keypress", { which: Keycodes.TAB }); + this.view.inputKeypress(e); + expect(this.view.createAspect).not.toHaveBeenCalled(); + }); + }); describe("#createAspect", function() { beforeEach(function() { this.view.render(); + this.view.$el.append($("<div id='flash-container'/>")); + app.flashMessages = new app.views.FlashMessages({ el: this.view.$("#flash-container") }); + app.aspects = new app.collections.Aspects(); }); it("should send the correct name to the server", function() { @@ -86,7 +93,8 @@ describe("app.views.AspectCreate", function() { }); it("should hide the modal", function() { - this.view.$(".modal").modal("show"); + this.view.$(".modal").removeClass("fade"); + this.view.$(".modal").modal("toggle"); expect(this.view.$(".modal")).toHaveClass("in"); this.view.createAspect(); jasmine.Ajax.requests.mostRecent().respondWith(this.response); @@ -96,7 +104,7 @@ describe("app.views.AspectCreate", function() { it("should display a flash message", function() { this.view.createAspect(); jasmine.Ajax.requests.mostRecent().respondWith(this.response); - expect($("[id^=\"flash\"]")).toBeSuccessFlashMessage( + expect(this.view.$(".flash-message")).toBeSuccessFlashMessage( Diaspora.I18n.t("aspects.create.success", {name: "new name"}) ); }); @@ -108,6 +116,7 @@ describe("app.views.AspectCreate", function() { }); it("should hide the modal", function() { + this.view.$(".modal").removeClass("fade"); this.view.$(".modal").modal("show"); expect(this.view.$(".modal")).toHaveClass("in"); this.view.createAspect(); @@ -118,7 +127,7 @@ describe("app.views.AspectCreate", function() { it("should display a flash message", function() { this.view.createAspect(); jasmine.Ajax.requests.mostRecent().respondWith(this.response); - expect($("[id^=\"flash\"]")).toBeErrorFlashMessage( + expect(this.view.$(".flash-message")).toBeErrorFlashMessage( Diaspora.I18n.t("aspects.create.failure") ); }); @@ -126,9 +135,10 @@ describe("app.views.AspectCreate", function() { }); }); - context("with a person id", function() { + context("with a person", function() { beforeEach(function() { - this.view = new app.views.AspectCreate({personId: "42"}); + var person = new app.models.Person({id: "42"}); + this.view = new app.views.AspectCreate({person: person}); }); describe("#render", function() { @@ -141,7 +151,7 @@ describe("app.views.AspectCreate", function() { expect(this.view.$("#newAspectModal form").length).toBe(1); expect(this.view.$("#newAspectModal input#aspect_name").length).toBe(1); expect(this.view.$("#newAspectModal input#aspect_contacts_visible").length).toBe(1); - expect(this.view.$("#newAspectModal .btn.creation").length).toBe(1); + expect(this.view.$("#newAspectModal .btn-primary").length).toBe(1); }); it("should show a hidden person id input", function() { @@ -153,6 +163,7 @@ describe("app.views.AspectCreate", function() { describe("#createAspect", function() { beforeEach(function() { this.view.render(); + app.aspects = new app.collections.Aspects(); }); it("should send the correct name to the server", function() { @@ -185,6 +196,36 @@ describe("app.views.AspectCreate", function() { expect(obj.person_id).toBe("42"); /* jshint camelcase: true */ }); + + it("should ensure that events order is fine", function() { + spyOn(this.view, "ensureEventsOrder").and.callThrough(); + this.view.$(".modal").removeClass("fade"); + this.view.$(".modal").modal("toggle"); + this.view.createAspect(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: JSON.stringify({id: 1337, name: "new name"}) + }); + expect(this.view.ensureEventsOrder.calls.count()).toBe(2); + }); + + it("should ensure that events order is fine after failure", function() { + spyOn(this.view, "ensureEventsOrder").and.callThrough(); + this.view.$(".modal").removeClass("fade"); + this.view.$(".modal").modal("toggle"); + this.view.createAspect(); + jasmine.Ajax.requests.mostRecent().respondWith({status: 422}); + expect(this.view.ensureEventsOrder.calls.count()).toBe(1); + + this.view.$(".modal").removeClass("fade"); + this.view.$(".modal").modal("toggle"); + this.view.createAspect(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: JSON.stringify({id: 1337, name: "new name"}) + }); + expect(this.view.ensureEventsOrder.calls.count()).toBe(3); + }); }); }); }); diff --git a/spec/javascripts/app/views/aspect_membership_view_spec.js b/spec/javascripts/app/views/aspect_membership_view_spec.js index 660ddc2159b725da2a38f163e0ab8d2124e63f17..7dabc075b07f106a7c00b8cf6d16357a7a75df7e 100644 --- a/spec/javascripts/app/views/aspect_membership_view_spec.js +++ b/spec/javascripts/app/views/aspect_membership_view_spec.js @@ -1,106 +1,108 @@ describe("app.views.AspectMembership", function(){ - var resp_success = {status: 200, responseText: '{}'}; + var success = {status: 200, responseText: "{}"}; var resp_fail = {status: 400}; beforeEach(function() { - // mock a dummy aspect dropdown - spec.loadFixture("aspect_membership_dropdown"); - this.view = new app.views.AspectMembership({el: $('.aspect_membership_dropdown')}); - this.person_id = $('.dropdown-menu').data('person_id'); - this.person_name = $('.dropdown-menu').data('person-short-name'); - Diaspora.I18n.load({ - aspect_dropdown: { - started_sharing_with: 'you started sharing with <%= name %>', - stopped_sharing_with: 'you stopped sharing with <%= name %>', - error: 'unable to add <%= name %>', - error_remove: 'unable to remove <%= name %>' - } - }); + var contact = factory.contact(); + this.person = contact.person; + this.personName = this.person.get("name"); + var aspectAttrs = contact.aspectMemberships.at(0).get("aspect"); + app.aspects = new app.collections.Aspects([factory.aspect(aspectAttrs), factory.aspect()]); + this.view = new app.views.AspectMembership({person: this.person}); + this.view.render(); + spec.content().append($("<div id='flash-container'/>")); + app.flashMessages = new app.views.FlashMessages({el: spec.content().find("#flash-container")}); }); context('adding to aspects', function() { beforeEach(function() { - this.newAspect = $('li:not(.selected)'); + this.newAspect = this.view.$("li:not(.selected)"); this.newAspectId = this.newAspect.data('aspect_id'); }); it('marks the aspect as selected', function() { this.newAspect.trigger('click'); - jasmine.Ajax.requests.mostRecent().respondWith(resp_success); - - expect(this.newAspect.attr('class')).toContain('selected'); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: JSON.stringify({ + id: factory.id.next(), + aspect: app.aspects.at(1).attributes + }) + }); + + expect(this.view.$("li[data-aspect_id=" + this.newAspectId + "]").attr("class")).toContain("selected"); }); it('displays flash message when added to first aspect', function() { - spec.content().find('li').removeClass('selected'); + this.view.$("li").removeClass("selected"); this.newAspect.trigger('click'); - jasmine.Ajax.requests.mostRecent().respondWith(resp_success); + jasmine.Ajax.requests.mostRecent().respondWith(success); - expect($('[id^="flash"]')).toBeSuccessFlashMessage( - Diaspora.I18n.t('aspect_dropdown.started_sharing_with', {name: this.person_name}) + expect(spec.content().find(".flash-message")).toBeSuccessFlashMessage( + Diaspora.I18n.t("aspect_dropdown.started_sharing_with", {name: this.personName}) ); }); + it("triggers aspect_membership:create", function() { + spyOn(app.events, "trigger"); + this.view.$("li").removeClass("selected"); + this.newAspect.trigger("click"); + jasmine.Ajax.requests.mostRecent().respondWith(success); + expect(app.events.trigger).toHaveBeenCalledWith("aspect_membership:create", { + membership: {aspectId: this.newAspectId, personId: this.person.id}, + startSharing: true + }); + }); + it('displays an error when it fails', function() { this.newAspect.trigger('click'); jasmine.Ajax.requests.mostRecent().respondWith(resp_fail); - expect($('[id^="flash"]')).toBeErrorFlashMessage( - Diaspora.I18n.t('aspect_dropdown.error', {name: this.person_name}) + expect(spec.content().find(".flash-message")).toBeErrorFlashMessage( + Diaspora.I18n.t("aspect_dropdown.error", {name: this.personName}) ); }); }); context('removing from aspects', function(){ beforeEach(function() { - this.oldAspect = $('li.selected').first(); - this.oldMembershipId = this.oldAspect.data('membership_id'); + this.oldAspect = this.view.$("li.selected").first(); + this.oldAspectId = this.oldAspect.data("aspect_id"); }); it('marks the aspect as unselected', function(){ this.oldAspect.trigger('click'); - jasmine.Ajax.requests.mostRecent().respondWith(resp_success); + jasmine.Ajax.requests.mostRecent().respondWith(success); - expect(this.oldAspect.attr('class')).not.toContain('selected'); + expect(this.view.$("li[data-aspect_id=" + this.oldAspectId + "]").attr("class")).not.toContain("selected"); }); it('displays a flash message when removed from last aspect', function() { - spec.content().find('li.selected:last').removeClass('selected'); this.oldAspect.trigger('click'); - jasmine.Ajax.requests.mostRecent().respondWith(resp_success); + jasmine.Ajax.requests.mostRecent().respondWith(success); - expect($('[id^="flash"]')).toBeSuccessFlashMessage( - Diaspora.I18n.t('aspect_dropdown.stopped_sharing_with', {name: this.person_name}) + expect(spec.content().find(".flash-message")).toBeSuccessFlashMessage( + Diaspora.I18n.t("aspect_dropdown.stopped_sharing_with", {name: this.personName}) ); }); + it("triggers aspect_membership:destroy", function() { + spyOn(app.events, "trigger"); + this.oldAspect.trigger("click"); + jasmine.Ajax.requests.mostRecent().respondWith(success); + expect(app.events.trigger).toHaveBeenCalledWith("aspect_membership:destroy", { + membership: {aspectId: this.oldAspectId, personId: this.person.id}, + stopSharing: true + }); + }); + it('displays an error when it fails', function() { this.oldAspect.trigger('click'); jasmine.Ajax.requests.mostRecent().respondWith(resp_fail); - expect($('[id^="flash"]')).toBeErrorFlashMessage( - Diaspora.I18n.t('aspect_dropdown.error_remove', {name: this.person_name}) + expect(spec.content().find(".flash-message")).toBeErrorFlashMessage( + Diaspora.I18n.t("aspect_dropdown.error_remove", {name: this.personName}) ); }); }); - - context('button summary text', function() { - beforeEach(function() { - this.Aspect = $('li:eq(0)'); - }); - - it('calls "_toggleCheckbox"', function() { - spyOn(this.view, "_toggleCheckbox"); - this.view.updateSummary(this.Aspect); - - expect(this.view._toggleCheckbox).toHaveBeenCalledWith(this.Aspect); - }); - - it('calls "_updateButton"', function() { - spyOn(this.view, "_updateButton"); - this.view.updateSummary(this.Aspect); - - expect(this.view._updateButton).toHaveBeenCalledWith('green'); - }); - }); }); diff --git a/spec/javascripts/app/views/aspect_view_spec.js b/spec/javascripts/app/views/aspect_view_spec.js index 12ce369411d0c1a02a5da56585d26abe4fd81218..09f6eb7bdb5a8a2a2be9fc33adbc41581f73cef1 100644 --- a/spec/javascripts/app/views/aspect_view_spec.js +++ b/spec/javascripts/app/views/aspect_view_spec.js @@ -9,8 +9,8 @@ describe("app.views.Aspect", function(){ this.view.render(); }); - it('should show the aspect selected', function(){ - expect(this.view.$el.children('.entypo.check').hasClass('selected')).toBeTruthy(); + it("should show the aspect selected", function(){ + expect(this.view.$el.find(".entypo-check").hasClass("selected")).toBeTruthy(); }); it('should show the name of the aspect', function(){ diff --git a/spec/javascripts/app/views/aspects_dropdown_view_spec.js b/spec/javascripts/app/views/aspects_dropdown_view_spec.js index a3b7238de0e634db84c941f4a19d677ad820da0a..004706b1dfb33cc1eb4afd50291c68217d9e664a 100644 --- a/spec/javascripts/app/views/aspects_dropdown_view_spec.js +++ b/spec/javascripts/app/views/aspects_dropdown_view_spec.js @@ -1,22 +1,13 @@ describe("app.views.AspectsDropdown", function(){ beforeEach(function() { spec.loadFixture("bookmarklet"); - Diaspora.I18n.reset({ - 'aspect_dropdown': { - 'select_aspects': "Select aspects", - 'all_aspects': "All aspects", - 'toggle': { - 'zero': "Select aspects", - 'one': "In <%= count %> aspect", - 'other': "In <%= count %> aspects" - }}}); this.view = new app.views.AspectsDropdown({el: $('.aspect_dropdown')}); }); context('_toggleCheckbox', function() { beforeEach(function() { - this.view.$('li.selected').removeClass('selected'); - this.view.$('li.all_aspects.radio').addClass('selected'); + this.view.$("li.selected").removeClass("selected"); + this.view.$("li.all_aspects").addClass("selected"); }); it('deselects all radio buttons', function() { @@ -45,67 +36,75 @@ describe("app.views.AspectsDropdown", function(){ }); it('deselects all checkboxes', function() { - this.view._toggleRadio(this.view.$('li.all_aspects.radio')); - expect(this.view.$('li.aspect_selector:eq(0)').hasClass('selected')).toBeFalsy(); - expect(this.view.$('li.aspect_selector:eq(1)').hasClass('selected')).toBeFalsy(); + this.view._toggleRadio(this.view.$("li.all_aspects")); + expect(this.view.$("li.aspect_selector:eq(0)").hasClass("selected")).toBeFalsy(); + expect(this.view.$("li.aspect_selector:eq(1)").hasClass("selected")).toBeFalsy(); }); it('toggles the clicked radio buttons', function() { - this.view._toggleRadio(this.view.$('li.all_aspects.radio')); - expect(this.view.$('li.all_aspects.radio').hasClass('selected')).toBeTruthy(); - expect(this.view.$('li.public.radio').hasClass('selected')).toBeFalsy(); - this.view._toggleRadio(this.view.$('li.public.radio')); - expect(this.view.$('li.all_aspects.radio').hasClass('selected')).toBeFalsy(); - expect(this.view.$('li.public.radio').hasClass('selected')).toBeTruthy(); - this.view._toggleRadio(this.view.$('li.all_aspects.radio')); - expect(this.view.$('li.all_aspects.radio').hasClass('selected')).toBeTruthy(); - expect(this.view.$('li.public.radio').hasClass('selected')).toBeFalsy(); + this.view._toggleRadio(this.view.$("li.all_aspects")); + expect(this.view.$("li.all_aspects").hasClass("selected")).toBeTruthy(); + expect(this.view.$("li.public").hasClass("selected")).toBeFalsy(); + this.view._toggleRadio(this.view.$("li.public")); + expect(this.view.$("li.all_aspects").hasClass("selected")).toBeFalsy(); + expect(this.view.$("li.public").hasClass("selected")).toBeTruthy(); + this.view._toggleRadio(this.view.$("li.all_aspects")); + expect(this.view.$("li.all_aspects").hasClass("selected")).toBeTruthy(); + expect(this.view.$("li.public").hasClass("selected")).toBeFalsy(); }); }); - context('_selectAspects', function(){ + context("_selectAspects", function(){ beforeEach(function() { - this.view.$('li.selected').removeClass('selected'); - this.view.$('li.aspect_selector:eq(0)').addClass('selected'); + this.view.$("li.selected").removeClass("selected"); + this.view.$("li.aspect_selector:eq(0)").addClass("selected"); }); - it('select aspects in the dropdown by a given list of ids', function() { - this.ids = [this.view.$('li.aspect_selector:eq(1)').data('aspect_id'),'public']; + it("select aspects in the dropdown by a given list of ids", function() { + this.ids = [this.view.$("li.aspect_selector:eq(1)").data("aspect_id"),"public"]; this.view._selectAspects(this.ids); - expect(this.view.$('li.all_aspects.radio').hasClass('selected')).toBeFalsy(); - expect(this.view.$('li.public.radio').hasClass('selected')).toBeTruthy(); - expect(this.view.$('li.aspect_selector:eq(0)').hasClass('selected')).toBeFalsy(); - expect(this.view.$('li.aspect_selector:eq(1)').hasClass('selected')).toBeTruthy(); + expect(this.view.$("li.all_aspects").hasClass("selected")).toBeFalsy(); + expect(this.view.$("li.public").hasClass("selected")).toBeTruthy(); + expect(this.view.$("li.aspect_selector:eq(0)").hasClass("selected")).toBeFalsy(); + expect(this.view.$("li.aspect_selector:eq(1)").hasClass("selected")).toBeTruthy(); }); }); - context('_updateButton', function() { + context("_updateButton", function() { beforeEach(function() { - this.view.$('li.selected').removeClass('selected'); + this.view.$("li.selected").removeClass("selected"); }); - it('shows "Select aspects" when nothing is selected', function() { - this.view._updateButton('inAspectClass'); - expect(this.view.$('.btn.dropdown-toggle > .text').text()).toContain(Diaspora.I18n.t('aspect_dropdown.select_aspects')); + it("shows 'Select aspects' when nothing is selected", function() { + this.view._updateButton("inAspectClass"); + expect(this.view.$(".btn.dropdown-toggle > .text").text()).toContain( + Diaspora.I18n.t("aspect_dropdown.select_aspects") + ); }); - it('shows the name of the selected radio button', function() { - this.view.$('li.all_aspects.radio').addClass('selected'); - this.view._updateButton('inAspectClass'); - expect(this.view.$('.btn.dropdown-toggle > .text').text()).toContain(Diaspora.I18n.t('aspect_dropdown.all_aspects')); + it("shows the name of the selected radio button", function() { + this.view.$("li.all_aspects").addClass("selected"); + this.view._updateButton("inAspectClass"); + expect(this.view.$(".btn.dropdown-toggle > .text").text()).toContain( + Diaspora.I18n.t("aspect_dropdown.all_aspects") + ); }); - it('shows the name of the selected aspect ( == 1 )', function() { - this.view.$('li.aspect_selector:eq(1)').addClass('selected'); - this.view._updateButton('inAspectClass'); - expect(this.view.$('.btn.dropdown-toggle > .text').text()).toContain(this.view.$('li.aspect_selector:eq(1) .text').text()); + it("shows the name of the selected aspect ( == 1 )", function() { + this.view.$("li.aspect_selector:eq(1)").addClass("selected"); + this.view._updateButton("inAspectClass"); + expect(this.view.$(".btn.dropdown-toggle > .text").text()).toContain( + this.view.$("li.aspect_selector:eq(1) .text").text() + ); }); - it('shows the number of selected aspects ( > 1)', function() { - this.view.$('li.aspect_selector:eq(0)').addClass('selected'); - this.view.$('li.aspect_selector:eq(1)').addClass('selected'); - this.view._updateButton('inAspectClass'); - expect(this.view.$('.btn.dropdown-toggle > .text').text()).toContain(Diaspora.I18n.t('aspect_dropdown.toggle', { 'count':2 })); + it("shows the number of selected aspects ( > 1)", function() { + this.view.$("li.aspect_selector:eq(0)").addClass("selected"); + this.view.$("li.aspect_selector:eq(1)").addClass("selected"); + this.view._updateButton("inAspectClass"); + expect(this.view.$(".btn.dropdown-toggle > .text").text()).toContain( + Diaspora.I18n.t("aspect_dropdown.toggle", { count: 2 }) + ); }); }); }); diff --git a/spec/javascripts/app/views/aspects_list_view_spec.js b/spec/javascripts/app/views/aspects_list_view_spec.js index 5a0ded38d1692b08cea34b91ec340cfc2c34552c..522f5dfd2fee606ef780931095bfbb5b0ce91fe2 100644 --- a/spec/javascripts/app/views/aspects_list_view_spec.js +++ b/spec/javascripts/app/views/aspects_list_view_spec.js @@ -1,15 +1,10 @@ describe("app.views.AspectsList", function(){ beforeEach(function(){ setFixtures('<ul id="aspects_list"></ul>'); - Diaspora.I18n.load({ aspect_navigation : { - 'select_all' : 'Select all', - 'deselect_all' : 'Deselect all' - }}); - var aspects = [{ name: 'Work', selected: true }, { name: 'Friends', selected: false }, { name: 'Acquaintances', selected: false }]; - this.aspects = new app.collections.Aspects(aspects); + this.aspects = new app.collections.AspectSelections(aspects); this.view = new app.views.AspectsList({ collection: this.aspects }); }); @@ -18,17 +13,17 @@ describe("app.views.AspectsList", function(){ this.view.render(); }); - it('should show the corresponding aspects selected', function(){ - expect(this.view.$('.selected').length).toBe(1); - expect(this.view.$('.selected + a.selectable').text()).toMatch('Work'); + it("should show the corresponding aspects selected", function(){ + expect(this.view.$(".selected").length).toBe(1); + expect(this.view.$(".selected").parent().text()).toMatch("Work"); }); - it('should show all the aspects', function(){ - var aspect_selectors = this.view.$('.entypo.check + a.selectable'); - expect(aspect_selectors.length).toBe(3); - expect(aspect_selectors[0].text).toMatch('Work'); - expect(aspect_selectors[1].text).toMatch('Friends'); - expect(aspect_selectors[2].text).toMatch('Acquaintances'); + it("should show all the aspects", function(){ + var aspectSelectors = this.view.$(".entypo-check").parent(); + expect(aspectSelectors.length).toBe(3); + expect(aspectSelectors[0].text).toMatch("Work"); + expect(aspectSelectors[1].text).toMatch("Friends"); + expect(aspectSelectors[2].text).toMatch("Acquaintances"); }); it('should show \'Select all\' link', function(){ diff --git a/spec/javascripts/app/views/bookmarklet_view_spec.js b/spec/javascripts/app/views/bookmarklet_view_spec.js index bab7b51974ac88c0eb00b7079d8c6fa5f3fc185a..d5de57466e80bae4e8d8a1a74095e34383068656 100644 --- a/spec/javascripts/app/views/bookmarklet_view_spec.js +++ b/spec/javascripts/app/views/bookmarklet_view_spec.js @@ -1,9 +1,9 @@ -describe('app.views.Bookmarklet', function() { +describe("app.views.Bookmarklet", function() { var test_data = { - url: 'https://www.youtube.com/watch?v=0Bmhjf0rKe8', - title: 'Surprised Kitty', - notes: 'cute kitty' + url: "https://www.youtube.com/watch?v=0Bmhjf0rKe8", + title: "Surprised Kitty", + notes: "cute kitty" }; var evil_test_data = _.extend({}, { notes: "**love** This is such a\n\n great \"cute kitty\" '''blabla''' %28%29\\" @@ -11,46 +11,46 @@ describe('app.views.Bookmarklet', function() { var init_bookmarklet = function(data) { app.bookmarklet = new app.views.Bookmarklet( - _.extend({el: $('#bookmarklet')}, data) + _.extend({el: $("#bookmarklet")}, data) ).render(); }; beforeEach(function() { app.stream = null; // avoid rendering posts loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); - spec.loadFixture('bookmarklet'); + spec.loadFixture("bookmarklet"); }); - it('initializes a standalone publisher', function() { + it("initializes a standalone publisher", function() { new app.views.Bookmarklet(); expect(app.publisher).not.toBeNull(); expect(app.publisher.standalone).toBeTruthy(); }); - it('prefills the publisher', function() { + it("prefills the publisher", function() { init_bookmarklet(test_data); - expect($.trim(app.publisher.el_input.val())).not.toEqual(''); - expect($.trim(app.publisher.el_hiddenInput.val())).not.toEqual(''); + expect($.trim(app.publisher.inputEl.val())).not.toEqual(""); + expect($.trim(app.publisher.hiddenInputEl.val())).not.toEqual(""); }); - it('handles dirty input well', function() { + it("handles dirty input well", function() { init_bookmarklet(evil_test_data); - expect($.trim(app.publisher.el_input.val())).not.toEqual(''); - expect($.trim(app.publisher.el_hiddenInput.val())).not.toEqual(''); + expect($.trim(app.publisher.inputEl.val())).not.toEqual(""); + expect($.trim(app.publisher.hiddenInputEl.val())).not.toEqual(""); }); - it('allows changing a prefilled publisher', function() { + it("allows changing a prefilled publisher", function() { init_bookmarklet(test_data); - app.publisher.setText(app.publisher.el_input.val()+'A'); + app.publisher.setText(app.publisher.inputEl.val()+"A"); - expect(app.publisher.el_hiddenInput.val()).toMatch(/.+A$/); + expect(app.publisher.hiddenInputEl.val()).toMatch(/.+A$/); }); - it('keeps the publisher disabled after successful post creation', function() { + it("keeps the publisher disabled after successful post creation", function() { init_bookmarklet(test_data); - spec.content().find('form').submit(); + spec.content().find("form").submit(); jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, // success! diff --git a/spec/javascripts/app/views/comment_stream_view_spec.js b/spec/javascripts/app/views/comment_stream_view_spec.js index 5028bf0d32bcb13015ac00bb477cd850f9e02235..c0f3f20fb34dd2bbb3c15f7ba06a9fc13a835c43 100644 --- a/spec/javascripts/app/views/comment_stream_view_spec.js +++ b/spec/javascripts/app/views/comment_stream_view_spec.js @@ -5,26 +5,19 @@ describe("app.views.CommentStream", function(){ }); describe("binds", function() { - it("re-renders on a commentsExpanded trigger", function(){ - spyOn(this.view, "render"); + it("calls appendComment on insertion to the comments collection", function() { + spyOn(this.view, "appendComment"); this.view.setupBindings(); - this.view.model.trigger("commentsExpanded"); - expect(this.view.render).toHaveBeenCalled(); - }); - }); - - describe("postRenderTemplate", function(){ - it("autoResizes the new comment textarea", function(){ - spyOn($.fn, "autoResize"); - this.view.postRenderTemplate(); - expect($.fn.autoResize).toHaveBeenCalled(); - expect($.fn.autoResize.calls.mostRecent().object.selector).toBe("textarea"); + this.view.model.comments.push(factory.comment()); + expect(this.view.appendComment).toHaveBeenCalled(); }); }); describe("createComment", function() { beforeEach(function() { this.view.render(); + this.view.$el.append($("<div id='flash-container'/>")); + app.flashMessages = new app.views.FlashMessages({ el: this.view.$("#flash-container") }); this.view.expandComments(); }); @@ -48,11 +41,12 @@ describe("app.views.CommentStream", function(){ }); it("doesn't add the comment to the view, when the request fails", function(){ - Diaspora.I18n.load({failed_to_post_message: "posting failed!"}); this.request.respondWith({status: 500}); expect(this.view.$(".comment-content p").text()).not.toEqual("a new comment"); - expect($('*[id^="flash"]')).toBeErrorFlashMessage("posting failed!"); + expect(this.view.$(".flash-message")).toBeErrorFlashMessage( + "Failed to comment. Maybe the author is ignoring you?" + ); }); }); @@ -76,10 +70,23 @@ describe("app.views.CommentStream", function(){ this.view.appendComment(comment); expect(comment.set).toHaveBeenCalled(); }); + + it("sorts comments in the right order", function() { + this.view.render(); + this.view.appendComment(factory.comment({"created_at": new Date(2000).toJSON(), "text": "2"})); + this.view.appendComment(factory.comment({"created_at": new Date(4000).toJSON(), "text": "4"})); + this.view.appendComment(factory.comment({"created_at": new Date(5000).toJSON(), "text": "5"})); + this.view.appendComment(factory.comment({"created_at": new Date(6000).toJSON(), "text": "6"})); + this.view.appendComment(factory.comment({"created_at": new Date(1000).toJSON(), "text": "1"})); + this.view.appendComment(factory.comment({"created_at": new Date(3000).toJSON(), "text": "3"})); + + expect(this.view.$(".comments div.comment.media").length).toEqual(6); + expect(this.view.$(".comments div.comment.media div.comment-content p").text()).toEqual("123456"); + }); }); describe("expandComments", function() { - it("refills the comment textbox on success", function() { + it("doesn't drop the comment textbox value on success", function() { this.view.render(); this.view.$("textarea").val("great post!"); this.view.expandComments(); @@ -102,8 +109,7 @@ describe("app.views.CommentStream", function(){ var form = this.view.$("form"); form.submit(submitCallback); - var e = $.Event("keydown", { keyCode: 13 }); - e.ctrlKey = false; + var e = $.Event("keydown", { which: Keycodes.ENTER, ctrlKey: false }); this.view.keyDownOnCommentBox(e); expect(submitCallback).not.toHaveBeenCalled(); @@ -114,12 +120,10 @@ describe("app.views.CommentStream", function(){ var form = this.view.$("form"); form.submit(submitCallback); - var e = $.Event("keydown", { keyCode: 13 }); - e.ctrlKey = true; + var e = $.Event("keydown", { which: Keycodes.ENTER, ctrlKey: true }); this.view.keyDownOnCommentBox(e); expect(submitCallback).toHaveBeenCalled(); }); }); - }); diff --git a/spec/javascripts/app/views/contact_stream_view_spec.js b/spec/javascripts/app/views/contact_stream_view_spec.js index 955dd2e7b16f7feac26721b8fd83e65b22fdb800..7ae93bb5352e6252b6a2a589f9d913fd16057d1e 100644 --- a/spec/javascripts/app/views/contact_stream_view_spec.js +++ b/spec/javascripts/app/views/contact_stream_view_spec.js @@ -2,76 +2,199 @@ describe("app.views.ContactStream", function() { beforeEach(function() { loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); spec.loadFixture("aspects_manage"); - this.contacts = new app.collections.Contacts($.parseJSON(spec.readFixture("contacts_json"))); - app.aspect = new app.models.Aspect(this.contacts.first().get('aspect_memberships')[0].aspect); + this.contacts = new app.collections.Contacts(); + this.contactsData = $.parseJSON(spec.readFixture("contacts_json")); + app.aspect = new app.models.Aspect(this.contactsData[0].aspect_memberships[0].aspect); this.view = new app.views.ContactStream({ collection : this.contacts, - el: $('.stream.contacts #contact_stream') + el: $(".stream.contacts #contact_stream"), + urlParams: "set=all" }); - - this.view.perPage=1; - - //clean the page - this.view.$el.html(''); }); describe("initialize", function() { it("binds an infinite scroll listener", function() { spyOn($.fn, "scroll"); - new app.views.ContactStream({collection : this.contacts}); + new app.views.ContactStream({collection: this.contacts}); expect($.fn.scroll).toHaveBeenCalled(); }); + + it("binds 'fetchContacts'", function() { + spyOn(app.views.ContactStream.prototype, "fetchContacts"); + this.view = new app.views.ContactStream({collection: this.contacts}); + this.view.trigger("fetchContacts"); + expect(app.views.ContactStream.prototype.fetchContacts).toHaveBeenCalled(); + }); + + it("sets the current page for pagination to 1", function() { + expect(this.view.page).toBe(1); + }); + + it("sets urlParams to the given value", function() { + expect(this.view.urlParams).toBe("set=all"); + }); }); - describe("search", function() { - it("filters the contacts", function() { + describe("render", function() { + it("calls fetchContacts", function() { + spyOn(this.view, "fetchContacts"); this.view.render(); - expect(this.view.$el.html()).toContain("alice"); - this.view.search("eve"); - expect(this.view.$el.html()).not.toContain("alice"); - expect(this.view.$el.html()).toContain("eve"); + expect(this.view.fetchContacts).toHaveBeenCalled(); }); }); - describe("infScroll", function() { - beforeEach(function() { - this.view.off("renderContacts"); - this.fn = jasmine.createSpy(); - this.view.on("renderContacts", this.fn); - spyOn($.fn, "height").and.returnValue(0); - spyOn($.fn, "scrollTop").and.returnValue(100); + describe("fetchContacts", function() { + it("adds the loading class", function() { + expect(this.view.$el).not.toHaveClass("loading"); + this.view.fetchContacts(); + expect(this.view.$el).toHaveClass("loading"); }); - it("triggers renderContacts when the user is at the bottom of the page", function() { - this.view.infScroll(); - expect(this.fn).toHaveBeenCalled(); + it("displays the loading spinner", function() { + expect($("#paginate .loader")).toHaveClass("hidden"); + this.view.fetchContacts(); + expect($("#paginate .loader")).not.toHaveClass("hidden"); + }); + + it("calls $.ajax with the URL given by _fetchUrl", function() { + spyOn(this.view, "_fetchUrl").and.returnValue("/myAwesomeFetchUrl?foo=bar"); + this.view.fetchContacts(); + expect(jasmine.Ajax.requests.mostRecent().url).toBe("/myAwesomeFetchUrl?foo=bar"); + }); + + it("calls onEmptyResponse on an empty response", function() { + spyOn(this.view, "onEmptyResponse"); + this.view.fetchContacts(); + jasmine.Ajax.requests.mostRecent().respondWith({status: 200, responseText: JSON.stringify([])}); + expect(this.view.onEmptyResponse).toHaveBeenCalled(); + }); + + it("calls appendContactViews on a non-empty response", function() { + spyOn(this.view, "appendContactViews"); + this.view.fetchContacts(); + jasmine.Ajax.requests.mostRecent().respondWith({status: 200, responseText: JSON.stringify(this.contactsData)}); + expect(this.view.appendContactViews).toHaveBeenCalledWith(this.contactsData); + }); + + it("increases the current page on a non-empty response", function() { + this.view.page = 42; + this.view.fetchContacts(); + jasmine.Ajax.requests.mostRecent().respondWith({status: 200, responseText: JSON.stringify(this.contactsData)}); + expect(this.view.page).toBe(43); }); }); - describe("render", function() { - beforeEach(function() { - spyOn(this.view, "renderContacts"); + describe("_fetchUrl", function() { + it("returns the correct URL to fetch contacts", function() { + this.view.page = 15; + this.view.urlParams = undefined; + expect(this.view._fetchUrl()).toBe("/contacts.json?page=15"); }); - it("calls renderContacts", function() { - this.view.render(); - expect(this.view.renderContacts).toHaveBeenCalled(); + it("appends urlParams if those are set", function() { + this.view.page = 23; + expect(this.view._fetchUrl()).toBe("/contacts.json?page=23&set=all"); }); }); - describe("renderContacts", function() { - beforeEach(function() { - this.view.off("renderContacts"); - this.view.renderContacts(); + describe("onEmptyResponse", function() { + context("with an empty collection", function() { + it("adds a 'no contacts' div", function() { + this.view.onEmptyResponse(); + expect(this.view.$("#no_contacts").text().trim()).toBe(Diaspora.I18n.t("contacts.search_no_results")); + }); + + it("hides the loading spinner", function() { + this.view.$el.addClass("loading"); + $("#paginate .loader").removeClass("hidden"); + this.view.onEmptyResponse(); + expect(this.view.$el).not.toHaveClass("loading"); + expect($("#paginate .loader")).toHaveClass("hidden"); + }); + + it("unbinds 'fetchContacts'", function() { + spyOn(this.view, "off"); + this.view.onEmptyResponse(); + expect(this.view.off).toHaveBeenCalledWith("fetchContacts"); + }); + }); + + context("with a non-empty collection", function() { + beforeEach(function() { + this.view.collection.add(factory.contact()); + }); + + it("adds no 'no contacts' div", function() { + this.view.onEmptyResponse(); + expect(this.view.$("#no_contacts").length).toBe(0); + }); + + it("hides the loading spinner", function() { + this.view.$el.addClass("loading"); + $("#paginate .loader").removeClass("hidden"); + this.view.onEmptyResponse(); + expect(this.view.$el).not.toHaveClass("loading"); + expect($("#paginate .loader")).toHaveClass("hidden"); + }); + + it("unbinds 'fetchContacts'", function() { + spyOn(this.view, "off"); + this.view.onEmptyResponse(); + expect(this.view.off).toHaveBeenCalledWith("fetchContacts"); + }); + }); + }); + + describe("appendContactViews", function() { + it("hides the loading spinner", function() { + this.view.$el.addClass("loading"); + $("#paginate .loader").removeClass("hidden"); + this.view.appendContactViews(this.contactsData); + expect(this.view.$el).not.toHaveClass("loading"); + expect($("#paginate .loader")).toHaveClass("hidden"); }); - it("renders perPage contacts", function() { - expect(this.view.$el.find('.stream_element.contact').length).toBe(1); + it("adds all contacts to an empty collection", function() { + expect(this.view.collection.length).toBe(0); + this.view.appendContactViews(this.contactsData); + expect(this.view.collection.length).toBe(this.contactsData.length); + expect(this.view.collection.pluck("id")).toEqual(_.pluck(this.contactsData, "id")); }); - it("renders more contacts when called a second time", function() { - this.view.renderContacts(); - expect(this.view.$el.find('.stream_element.contact').length).toBe(2); + it("appends contacts to an existing collection", function() { + this.view.collection.add(this.contactsData[0]); + expect(this.view.collection.length).toBe(1); + this.view.appendContactViews(_.rest(this.contactsData)); + expect(this.view.collection.length).toBe(this.contactsData.length); + expect(this.view.collection.pluck("id")).toEqual(_.pluck(this.contactsData, "id")); + }); + + it("renders all added contacts", function() { + expect(this.view.$(".stream_element.contact").length).toBe(0); + this.view.appendContactViews(this.contactsData); + expect(this.view.$(".stream_element.contact").length).toBe(this.contactsData.length); + }); + + it("appends contacts to an existing contact list", function() { + this.view.appendContactViews([this.contactsData[0]]); + expect(this.view.$(".stream_element.contact").length).toBe(1); + this.view.appendContactViews(_.rest(this.contactsData)); + expect(this.view.$(".stream_element.contact").length).toBe(this.contactsData.length); + }); + }); + + describe("infScroll", function() { + beforeEach(function() { + this.view.off("fetchContacts"); + this.fn = jasmine.createSpy(); + this.view.on("fetchContacts", this.fn); + spyOn($.fn, "height").and.returnValue(0); + spyOn($.fn, "scrollTop").and.returnValue(100); + }); + + it("triggers fetchContacts when the user is at the bottom of the page", function() { + this.view.infScroll(); + expect(this.fn).toHaveBeenCalled(); }); }); }); diff --git a/spec/javascripts/app/views/contact_view_spec.js b/spec/javascripts/app/views/contact_view_spec.js index b1d400ed16a422c671f3124a0486cadd4d8b66d3..f5f8ba1c5c7c308d8b23c0dbdbec5e87d6c114a4 100644 --- a/spec/javascripts/app/views/contact_view_spec.js +++ b/spec/javascripts/app/views/contact_view_spec.js @@ -5,18 +5,10 @@ describe("app.views.Contact", function(){ this.model = new app.models.Contact({ person_id: 42, - person: { id: 42, name: 'alice' }, + person: { id: 42, name: "alice" }, aspect_memberships: [{id: 23, aspect: this.aspect1}] }); this.view = new app.views.Contact({ model: this.model }); - Diaspora.I18n.load({ - contacts: { - add_contact: "Add contact", - remove_contact: "Remove contact", - error_add: "Couldn't add <%= name %> to the aspect :(", - error_remove: "Couldn't remove <%= name %> from the aspect :(" - } - }); }); context("#presenter", function() { @@ -24,42 +16,57 @@ describe("app.views.Contact", function(){ app.aspect = this.aspect1; expect(this.view.presenter()).toEqual(jasmine.objectContaining({ person_id: 42, - person: jasmine.objectContaining({id: 42, name: 'alice'}), + person: jasmine.objectContaining({id: 42, name: "alice"}), in_aspect: 'in_aspect' })); }); }); - context('add contact to aspect', function() { + context("add contact to aspect", function() { beforeEach(function() { app.aspect = this.aspect2; this.view.render(); - this.button = this.view.$el.find('.contact_add-to-aspect'); - this.contact = this.view.$el.find('.stream_element.contact'); - this.aspect_membership = {id: 42, aspect: app.aspect.toJSON()}; - this.response = JSON.stringify(this.aspect_membership); + this.view.$el.append($("<div id='flash-container'/>")); + app.flashMessages = new app.views.FlashMessages({ el: this.view.$("#flash-container") }); + this.button = this.view.$el.find(".contact_add-to-aspect"); + this.contact = this.view.$el.find(".stream_element.contact"); + this.aspectMembership = {id: 42, aspect: app.aspect.toJSON()}; + this.response = JSON.stringify(this.aspectMembership); }); - it('sends a correct ajax request', function() { - this.button.trigger('click'); + it("sends a correct ajax request", function() { + this.button.trigger("click"); var obj = $.parseJSON(jasmine.Ajax.requests.mostRecent().params); expect(obj.person_id).toBe(this.model.get('person_id')); expect(obj.aspect_id).toBe(app.aspect.get('id')); }); - it('adds a aspect_membership to the contact', function() { - expect(this.model.aspect_memberships.length).toBe(1); - $('.contact_add-to-aspect',this.contact).trigger('click'); + it("adds a aspect_membership to the contact", function() { + expect(this.model.aspectMemberships.length).toBe(1); + $(".contact_add-to-aspect",this.contact).trigger("click"); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, // success + responseText: this.response + }); + expect(this.model.aspectMemberships.length).toBe(2); + }); + + it("triggers aspect_membership:create", function() { + spyOn(app.events, "trigger"); + $(".contact_add-to-aspect", this.contact).trigger("click"); jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, // success responseText: this.response }); - expect(this.model.aspect_memberships.length).toBe(2); + expect(app.events.trigger).toHaveBeenCalledWith("aspect_membership:create", { + membership: {aspectId: app.aspect.get("id"), personId: this.model.get("person_id")}, + startSharing: false + }); }); - it('calls render', function() { - spyOn(this.view, 'render'); - $('.contact_add-to-aspect',this.contact).trigger('click'); + it("calls render", function() { + spyOn(this.view, "render"); + $(".contact_add-to-aspect",this.contact).trigger("click"); jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, // success responseText: this.response @@ -68,50 +75,62 @@ describe("app.views.Contact", function(){ }); - it('displays a flash message on errors', function(){ - $('.contact_add-to-aspect',this.contact).trigger('click'); + it("displays a flash message on errors", function(){ + $(".contact_add-to-aspect",this.contact).trigger("click"); jasmine.Ajax.requests.mostRecent().respondWith({ - status: 400, // fail + status: 400 // fail }); - expect($('[id^="flash"]')).toBeErrorFlashMessage( - Diaspora.I18n.t( - 'contacts.error_add', - {name: this.model.get('person').name} - ) + expect(this.view.$(".flash-message")).toBeErrorFlashMessage( + Diaspora.I18n.t( "contacts.error_add", {name: this.model.get("person").name} ) ); }); }); - context('remove contact from aspect', function() { + context("remove contact from aspect", function() { beforeEach(function() { app.aspect = this.aspect1; this.view.render(); - this.button = this.view.$el.find('.contact_remove-from-aspect'); - this.contact = this.view.$el.find('.stream_element.contact'); - this.aspect_membership = this.model.aspect_memberships.first().toJSON(); - this.response = JSON.stringify(this.aspect_membership); + this.view.$el.append($("<div id='flash-container'/>")); + app.flashMessages = new app.views.FlashMessages({ el: this.view.$("#flash-container") }); + this.button = this.view.$el.find(".contact_remove-from-aspect"); + this.contact = this.view.$el.find(".stream_element.contact"); + this.aspectMembership = this.model.aspectMemberships.first().toJSON(); + this.response = JSON.stringify(this.aspectMembership); }); - it('sends a correct ajax request', function() { - $('.contact_remove-from-aspect',this.contact).trigger('click'); + it("sends a correct ajax request", function() { + $(".contact_remove-from-aspect",this.contact).trigger("click"); expect(jasmine.Ajax.requests.mostRecent().url).toBe( - "/aspect_memberships/"+this.aspect_membership.id + "/aspect_memberships/"+this.aspectMembership.id ); }); - it('removes the aspect_membership from the contact', function() { - expect(this.model.aspect_memberships.length).toBe(1); - $('.contact_remove-from-aspect',this.contact).trigger('click'); + it("removes the aspect_membership from the contact", function() { + expect(this.model.aspectMemberships.length).toBe(1); + $(".contact_remove-from-aspect",this.contact).trigger("click"); jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, // success responseText: this.response }); - expect(this.model.aspect_memberships.length).toBe(0); + expect(this.model.aspectMemberships.length).toBe(0); + }); + + it("triggers aspect_membership:destroy", function() { + spyOn(app.events, "trigger"); + $(".contact_remove-from-aspect", this.contact).trigger("click"); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, // success + responseText: this.response + }); + expect(app.events.trigger).toHaveBeenCalledWith("aspect_membership:destroy", { + membership: {aspectId: app.aspect.get("id"), personId: this.model.get("person_id")}, + stopSharing: true + }); }); - it('calls render', function() { - spyOn(this.view, 'render'); - $('.contact_remove-from-aspect',this.contact).trigger('click'); + it("calls render", function() { + spyOn(this.view, "render"); + $(".contact_remove-from-aspect",this.contact).trigger("click"); jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, // success responseText: this.response, @@ -119,16 +138,13 @@ describe("app.views.Contact", function(){ expect(this.view.render).toHaveBeenCalled(); }); - it('displays a flash message on errors', function(){ - $('.contact_remove-from-aspect',this.contact).trigger('click'); + it("displays a flash message on errors", function(){ + $(".contact_remove-from-aspect",this.contact).trigger("click"); jasmine.Ajax.requests.mostRecent().respondWith({ - status: 400, // fail + status: 400 // fail }); - expect($('[id^="flash"]')).toBeErrorFlashMessage( - Diaspora.I18n.t( - 'contacts.error_remove', - {name: this.model.get('person').name} - ) + expect(this.view.$(".flash-message")).toBeErrorFlashMessage( + Diaspora.I18n.t( "contacts.error_remove", {name: this.model.get("person").name}) ); }); }); diff --git a/spec/javascripts/app/views/content_view_spec.js b/spec/javascripts/app/views/content_view_spec.js index 6a701aaa363febd992b27bbdb49df57f7f9e6f7d..90fa3c4afb0445adfdec30e3bafece5ae4bfc3bc 100644 --- a/spec/javascripts/app/views/content_view_spec.js +++ b/spec/javascripts/app/views/content_view_spec.js @@ -24,5 +24,10 @@ describe("app.views.Content", function(){ this.post.set({post_type : "Reshare"}); expect(this.view.presenter().isReshare).toBeTruthy(); }); + + it("provides location", function(){ + this.post.set({location : factory.location()}); + expect(this.view.presenter().location).toEqual(factory.location()); + }); }); }); diff --git a/spec/javascripts/app/views/conversations_view_spec.js b/spec/javascripts/app/views/conversations_view_spec.js index 44abb502274e0452f5948767bf0acfc35015eb3c..ae5d62e103d48c9c4406ed7ada695a2dccb4a697 100644 --- a/spec/javascripts/app/views/conversations_view_spec.js +++ b/spec/javascripts/app/views/conversations_view_spec.js @@ -4,8 +4,8 @@ describe("app.views.Conversations", function(){ beforeEach(function() { spec.loadFixture("conversations_unread"); // select second conversation that is still unread - $(".conversation-wrapper > .conversation.selected").removeClass("selected") - $(".conversation-wrapper > .conversation.unread").addClass("selected") + $(".conversation-wrapper > .conversation.selected").removeClass("selected"); + $(".conversation-wrapper > .conversation.unread").addClass("selected"); }); it("removes the unread class from the conversation", function() { @@ -15,28 +15,28 @@ describe("app.views.Conversations", function(){ }); it("removes the unread message counter from the conversation", function() { - expect($(".conversation-wrapper > .conversation.selected .unread_message_count").length).toEqual(1); + expect($(".conversation-wrapper > .conversation.selected .unread-message-count").length).toEqual(1); new app.views.Conversations(); - expect($(".conversation-wrapper > .conversation.selected .unread_message_count").length).toEqual(0); + expect($(".conversation-wrapper > .conversation.selected .unread-message-count").length).toEqual(0); }); it("decreases the unread message count in the header", function() { - var badge = "<div id=\"conversations_badge\"><div class=\"badge_count\">3</div></div>"; + var badge = "<div id=\"conversations-link\"><div class=\"badge\">3</div></div>"; $("header").append(badge); - expect($("#conversations_badge .badge_count").text().trim()).toEqual("3"); - expect($(".conversation-wrapper > .conversation .unread_message_count").text().trim()).toEqual("1"); + expect($("#conversations-link .badge").text().trim()).toEqual("3"); + expect($(".conversation-wrapper > .conversation .unread-message-count").text().trim()).toEqual("1"); new app.views.Conversations(); - expect($("#conversations_badge .badge_count").text().trim()).toEqual("2"); + expect($("#conversations-link .badge").text().trim()).toEqual("2"); }); - it("removes the badge_count in the header if there are no unread messages left", function() { - var badge = "<div id=\"conversations_badge\"><div class=\"badge_count\">1</div></div>"; + it("removes the badge in the header if there are no unread messages left", function() { + var badge = "<div id=\"conversations-link\"><div class=\"badge\">1</div></div>"; $("header").append(badge); - expect($("#conversations_badge .badge_count").text().trim()).toEqual("1"); - expect($(".conversation-wrapper > .conversation.selected .unread_message_count").text().trim()).toEqual("1"); + expect($("#conversations-link .badge").text().trim()).toEqual("1"); + expect($(".conversation-wrapper > .conversation.selected .unread-message-count").text().trim()).toEqual("1"); new app.views.Conversations(); - expect($("#conversations_badge .badge_count").text().trim()).toEqual("0"); - expect($("#conversations_badge .badge_count")).toHaveClass("hidden"); + expect($("#conversations-link .badge").text().trim()).toEqual("0"); + expect($("#conversations-link .badge")).toHaveClass("hidden"); }); }); @@ -45,12 +45,12 @@ describe("app.views.Conversations", function(){ spec.loadFixture("conversations_read"); }); - it("does not change the badge_count in the header", function() { - var badge = "<div id=\"conversations_badge\"><div class=\"badge_count\">3</div></div>"; + it("does not change the badge in the header", function() { + var badge = "<div id=\"conversations-link\"><div class=\"badge\">3</div></div>"; $("header").append(badge); - expect($("#conversations_badge .badge_count").text().trim()).toEqual("3"); + expect($("#conversations-link .badge").text().trim()).toEqual("3"); new app.views.Conversations(); - expect($("#conversations_badge .badge_count").text().trim()).toEqual("3"); + expect($("#conversations-link .badge").text().trim()).toEqual("3"); }); }); }); @@ -64,14 +64,14 @@ describe("app.views.Conversations", function(){ it("should submit the form with ctrl+enter", function(){ $("form#new_message").submit(this.submitCallback); - var e = $.Event("keydown", { keyCode: 13, ctrlKey: true }); + var e = $.Event("keydown", { which: Keycodes.ENTER, ctrlKey: true }); $("textarea#message_text").trigger(e); expect(this.submitCallback).toHaveBeenCalled(); }); it("shouldn't submit the form without the ctrl key", function(){ $("form#new_message").submit(this.submitCallback); - var e = $.Event("keydown", { keyCode: 13, ctrlKey: false }); + var e = $.Event("keydown", { which: Keycodes.ENTER, ctrlKey: false }); $("textarea#message_text").trigger(e); expect(this.submitCallback).not.toHaveBeenCalled(); }); diff --git a/spec/javascripts/app/views/feedback_view_spec.js b/spec/javascripts/app/views/feedback_view_spec.js index 18f093fe6475ab597cc55a5094082fb0a6224ab6..fa69641e01526ca785c9604f92c3da5f10fa9847 100644 --- a/spec/javascripts/app/views/feedback_view_spec.js +++ b/spec/javascripts/app/views/feedback_view_spec.js @@ -2,14 +2,6 @@ describe("app.views.Feedback", function(){ beforeEach(function(){ this.userAttrs = _.extend(factory.userAttrs(), {guid : -1}); loginAs(this.userAttrs); - - Diaspora.I18n.load({stream : { - 'like' : "Like", - 'unlike' : "Unlike", - 'public' : "Public", - 'limited' : "Limted" - }}); - var posts = $.parseJSON(spec.readFixture("stream_json")); this.post = new app.models.Post(posts[0]); diff --git a/spec/javascripts/app/views/flash_messages_view-spec.js b/spec/javascripts/app/views/flash_messages_view-spec.js new file mode 100644 index 0000000000000000000000000000000000000000..bcae20b2c0d98839f22771bbdbfe23d802f6558d --- /dev/null +++ b/spec/javascripts/app/views/flash_messages_view-spec.js @@ -0,0 +1,33 @@ +describe("app.views.FlashMessages", function(){ + var flashMessages = new app.views.FlashMessages(); + + describe("flash", function(){ + it("call _flash with correct parameters", function() { + spyOn(flashMessages, "_flash"); + flashMessages.success("success!"); + expect(flashMessages._flash).toHaveBeenCalledWith("success!", false); + flashMessages.error("error!"); + expect(flashMessages._flash).toHaveBeenCalledWith("error!", true); + }); + }); + + describe("render", function(){ + beforeEach(function(){ + spec.content().html("<div class='flash-container'/>"); + flashMessages = new app.views.FlashMessages({ el: $(".flash-container") }); + }); + + it("renders a success message", function(){ + flashMessages.success("success!"); + expect(flashMessages.$(".flash-body")).toHaveClass("expose"); + expect($(".flash-message")).toHaveClass("alert-success"); + expect($(".flash-message").text().trim()).toBe("success!"); + }); + it("renders an error message", function(){ + flashMessages.error("error!"); + expect(flashMessages.$(".flash-body")).toHaveClass("expose"); + expect($(".flash-message")).toHaveClass("alert-danger"); + expect($(".flash-message").text().trim()).toBe("error!"); + }); + }); +}); diff --git a/spec/javascripts/app/views/header_view_spec.js b/spec/javascripts/app/views/header_view_spec.js index 384c92a5929f0db8c5ca6d3f875dc113f828cc6a..0850935e8b638d2dc2b71505b28538a4880a5bd0 100644 --- a/spec/javascripts/app/views/header_view_spec.js +++ b/spec/javascripts/app/views/header_view_spec.js @@ -1,10 +1,11 @@ describe("app.views.Header", function() { beforeEach(function() { - this.userAttrs = {name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}; + this.userAttrs = {name: "alice", avatar: {small: "http://avatar.com/photo.jpg"}, guid: "foo" }; loginAs(this.userAttrs); spec.loadFixture("aspects_index"); + gon.appConfig = {settings: {podname: "MyPod"}}; this.view = new app.views.Header().render(); }); @@ -13,14 +14,14 @@ describe("app.views.Header", function() { it("displays a count when the current user has a notification", function(){ loginAs(_.extend(this.userAttrs, {notifications_count : 1})); this.view.render(); - expect(this.view.$("#notification_badge .badge_count").hasClass('hidden')).toBe(false); - expect(this.view.$("#notification_badge .badge_count").text()).toContain("1"); + expect(this.view.$(".notifications-link .badge").hasClass("hidden")).toBe(false); + expect(this.view.$(".notifications-link .badge").text()).toContain("1"); }); it("does not display a count when the current user has a notification", function(){ loginAs(_.extend(this.userAttrs, {notifications_count : 0})); this.view.render(); - expect(this.view.$("#notification_badge .badge_count").hasClass('hidden')).toBe(true); + expect(this.view.$(".notifications-link .badge").hasClass("hidden")).toBe(true); }); }); @@ -28,14 +29,14 @@ describe("app.views.Header", function() { it("displays a count when the current user has a notification", function(){ loginAs(_.extend(this.userAttrs, {unread_messages_count : 1})); this.view.render(); - expect(this.view.$("#conversations_badge .badge_count").hasClass('hidden')).toBe(false); - expect(this.view.$("#conversations_badge .badge_count").text()).toContain("1"); + expect(this.view.$("#conversations-link .badge").hasClass("hidden")).toBe(false); + expect(this.view.$("#conversations-link .badge").text()).toContain("1"); }); it("does not display a count when the current user has a notification", function(){ loginAs(_.extend(this.userAttrs, {unread_messages_count : 0})); this.view.render(); - expect(this.view.$("#conversations_badge .badge_count").hasClass('hidden')).toBe(true); + expect(this.view.$("#conversations-link .badge").hasClass("hidden")).toBe(true); }); }); @@ -53,54 +54,4 @@ describe("app.views.Header", function() { }); }); }); - - describe("#toggleUserDropdown", function() { - it("adds the class 'active'", function() { - expect(this.view.$(".dropdown")).not.toHaveClass("active"); - this.view.toggleUserDropdown($.Event()); - expect(this.view.$(".dropdown")).toHaveClass("active"); - }); - }); - - describe("#hideUserDropdown", function() { - it("removes the class 'active' if the user clicks anywhere that isn't the menu element", function() { - this.view.toggleUserDropdown($.Event()); - expect(this.view.$(".dropdown")).toHaveClass("active"); - - this.view.hideUserDropdown($.Event()); - expect(this.view.$(".dropdown")).not.toHaveClass("active"); - }); - }); - - - describe("search", function() { - var input; - - beforeEach(function() { - $('#jasmine_content').html(this.view.el); - input = $(this.view.el).find('#q'); - }); - - describe("focus", function() { - beforeEach(function(done){ - input.trigger('focusin'); - done(); - }); - - it("adds the class 'active' when the user focuses the text field", function() { - expect(input).toHaveClass("active"); - }); - }); - - describe("blur", function() { - beforeEach(function(done) { - input.trigger('focusin').trigger('focusout'); - done(); - }); - - it("removes the class 'active' when the user blurs the text field", function() { - expect(input).not.toHaveClass("active"); - }); - }); - }); }); diff --git a/spec/javascripts/app/views/help_view_spec.js b/spec/javascripts/app/views/help_view_spec.js index 7a2555a3f2c23729e85fa91b8021de4906fbb8e4..098e7dfcc8ac8f2d9bb35e55dc909728ee59275c 100644 --- a/spec/javascripts/app/views/help_view_spec.js +++ b/spec/javascripts/app/views/help_view_spec.js @@ -1,10 +1,9 @@ describe("app.views.Help", function(){ beforeEach(function(){ + gon.appConfig = {chat: {enabled: false}}; + this.locale = JSON.parse(spec.readFixture("locale_en_help_json")); + Diaspora.I18n.load(this.locale, "en"); this.view = new app.views.Help(); - }); - - beforeEach(function(){ - Diaspora.I18n.load({"tutorials":"tutorials","tutorial":"tutorial","irc":"IRC","wiki":"wiki","markdown":"Markdown","here":"here","foundation_website":"diaspora foundation website","third_party_tools":"third party tools","getting_started_tutorial":"'Getting started' tutorial series","getting_help":{"title":"Getting help","getting_started_q":"Help! I need some basic help to get me started!","getting_started_a":"You're in luck. Try the %{tutorial_series} on our project site. It will take you step-by-step through the registration process and teach you all the basic things you need to know about using diaspora*.","get_support_q":"What if my question is not answered in this FAQ? Where else can I get support?","get_support_a_website":"visit our %{link}","get_support_a_tutorials":"check out our %{tutorials}","get_support_a_wiki":"search the %{link}","get_support_a_irc":"join us on %{irc} (Live chat)","get_support_a_hashtag":"ask in a public post on diaspora* using the %{question} hashtag"},"account_and_data_management":{"title":"Account and data management","move_pods_q":"How do I move my seed (account) from one pod to another?","move_pods_a":"In the future you will be able to export your seed from a pod and import it on another, but this is not currently possible. You could always open a new account and add your contacts to aspects on that new seed, and ask them to add your new seed to their aspects.","download_data_q":"Can I download a copy of all of my data contained in my seed (account)?","download_data_a":"Yes. At the bottom of the Account tab of your settings page there are two buttons for downloading your data.","close_account_q":"How do I delete my seed (account)?","close_account_a":"Go to the bottom of your settings page and click the Close Account button.","data_visible_to_podmin_q":"How much of my information can my pod administrator see?","data_visible_to_podmin_a":"Communication *between* pods is always encrypted (using SSL and diaspora*'s own transport encryption), but the storage of data on pods is not encrypted. If they wanted to, the database administrator for your pod (usually the person running the pod) could access all your profile data and everything that you post (as is the case for most websites that store user data). Running your own pod provides more privacy since you then control access to the database.","data_other_podmins_q":"Can the administrators of other pods see my information?","data_other_podmins_a":"Once you are sharing with someone on another pod, any posts you share with them and a copy of your profile data are stored (cached) on their pod, and are accessible to that pod's database administrator. When you delete a post or profile data it is deleted from your pod and any other pods where it had previously been stored."},"aspects":{"title":"Aspects","what_is_an_aspect_q":"What is an aspect?","what_is_an_aspect_a":"Aspects are the way you group your contacts on diaspora*. An aspect is one of the faces you show to the world. It might be who you are at work, or who you are to your family, or who you are to your friends in a club you belong to.","who_sees_post_q":"When I post to an aspect, who sees it?","who_sees_post_a":"If you make a limited post, it will only be visible the people you have put in that aspect (or those aspects, if it is made to multiple aspects). Contacts you have that aren't in the aspect have no way of seeing the post, unless you've made it public. Only public posts will ever be visible to anyone who you haven't placed into one of your aspects.","restrict_posts_i_see_q":"Can I restrict the posts I see to just those from certain aspects?","restrict_posts_i_see_a":"Yes. Click on My Aspects in the side-bar and then click individual aspects in the list to select or deselect them. Only the posts by people in the selected aspects will appear in your stream.","contacts_know_aspect_q":"Do my contacts know which aspects I have put them in?","contacts_know_aspect_a":"No. They cannot see the name of the aspect under any circumstances.","contacts_visible_q":"What does \"make contacts in this aspect visible to each other\" mean?","contacts_visible_a":"If you check this option then contacts from that aspect will be able to see who else is in it, on your profile page under your picture. It's best to select this option only if the contacts in that aspect all know each other. They still won't be able to see what the aspect is called.","remove_notification_q":"If I remove someone from an aspect, or all of my aspects, are they notified of this?","remove_notification_a":"No.","rename_aspect_q":"Can I rename an aspect?","rename_aspect_a":"Yes. In your list of aspects on the left side of the main page, point your mouse at the aspect you want to rename. Click the little 'edit' pencil that appears to the right. Click rename in the box that appears.","change_aspect_of_post_q":"Once I have posted something, can I change the aspect(s) that can see it?","change_aspect_of_post_a":"No, but you can always make a new post with the same content and post it to a different aspect.","post_multiple_aspects_q":"Can I post content to multiple aspects at once?","post_multiple_aspects_a":"Yes. When you are making a post, use the aspect selector button to select or deselect aspects. Your post will be visible to all the aspects you select. You could also select the aspects you want to post to in the side-bar. When you post, the aspect(s) that you have selected in the list on the left will automatically be selected in the aspect selector when you start to make a new post.","person_multiple_aspects_q":"Can I add a person to multiple aspects?","person_multiple_aspects_a":"Yes. Go to your contacts page and click my contacts. For each contact you can use the menu on the right to add them to (or remove them from) as many aspects as you want. Or you can add them to a new aspect (or remove them from an aspect) by clicking the aspect selector button on their profile page. Or you can even just move the pointer over their name where you see it in the stream, and a 'hover-card' will appear. You can change the aspects they are in right there.","delete_aspect_q":"How do I delete an aspect?","delete_aspect_a":"In your list of aspects on the left side of the main page, point your mouse at the aspect you want to delete. Click the little 'edit' pencil that appears on the right. Click the delete button in the box that appears."},"mentions":{"title":"Mentions","what_is_a_mention_q":"What is a \"mention\"?","what_is_a_mention_a":"A mention is a link to a person's profile page that appears in a post. When someone is mentioned they receive a notification that calls their attention to the post.","how_to_mention_q":"How do I mention someone when making a post?","how_to_mention_a":"Type the \"@\" sign and start typing their name. A drop down menu should appear to let you select them more easily. Note that it is only possible to mention people you have added to an aspect.","mention_in_comment_q":"Can I mention someone in a comment?","mention_in_comment_a":"No, not currently.","see_mentions_q":"Is there a way to see the posts in which I have been mentioned?","see_mentions_a":"Yes, click \"Mentions\" in the left hand column on your home page."},"pods":{"title":"Pods","what_is_a_pod_q":"What is a pod?","what_is_a_pod_a":"A pod is a server running the diaspora* software and connected to the diaspora* network. \"Pod\" is a metaphor referring to pods on plants which contain seeds, in the way that a server contains a number of user accounts. There are many different pods. You can add friends from other pods and communicate with them. (You can think of a diaspora* pod as similar to an email provider: there are public pods, private pods, and with some effort you can even run your own).","find_people_q":"I just joined a pod, how can I find people to share with?","find_people_a":"Invite your friends using the email link in the side-bar. Follow #tags to discover others who share your interests, and add those who post things that interest you to an aspect. Shout out that you're #newhere in a public post.","use_search_box_q":"How do I use the search box to find particular individuals?","use_search_box_a":"If you know their full diaspora* ID (e.g. username@podname.org), you can find them by searching for it. If you are on the same pod you can search for just their username. An alternative is to search for them by their profile name (the name you see on screen). If a search does not work the first time, try it again."},"posts_and_posting":{"title":"Posts and posting","hide_posts_q":"How do I hide a post? / How do I stop getting notifications about a post that I commented on?","hide_posts_a":"If you point your mouse at the top of a post, an X appears on the right. Click it to hide the post and mute notifications about it. You can still see the post if you visit the profile page of the person who posted it.","format_text_q":"How can I format the text in my posts (bold, italics, etc.)?","format_text_a":"By using a simplified system called %{markdown}. You can find the full Markdown syntax %{here}. The preview button is really helpful here, as you can see how your message will look before you share it.","insert_images_q":"How do I insert images into posts?","insert_images_a":"Click the little camera icon to insert an image into a post. Press the photo icon again to add another photo, or you can select multiple photos to upload in one go.","insert_images_comments_q":"Can I insert images into comments?","insert_images_comments_a1":"The following Markdown code","image_text":"image text","image_url":"image url","insert_images_comments_a2":"can be used to insert images from the web into comments as well as posts.","size_of_images_q":"Can I customize the size of images in posts or comments?","size_of_images_a":"No. Images are resized automatically to fit the stream. Markdown does not have a code for specifying the size of an image.","embed_multimedia_q":"How do I embed a video, audio, or other multimedia content into a post?","embed_multimedia_a":"You can usually just paste the URL (e.g. http://www.youtube.com/watch?v=nnnnnnnnnnn ) into your post and the video or audio will be embedded automatically. Some of the sites that are supported are: YouTube, Vimeo, SoundCloud, Flickr and a few more. diaspora* uses oEmbed for this feature. We're supporting new sites all the time. Remember to always post simple, full links: no shortened links; no operators after the base URL; and give it a little time before you refresh the page after posting for seeing the preview.","character_limit_q":"What is the character limit for posts?","character_limit_a":"65,535 characters. That's 65,395 more characters than you get on Twitter! ;)","char_limit_services_q":"What is the character limit for posts shared through a connected service with a smaller character count?","char_limit_services_a":"In that case your post is limited to the smaller character count (140 in the case of Twitter; 1000 in the case of Tumblr), and the number of characters you have left to use is displayed when that service's icon is highlighted. You can still post to these services if your post is longer than their limit, but the text is truncated on those services.","stream_full_of_posts_q":"Why is my stream full of posts from people I don't know and don't share with?","stream_full_of_posts_a1":"Your stream is made up of three types of posts:","stream_full_of_posts_li1":"Posts by people you are sharing with, which come in two types: public posts and limited posts shared with an aspect that you are part of. To remove these posts from your stream, simply stop sharing with the person.","stream_full_of_posts_li2":"Public posts containing one of the tags that you follow. To remove these, stop following the tag.","stream_full_of_posts_li3":"Public posts by people listed in the Community Spotlight. These can be removed by unchecking the “Show Community Spotlight in Stream?†option in the Account tab of your Settings."},"private_posts":{"title":"Private posts","who_sees_post_q":"When I post a message to an aspect (i.e., a private post), who can see it?","who_sees_post_a":"Only logged-in diaspora* users you have placed in that aspect can see your private post.","can_comment_q":"Who can comment on or like my private post?","can_comment_a":"Only logged-in diaspora* users you have placed in that aspect can comment on or like your private post.","can_reshare_q":"Who can reshare my private post?","can_reshare_a":"Nobody. Private posts are not resharable. Logged-in diaspora* users in that aspect can potentially copy and paste it, however.","see_comment_q":"When I comment on or like a private post, who can see it?","see_comment_a":"Only the people that the post was shared with (the people who are in the aspects selected by the original poster) can see its comments and likes. "},"private_profiles":{"title":"Private profiles","who_sees_profile_q":"Who sees my private profile?","who_sees_profile_a":"Any logged-in user that you are sharing with (meaning, you have added them to one of your aspects). However, people following you, but whom you do not follow, will see only your public information.","whats_in_profile_q":"What's in my private profile?","whats_in_profile_a":"Biography, location, gender, and birthday. It's the stuff in the bottom section of the edit profile page. All this information is optional – it's up to you whether you fill it in. Logged-in users who you have added to your aspects are the only people who can see your private profile. They will also see the private posts that made to the aspect(s) they are in, mixed in with your public posts, when they visit your profile page.","who_sees_updates_q":"Who sees updates to my private profile?","who_sees_updates_a":"Anyone in your aspects sees changes to your private profile. "},"public_posts":{"title":"Public posts","who_sees_post_q":"When I post something publicly, who can see it?","who_sees_post_a":"Anyone using the internet can potentially see a post you mark public, so make sure you really do want your post to be public. It's a great way of reaching out to the world.","find_public_post_q":"How can other people find my public post?","find_public_post_a":"Your public posts will appear in the streams of anyone following you. If you included #tags in your public post, anyone following those tags will find your post in their streams. Every public post also has a specific URL that anyone can view, even if they're not logged in - thus public posts may be linked to directly from Twitter, blogs, etc. Public posts may also be indexed by search engines.","can_comment_reshare_like_q":"Who can comment on, reshare, or like my public post?","can_comment_reshare_like_a":"Any logged-in diaspora* user can comment on, reshare, or like your public post.","see_comment_reshare_like_q":"When I comment on, reshare, or like a public post, who can see it?","see_comment_reshare_like_a":"Any logged-in diaspora* user and anyone else on the internet. Comments, likes, and reshares of public posts are also public.","deselect_aspect_posting_q":"What happens when I deselect one or more aspects when making a public post?","deselect_aspect_posting_a":"Deselecting aspects does not affect a public post. It will still appear in the streams of all of your contacts. To make a post visible only to specific aspects, you need to select those aspects from the button under the publisher."},"public_profiles":{"title":"Public profiles","who_sees_profile_q":"Who sees my public profile?","who_sees_profile_a":"Any logged-in diaspora* user, as well as the wider internet, can see it. Each profile has a direct URL, so it may be linked to directly from outside sites. It may be indexed by search engines.","whats_in_profile_q":"What's in my public profile","whats_in_profile_a":"Your name, the five tags you chose to describe yourself, and your photo. It's the stuff in the top section of the edit profile page. You can make this profile information as identifiable or anonymous as you like. Your profile page also shows any public posts you have made.","who_sees_updates_q":"Who sees updates to my public profile?","who_sees_updates_a":"Anyone can see changes if they visit your profile page.","what_do_tags_do_q":"What do the tags on my public profile do?","what_do_tags_do_a":"They help people get to know you. Your profile picture will also appear on the left-hand side of those particular tag pages, along with anyone else who has them in their public profile."},"resharing_posts":{"title":"Resharing posts","reshare_public_post_aspects_q":"Can I reshare a public post with only certain aspects?","reshare_public_post_aspects_a":"No, when you reshare a public post it automatically becomes one of your public posts. To share it with certain aspects, copy and paste the contents of the post into a new post.","reshare_private_post_aspects_q":"Can I reshare a private post with only certain aspects?","reshare_private_post_aspects_a":"No, it is not possible to reshare a private post. This is to respect the intentions of the original poster who only shared it with a particular group of people."},"sharing":{"title":"Sharing","add_to_aspect_q":"What happens when I add someone to one of my aspects? Or when someone adds me to one of their aspects?","add_to_aspect_a1":"Let's say that Amy adds Ben to an aspect, but Ben has not (yet) added Amy to an aspect:","add_to_aspect_li1":"Ben will receive a notification that Amy has \"started sharing\" with Ben.","add_to_aspect_li2":"Amy will start to see Ben's public posts in her stream.","add_to_aspect_li3":"Amy will not see any of Ben's private posts.","add_to_aspect_li4":"Ben will not see Amy's public or private posts in his stream.","add_to_aspect_li5":"But if Ben goes to Amy's profile page, then he will see Amy's private posts that she makes to her aspect that has him in it (as well as her public posts which anyone can see there).","add_to_aspect_li6":"Ben will be able to see Amy's private profile (bio, location, gender, birthday).","add_to_aspect_li7":"Amy will appear under \"Only sharing with me\" on Ben's contacts page.","add_to_aspect_a2":"This is known as asymmetrical sharing. If and when Ben also adds Amy to an aspect then it would become mutual sharing, with both Amy's and Ben's public posts and relevant private posts appearing in each other's streams, etc. ","only_sharing_q":"Who are the people listed in \"Only sharing with me\" on my contacts page?","only_sharing_a":"These are people that have added you to one of their aspects, but who are not (yet) in any of your aspects. In other words, they are sharing with you, but you are not sharing with them (asymmetrical sharing). If you add them to an aspect, they will then appear under that aspect and not under \"only sharing with you\". See above.","list_not_sharing_q":"Is there a list of people whom I have added to one of my aspects, but who have not added me to one of theirs?","list_not_sharing_a":"No, but you can see whether or not someone is sharing with you by visiting their profile page. If they are, the bar under their profile picture will be green; if not, it'll be grey. You should get a notification each time someone starts sharing with you.","see_old_posts_q":"When I add someone to an aspect, can they see older posts that I have already posted to that aspect?","see_old_posts_a":"No. They will only be able to see new posts to that aspect. They (and everyone else) can see your older public posts on your profile page, and they may also see them in their stream."},"tags":{"title":"Tags","what_are_tags_for_q":"What are tags for?","what_are_tags_for_a":"Tags are a way to categorize a post, usually by topic. Searching for a tag shows all posts with that tag that you can see (both public and private posts). This lets people who are interested in a given topic find public posts about it.","tags_in_comments_q":"Can I put tags in comments or just in posts?","tags_in_comments_a":"A tag added to a comment will still appear as a link to that tag's page, but it will not make that post (or comment) appear on that tag page. This only works for tags in posts.","followed_tags_q":"What are \"#Followed Tags\" and how do I follow a tag?","followed_tags_a":"After searching for a tag you can click the button at the top of the tag's page to \"follow\" that tag. It will then appear in your list of followed tags on the left. Clicking one of your followed tags takes you to that tag's page so you can see recent posts containing that tag. Click on #Followed Tags to see a stream of posts that include one of any of your followed tags. ","people_tag_page_q":"Who are the people listed on the left-hand side of a tag page?","people_tag_page_a":"They are people who have listed that tag to describe themselves in their public profile.","filter_tags_q":"How can I filter/exclude some tags from my stream?","filter_tags_a":"This is not yet available directly through diaspora*, but some %{third_party_tools} have been written that might provide this."},"miscellaneous":{"title":"Miscellaneous","back_to_top_q":"Is there a quick way to go back to the top of a page after I scroll down?","back_to_top_a":"Yes. After scrolling down a page, click on the grey arrow that appears in the bottom right corner of your browser window.","photo_albums_q":"Are there photo or video albums?","photo_albums_a":"No, not currently. However you can view a stream of their uploaded pictures from the Photos section in the side-bar of their profile page.","subscribe_feed_q":"Can I subscribe to someone's public posts with a feed reader?","subscribe_feed_a":"Yes, but this is still not a polished feature and the formatting of the results is still pretty rough. If you want to try it anyway, go to someone's profile page and click the feed button in your browser, or you can copy the profile URL (i.e. https://joindiaspora.com/people/somenumber), and paste it into a feed reader. The resulting feed address looks like this: https://joindiaspora.com/public/username.atom Diaspora uses Atom rather than RSS.","diaspora_app_q":"Is there a diaspora* app for Android or iOS?","diaspora_app_a":"There are several Android apps in very early development. Several are long-abandoned projects and so do not work well with the current version of diaspora*. Don't expect much from these apps at the moment. Currently the best way to access diaspora* from your mobile device is through a browser, because we've designed a mobile version of the site which should work well on all devices. There is currently no app for iOS. Again, diaspora* should work fine via your browser."}}, "en"); Diaspora.Page = "HelpFaq"; }); @@ -138,7 +137,7 @@ describe("app.views.Help", function(){ describe("chat section", function(){ describe("chat enabled", function(){ beforeEach(function(){ - gon.chatEnabled = true; + gon.appConfig = {chat: {enabled: true}}; this.view = new app.views.Help(); this.view.render(); }); @@ -150,7 +149,7 @@ describe("app.views.Help", function(){ describe("chat disabled", function(){ beforeEach(function(){ - gon.chatEnabled = false; + gon.appConfig = {chat: {enabled: false}}; this.view = new app.views.Help(); this.view.render(); }); diff --git a/spec/javascripts/app/views/hovercard_view_spec.js b/spec/javascripts/app/views/hovercard_view_spec.js index 6f7e4c26097b522a445b6d07e91d64c1908a0849..1bcbe8444481ccff13287b4ef8ef6a3056740eaf 100644 --- a/spec/javascripts/app/views/hovercard_view_spec.js +++ b/spec/javascripts/app/views/hovercard_view_spec.js @@ -1,16 +1,24 @@ describe("app.views.Hovercard", function() { + + afterEach(function() { + $("body #hovercard_container").remove(); + }); + context("user not signed in", function() { beforeEach(function() { logout(); this.view = new app.views.Hovercard(); }); - describe("_populateHovercardWith", function() { - it("doesn't fetch the aspect dropdown", function() { - spyOn(jQuery, "ajax").and.callThrough(); + describe("_populateHovercard", function() { + it("doesn't create the aspect dropdown", function() { this.view.parent = spec.content(); - this.view._populateHovercardWith({}); - expect(jQuery.ajax).not.toHaveBeenCalled(); + this.view._populateHovercard(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: JSON.stringify({id: 1337}) + }); + expect(this.view.aspectMembershipDropdown).toEqual(undefined); }); }); }); @@ -40,17 +48,15 @@ describe("app.views.Hovercard", function() { this.view._populateHovercard(); expect(jQuery.ajax).toHaveBeenCalledWith("undefined/hovercard.json", {preventGlobalErrorHandling: true}); }); - }); - describe("_populateHovercardWith", function() { - it("prevents global error handling for the ajax call", function() { - spyOn(jQuery, "ajax").and.callThrough(); + it("creates the aspect dropdown", function() { this.view.parent = spec.content(); - this.view._populateHovercardWith({}); - expect(jQuery.ajax).toHaveBeenCalledWith( - "undefined/aspect_membership_button", - {preventGlobalErrorHandling: true} - ); + this.view._populateHovercard(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + responseText: JSON.stringify({id: 1337}) + }); + expect(this.view.aspectMembershipDropdown).not.toEqual(undefined); }); }); }); diff --git a/spec/javascripts/app/views/likes_info_view_spec.js b/spec/javascripts/app/views/likes_info_view_spec.js index 9e57f6c631f89e1b3f209d24b01a636f9b96d43e..f0848675d8a5945066db91f2c57e5dddc8e25e1e 100644 --- a/spec/javascripts/app/views/likes_info_view_spec.js +++ b/spec/javascripts/app/views/likes_info_view_spec.js @@ -1,14 +1,6 @@ describe("app.views.LikesInfo", function(){ beforeEach(function(){ loginAs({id : -1, name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); - - Diaspora.I18n.load({stream : { - pins : { - zero : "<%= count %> Pins", - one : "<%= count %> Pin"} - } - }); - var posts = $.parseJSON(spec.readFixture("stream_json")); this.post = new app.models.Post(posts[0]); // post with a like this.view = new app.views.LikesInfo({model: this.post}); @@ -18,7 +10,7 @@ describe("app.views.LikesInfo", function(){ it("displays a the like count if it is above zero", function() { spyOn(this.view.model.interactions, "likesCount").and.returnValue(3); this.view.render(); - expect($(this.view.el).find(".expand_likes").length).toBe(1); + expect($(this.view.el).find(".expand-likes").length).toBe(1); }); it("does not display the like count if it is zero", function() { @@ -44,12 +36,10 @@ describe("app.views.LikesInfo", function(){ expect(this.post.interactions.fetch).toHaveBeenCalled(); }); - it("sets the fetched response to the model's likes", function(){ - //placeholder... not sure how to test done functionalty here - }); - - it("re-renders the view", function(){ - //placeholder... not sure how to test done functionalty here + it("sets 'displayAvatars' to true", function(){ + this.view.displayAvatars = false; + this.view.showAvatars(); + expect(this.view.displayAvatars).toBeTruthy(); }); }); }); diff --git a/spec/javascripts/app/views/location_stream_spec.js b/spec/javascripts/app/views/location_stream_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..ba0d2e2dbcba232cfc188b76130852da0c7346b8 --- /dev/null +++ b/spec/javascripts/app/views/location_stream_spec.js @@ -0,0 +1,45 @@ +describe("app.views.LocationStream", function() { + beforeEach(function(){ + this.post = factory.post(); + this.view = new app.views.LocationStream({model : this.post}); + /* jshint camelcase: false */ + gon.appConfig = {map: { mapbox: {enabled: true, id: "yourID", access_token: "yourAccessToken" }}}; + /* jshint camelcase: true */ + }); + + describe("toggleMap", function() { + context("with location provided", function() { + beforeEach(function(){ + this.post.set({location : factory.location()}); // set location + spec.content().html(this.view.render().el); // loads html element to the page + }); + + it("should contain a map container", function() { + expect(spec.content()).toContainElement(".mapContainer"); + }); + + it("should initialize map", function() { + expect($(".mapContainer")).toHaveClass("empty"); + this.view.toggleMap(); + expect($(".mapContainer")).not.toHaveClass("empty"); + }); + + it("should change display status on every click", function() { + this.view.toggleMap(); + expect($(".mapContainer")).toHaveCss({display: "block"}); + this.view.toggleMap(); + expect($(".mapContainer")).toHaveCss({display: "none"}); + }); + }); + + context("without location provided", function() { + beforeEach(function(){ + spec.content().html(this.view.render().el); + }); + + it("should not initialize the map", function() { + expect(spec.content()).not.toContainElement(".mapContainer"); + }); + }); + }); +}); diff --git a/spec/javascripts/app/views/location_view_spec.js b/spec/javascripts/app/views/locator_spec.js similarity index 96% rename from spec/javascripts/app/views/location_view_spec.js rename to spec/javascripts/app/views/locator_spec.js index 42e04741c27feb797e6e9d33205b60148d7174c9..f600de8b9728cd04cd31030623ac0b99c248ba65 100644 --- a/spec/javascripts/app/views/location_view_spec.js +++ b/spec/javascripts/app/views/locator_spec.js @@ -1,6 +1,5 @@ describe("app.views.Location", function(){ beforeEach(function(){ - OSM = {}; OSM.Locator = function(){return { getAddress:function(){}}}; this.view = new app.views.Location(); diff --git a/spec/javascripts/app/views/no_posts_info_view_spec.js b/spec/javascripts/app/views/no_posts_info_view_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..4dd270342c58b0c154a02945d3f851dde3a976ba --- /dev/null +++ b/spec/javascripts/app/views/no_posts_info_view_spec.js @@ -0,0 +1,11 @@ +describe("app.views.NoPostsInfo", function() { + describe("render", function() { + beforeEach(function() { + this.view = new app.views.NoPostsInfo(); + }); + + it("renders the no posts info message", function() { + expect(this.view.render().$el.text().trim()).toBe(Diaspora.I18n.t("stream.no_posts_yet")); + }); + }); +}); diff --git a/spec/javascripts/app/views/notification_dropdown_view_spec.js b/spec/javascripts/app/views/notification_dropdown_view_spec.js index f6972c5be91bc87a24d6b681ada2d0ed1cc629f4..ec9641030433359d9278c12a8fe2ae203eac4c79 100644 --- a/spec/javascripts/app/views/notification_dropdown_view_spec.js +++ b/spec/javascripts/app/views/notification_dropdown_view_spec.js @@ -1,34 +1,42 @@ -describe('app.views.NotificationDropdown', function() { +describe("app.views.NotificationDropdown", function() { beforeEach(function (){ - spec.loadFixture('notifications'); + spec.loadFixture("notifications"); + gon.appConfig = {settings: {podname: "MyPod"}}; this.header = new app.views.Header(); $("header").prepend(this.header.el); + loginAs({guid: "foo"}); this.header.render(); - this.view = new app.views.NotificationDropdown({el: '#notification_badge'}); + this.view = new app.views.NotificationDropdown({el: "#notification-dropdown"}); }); - context('showDropdown', function(){ - it('Calls resetParam()', function(){ - spyOn(this.view, 'resetParams'); + context("showDropdown", function(){ + it("Calls resetParam()", function(){ + spyOn(this.view, "resetParams"); this.view.showDropdown(); expect(this.view.resetParams).toHaveBeenCalled(); }); - it('Changes CSS', function(){ + it("Calls updateScrollbar()", function(){ + spyOn(this.view, "updateScrollbar"); this.view.showDropdown(); - expect($('#notification_dropdown').css('display')).toBe('block'); + expect(this.view.updateScrollbar).toHaveBeenCalled(); }); - it('Calls getNotifications()', function(){ - spyOn(this.view, 'getNotifications'); + it("Changes CSS", function(){ + expect($("#notification-dropdown")).not.toHaveClass("dropdown-open"); + this.view.showDropdown(); + expect($("#notification-dropdown")).toHaveClass("dropdown-open"); + }); + it("Calls getNotifications()", function(){ + spyOn(this.view, "getNotifications"); this.view.showDropdown(); expect(this.view.getNotifications).toHaveBeenCalled(); }); }); - context('dropdownScroll', function(){ - it('Calls getNotifications if is at the bottom and has more notifications to load', function(){ + context("dropdownScroll", function(){ + it("Calls getNotifications if is at the bottom and has more notifications to load", function(){ this.view.isBottom = function(){ return true; }; this.view.hasMoreNotifs = true; - spyOn(this.view, 'getNotifications'); + spyOn(this.view, "getNotifications"); this.view.dropdownScroll(); expect(this.view.getNotifications).toHaveBeenCalled(); }); @@ -36,7 +44,7 @@ describe('app.views.NotificationDropdown', function() { it("Doesn't call getNotifications if is not at the bottom", function(){ this.view.isBottom = function(){ return false; }; this.view.hasMoreNotifs = true; - spyOn(this.view, 'getNotifications'); + spyOn(this.view, "getNotifications"); this.view.dropdownScroll(); expect(this.view.getNotifications).not.toHaveBeenCalled(); }); @@ -44,64 +52,109 @@ describe('app.views.NotificationDropdown', function() { it("Doesn't call getNotifications if is not at the bottom", function(){ this.view.isBottom = function(){ return true; }; this.view.hasMoreNotifs = false; - spyOn(this.view, 'getNotifications'); + spyOn(this.view, "getNotifications"); this.view.dropdownScroll(); expect(this.view.getNotifications).not.toHaveBeenCalled(); }); }); - context('getNotifications', function(){ - it('Has more notifications', function(){ - var response = ['', '', '', '', '']; - spyOn($, 'getJSON').and.callFake(function(url, callback){ callback(response); }); + context("getNotifications", function(){ + it("Has more notifications", function(){ + var response = ["", "", "", "", ""]; + spyOn($, "getJSON").and.callFake(function(url, callback){ callback(response); }); this.view.getNotifications(); expect(this.view.hasMoreNotifs).toBe(true); }); - it('Has no more notifications', function(){ - spyOn($, 'getJSON').and.callFake(function(url, callback){ callback([]); }); + it("Has no more notifications", function(){ + spyOn($, "getJSON").and.callFake(function(url, callback){ callback([]); }); this.view.getNotifications(); expect(this.view.hasMoreNotifs).toBe(false); }); - it('Correctly sets the next page', function(){ - spyOn($, 'getJSON').and.callFake(function(url, callback){ callback([]); }); - expect(typeof this.view.nextPage).toBe('undefined'); + it("Correctly sets the next page", function(){ + spyOn($, "getJSON").and.callFake(function(url, callback){ callback([]); }); + expect(typeof this.view.nextPage).toBe("undefined"); this.view.getNotifications(); expect(this.view.nextPage).toBe(3); }); - it('Increase the page count', function(){ - var response = ['', '', '', '', '']; - spyOn($, 'getJSON').and.callFake(function(url, callback){ callback(response); }); + it("Increase the page count", function(){ + var response = ["", "", "", "", ""]; + spyOn($, "getJSON").and.callFake(function(url, callback){ callback(response); }); this.view.getNotifications(); expect(this.view.nextPage).toBe(3); this.view.getNotifications(); expect(this.view.nextPage).toBe(4); }); - it('Calls renderNotifications()', function(){ - spyOn($, 'getJSON').and.callFake(function(url, callback){ callback([]); }); - spyOn(this.view, 'renderNotifications'); + it("Calls renderNotifications()", function(){ + spyOn($, "getJSON").and.callFake(function(url, callback){ callback([]); }); + spyOn(this.view, "renderNotifications"); this.view.getNotifications(); expect(this.view.renderNotifications).toHaveBeenCalled(); }); - it('Adds the notifications to this.notifications', function(){ - var response = ['', '', '', '', '']; + it("Adds the notifications to this.notifications", function(){ + var response = ["", "", "", "", ""]; this.view.notifications.length = 0; - spyOn($, 'getJSON').and.callFake(function(url, callback){ callback(response); }); + spyOn($, "getJSON").and.callFake(function(url, callback){ callback(response); }); this.view.getNotifications(); expect(this.view.notifications).toEqual(response); }); }); - context('renderNotifications', function(){ - it('Removes the previous notifications', function(){ - this.view.dropdownNotifications.append('<div class="media stream_element">Notification</div>'); - expect(this.view.dropdownNotifications.find('.media.stream_element').length).toBe(1); + context("renderNotifications", function(){ + it("Removes the previous notifications", function(){ + this.view.dropdownNotifications.append("<div class=\"media stream_element\">Notification</div>"); + expect(this.view.dropdownNotifications.find(".media.stream_element").length).toBe(1); this.view.renderNotifications(); - expect(this.view.dropdownNotifications.find('.media.stream_element').length).toBe(0); + expect(this.view.dropdownNotifications.find(".media.stream_element").length).toBe(0); }); - it('Calls hideAjaxLoader()', function(){ - spyOn(this.view, 'hideAjaxLoader'); + it("Calls hideAjaxLoader()", function(){ + spyOn(this.view, "hideAjaxLoader"); this.view.renderNotifications(); expect(this.view.hideAjaxLoader).toHaveBeenCalled(); }); + it("Calls updateScrollbar()", function(){ + spyOn(this.view, "updateScrollbar"); + this.view.renderNotifications(); + expect(this.view.updateScrollbar).toHaveBeenCalled(); + }); + }); + + context("updateScrollbar", function() { + it("Initializes perfectScrollbar", function(){ + this.view.perfectScrollbarInitialized = false; + spyOn($.fn, "perfectScrollbar"); + this.view.updateScrollbar(); + expect($.fn.perfectScrollbar).toHaveBeenCalledWith(); + expect($.fn.perfectScrollbar.calls.mostRecent().object).toEqual(this.view.dropdownNotifications); + expect(this.view.perfectScrollbarInitialized).toBeTruthy(); + }); + + it("Updates perfectScrollbar", function(){ + this.view.perfectScrollbarInitialized = true; + this.view.dropdownNotifications.perfectScrollbar(); + spyOn($.fn, "perfectScrollbar"); + this.view.updateScrollbar(); + expect($.fn.perfectScrollbar).toHaveBeenCalledWith("update"); + expect($.fn.perfectScrollbar.calls.mostRecent().object).toEqual(this.view.dropdownNotifications); + expect(this.view.perfectScrollbarInitialized).toBeTruthy(); + }); + }); + + context("destroyScrollbar", function() { + it("destroys perfectScrollbar", function(){ + this.view.perfectScrollbarInitialized = true; + this.view.dropdownNotifications.perfectScrollbar(); + spyOn($.fn, "perfectScrollbar"); + this.view.destroyScrollbar(); + expect($.fn.perfectScrollbar).toHaveBeenCalledWith("destroy"); + expect($.fn.perfectScrollbar.calls.mostRecent().object).toEqual(this.view.dropdownNotifications); + expect(this.view.perfectScrollbarInitialized).toBeFalsy(); + }); + + it("doesn't destroy perfectScrollbar if it isn't initialized", function(){ + this.view.perfectScrollbarInitialized = false; + spyOn($.fn, "perfectScrollbar"); + this.view.destroyScrollbar(); + expect($.fn.perfectScrollbar).not.toHaveBeenCalled(); + }); }); }); diff --git a/spec/javascripts/app/views/notifications_view_spec.js b/spec/javascripts/app/views/notifications_view_spec.js index ab422515add221fb9b4c1cff112ee8199b74ea68..8906764785c158506b3b890f463ea8fa5b34cb0b 100644 --- a/spec/javascripts/app/views/notifications_view_spec.js +++ b/spec/javascripts/app/views/notifications_view_spec.js @@ -1,106 +1,173 @@ describe("app.views.Notifications", function(){ - beforeEach(function() { - spec.loadFixture("notifications"); - this.view = new app.views.Notifications({el: '#notifications_container'}); - }); - - context('mark read', function() { + context("on the notifications page", function() { beforeEach(function() { - this.unreadN = $('.stream_element.unread').first(); - this.guid = this.unreadN.data("guid"); + spec.loadFixture("notifications"); + this.view = new app.views.Notifications({el: "#notifications_container"}); }); - it('calls "setRead"', function() { - spyOn(this.view, "setRead"); - this.unreadN.find('.unread-toggle').trigger('click'); + describe("mark read", function() { + beforeEach(function() { + this.unreadN = $(".stream_element.unread").first(); + this.guid = this.unreadN.data("guid"); + }); - expect(this.view.setRead).toHaveBeenCalledWith(this.guid); - }); - }); + it("calls 'setRead'", function() { + spyOn(this.view, "setRead"); + this.unreadN.find(".unread-toggle").trigger("click"); - context('mark unread', function() { - beforeEach(function() { - this.readN = $('.stream_element.read').first(); - this.guid = this.readN.data("guid"); + expect(this.view.setRead).toHaveBeenCalledWith(this.guid); + }); }); - it('calls "setUnread"', function() { - spyOn(this.view, "setUnread"); - this.readN.find('.unread-toggle').trigger('click'); + describe("mark unread", function() { + beforeEach(function() { + this.readN = $(".stream_element.read").first(); + this.guid = this.readN.data("guid"); + }); - expect(this.view.setUnread).toHaveBeenCalledWith(this.guid); - }); - }); + it("calls 'setUnread'", function() { + spyOn(this.view, "setUnread"); + this.readN.find(".unread-toggle").trigger("click"); - context('updateView', function() { - beforeEach(function() { - this.readN = $('.stream_element.read').first(); - this.guid = this.readN.data('guid'); - this.type = this.readN.data('type'); + expect(this.view.setUnread).toHaveBeenCalledWith(this.guid); + }); }); - it('changes the "all notifications" count', function() { - var badge = $('ul.nav > li:eq(0) .badge'); - var count = parseInt(badge.text()); + describe("updateView", function() { + beforeEach(function() { + this.readN = $(".stream_element.read").first(); + this.guid = this.readN.data("guid"); + this.type = this.readN.data("type"); + }); - this.view.updateView(this.guid, this.type, true); - expect(parseInt(badge.text())).toBe(count + 1); + it("changes the 'all notifications' count", function() { + var badge = $(".list-group > a:eq(0) .badge"); + var count = parseInt(badge.text()); - this.view.updateView(this.guid, this.type, false); - expect(parseInt(badge.text())).toBe(count); - }); + this.view.updateView(this.guid, this.type, true); + expect(parseInt(badge.text())).toBe(count + 1); - it('changes the notification type count', function() { - var badge = $('ul.nav > li[data-type=' + this.type + '] .badge'); - var count = parseInt(badge.text()); + this.view.updateView(this.guid, this.type, false); + expect(parseInt(badge.text())).toBe(count); + }); - this.view.updateView(this.guid, this.type, true); - expect(parseInt(badge.text())).toBe(count + 1); + it("changes the notification type count", function() { + var badge = $(".list-group > a[data-type=" + this.type + "] .badge"); + var count = parseInt(badge.text()); - this.view.updateView(this.guid, this.type, false); - expect(parseInt(badge.text())).toBe(count); - }); + this.view.updateView(this.guid, this.type, true); + expect(parseInt(badge.text())).toBe(count + 1); + + this.view.updateView(this.guid, this.type, false); + expect(parseInt(badge.text())).toBe(count); + }); - it('toggles the unread class and changes the title', function() { - this.view.updateView(this.readN.data('guid'), this.readN.data('type'), true); - expect(this.readN.hasClass('unread')).toBeTruthy(); - expect(this.readN.hasClass('read')).toBeFalsy(); - expect(this.readN.find('.unread-toggle .entypo').data('original-title')).toBe(Diaspora.I18n.t('notifications.mark_read')); + it("toggles the unread class and changes the title", function() { + this.view.updateView(this.readN.data("guid"), this.readN.data("type"), true); + expect(this.readN.hasClass("unread")).toBeTruthy(); + expect(this.readN.hasClass("read")).toBeFalsy(); + expect(this.readN.find(".unread-toggle .entypo-eye").attr("data-original-title")).toBe( + Diaspora.I18n.t("notifications.mark_read") + ); + + this.view.updateView(this.readN.data("guid"), this.readN.data("type"), false); + expect(this.readN.hasClass("read")).toBeTruthy(); + expect(this.readN.hasClass("unread")).toBeFalsy(); + expect(this.readN.find(".unread-toggle .entypo-eye").attr("data-original-title")).toBe( + Diaspora.I18n.t("notifications.mark_unread") + ); + }); - this.view.updateView(this.readN.data('guid'), this.readN.data('type'), false); - expect(this.readN.hasClass('read')).toBeTruthy(); - expect(this.readN.hasClass('unread')).toBeFalsy(); - expect(this.readN.find('.unread-toggle .entypo').data('original-title')).toBe(Diaspora.I18n.t('notifications.mark_unread')); + context("with a header", function() { + beforeEach(function() { + /* jshint camelcase: false */ + loginAs({name: "alice", avatar: {small: "http://avatar.com/photo.jpg"}, notifications_count: 2, guid: "foo"}); + /* jshint camelcase: true */ + gon.appConfig = {settings: {podname: "MyPod"}}; + this.header = new app.views.Header(); + $("header").prepend(this.header.el); + this.header.render(); + }); + + it("changes the header notifications count", function() { + var badge1 = $(".notifications-link:eq(0) .badge"); + var badge2 = $(".notifications-link:eq(1) .badge"); + var count = parseInt(badge1.text(), 10); + + this.view.updateView(this.guid, this.type, true); + expect(parseInt(badge1.text(), 10)).toBe(count + 1); + + this.view.updateView(this.guid, this.type, false); + expect(parseInt(badge1.text(), 10)).toBe(count); + + this.view.updateView(this.guid, this.type, true); + expect(parseInt(badge2.text(), 10)).toBe(count + 1); + + this.view.updateView(this.guid, this.type, false); + expect(parseInt(badge2.text(), 10)).toBe(count); + }); + }); }); - context("with a header", function() { - beforeEach(function() { - loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}, notifications_count : 2}); - this.header = new app.views.Header(); - $("header").prepend(this.header.el); - this.header.render(); + describe("markAllRead", function() { + it("calls setRead for each unread notification", function(){ + spyOn(this.view, "setRead"); + this.view.markAllRead(); + expect(this.view.setRead).toHaveBeenCalledWith(this.view.$(".stream_element.unread").eq(0).data("guid")); + this.view.markAllRead(); + expect(this.view.setRead).toHaveBeenCalledWith(this.view.$(".stream_element.unread").eq(1).data("guid")); }); + }); + }); + context("on the contacts page", function() { + beforeEach(function() { + spec.loadFixture("aspects_manage"); + this.view = new app.views.Notifications({el: "#notifications_container"}); + /* jshint camelcase: false */ + loginAs({name: "alice", avatar: {small: "http://avatar.com/photo.jpg"}, notifications_count: 2, guid: "foo"}); + /* jshint camelcase: true */ + gon.appConfig = {settings: {podname: "MyPod"}}; + this.header = new app.views.Header(); + $("header").prepend(this.header.el); + this.header.render(); + }); + + describe("updateView", function() { it("changes the header notifications count", function() { - var badge = $("#notification_badge .badge_count"); - var count = parseInt(badge.text(), 10); + var badge1 = $(".notifications-link:eq(0) .badge"); + var badge2 = $(".notifications-link:eq(1) .badge"); + var count = parseInt(badge1.text(), 10); + + this.view.updateView(this.guid, this.type, true); + expect(parseInt(badge1.text(), 10)).toBe(count + 1); + + this.view.updateView(this.guid, this.type, false); + expect(parseInt(badge1.text(), 10)).toBe(count); this.view.updateView(this.guid, this.type, true); - expect(parseInt(badge.text(), 10)).toBe(count + 1); + expect(parseInt(badge2.text(), 10)).toBe(count + 1); this.view.updateView(this.guid, this.type, false); - expect(parseInt(badge.text(), 10)).toBe(count); + expect(parseInt(badge2.text(), 10)).toBe(count); }); - context("markAllRead", function() { - it("calls setRead for each unread notification", function(){ - spyOn(this.view, "setRead"); - this.view.markAllRead(); - expect(this.view.setRead).toHaveBeenCalledWith(this.view.$('.stream_element.unread').eq(0).data('guid')); - this.view.markAllRead(); - expect(this.view.setRead).toHaveBeenCalledWith(this.view.$('.stream_element.unread').eq(1).data('guid')); - }); + it("doesn't change the contacts count", function() { + expect($("#aspect_nav .badge").length).toBeGreaterThan(0); + $("#aspect_nav .badge").each(function(index, el) { + $(el).text(index + 1337); + }); + + this.view.updateView(this.guid, this.type, true); + $("#aspect_nav .badge").each(function(index, el) { + expect(parseInt($(el).text(), 10)).toBe(index + 1337); + }); + + this.view.updateView(this.guid, this.type, false); + $("#aspect_nav .badge").each(function(index, el) { + expect(parseInt($(el).text(), 10)).toBe(index + 1337); }); + }); }); }); }); diff --git a/spec/javascripts/app/views/photo_viewer_spec.js b/spec/javascripts/app/views/photo_viewer_spec.js deleted file mode 100644 index 645f50d2123026c736f6c6258b6a98e191d50047..0000000000000000000000000000000000000000 --- a/spec/javascripts/app/views/photo_viewer_spec.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("app.views.PhotoViewer", function(){ - beforeEach(function(){ - this.model = factory.post({ - photos : [ - factory.photoAttrs({sizes : {large : "http://tieguy.org/me.jpg"}}), - factory.photoAttrs({sizes : {large : "http://whatthefuckiselizabethstarkupto.com/none_knows.gif"}}) //SIC - ] - }); - this.view = new app.views.PhotoViewer({model : this.model}); - }); - - describe("rendering", function(){ - it("should have an image for each photoAttr on the model", function(){ - this.view.render(); - expect(this.view.$("img").length).toBe(2); - expect(this.view.$("img[src='http://tieguy.org/me.jpg']")).toExist(); - }); - }); -}); diff --git a/spec/javascripts/app/views/pod_entry_view_spec.js b/spec/javascripts/app/views/pod_entry_view_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..2c04effc804b5abfcfba055bcb001cc7486b0fa9 --- /dev/null +++ b/spec/javascripts/app/views/pod_entry_view_spec.js @@ -0,0 +1,96 @@ + +describe("app.views.PodEntry", function() { + beforeEach(function() { + this.pod = factory.pod(); + this.view = new app.views.PodEntry({ + model: this.pod, + parent: document.createDocumentFragment() + }); + }); + + describe("className", function() { + it("returns danger bg when offline", function() { + this.pod.set("offline", true); + expect(this.view.className()).toEqual("bg-danger"); + }); + + it("returns warning bg when version unknown", function() { + this.pod.set("status", "version_failed"); + expect(this.view.className()).toEqual("bg-warning"); + }); + + it("returns success bg for no errors", function() { + this.pod.set("status", "no_errors"); + expect(this.view.className()).toEqual("bg-success"); + }); + }); + + describe("presenter", function() { + it("contains calculated attributes", function() { + this.pod.set({ + status: "no_errors", + ssl: true, + host: "pod.example.com" + }); + var actual = this.view.presenter(); + expect(actual).toEqual(jasmine.objectContaining({ + /* jshint camelcase: false */ + is_unchecked: false, + has_no_errors: true, + has_errors: false, + status_text: jasmine.anything(), + response_time_fmt: jasmine.anything(), + pod_url: "https://pod.example.com" + /* jshint camelcase: true */ + })); + }); + }); + + describe("postRenderTemplate", function() { + it("appends itself to the parent", function() { + var childCount = $(this.view.parent).children().length; + this.view.render(); + expect($(this.view.parent).children().length).toEqual(childCount+1); + }); + }); + + describe("recheckPod", function() { + var ajaxSuccess = { status: 200, responseText: "{}" }; + var ajaxFail = { status: 400 }; + beforeEach(function(){ + this.view.render(); + this.view.$el.append($("<div id='flash-container'/>")); + app.flashMessages = new app.views.FlashMessages({ el: this.view.$("#flash-container") }); + }); + + it("calls .recheck() on the model", function() { + spyOn(this.pod, "recheck").and.returnValue($.Deferred()); + this.view.recheckPod(); + expect(this.pod.recheck).toHaveBeenCalled(); + }); + + it("renders a success flash message", function() { + this.view.recheckPod(); + jasmine.Ajax.requests.mostRecent().respondWith(ajaxSuccess); + expect(this.view.$(".flash-message")).toBeSuccessFlashMessage(); + }); + + it("renders an error flash message", function() { + this.view.recheckPod(); + jasmine.Ajax.requests.mostRecent().respondWith(ajaxFail); + expect(this.view.$(".flash-message")).toBeErrorFlashMessage(); + }); + + it("sets the appropriate CSS class", function() { + this.view.$el.addClass("bg-danger"); + this.pod.set({ offline: false, status: "no_errors" }); + + this.view.recheckPod(); + expect(this.view.$el.attr("class")).toContain("checking"); + jasmine.Ajax.requests.mostRecent().respondWith(ajaxSuccess); + expect(this.view.$el.attr("class")).toContain("bg-success"); + expect(this.view.$el.attr("class")).not.toContain("checking"); + expect(this.view.$el.attr("class")).not.toContain("bg-danger"); + }); + }); +}); diff --git a/spec/javascripts/app/views/poll_view_spec.js b/spec/javascripts/app/views/poll_view_spec.js index 0b9b7d5cc5e59306c58d9b5a2381aed56ed6c232..93d68533299cfdfa091c308c0e16d2ff17390ed4 100644 --- a/spec/javascripts/app/views/poll_view_spec.js +++ b/spec/javascripts/app/views/poll_view_spec.js @@ -2,7 +2,7 @@ describe("app.views.Poll", function(){ beforeEach(function() { loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); this.view = new app.views.Poll({ model: factory.postWithPoll()}); - this.view.render(); + spec.content().html(this.view.render().el); }); describe("setProgressBar", function(){ @@ -15,9 +15,9 @@ describe("app.views.Poll", function(){ describe("toggleResult", function(){ it("toggles the progress bar and result", function(){ - expect(this.view.$('.poll_progress_bar_wrapper:first').css('display')).toBe("none"); - this.view.toggleResult(null); - expect(this.view.$('.poll_progress_bar_wrapper:first').css('display')).toBe("block"); + expect($(".poll_progress_bar_wrapper:first")).toBeHidden(); + this.view.toggleResult(); + expect($(".poll_progress_bar_wrapper:first")).toBeVisible(); }); }); @@ -45,12 +45,6 @@ describe("app.views.Poll", function(){ describe("reshared post", function(){ beforeEach(function(){ - Diaspora.I18n.load({ - poll: { - go_to_original_post: "You can participate in this poll on the <%= original_post_link %>.", - original_post: "original post" - } - }); this.view.model.attributes.post_type = "Reshare"; this.view.model.attributes.root = {id: 1}; this.view.render(); diff --git a/spec/javascripts/app/views/preview_post_view_spec.js b/spec/javascripts/app/views/preview_post_view_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..e2c1b5aecb848f7cc50550efc59b50ecba07ec88 --- /dev/null +++ b/spec/javascripts/app/views/preview_post_view_spec.js @@ -0,0 +1,81 @@ +describe("app.views.PreviewPost", function() { + beforeEach(function() { + this.model = new app.models.Post(factory.postAttrs()); + this.view = new app.views.PreviewPost({model: this.model}); + }); + + describe("initialize", function() { + it("sets preview property in model", function() { + this.view.initialize(); + expect(this.view.model.get("preview")).toBe(true); + }); + + it("calls app.views.OEmbed.initialize", function() { + spyOn(app.views.OEmbed.prototype, "initialize"); + this.view.initialize(); + expect(app.views.OEmbed.prototype.initialize).toHaveBeenCalledWith({model: this.model}); + }); + + it("calls app.views.OpenGraph.initialize", function() { + spyOn(app.views.OpenGraph.prototype, "initialize"); + this.view.initialize(); + expect(app.views.OpenGraph.prototype.initialize).toHaveBeenCalledWith({model: this.model}); + }); + + it("calls app.views.Poll.initialize", function() { + spyOn(app.views.Poll.prototype, "initialize"); + this.view.initialize(); + expect(app.views.Poll.prototype.initialize).toHaveBeenCalledWith({model: this.model}); + }); + + it("calls app.views.Poll.initialize", function() { + spyOn(app.views.Poll.prototype, "initialize"); + this.view.initialize(); + expect(app.views.Poll.prototype.initialize).toHaveBeenCalledWith({model: this.model}); + }); + }); + + describe("render", function() { + it("calls feedbackView", function() { + spyOn(app.views.PreviewPost.prototype, "feedbackView"); + this.view.render(); + expect(app.views.PreviewPost.prototype.feedbackView).toHaveBeenCalled(); + }); + + it("calls postContentView", function() { + spyOn(app.views.PreviewPost.prototype, "postContentView"); + this.view.render(); + expect(app.views.PreviewPost.prototype.postContentView).toHaveBeenCalled(); + }); + + it("calls postLocationStreamView", function() { + spyOn(app.views.PreviewPost.prototype, "postLocationStreamView"); + this.view.render(); + expect(app.views.PreviewPost.prototype.postLocationStreamView).toHaveBeenCalled(); + }); + }); + + describe("feedbackView", function() { + it("calls app.views.Feedback.initialise", function() { + spyOn(app.views.Feedback.prototype, "initialize"); + this.view.feedbackView(); + expect(app.views.Feedback.prototype.initialize).toHaveBeenCalledWith({model: this.model}); + }); + }); + + describe("postContentView", function() { + it("calls app.views.Feedback.initialise", function() { + spyOn(app.views.StatusMessage.prototype, "initialize"); + this.view.postContentView(); + expect(app.views.StatusMessage.prototype.initialize).toHaveBeenCalledWith({model: this.model}); + }); + }); + + describe("postLocationStreamView", function() { + it("calls app.views.Feedback.initialise", function() { + spyOn(app.views.LocationStream.prototype, "initialize"); + this.view.postLocationStreamView(); + expect(app.views.LocationStream.prototype.initialize).toHaveBeenCalledWith({model: this.model}); + }); + }); +}); diff --git a/spec/javascripts/app/views/profile_sidebar_view_spec.js b/spec/javascripts/app/views/profile_sidebar_view_spec.js index f648bb118732cadf9f9c987e8b1c64d797e684c4..e54ac9062d0320c0e61bdf4303fcc8d8ca343e8e 100644 --- a/spec/javascripts/app/views/profile_sidebar_view_spec.js +++ b/spec/javascripts/app/views/profile_sidebar_view_spec.js @@ -5,6 +5,7 @@ describe("app.views.ProfileSidebar", function() { diaspora_id: "alice@umbrella.corp", name: "Project Alice", relationship: 'mutual', + show_profile_info: true, profile: { bio: "confidential", location: "underground", diff --git a/spec/javascripts/app/views/publisher_mention_view_spec.js b/spec/javascripts/app/views/publisher_mention_view_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..436e5e674adbb334b91de3f4c11afe8a797cb1cd --- /dev/null +++ b/spec/javascripts/app/views/publisher_mention_view_spec.js @@ -0,0 +1,480 @@ +describe("app.views.PublisherMention", function() { + beforeEach(function() { + spec.loadFixture("aspects_index"); + }); + + describe("initialize", function() { + it("initializes object properties", function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + expect(this.view.mentionedPeople).toEqual([]); + expect(this.view.invisibleChar).toBe("\u200B"); + expect(this.view.triggerChar).toBe("@"); + }); + + it("calls app.views.SearchBase.initialize", function() { + spyOn(app.views.SearchBase.prototype, "initialize"); + this.view = new app.views.PublisherMention({ el: "#publisher" }); + expect(app.views.SearchBase.prototype.initialize).toHaveBeenCalled(); + var call = app.views.SearchBase.prototype.initialize.calls.mostRecent(); + expect(call.args[0].typeaheadInput.selector).toBe("#publisher .typeahead-mention-box"); + expect(call.args[0].customSearch).toBeTruthy(); + expect(call.args[0].autoselect).toBeTruthy(); + expect(call.args[0].remoteRoute).toBe("/contacts"); + }); + + it("calls bindTypeaheadEvents", function() { + spyOn(app.views.PublisherMention.prototype, "bindTypeaheadEvents"); + this.view = new app.views.PublisherMention({ el: "#publisher" }); + expect(app.views.PublisherMention.prototype.bindTypeaheadEvents).toHaveBeenCalled(); + }); + }); + + describe("bindTypeaheadEvents", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + this.view.bloodhound.add([ + {person: true, name: "user1", handle: "user1@pod.tld"}, + {person: true, name: "user2", handle: "user2@pod.tld"} + ]); + }); + + it("process mention when clicking a result", function() { + spyOn(this.view, "onSuggestionSelection"); + this.view.typeaheadInput.typeahead("val", "user"); + this.view.typeaheadInput.typeahead("open"); + $(".tt-suggestion").first().click(); + expect(this.view.onSuggestionSelection).toHaveBeenCalledWith( + {person: true, name: "user1", handle: "user1@pod.tld"} + ); + }); + }); + + describe("addPersonToMentions", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + }); + + it("adds a person to mentioned people", function() { + expect(this.view.mentionedPeople.length).toBe(0); + this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"}); + expect(this.view.mentionedPeople.length).toBe(1); + expect(this.view.mentionedPeople[0]).toEqual({ + /* jshint camelcase: false */ + name: "user1", handle: "user1@pod.tld", diaspora_id: "user1@pod.tld"}); + /* jshint camelcase: true */ + }); + + it("adds a person to the ignored diaspora ids", function() { + spyOn(this.view, "ignorePersonForSuggestions"); + this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"}); + expect(this.view.ignorePersonForSuggestions).toHaveBeenCalledWith({ + /* jshint camelcase: false */ + name: "user1", handle: "user1@pod.tld", diaspora_id: "user1@pod.tld"}); + /* jshint camelcase: true */ + }); + + it("doesn't add mention if not a person", function() { + expect(this.view.mentionedPeople.length).toBe(0); + this.view.addPersonToMentions(); + expect(this.view.mentionedPeople.length).toBe(0); + this.view.addPersonToMentions({}); + expect(this.view.mentionedPeople.length).toBe(0); + this.view.addPersonToMentions({name: "user1"}); + expect(this.view.mentionedPeople.length).toBe(0); + this.view.addPersonToMentions({handle: "user1@pod.tld"}); + expect(this.view.mentionedPeople.length).toBe(0); + }); + }); + + describe("cleanMentionedPeople", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + }); + + it("removes person from mentioned people if not mentioned anymore", function() { + this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"}); + expect(this.view.mentionedPeople.length).toBe(1); + this.view.cleanMentionedPeople(); + expect(this.view.mentionedPeople.length).toBe(0); + }); + + it("removes person from ignored people if not mentioned anymore", function() { + this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"}); + expect(this.view.ignoreDiasporaIds.length).toBe(1); + this.view.cleanMentionedPeople(); + expect(this.view.ignoreDiasporaIds.length).toBe(0); + }); + + it("keeps mentioned persons", function() { + this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"}); + this.view.inputBox.val("user1"); + expect(this.view.mentionedPeople.length).toBe(1); + this.view.cleanMentionedPeople(); + expect(this.view.mentionedPeople.length).toBe(1); + }); + + it("keeps mentioned persons for ignored diaspora ids", function() { + this.view.addPersonToMentions({name: "user1", handle: "user1@pod.tld"}); + this.view.inputBox.val("user1"); + expect(this.view.ignoreDiasporaIds.length).toBe(1); + this.view.cleanMentionedPeople(); + expect(this.view.ignoreDiasporaIds.length).toBe(1); + }); + }); + + describe("onSuggestionSelection", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + this.view.inputBox.val("@user1337 Text before @user1 text after"); + this.view.inputBox[0].setSelectionRange(28, 28); + }); + + it("doesn't do anything if there is no '@' in front of the caret", function() { + spyOn(this.view, "addPersonToMentions"); + this.view.inputBox.val("user1337 Text before @user1 text after"); + this.view.inputBox[0].setSelectionRange(9, 9); + this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"}); + expect(this.view.addPersonToMentions).not.toHaveBeenCalled(); + }); + + it("adds a person to mentioned people", function() { + spyOn(this.view, "addPersonToMentions"); + this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"}); + expect(this.view.addPersonToMentions).toHaveBeenCalledWith({name: "user1337", handle: "user1@pod.tld"}); + }); + + it("closes the suggestions box", function() { + spyOn(this.view, "closeSuggestions"); + this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"}); + expect(this.view.closeSuggestions).toHaveBeenCalled(); + }); + + it("correctly formats the text", function() { + this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"}); + expect(this.view.inputBox.val()).toBe("@user1337 Text before \u200Buser1337 text after"); + }); + + it("replaces the correct mention", function() { + this.view.inputBox.val("@user1337 123 user2 @user2 456 @user3 789"); + this.view.inputBox[0].setSelectionRange(26, 26); + this.view.onSuggestionSelection({name: "user23", handle: "user2@pod.tld"}); + expect(this.view.inputBox.val()).toBe("@user1337 123 user2 \u200Buser23 456 @user3 789"); + this.view.inputBox[0].setSelectionRange(9, 9); + this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"}); + expect(this.view.inputBox.val()).toBe("\u200Buser1337 123 user2 \u200Buser23 456 @user3 789"); + this.view.inputBox[0].setSelectionRange(38, 38); + this.view.onSuggestionSelection({name: "user32", handle: "user3@pod.tld"}); + expect(this.view.inputBox.val()).toBe("\u200Buser1337 123 user2 \u200Buser23 456 \u200Buser32 789"); + }); + + it("calls updateMessageTexts", function() { + spyOn(this.view, "updateMessageTexts"); + this.view.onSuggestionSelection({name: "user1337", handle: "user1@pod.tld"}); + expect(this.view.updateMessageTexts).toHaveBeenCalled(); + }); + + it("places the caret at the right position", function() { + this.view.onSuggestionSelection({"name": "user1WithLongName", "handle": "user1@pod.tld"}); + var expectedCaretPosition = ("@user1337 Text before \u200Buser1WithLongName").length; + expect(this.view.inputBox[0].selectionStart).toBe(expectedCaretPosition); + }); + }); + + describe("updateMessageTexts", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + this.view.inputBox.val("@user1 Text before \u200Buser1\ntext after"); + this.view.mentionedPeople.push({"name": "user1", "handle": "user1@pod.tld"}); + }); + + it("sets the correct messageText", function() { + this.view.updateMessageTexts(); + expect(this.view.inputBox.data("messageText")).toBe("@user1 Text before @{user1 ; user1@pod.tld}\ntext after"); + }); + + it("formats overlay text to HTML", function() { + this.view.updateMessageTexts(); + expect(this.view.mentionsBox.find(".mentions").html()) + .toBe("@user1 Text before <strong><span>user1</span></strong>\ntext after"); + }); + + it("properly escapes the user input", function() { + this.view.inputBox.val("<img src=\"/default.png\"> @user1 Text before \u200Buser1\ntext after"); + this.view.updateMessageTexts(); + expect(this.view.mentionsBox.find(".mentions").html()) + .toBe("<img src=\"/default.png\"> @user1 Text before <strong><span>user1</span></strong>\ntext after"); + }); + }); + + describe("updateTypeaheadInput", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + this.view.inputBox.val("@user1337 Text before @user1 text after"); + this.view.inputBox[0].setSelectionRange(28, 28); + }); + + it("calls 'closeSuggestions' if there is no '@' in front of the caret", function() { + spyOn(this.view, "closeSuggestions"); + this.view.inputBox.val("user1337 Text before @user1 text after"); + this.view.inputBox[0].setSelectionRange(9, 9); + this.view.updateTypeaheadInput(); + expect(this.view.closeSuggestions).toHaveBeenCalled(); + }); + + it("calls 'closeSuggestions' if there is a whitespace between the '@' and the caret", function() { + spyOn(this.view, "closeSuggestions"); + this.view.inputBox.val("@user1337 Text before @user1 text after"); + this.view.inputBox[0].setSelectionRange(9, 9); + this.view.updateTypeaheadInput(); + expect(this.view.closeSuggestions.calls.count()).toEqual(0); + this.view.inputBox[0].setSelectionRange(10, 10); + this.view.updateTypeaheadInput(); + expect(this.view.closeSuggestions.calls.count()).toEqual(1); + this.view.inputBox[0].setSelectionRange(11, 11); + this.view.updateTypeaheadInput(); + expect(this.view.closeSuggestions.calls.count()).toEqual(2); + }); + + it("fills the typeahead input with the correct text", function() { + spyOn(this.view, "closeSuggestions"); + this.view.inputBox.val("@user1337 Text before @user1 text after"); + this.view.inputBox[0].setSelectionRange(2, 2); + this.view.updateTypeaheadInput(); + expect(this.view.closeSuggestions).not.toHaveBeenCalled(); + expect(this.view.typeaheadInput.val()).toBe("u"); + this.view.inputBox[0].setSelectionRange(9, 9); + this.view.updateTypeaheadInput(); + expect(this.view.closeSuggestions).not.toHaveBeenCalled(); + expect(this.view.typeaheadInput.val()).toBe("user1337"); + this.view.inputBox[0].setSelectionRange(27, 27); + this.view.updateTypeaheadInput(); + expect(this.view.closeSuggestions).not.toHaveBeenCalled(); + expect(this.view.typeaheadInput.val()).toBe("user"); + }); + }); + + describe("prefillMention", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + spyOn(this.view, "addPersonToMentions"); + spyOn(this.view, "updateMessageTexts"); + }); + + it("prefills one mention", function() { + this.view.prefillMention([{"name": "user1", "handle": "user1@pod.tld"}]); + expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user1", "handle": "user1@pod.tld"}); + expect(this.view.updateMessageTexts).toHaveBeenCalled(); + expect(this.view.inputBox.val()).toBe("\u200Buser1"); + }); + + it("prefills multiple mentions", function() { + this.view.prefillMention([ + {"name": "user1", "handle": "user1@pod.tld"}, + {"name": "user2", "handle": "user2@pod.tld"} + ]); + + expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user1", "handle": "user1@pod.tld"}); + expect(this.view.addPersonToMentions).toHaveBeenCalledWith({"name": "user2", "handle": "user2@pod.tld"}); + expect(this.view.updateMessageTexts).toHaveBeenCalled(); + expect(this.view.inputBox.val()).toBe("\u200Buser1 \u200Buser2"); + }); + }); + + describe("onInputBoxKeyDown", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + }); + + context("escape key", function() { + beforeEach(function() { + this.evt = $.Event("keydown", {which: Keycodes.ESC}); + }); + + it("calls 'closeSuggestions'", function() { + spyOn(this.view, "closeSuggestions"); + this.view.onInputBoxKeyDown(this.evt); + expect(this.view.closeSuggestions).toHaveBeenCalled(); + }); + }); + + context("space key", function() { + beforeEach(function() { + this.evt = $.Event("keydown", {which: Keycodes.SPACE}); + }); + + it("calls 'closeSuggestions'", function() { + spyOn(this.view, "closeSuggestions"); + this.view.onInputBoxKeyDown(this.evt); + expect(this.view.closeSuggestions).toHaveBeenCalled(); + }); + }); + + context("up key", function() { + beforeEach(function() { + this.evt = $.Event("keydown", {which: Keycodes.UP}); + }); + + it("calls 'onArrowKeyDown'", function() { + spyOn(this.view, "onArrowKeyDown"); + this.view.onInputBoxKeyDown(this.evt); + expect(this.view.onArrowKeyDown).toHaveBeenCalled(); + }); + }); + + context("down key", function() { + beforeEach(function() { + this.evt = $.Event("keydown", {which: Keycodes.DOWN}); + }); + + it("calls 'onArrowKeyDown'", function() { + spyOn(this.view, "onArrowKeyDown"); + this.view.onInputBoxKeyDown(this.evt); + expect(this.view.onArrowKeyDown).toHaveBeenCalled(); + }); + }); + + context("return key", function() { + beforeEach(function() { + this.evt = $.Event("keydown", {which: Keycodes.RETURN}); + this.view.bloodhound.add([ + {person: true, name: "user1", handle: "user1@pod.tld"}, + {person: true, name: "user2", handle: "user2@pod.tld"} + ]); + this.view.typeaheadInput.typeahead("val", "user"); + this.view.typeaheadInput.typeahead("open"); + $(".tt-suggestion").first().addClass(".tt-cursor"); + }); + + it("calls 'onSuggestionSelection'", function() { + spyOn(this.view, "onSuggestionSelection"); + this.view.onInputBoxKeyDown(this.evt); + expect(this.view.onSuggestionSelection).toHaveBeenCalled(); + }); + }); + + context("tab key", function() { + beforeEach(function() { + this.evt = $.Event("keydown", {which: Keycodes.TAB}); + this.view.bloodhound.add([ + {person: true, name: "user1", handle: "user1@pod.tld"}, + {person: true, name: "user2", handle: "user2@pod.tld"} + ]); + this.view.typeaheadInput.typeahead("val", "user"); + this.view.typeaheadInput.typeahead("open"); + $(".tt-suggestion").first().addClass(".tt-cursor"); + }); + + it("calls 'onSuggestionSelection'", function() { + spyOn(this.view, "onSuggestionSelection"); + this.view.onInputBoxKeyDown(this.evt); + expect(this.view.onSuggestionSelection).toHaveBeenCalled(); + }); + }); + }); + + describe("onInputBoxInput", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + }); + + it("calls 'cleanMentionedPeople'", function() { + spyOn(this.view, "cleanMentionedPeople"); + this.view.onInputBoxInput(); + expect(this.view.cleanMentionedPeople).toHaveBeenCalled(); + }); + + it("calls 'updateMessageTexts'", function() { + spyOn(this.view, "updateMessageTexts"); + this.view.onInputBoxInput(); + expect(this.view.updateMessageTexts).toHaveBeenCalled(); + }); + + it("calls 'updateTypeaheadInput'", function() { + spyOn(this.view, "updateTypeaheadInput"); + this.view.onInputBoxInput(); + expect(this.view.updateTypeaheadInput).toHaveBeenCalled(); + }); + }); + + describe("onInputBoxClick", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + }); + + it("calls 'updateTypeaheadInput'", function() { + spyOn(this.view, "updateTypeaheadInput"); + this.view.onInputBoxClick(); + expect(this.view.updateTypeaheadInput).toHaveBeenCalled(); + }); + }); + + describe("onInputBoxBlur", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + }); + + it("calls 'closeSuggestions'", function() { + spyOn(this.view, "closeSuggestions"); + this.view.onInputBoxBlur(); + expect(this.view.closeSuggestions).toHaveBeenCalled(); + }); + }); + + describe("reset", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + spyOn(this.view, "onInputBoxInput"); + }); + + it("resets the mention box", function() { + this.view.reset(); + expect(this.view.inputBox.val()).toBe(""); + expect(this.view.onInputBoxInput).toHaveBeenCalled(); + }); + }); + + describe("closeSuggestions", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + this.view.bloodhound.add([ + {"person": true, "name": "user1", "handle": "user1@pod.tld"} + ]); + }); + + it("resets results and closes mention box", function() { + this.view.typeaheadInput.typeahead("val", "user"); + this.view.typeaheadInput.typeahead("open"); + expect(this.view.$(".tt-menu").is(":visible")).toBe(true); + expect(this.view.$(".tt-menu .tt-suggestion").length).toBeGreaterThan(0); + expect(this.view.typeaheadInput.val()).toBe("user"); + this.view.closeSuggestions(); + expect(this.view.$(".tt-menu").is(":visible")).toBe(false); + expect(this.view.$(".tt-menu .tt-suggestion").length).toBe(0); + expect(this.view.typeaheadInput.val()).toBe(""); + }); + }); + + describe("getTextForSubmit", function() { + beforeEach(function() { + this.view = new app.views.PublisherMention({ el: "#publisher" }); + this.view.bloodhound.add([ + {person: true, name: "user1", handle: "user1@pod.tld"} + ]); + }); + + it("returns text with mention if someone has been mentioned", function() { + this.view.inputBox.val("@user"); + this.view.inputBox[0].setSelectionRange(5, 5); + this.view.typeaheadInput.typeahead("val", "user"); + this.view.typeaheadInput.typeahead("open"); + this.view.$(".tt-suggestion").first().click(); + expect(this.view.getTextForSubmit()).toBe("@{user1 ; user1@pod.tld}"); + }); + + it("returns normal text if nobody has been mentioned", function() { + this.view.inputBox.data("messageText", "Bad text"); + this.view.inputBox.val("Good text"); + expect(this.view.getTextForSubmit()).toBe("Good text"); + }); + }); +}); diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index 428fc7efa6cd7a320978ca0b90c2c6e2b479949e..47e552f3c11a1504fcad3f1d060a7e6e2b130527 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -6,21 +6,17 @@ describe("app.views.Publisher", function() { context("standalone", function() { beforeEach(function() { - // TODO should be jasmine helper - loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); + loginAs(factory.userAttrs()); spec.loadFixture("aspects_index"); this.view = new app.views.Publisher({ standalone: true }); + this.view.open(); }); it("hides the close button in standalone mode", function() { - expect(this.view.$("#hide_publisher").is(":visible")).toBeFalsy(); - }); - - it("hides the post preview button in standalone mode", function() { - expect(this.view.$(".post_preview_button").is(":visible")).toBeFalsy(); + expect(this.view.$(".md-cancel").is(":visible")).toBeFalsy(); }); it("hides the manage services link in standalone mode", function() { @@ -40,13 +36,27 @@ describe("app.views.Publisher", function() { context("plain publisher", function() { beforeEach(function() { - // TODO should be jasmine helper - loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); + loginAs(factory.userAttrs()); spec.loadFixture("aspects_index"); this.view = new app.views.Publisher(); }); + describe("#initSubviews", function() { + it("calls handleTextchange if the publisher is prefilled with mentions", function() { + spyOn(this.view, "handleTextchange"); + this.view.prefillMention = "user@example.org"; + this.view.initSubviews(); + expect(this.view.handleTextchange).toHaveBeenCalled(); + }); + + it("doesn't call handleTextchange if there are no prefilled mentions", function() { + spyOn(this.view, "handleTextchange"); + this.view.initSubviews(); + expect(this.view.handleTextchange).not.toHaveBeenCalled(); + }); + }); + describe("#open", function() { it("removes the 'closed' class from the publisher element", function() { expect($(this.view.el)).toHaveClass("closed"); @@ -76,6 +86,49 @@ describe("app.views.Publisher", function() { this.view.close($.Event()); expect($(this.view.el).find("#status_message_fake_text").attr("style")).not.toContain("height"); }); + + it("should hide the poll container correctly", function() { + this.view.$el.find(".poll-creator").click(); + expect(this.view.$el.find(".publisher-textarea-wrapper")).toHaveClass("with-poll"); + expect(this.view.$el.find(".poll-creator-container")).toBeVisible(); + this.view.close(); + expect(this.view.$el.find(".publisher-textarea-wrapper")).not.toHaveClass("with-poll"); + expect(this.view.$el.find(".poll-creator-container")).not.toBeVisible(); + this.view.open(); + expect(this.view.$el.find(".publisher-textarea-wrapper")).not.toHaveClass("with-poll"); + expect(this.view.$el.find(".poll-creator-container")).not.toBeVisible(); + this.view.$el.find(".poll-creator").click(); + expect(this.view.$el.find(".publisher-textarea-wrapper")).toHaveClass("with-poll"); + expect(this.view.$el.find(".poll-creator-container")).toBeVisible(); + }); + + it("should close the publisher when clicking outside", function() { + expect("#publisher").not.toHaveClass("closed"); + $("body").click(); + expect("#publisher").toHaveClass("closed"); + }); + + it("should not close the publisher when clicking inside", function() { + expect("#publisher").not.toHaveClass("closed"); + $("#publisher").find(".publisher-textarea-wrapper").click(); + expect("#publisher").not.toHaveClass("closed"); + $("#publisher").find(".aspect_dropdown button").click(); + expect("#publisher").not.toHaveClass("closed"); + }); + + it("should not close the publisher when clicking inside on a mobile", function() { + // Bootstrap inserts a .dropdown-backdrop next to the dropdown menu + // that take the whole page when it detects a mobile. + // Clicking on this element should not close the publisher. + // See https://github.com/diaspora/diaspora/issues/6979. + $("#publisher").find(".aspect_dropdown").append("<div class='dropdown-backdrop'></div>") + .css({position: "fixed", left: 0, right: 0, bottom: 0, top: 0, "z-index": 990}); + expect("#publisher").not.toHaveClass("closed"); + $("#publisher").find(".aspect_dropdown button").click(); + expect("#publisher").not.toHaveClass("closed"); + $("#publisher").find(".dropdown-backdrop").click(); + expect("#publisher").not.toHaveClass("closed"); + }); }); describe("#clear", function() { @@ -86,11 +139,11 @@ describe("app.views.Publisher", function() { expect(this.view.close).toHaveBeenCalled(); }); - it("calls removePostPreview", function(){ - spyOn(this.view, "removePostPreview"); + it("calls hidePreview", function() { + spyOn(this.view.markdownEditor, "hidePreview"); this.view.clear($.Event()); - expect(this.view.removePostPreview).toHaveBeenCalled(); + expect(this.view.markdownEditor.hidePreview).toHaveBeenCalled(); }); it("clears all textareas", function(){ @@ -109,12 +162,12 @@ describe("app.views.Publisher", function() { it("removes all photos from the dropzone area", function(){ var self = this; _.times(3, function(){ - self.view.el_photozone.append($("<li>")); + self.view.photozoneEl.append($("<li>")); }); - expect(this.view.el_photozone.html()).not.toBe(""); + expect(this.view.photozoneEl.html()).not.toBe(""); this.view.clear($.Event()); - expect(this.view.el_photozone.html()).toBe(""); + expect(this.view.photozoneEl.html()).toBe(""); }); it("removes all photo values appended by the photo uploader", function(){ @@ -134,6 +187,13 @@ describe("app.views.Publisher", function() { this.view.clear($.Event()); expect($("#location").length).toBe(0); }); + + it("removes the 'submitting' class from the textarea wrapper", function(){ + this.view.wrapperEl.addClass("submitting"); + expect(this.view.wrapperEl).toHaveClass("submitting"); + this.view.clear($.Event()); + expect(this.view.wrapperEl).not.toHaveClass("submitting"); + }); }); describe("createStatusMessage", function(){ @@ -150,35 +210,47 @@ describe("app.views.Publisher", function() { jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, responseText: "{\"id\": 1}" }); expect(app.stream.addNow).toHaveBeenCalled(); }); + + it("adds the 'submitting' class from the textarea wrapper", function(){ + expect(this.view.wrapperEl).not.toHaveClass("submitting"); + this.view.createStatusMessage($.Event()); + expect(this.view.wrapperEl).toHaveClass("submitting"); + }); + }); + + describe("createPostPreview", function(){ + it("calls handleTextchange to complete missing mentions", function(){ + spyOn(this.view, "handleTextchange"); + this.view.createPostPreview(); + expect(this.view.handleTextchange).toHaveBeenCalled(); + }); }); describe('#setText', function() { - it('sets the content text', function() { - this.view.setText('FOO bar'); + it("sets the content text", function() { + this.view.setText("FOO bar"); - expect(this.view.el_input.val()).toEqual('FOO bar'); - expect(this.view.el_hiddenInput.val()).toEqual('FOO bar'); + expect(this.view.inputEl.val()).toEqual("FOO bar"); + expect(this.view.hiddenInputEl.val()).toEqual("FOO bar"); }); }); describe('#setEnabled', function() { - it('disables the publisher', function() { + it("disables the publisher", function() { expect(this.view.disabled).toBeFalsy(); this.view.setEnabled(false); expect(this.view.disabled).toBeTruthy(); - expect(this.view.el_input.prop('disabled')).toBeTruthy(); - expect(this.view.el_hiddenInput.prop('disabled')).toBeTruthy(); + expect(this.view.inputEl.prop("disabled")).toBeTruthy(); + expect(this.view.hiddenInputEl.prop("disabled")).toBeTruthy(); }); it("disables submitting", function() { - this.view.setText('TESTING'); - expect(this.view.el_submit.prop('disabled')).toBeFalsy(); - expect(this.view.el_preview.prop('disabled')).toBeFalsy(); + this.view.setText("TESTING"); + expect(this.view.submitEl.prop("disabled")).toBeFalsy(); this.view.setEnabled(false); - expect(this.view.el_submit.prop('disabled')).toBeTruthy(); - expect(this.view.el_preview.prop('disabled')).toBeTruthy(); + expect(this.view.submitEl.prop("disabled")).toBeTruthy(); }); }); @@ -189,8 +261,7 @@ describe("app.views.Publisher", function() { var submitCallback = jasmine.createSpy().and.returnValue(false); form.submit(submitCallback); - var e = $.Event("keydown", { keyCode: 13 }); - e.ctrlKey = true; + var e = $.Event("keydown", { which: Keycodes.ENTER, ctrlKey: true }); this.view.keyDown(e); expect(submitCallback).toHaveBeenCalled(); @@ -199,10 +270,6 @@ describe("app.views.Publisher", function() { }); describe("_beforeUnload", function(){ - beforeEach(function(){ - Diaspora.I18n.load({ confirm_unload: "Please confirm that you want to leave this page - data you have entered won't be saved."}); - }); - it("calls _submittable", function(){ spyOn(this.view, "_submittable"); $(window).trigger('beforeunload'); @@ -301,65 +368,35 @@ describe("app.views.Publisher", function() { context("aspect selection", function(){ beforeEach( function(){ - loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); + loginAs(factory.userAttrs()); spec.loadFixture("status_message_new"); - Diaspora.I18n.load({ stream: { public: 'Public' }}); this.view = new app.views.Publisher(); this.view.open(); - - this.radio_els = this.view.$('#publisher .aspect_dropdown li.radio'); - this.check_els = this.view.$('#publisher .aspect_dropdown li.aspect_selector'); - this.visibility_icon = this.view.$('#visibility-icon'); }); it("initializes with 'all_aspects'", function(){ - expect($('.aspect_dropdown li.public')).not.toHaveClass('selected'); - expect($('.aspect_dropdown li.all_aspects')).toHaveClass('selected'); - expect($('.aspect_dropdown li.aspect_selector')).not.toHaveClass('selected'); - - expect($('#publisher #visibility-icon')).not.toHaveClass('globe'); - expect($('#publisher #visibility-icon')).toHaveClass('lock'); - }); - - it("toggles the selected entry visually", function(){ - // click on the first aspect - var evt = $.Event("click", { target: $('.aspect_dropdown li.aspect_selector:first') }); - this.view.view_aspect_selector.toggleAspect(evt); - // public and "all aspects" are deselected - expect($('.aspect_dropdown li.public')).not.toHaveClass('selected'); - expect($('.aspect_dropdown li.all_aspects')).not.toHaveClass('selected'); - // the first aspect is selected - expect($('.aspect_dropdown li.aspect_selector:first')).toHaveClass('selected'); - // the last aspect is not selected - expect($('.aspect_dropdown li.aspect_selector:last')).not.toHaveClass('selected'); - // visibility icon is set to the lock icon - expect($('#publisher #visibility-icon')).not.toHaveClass('globe'); - expect($('#publisher #visibility-icon')).toHaveClass('lock'); - - // click on public - evt = $.Event("click", { target: $('.aspect_dropdown li.public') }); - this.view.view_aspect_selector.toggleAspect(evt); - // public is selected, "all aspects" is deselected - expect($('.aspect_dropdown li.public').hasClass('selected')).toBeTruthy(); - expect($('.aspect_dropdown li.all_aspects').hasClass('selected')).toBeFalsy(); - // the aspects are deselected - expect($('.aspect_dropdown li.aspect_selector').hasClass('selected')).toBeFalsy(); - // visibility icon is set to the globe icon - expect($('#publisher #visibility-icon').hasClass('globe')).toBeTruthy(); - expect($('#publisher #visibility-icon').hasClass('lock')).toBeFalsy(); - - // click on "all aspects" - evt = $.Event("click", { target: $('.aspect_dropdown li.all_aspects') }); - this.view.view_aspect_selector.toggleAspect(evt); - // public is deselected, "all aspects" is selected - expect($('.aspect_dropdown li.public').hasClass('selected')).toBeFalsy(); - expect($('.aspect_dropdown li.all_aspects').hasClass('selected')).toBeTruthy(); - // the aspects are deselected - expect($('.aspect_dropdown li.aspect_selector').hasClass('selected')).toBeFalsy(); - // visibility icon is set to the lock icon - expect($('#publisher #visibility-icon').hasClass('globe')).toBeFalsy(); - expect($('#publisher #visibility-icon').hasClass('lock')).toBeTruthy(); + expect($("#publisher #visibility-icon")).not.toHaveClass("entypo-globe"); + expect($("#publisher #visibility-icon")).toHaveClass("entypo-lock"); + }); + + describe("toggles the selected entry visually", function(){ + it("click on the first aspect", function(){ + this.view.$(".aspect_dropdown li.aspect_selector:first").click(); + expect($("#publisher #visibility-icon")).not.toHaveClass("entypo-globe"); + expect($("#publisher #visibility-icon")).toHaveClass("entypo-lock"); + }); + + it("click on public", function(){ + this.view.$(".aspect_dropdown li.public").click(); + expect($("#publisher #visibility-icon")).toHaveClass("entypo-globe"); + expect($("#publisher #visibility-icon")).not.toHaveClass("entypo-lock"); + }); + + it("click on 'all aspects'", function(){ + expect($("#publisher #visibility-icon")).not.toHaveClass("entypo-globe"); + expect($("#publisher #visibility-icon")).toHaveClass("entypo-lock"); + }); }); describe("hidden form elements", function(){ @@ -373,7 +410,7 @@ describe("app.views.Publisher", function() { expect(selected.first().val()).toBe('all_aspects'); var evt = $.Event("click", { target: $('.aspect_dropdown li.aspect_selector:last') }); - this.view.view_aspect_selector.toggleAspect(evt); + this.view.viewAspectSelector.toggleAspect(evt); selected = $('input[name="aspect_ids[]"]'); expect(selected.length).toBe(1); @@ -384,20 +421,20 @@ describe("app.views.Publisher", function() { expect($('input[name="aspect_ids[]"][value="42"]').length).toBe(0); var evt = $.Event("click", { target: $('.aspect_dropdown li.aspect_selector:last') }); - this.view.view_aspect_selector.toggleAspect(evt); + this.view.viewAspectSelector.toggleAspect(evt); expect($('input[name="aspect_ids[]"][value="42"]').length).toBe(1); evt = $.Event("click", { target: $('.aspect_dropdown li.aspect_selector:last') }); - this.view.view_aspect_selector.toggleAspect(evt); + this.view.viewAspectSelector.toggleAspect(evt); expect($('input[name="aspect_ids[]"][value="42"]').length).toBe(0); }); it("keeps other fields with different values", function() { $('.dropdown-menu').append('<li data-aspect_id="99" class="aspect_selector" />'); var evt = $.Event("click", { target: $('.aspect_dropdown li.aspect_selector:eq(-2)') }); - this.view.view_aspect_selector.toggleAspect(evt); + this.view.viewAspectSelector.toggleAspect(evt); evt = $.Event("click", { target: $('.aspect_dropdown li.aspect_selector:eq(-1)') }); - this.view.view_aspect_selector.toggleAspect(evt); + this.view.viewAspectSelector.toggleAspect(evt); expect($('input[name="aspect_ids[]"][value="42"]').length).toBe(1); expect($('input[name="aspect_ids[]"][value="99"]').length).toBe(1); @@ -407,8 +444,7 @@ describe("app.views.Publisher", function() { context("locator", function() { beforeEach(function() { - // should be jasmine helper - loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); + loginAs(factory.userAttrs()); spec.loadFixture("aspects_index"); this.view = new app.views.Publisher(); @@ -418,7 +454,7 @@ describe("app.views.Publisher", function() { it("Show location", function(){ // inserts location to the DOM; it is the location's view element - setFixtures('<div id="location_container"></div>'); + setFixtures('<div class="location-container"></div>'); // creates a fake Locator OSM = {}; @@ -448,8 +484,7 @@ describe("app.views.Publisher", function() { describe('#avoidEnter', function(){ it("Avoid submitting the form when pressing enter", function(){ // simulates the event object - var evt = {}; - evt.keyCode = 13; + var evt = $.Event("keydown", { which: Keycodes.ENTER }); // should return false in order to avoid the form submition expect(this.view.avoidEnter(evt)).toBeFalsy(); @@ -466,7 +501,6 @@ describe("app.views.Publisher", function() { ' <div id="publisher_textarea_wrapper"></div>'+ ' <div id="photodropzone"></div>'+ ' <input type="submit" />'+ - ' <button class="post_preview_button" />'+ ' </form></div>'+ '</div>' ); @@ -484,7 +518,7 @@ describe("app.views.Publisher", function() { this.view = new app.views.Publisher(); // replace the uploader plugin with a dummy object - var upload_view = this.view.view_uploader; + var upload_view = this.view.viewUploader; this.uploader = { onProgress: _.bind(upload_view.progressHandler, upload_view), onSubmit: _.bind(upload_view.submitHandler, upload_view), @@ -497,7 +531,7 @@ describe("app.views.Publisher", function() { it('shows progress in percent', function() { this.uploader.onProgress(null, 'test.jpg', 20, 100); - var info = this.view.view_uploader.el_info; + var info = this.view.viewUploader.info; expect(info.text()).toContain('test.jpg'); expect(info.text()).toContain('20%'); }); @@ -509,19 +543,17 @@ describe("app.views.Publisher", function() { }); it('adds a placeholder', function() { - expect(this.view.el_wrapper.attr('class')).toContain('with_attachments'); - expect(this.view.el_photozone.find('li').length).toBe(1); + expect(this.view.wrapperEl.attr("class")).toContain("with_attachments"); + expect(this.view.photozoneEl.find("li").length).toBe(1); }); it('disables the publisher buttons', function() { - expect(this.view.el_submit.prop('disabled')).toBeTruthy(); - expect(this.view.el_preview.prop('disabled')).toBeTruthy(); + expect(this.view.submitEl.prop("disabled")).toBeTruthy(); }); }); context('successful completion', function() { beforeEach(function() { - Diaspora.I18n.load({ photo_uploader: { completed: '<%= file %> completed' }}); $('#photodropzone').html('<li class="publisher_photo loading"><img src="" /></li>'); this.uploader.onComplete(null, 'test.jpg', { @@ -533,7 +565,7 @@ describe("app.views.Publisher", function() { }); it('shows it in text form', function() { - var info = this.view.view_uploader.el_info; + var info = this.view.viewUploader.info; expect(info.text()).toBe(Diaspora.I18n.t('photo_uploader.completed', {file: 'test.jpg'})); }); @@ -543,7 +575,7 @@ describe("app.views.Publisher", function() { }); it('replaces the placeholder', function() { - var li = this.view.el_photozone.find('li'); + var li = this.view.photozoneEl.find("li"); var img = li.find('img'); expect(li.attr('class')).not.toContain('loading'); @@ -552,14 +584,12 @@ describe("app.views.Publisher", function() { }); it('re-enables the buttons', function() { - expect(this.view.el_submit.prop('disabled')).toBeFalsy(); - expect(this.view.el_preview.prop('disabled')).toBeFalsy(); + expect(this.view.submitEl.prop("disabled")).toBeFalsy(); }); }); context('unsuccessful completion', function() { beforeEach(function() { - Diaspora.I18n.load({ photo_uploader: { completed: '<%= file %> completed' }}); $('#photodropzone').html('<li class="publisher_photo loading"><img src="" /></li>'); this.uploader.onComplete(null, 'test.jpg', { @@ -571,7 +601,7 @@ describe("app.views.Publisher", function() { }); it('shows error message', function() { - var info = this.view.view_uploader.el_info; + var info = this.view.viewUploader.info; expect(info.text()).toBe(Diaspora.I18n.t('photo_uploader.error', {file: 'test.jpg'})); }); }); @@ -580,21 +610,21 @@ describe("app.views.Publisher", function() { context('photo removal', function() { beforeEach(function() { this.view = new app.views.Publisher(); - this.view.el_wrapper.addClass('with_attachments'); - this.view.el_photozone.html( - '<li class="publisher_photo">.'+ - ' <img data-id="444" />'+ - ' <div class="x">X</div>'+ - ' <div class="circle"></div>'+ - '</li>' + this.view.wrapperEl.addClass("with_attachments"); + this.view.photozoneEl.html( + "<li class=\"publisher_photo\">."+ + " <img data-id=\"444\" />"+ + " <div class=\"x\">X</div>"+ + " <div class=\"circle\"></div>"+ + "</li>" ); spyOn(jQuery, 'ajax').and.callFake(function(opts) { opts.success(); }); - this.view.el_photozone.find('.x').click(); + this.view.photozoneEl.find(".x").click(); }); it('removes the element', function() { - var photo = this.view.el_photozone.find('li.publisher_photo'); + var photo = this.view.photozoneEl.find("li.publisher_photo"); expect(photo.length).toBe(0); }); @@ -603,10 +633,8 @@ describe("app.views.Publisher", function() { }); it('removes class on wrapper element', function() { - expect(this.view.el_wrapper.attr('class')).not.toContain('with_attachments'); + expect(this.view.wrapperEl.attr("class")).not.toContain("with_attachments"); }); }); }); - }); - diff --git a/spec/javascripts/app/views/reshares_info_view_spec.js b/spec/javascripts/app/views/reshares_info_view_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..b36853cc08e149da8e99bc37ac5350cd9cb0218d --- /dev/null +++ b/spec/javascripts/app/views/reshares_info_view_spec.js @@ -0,0 +1,46 @@ +describe("app.views.ResharesInfo", function(){ + beforeEach(function(){ + loginAs({id : -1, name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); + + var posts = $.parseJSON(spec.readFixture("stream_json")); + this.post = new app.models.Post(posts[0]); // post with a like + this.view = new app.views.ResharesInfo({model: this.post}); + }); + + describe(".render", function(){ + it("displays a the reshare count if it is above zero", function() { + spyOn(this.view.model.interactions, "resharesCount").and.returnValue(3); + this.view.render(); + expect($(this.view.el).find(".expand-reshares").length).toBe(1); + }); + + it("does not display the reshare count if it is zero", function() { + spyOn(this.view.model.interactions, "resharesCount").and.returnValue(0); + this.view.render(); + expect($(this.view.el).html().trim()).toBe(""); + }); + + it("fires on a model change", function(){ + spyOn(this.view, "postRenderTemplate"); + this.view.model.interactions.trigger("change"); + expect(this.view.postRenderTemplate).toHaveBeenCalled(); + }); + }); + + describe("showAvatars", function(){ + beforeEach(function(){ + spyOn(this.post.interactions, "fetch").and.callThrough(); + }); + + it("calls fetch on the model's reshare collection", function(){ + this.view.showAvatars(); + expect(this.post.interactions.fetch).toHaveBeenCalled(); + }); + + it("sets 'displayAvatars' to true", function(){ + this.view.displayAvatars = false; + this.view.showAvatars(); + expect(this.view.displayAvatars).toBeTruthy(); + }); + }); +}); diff --git a/spec/javascripts/app/views/search_base_view_spec.js b/spec/javascripts/app/views/search_base_view_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..5ed6be4db625c373fff4701c479d8d78e8bd47f9 --- /dev/null +++ b/spec/javascripts/app/views/search_base_view_spec.js @@ -0,0 +1,283 @@ +describe("app.views.SearchBase", function() { + beforeEach(function() { + spec.content().html( + "<form action='/search' id='search_people_form'><input id='q' name='q' type='search'/></form>" + ); + this.search = function(view, name) { + view.$("#q").trigger("focusin"); + view.$("#q").val(name); + view.$("#q").trigger("keypress"); + view.$("#q").trigger("input"); + view.$("#q").trigger("focus"); + }; + this.bloodhoundData = [ + {"person": true, "name": "user1", "handle": "user1@pod.tld"}, + {"person": true, "name": "user2", "handle": "user2@pod.tld"} + ]; + }); + + describe("initialize", function() { + it("calls setupBloodhound", function() { + spyOn(app.views.SearchBase.prototype, "setupBloodhound").and.callThrough(); + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + expect(app.views.SearchBase.prototype.setupBloodhound).toHaveBeenCalled(); + }); + + it("doesn't call setupCustomSearch if customSearch hasn't been enabled", function() { + spyOn(app.views.SearchBase.prototype, "setupCustomSearch"); + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + expect(app.views.SearchBase.prototype.setupCustomSearch).not.toHaveBeenCalled(); + }); + + it("calls setupCustomSearch if customSearch has been enabled", function() { + spyOn(app.views.SearchBase.prototype, "setupCustomSearch"); + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q"), customSearch: true}); + expect(app.views.SearchBase.prototype.setupCustomSearch).toHaveBeenCalled(); + }); + + it("calls setupTypeahead", function() { + spyOn(app.views.SearchBase.prototype, "setupTypeahead"); + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + expect(app.views.SearchBase.prototype.setupTypeahead).toHaveBeenCalled(); + }); + + it("calls setupMouseSelectionEvents", function() { + spyOn(app.views.SearchBase.prototype, "setupMouseSelectionEvents"); + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + expect(app.views.SearchBase.prototype.setupMouseSelectionEvents).toHaveBeenCalled(); + }); + + it("initializes the array of diaspora ids that should be excluded from the search results", function() { + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + expect(this.view.ignoreDiasporaIds.length).toBe(0); + }); + + it("doesn't call setupAutoselect if autoselect hasn't been enabled", function() { + spyOn(app.views.SearchBase.prototype, "setupAutoselect"); + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + expect(app.views.SearchBase.prototype.setupAutoselect).not.toHaveBeenCalled(); + }); + + it("calls setupAutoselect if autoselect has been enabled", function() { + spyOn(app.views.SearchBase.prototype, "setupAutoselect"); + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q"), autoselect: true}); + expect(app.views.SearchBase.prototype.setupAutoselect).toHaveBeenCalled(); + }); + }); + + describe("bloodhoundTokenizer", function() { + beforeEach(function() { + this.view = new app.views.SearchBase({ el: "#search_people_form", typeaheadInput: $("#q") }); + }); + + it("splits the string at whitespaces and punctuation chars", function() { + expect(this.view.bloodhoundTokenizer("ab.c-d_ef g;h,i #jkl?mnopq!rstu[vwx]::y(z){}")).toEqual( + ["ab", "c", "d", "ef", "g", "h", "i", "jkl", "mnopq", "rstu", "vwx", "y", "z"] + ); + }); + + it("doesn't split the string at Cyrillic chars", function() { + expect(this.view.bloodhoundTokenizer("ÐаБбВвГгДдЕеÐÑ‘ ЖжЗзИиЙйКкЛлМмÐнОоПпРрСÑТтУуФф")).toEqual( + ["ÐаБбВвГгДдЕеÐÑ‘", "ЖжЗзИиЙйКкЛлМмÐнОоПпРрСÑТтУуФф"] + ); + }); + + it("doesn't split the string at Malayalam chars", function() { + expect(this.view.bloodhoundTokenizer("ബിപിൻദാസàµ")).toEqual( + ["ബിപിൻദാസàµ"] + ); + }); + + it("returns an empty array inputs which are not a string", function() { + expect(this.view.bloodhoundTokenizer(undefined)).toEqual([]); + expect(this.view.bloodhoundTokenizer(null)).toEqual([]); + expect(this.view.bloodhoundTokenizer(23)).toEqual([]); + expect(this.view.bloodhoundTokenizer({foo: "bar"})).toEqual([]); + }); + }); + + describe("setupCustomSearch", function() { + it("sets bloodhound.customSearch", function() { + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + expect(this.view.bloodhound.customSearch).toBeUndefined(); + this.view.setupCustomSearch(); + expect(this.view.bloodhound.customSearch).toBeDefined(); + }); + + describe("customSearch", function() { + beforeEach(function() { + this.view = new app.views.SearchBase({ + el: "#search_people_form", + typeaheadInput: $("#q"), + customSearch: true, + remoteRoute: "/contacts" + }); + this.view.bloodhound.search = function(query, sync, async) { + sync([]); + async(this.bloodhoundData); + }.bind(this); + }); + + it("returns all results if none of them should be ignored", function() { + var spy = jasmine.createSpyObj("callbacks", ["syncCallback", "asyncCallback"]); + this.view.bloodhound.customSearch("user", spy.syncCallback, spy.asyncCallback); + expect(spy.asyncCallback).toHaveBeenCalledWith(this.bloodhoundData); + }); + + it("doesn't return results that should be ignored", function() { + var spy = jasmine.createSpyObj("callbacks", ["syncCallback", "asyncCallback"]); + this.view.ignorePersonForSuggestions({handle: "user1@pod.tld"}); + this.view.bloodhound.customSearch("user", spy.syncCallback, spy.asyncCallback); + expect(spy.asyncCallback).toHaveBeenCalledWith([this.bloodhoundData[1]]); + }); + }); + }); + + describe("transformBloodhoundResponse", function() { + beforeEach(function() { + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + }); + + context("with persons", function() { + beforeEach(function() { + this.response = [{name: "Person", handle: "person@pod.tld"},{name: "User", handle: "user@pod.tld"}]; + }); + + it("sets data.person to true", function() { + expect(this.view.transformBloodhoundResponse(this.response)).toEqual([ + {name: "Person", handle: "person@pod.tld", person: true}, + {name: "User", handle: "user@pod.tld", person: true} + ]); + }); + }); + + context("with hashtags", function() { + beforeEach(function() { + this.response = [{name: "#tag"}, {name: "#hashTag"}]; + }); + + it("sets data.hashtag to true and adds the correct URL", function() { + expect(this.view.transformBloodhoundResponse(this.response)).toEqual([ + {name: "#tag", hashtag: true, url: Routes.tag("tag")}, + {name: "#hashTag", hashtag: true, url: Routes.tag("hashTag")} + ]); + }); + }); + }); + + describe("setupMouseSelectionEvents", function() { + beforeEach(function() { + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + this.view.bloodhound.add(this.bloodhoundData); + }); + + it("binds mouseover and mouseleave events only once", function() { + this.search(this.view, "user"); + $("#q").trigger("focusout"); + expect($._data($(".tt-menu .tt-suggestion")[0], "events").mouseover.length).toBe(1); + expect($._data($(".tt-menu .tt-suggestion")[0], "events").mouseout.length).toBe(1); + + this.search(this.view, "user"); + $("#q").trigger("focusout"); + expect($._data($(".tt-menu .tt-suggestion")[0], "events").mouseover.length).toBe(1); + expect($._data($(".tt-menu .tt-suggestion")[0], "events").mouseout.length).toBe(1); + }); + + it("allows selecting results with the mouse", function() { + this.search(this.view, "user"); + this.view.$(".tt-menu .tt-suggestion:eq(0)").trigger("mouseover"); + expect(this.view.$(".tt-menu .tt-suggestion:eq(0)")).toHaveClass("tt-cursor"); + expect(this.view.$(".tt-cursor").length).toBe(1); + + this.view.$(".tt-menu .tt-suggestion:eq(1)").trigger("mouseover"); + expect(this.view.$(".tt-menu .tt-suggestion:eq(1)")).toHaveClass("tt-cursor"); + expect(this.view.$(".tt-cursor").length).toBe(1); + + this.view.$(".tt-menu .tt-suggestion:eq(1)").trigger("mouseleave"); + expect(this.view.$(".tt-cursor").length).toBe(0); + + this.view.$(".tt-menu .tt-suggestion:eq(0)").trigger("mouseover"); + expect(this.view.$(".tt-menu .tt-suggestion:eq(0)")).toHaveClass("tt-cursor"); + expect(this.view.$(".tt-cursor").length).toBe(1); + }); + }); + + describe("_deselectAllSuggestions", function() { + beforeEach(function() { + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + this.view.bloodhound.add(this.bloodhoundData); + this.search(this.view, "user"); + }); + + it("deselects all suggestions", function() { + $(".tt-suggestion").addClass(".tt-cursor"); + this.view._deselectAllSuggestions(); + expect($(".tt-suggestion.tt-cursor").length).toBe(0); + + $(".tt-suggestion:eq(1)").addClass(".tt-cursor"); + this.view._deselectAllSuggestions(); + expect($(".tt-suggestion.tt-cursor").length).toBe(0); + }); + }); + + describe("_selectSuggestion", function() { + beforeEach(function() { + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + this.view.bloodhound.add(this.bloodhoundData); + this.search(this.view, "user"); + }); + + it("selects a suggestion", function() { + this.view._selectSuggestion($(".tt-suggestion:eq(1)")); + expect($(".tt-suggestion.tt-cursor").length).toBe(1); + expect($(".tt-suggestion:eq(1)")).toHaveClass("tt-cursor"); + }); + + it("deselects all other suggestions", function() { + spyOn(this.view, "_deselectAllSuggestions").and.callThrough(); + $(".tt-suggestion:eq(0)").addClass(".tt-cursor"); + this.view._selectSuggestion($(".tt-suggestion:eq(1)")); + expect(this.view._deselectAllSuggestions).toHaveBeenCalled(); + expect($(".tt-suggestion.tt-cursor").length).toBe(1); + expect($(".tt-suggestion:eq(1)")).toHaveClass("tt-cursor"); + }); + }); + + describe("setupAutoSelect", function() { + beforeEach(function() { + this.view = new app.views.SearchBase({ + el: "#search_people_form", + typeaheadInput: $("#q"), + autoselect: true + }); + this.view.bloodhound.add(this.bloodhoundData); + }); + + it("selects the first suggestion when showing the results", function() { + this.search(this.view, "user"); + expect($(".tt-suggestion:eq(0)")).toHaveClass("tt-cursor"); + expect($(".tt-suggestion:eq(1)")).not.toHaveClass("tt-cursor"); + }); + }); + + describe("ignorePersonForSuggestions", function() { + beforeEach(function() { + this.view = new app.views.SearchBase({el: "#search_people_form", typeaheadInput: $("#q")}); + }); + + it("adds the diaspora ids to the ignore list", function() { + expect(this.view.ignoreDiasporaIds.length).toBe(0); + this.view.ignorePersonForSuggestions({handle: "user1@pod.tld"}); + expect(this.view.ignoreDiasporaIds.length).toBe(1); + this.view.ignorePersonForSuggestions({handle: "user2@pod.tld", someData: true}); + expect(this.view.ignoreDiasporaIds.length).toBe(2); + expect(this.view.ignoreDiasporaIds).toEqual(["user1@pod.tld", "user2@pod.tld"]); + }); + + it("doesn't fail when the diaspora id is missing", function() { + expect(this.view.ignoreDiasporaIds.length).toBe(0); + this.view.ignorePersonForSuggestions({data: "user1@pod.tld"}); + expect(this.view.ignoreDiasporaIds.length).toBe(0); + }); + }); +}); diff --git a/spec/javascripts/app/views/search_view_spec.js b/spec/javascripts/app/views/search_view_spec.js index ca23e6f7cd778b713e39b66a3df0132ca87b85db..74e4831ebda0f95339abcd2084af3183a920d9a0 100644 --- a/spec/javascripts/app/views/search_view_spec.js +++ b/spec/javascripts/app/views/search_view_spec.js @@ -1,14 +1,48 @@ describe("app.views.Search", function() { - beforeEach(function(){ - spec.content().html('<form action="#" id="search_people_form"></form>'); - this.view = new app.views.Search({ el: '#search_people_form' }); + beforeEach(function() { + spec.content().html( + "<form action='/search' id='search_people_form'><input id='q' name='q' type='search'/></form>" + ); }); - describe("parse", function() { - it("escapes a persons name", function() { - var person = { 'name': '</script><script>alert("xss");</script' }; - this.view.context = this.view; - var result = this.view.parse([$.extend({}, person)]); - expect(result[0].data.name).not.toEqual(person.name); + + describe("initialize", function() { + it("calls app.views.SearchBase.prototype.initialize", function() { + spyOn(app.views.SearchBase.prototype, "initialize"); + this.view = new app.views.Search({el: "#search_people_form"}); + var call = app.views.SearchBase.prototype.initialize.calls.mostRecent(); + expect(call.args[0].typeaheadInput.selector).toBe("#search_people_form #q"); + expect(call.args[0].remoteRoute).toBe("/search"); + }); + + it("binds typeahead:select", function() { + this.view = new app.views.Search({el: "#search_people_form"}); + expect($._data($("#q")[0], "events")["typeahead:select"].length).toBe(1); + }); + }); + + describe("toggleSearchActive", function() { + beforeEach(function() { + this.view = new app.views.Search({ el: "#search_people_form" }); + this.typeaheadInput = this.view.$("#q"); + }); + + context("focus", function() { + it("adds the class 'active' when the user focuses the text field", function() { + expect(this.typeaheadInput).not.toHaveClass("active"); + this.typeaheadInput.trigger("focusin"); + expect(this.typeaheadInput).toHaveClass("active"); + }); + }); + + context("blur", function() { + beforeEach(function() { + this.typeaheadInput.addClass("active"); + }); + + it("removes the class 'active' when the user blurs the text field", function() { + this.typeaheadInput.trigger("focusout"); + expect(this.typeaheadInput).not.toHaveClass("active"); + }); }); }); }); diff --git a/spec/javascripts/app/views/single_post_content_view_spec.js b/spec/javascripts/app/views/single_post_content_view_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..956866424990f1ddb1d5b4bad3a84eb881a38d49 --- /dev/null +++ b/spec/javascripts/app/views/single_post_content_view_spec.js @@ -0,0 +1,42 @@ +describe("app.views.SinglePostContent", function() { + beforeEach(function(){ + this.post = factory.post(); + this.view = new app.views.SinglePostContent({model : this.post}); + }); + + describe("map", function() { + context("with location provided", function() { + beforeEach(function(){ + this.post.set({location : factory.location()}); + spec.content().html(this.view.render().el); + gon.appConfig = { map: {mapbox: {enabled: false }}}; + }); + + it("initializes the leaflet map", function() { + spyOn(L, "map").and.callThrough(); + this.view.map(); + expect(L.map).toHaveBeenCalled(); + }); + + it("should add a map container", function() { + expect(spec.content()).toContainElement(".mapContainer"); + }); + }); + + context("without location provided", function() { + beforeEach(function(){ + spec.content().html(this.view.render().el); + }); + + it("doesn't initialize the leaflet map", function() { + spyOn(L, "map"); + this.view.map(); + expect(L.map).not.toHaveBeenCalled(); + }); + + it("shouldn't add a map container", function() { + expect(spec.content()).not.toContainElement(".mapContainer"); + }); + }); + }); +}); diff --git a/spec/javascripts/app/views/stream/shortcuts_spec.js b/spec/javascripts/app/views/stream/shortcuts_spec.js index a90b8ddd5a547a683fadbd586b626c1904a8836e..071a0605a83d7e30f24c8d37cbf7c6a5831c60ae 100644 --- a/spec/javascripts/app/views/stream/shortcuts_spec.js +++ b/spec/javascripts/app/views/stream/shortcuts_spec.js @@ -16,9 +16,7 @@ describe("app.views.StreamShortcuts", function () { describe("pressing 'j'", function(){ it("should call 'gotoNext' if not pressed in an input field", function(){ spyOn(this.view, 'gotoNext'); - var e = $.Event("keydown", { which: 74, target: {type: "div"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('j'); + var e = $.Event("keydown", { which: Keycodes.J, target: {type: "div"} }); this.view._onHotkeyDown(e); expect(this.view.gotoNext).toHaveBeenCalled(); }); @@ -32,9 +30,7 @@ describe("app.views.StreamShortcuts", function () { it("shouldn't do anything if the user types in an input field", function(){ spyOn(this.view, 'gotoNext'); spyOn(this.view, 'selectPost'); - var e = $.Event("keydown", { which: 74, target: {type: "textarea"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('j'); + var e = $.Event("keydown", { which: Keycodes.J, target: {type: "textarea"} }); this.view._onHotkeyDown(e); expect(this.view.gotoNext).not.toHaveBeenCalled(); expect(this.view.selectPost).not.toHaveBeenCalled(); @@ -44,9 +40,7 @@ describe("app.views.StreamShortcuts", function () { describe("pressing 'k'", function(){ it("should call 'gotoPrev' if not pressed in an input field", function(){ spyOn(this.view, 'gotoPrev'); - var e = $.Event("keydown", { which: 75, target: {type: "div"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('k'); + var e = $.Event("keydown", { which: Keycodes.K, target: {type: "div"} }); this.view._onHotkeyDown(e); expect(this.view.gotoPrev).toHaveBeenCalled(); }); @@ -60,9 +54,7 @@ describe("app.views.StreamShortcuts", function () { it("shouldn't do anything if the user types in an input field", function(){ spyOn(this.view, 'gotoPrev'); spyOn(this.view, 'selectPost'); - var e = $.Event("keydown", { which: 75, target: {type: "textarea"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('k'); + var e = $.Event("keydown", { which: Keycodes.K, target: {type: "textarea"} }); this.view._onHotkeyDown(e); expect(this.view.gotoPrev).not.toHaveBeenCalled(); expect(this.view.selectPost).not.toHaveBeenCalled(); @@ -72,18 +64,14 @@ describe("app.views.StreamShortcuts", function () { describe("pressing 'c'", function(){ it("should click on the comment-button if not pressed in an input field", function(){ spyOn(this.view, 'commentSelected'); - var e = $.Event("keyup", { which: 67, target: {type: "div"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('c'); + var e = $.Event("keyup", { which: Keycodes.C, target: {type: "div"} }); this.view._onHotkeyUp(e); expect(this.view.commentSelected).toHaveBeenCalled(); }); it("shouldn't do anything if the user types in an input field", function(){ spyOn(this.view, 'commentSelected'); - var e = $.Event("keyup", { which: 67, target: {type: "textarea"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('c'); + var e = $.Event("keyup", { which: Keycodes.C, target: {type: "textarea"} }); this.view._onHotkeyUp(e); expect(this.view.commentSelected).not.toHaveBeenCalled(); }); @@ -92,18 +80,14 @@ describe("app.views.StreamShortcuts", function () { describe("pressing 'l'", function(){ it("should click on the like-button if not pressed in an input field", function(){ spyOn(this.view, 'likeSelected'); - var e = $.Event("keyup", { which: 76, target: {type: "div"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('l'); + var e = $.Event("keyup", { which: Keycodes.L, target: {type: "div"} }); this.view._onHotkeyUp(e); expect(this.view.likeSelected).toHaveBeenCalled(); }); it("shouldn't do anything if the user types in an input field", function(){ spyOn(this.view, 'likeSelected'); - var e = $.Event("keyup", { which: 76, target: {type: "textarea"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('l'); + var e = $.Event("keyup", { which: Keycodes.L, target: {type: "textarea"} }); this.view._onHotkeyUp(e); expect(this.view.likeSelected).not.toHaveBeenCalled(); }); @@ -112,18 +96,14 @@ describe("app.views.StreamShortcuts", function () { describe("pressing 'r'", function(){ it("should click on the reshare-button if not pressed in an input field", function(){ spyOn(this.view, 'reshareSelected'); - var e = $.Event("keyup", { which: 82, target: {type: "div"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('r'); + var e = $.Event("keyup", { which: Keycodes.R, target: {type: "div"} }); this.view._onHotkeyUp(e); expect(this.view.reshareSelected).toHaveBeenCalled(); }); it("shouldn't do anything if the user types in an input field", function(){ spyOn(this.view, 'reshareSelected'); - var e = $.Event("keyup", { which: 82, target: {type: "textarea"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('r'); + var e = $.Event("keyup", { which: Keycodes.R, target: {type: "textarea"} }); this.view._onHotkeyUp(e); expect(this.view.reshareSelected).not.toHaveBeenCalled(); }); @@ -132,18 +112,14 @@ describe("app.views.StreamShortcuts", function () { describe("pressing 'm'", function(){ it("should click on the more-button if not pressed in an input field", function(){ spyOn(this.view, 'expandSelected'); - var e = $.Event("keyup", { which: 77, target: {type: "div"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('m'); + var e = $.Event("keyup", { which: Keycodes.M, target: {type: "div"} }); this.view._onHotkeyUp(e); expect(this.view.expandSelected).toHaveBeenCalled(); }); it("shouldn't do anything if the user types in an input field", function(){ spyOn(this.view, 'expandSelected'); - var e = $.Event("keyup", { which: 77, target: {type: "textarea"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('m'); + var e = $.Event("keyup", { which: Keycodes.M, target: {type: "textarea"} }); this.view._onHotkeyUp(e); expect(this.view.expandSelected).not.toHaveBeenCalled(); }); @@ -152,18 +128,14 @@ describe("app.views.StreamShortcuts", function () { describe("pressing 'o'", function(){ it("should click on the more-button if not pressed in an input field", function(){ spyOn(this.view, 'openFirstLinkSelected'); - var e = $.Event("keyup", { which: 79, target: {type: "div"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('o'); + var e = $.Event("keyup", { which: Keycodes.O, target: {type: "div"} }); this.view._onHotkeyUp(e); expect(this.view.openFirstLinkSelected).toHaveBeenCalled(); }); it("shouldn't do anything if the user types in an input field", function(){ spyOn(this.view, 'openFirstLinkSelected'); - var e = $.Event("keyup", { which: 79, target: {type: "textarea"} }); - //verify that the test is correct - expect(String.fromCharCode( e.which ).toLowerCase()).toBe('o'); + var e = $.Event("keyup", { which: Keycodes.O, target: {type: "textarea"} }); this.view._onHotkeyUp(e); expect(this.view.openFirstLinkSelected).not.toHaveBeenCalled(); }); diff --git a/spec/javascripts/app/views/stream_faces_view_spec.js b/spec/javascripts/app/views/stream_faces_view_spec.js deleted file mode 100644 index af42b3c6d7f77de7cc219ad39e89eff5504d7d91..0000000000000000000000000000000000000000 --- a/spec/javascripts/app/views/stream_faces_view_spec.js +++ /dev/null @@ -1,54 +0,0 @@ -describe("app.views.StreamFaces", function(){ - beforeEach(function(){ - var rebeccaBlack = factory.author({name : "Rebecca Black", id : 1492}); - this.post1 = factory.post({author : rebeccaBlack}); - this.post2 = factory.post({author : factory.author({name : "John Stamos", id : 1987})}); - this.post3 = factory.post({author : factory.author({name : "Michelle Tanner", id : 1986})}); - this.post4 = factory.post({author : factory.author({name : "Barack Obama", id : 2000})}); - this.post5 = factory.post({author : factory.author({name : "Obi-wan Kenobi", id : 2020})}); - this.post6 = factory.post({author : rebeccaBlack}); - this.post7 = factory.post({author : rebeccaBlack}); - - app.stream = new app.models.Stream(); - app.stream.add([this.post1, this.post2, this.post3, this.post4, this.post5, this.post6, this.post7]); - this.posts = app.stream.items; - - this.view = new app.views.StreamFaces({collection : this.posts}); - }); - - it("should take them unique", function(){ - this.view.render(); - expect(this.view.people.length).toBe(5); - }); - - it("Finds people that were added to the collection", function() { - this.posts.add(factory.post({author : factory.author({name : "Harriet Tubman"})})); - expect(this.view.people.length).toBe(6); - }); - - it("Finds people that were removed from the collection", function() { - this.posts.remove([this.post2, this.post3]); - expect(this.view.people.length).toBe(3); - }); - - describe(".render", function(){ - beforeEach(function(){ - this.view.render(); - }); - - it("appends the people's avatars", function(){ - expect(this.view.$("img").length).toBe(5); - }); - - it("links to the people", function(){ - expect(this.view.$("a").length).toBe(5); - }); - - it("rerenders when people are added, but caps to 15 people", function(){ - var posts = _.map(_.range(20), function(){ return factory.post()}); - this.posts.reset(posts); //add 20 posts silently to the collection - this.posts.add(factory.post()); //trigger an update - expect(this.view.$("img").length).toBe(15); - }); - }); -}); diff --git a/spec/javascripts/app/views/stream_post_spec.js b/spec/javascripts/app/views/stream_post_spec.js index 47084bd6e600af8395b55217f03bcda0ea9cb234..d36a95e4ad97756dff9bd16daa23db12a4d3c079 100644 --- a/spec/javascripts/app/views/stream_post_spec.js +++ b/spec/javascripts/app/views/stream_post_spec.js @@ -6,6 +6,7 @@ describe("app.views.StreamPost", function(){ this.collection = new app.collections.Posts(posts); this.statusMessage = this.collection.models[0]; this.reshare = this.collection.models[1]; + app.stream = new app.models.Stream(); }); describe("events", function(){ @@ -52,32 +53,18 @@ describe("app.views.StreamPost", function(){ beforeEach(function(){ loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); - - Diaspora.I18n.load({stream : { - reshares : { - one : "<%= count %> reshare", - other : "<%= count %> reshares" - }, - likes : { - zero : "<%= count %> Likes", - one : "<%= count %> Like", - other : "<%= count %> Likes" - } - }}); }); - context("reshare", function(){ + context("reshares", function(){ it("displays a reshare count", function(){ - this.statusMessage.set({ interactions: {reshares_count : 2 }}); + this.statusMessage.interactions.set({"reshares_count": 2}); var view = new this.PostViewClass({model : this.statusMessage}).render(); - expect($(view.el).html()).toContain(Diaspora.I18n.t('stream.reshares', {count: 2})); }); it("does not display a reshare count for 'zero'", function(){ - this.statusMessage.interactions.set({ interactions: { reshares_count : 0}} ); + this.statusMessage.interactions.set({"reshares_count": 0}); var view = new this.PostViewClass({model : this.statusMessage}).render(); - expect($(view.el).html()).not.toContain("0 Reshares"); }); }); @@ -86,13 +73,12 @@ describe("app.views.StreamPost", function(){ it("displays a like count", function(){ this.statusMessage.interactions.set({likes_count : 1}); var view = new this.PostViewClass({model : this.statusMessage}).render(); - expect($(view.el).html()).toContain(Diaspora.I18n.t('stream.likes', {count: 1})); }); + it("does not display a like count for 'zero'", function(){ this.statusMessage.interactions.set({likes_count : 0}); var view = new this.PostViewClass({model : this.statusMessage}).render(); - expect($(view.el).html()).not.toContain("0 Likes"); }); }); diff --git a/spec/javascripts/app/views/tag_following_action_view_spec.js b/spec/javascripts/app/views/tag_following_action_view_spec.js index 8639ee5fa86ec7e4d5d4c2141bb0c88d331a0bd5..17769de1154e135cb75dfe8d7d3c8e039270e432 100644 --- a/spec/javascripts/app/views/tag_following_action_view_spec.js +++ b/spec/javascripts/app/views/tag_following_action_view_spec.js @@ -14,8 +14,8 @@ describe("app.views.TagFollowingAction", function(){ it("should have the extra classes if the tag is followed", function(){ spyOn(this.view, "tag_is_followed").and.returnValue(true); - expect(this.view.render().$('input').hasClass("followed")).toBe(true); - expect(this.view.render().$('input').hasClass("green")).toBe(true); + expect(this.view.render().$("input").hasClass("followed")).toBe(true); + expect(this.view.render().$("input").hasClass("btn-success")).toBe(true); }); }); diff --git a/spec/javascripts/app/views_spec.js b/spec/javascripts/app/views_spec.js index ae3cb5a48480261b0e28f21b970384b60ba496bf..6992f0372e48af1c986c34b9b04e90e0ff93971e 100644 --- a/spec/javascripts/app/views_spec.js +++ b/spec/javascripts/app/views_spec.js @@ -1,10 +1,12 @@ describe("app.views.Base", function(){ + beforeEach(function(){ + var StaticTemplateClass = app.views.Base.extend({ templateName : "static-text" }); + this.model = new Backbone.Model({text : "model attributes are in the default presenter"}); + this.view = new StaticTemplateClass({model: this.model}); + }); + describe("#render", function(){ beforeEach(function(){ - var staticTemplateClass = app.views.Base.extend({ templateName : "static-text" }); - - this.model = new Backbone.Model({text : "model attributes are in the default presenter"}); - this.view = new staticTemplateClass({model: this.model}); this.view.render(); }); @@ -83,10 +85,40 @@ describe("app.views.Base", function(){ it("renders the sub views from functions", function(){ expect(this.view.$('.subview2').text().trim()).toBe("furreal this is the Second Subview"); }); + + context("with nested matching elements", function() { + var subviewInstance; + + beforeEach(function() { + var counter = 0; + var Subview = app.views.Base.extend({ + templateName: "static-text", + + className: "subview1", // making the internal view's div class match to the external one + + presenter: function() { + return {text: "rendered " + ++counter + " times"}; + } + }); + + this.view.templateName = false; // this is also important specification for the test below + this.view.subview1 = function() { + subviewInstance = new Subview(); + return subviewInstance; + }; + }); + + it("properly handles nested selectors case", function() { + this.view.render(); + this.view.render(); + subviewInstance.render(); + expect(this.view.$(".subview1 .subview1").text()).toBe("rendered 3 times"); + }); + }); }); - context("calling out to third party plugins", function(){ - it("replaces .time with relative time ago in words", function(){ + context("calling out to third party plugins", function() { + it("replaces .time with relative time ago in words", function() { spyOn($.fn, "timeago"); this.view.render(); expect($.fn.timeago).toHaveBeenCalled(); @@ -109,4 +141,20 @@ describe("app.views.Base", function(){ }); }); }); + + describe("#renderTemplate", function(){ + it("calls jQuery.placeholder() for inputs", function() { + spyOn($.fn, "placeholder"); + this.view.renderTemplate(); + expect($.fn.placeholder).toHaveBeenCalled(); + expect($.fn.placeholder.calls.mostRecent().object.selector).toBe("input, textarea"); + }); + + it("initializes autosize for textareas", function(){ + spyOn(window, "autosize"); + this.view.renderTemplate(); + expect(window.autosize).toHaveBeenCalled(); + expect(window.autosize.calls.mostRecent().args[0].selector).toBe("textarea"); + }); + }); }); diff --git a/spec/javascripts/bookmarklet-spec.js b/spec/javascripts/bookmarklet-spec.js new file mode 100644 index 0000000000000000000000000000000000000000..d12fd6e47604f6393fea3958ddf6468d9f954322 --- /dev/null +++ b/spec/javascripts/bookmarklet-spec.js @@ -0,0 +1,25 @@ +describe("bookmarklet", function(){ + var fakeUrl = "http://pod.example.com/bookmarklet"; + + it("opens a popup window", function(){ + spyOn(window, "open").and.returnValue(true); + bookmarklet(fakeUrl, 800, 600); + jasmine.clock().tick(1); + expect(window.open).toHaveBeenCalled(); + }); + + it("shortens the GET string to less than 2000 characters", function(){ + var url, + selTxt = new Array(1000).join("abcdefghijklmnopqrstuvwxyz1234567890"); + + spyOn(window, "open").and.callFake(function(_url){ + url = _url; + return true; + }); + spyOn(window, "getSelection").and.returnValue(selTxt); + + bookmarklet(fakeUrl, 800, 600); + jasmine.clock().tick(1); + expect(url.length).toBeLessThan(2000); + }); +}); diff --git a/spec/javascripts/helpers/i18n_spec.js b/spec/javascripts/helpers/i18n_spec.js index 2315957ce93afb27cbb0acd9aa2796cc8d038fa2..79dfabe27f1546b6c537fbc494403cb71ed52ab6 100644 --- a/spec/javascripts/helpers/i18n_spec.js +++ b/spec/javascripts/helpers/i18n_spec.js @@ -24,6 +24,10 @@ describe("Diaspora.I18n", function() { Diaspora.I18n.reset(); // run tests with clean locale }); + afterEach(function() { + Diaspora.I18n.load(spec.defaultLocale, "en"); // leave the tests with the default locale + }); + describe("::load", function() { it("sets the class's locale variable", function() { Diaspora.I18n.load(locale, "en", locale); @@ -65,8 +69,10 @@ describe("Diaspora.I18n", function() { expect(translation).toEqual("it works!"); }); - it("returns an empty string if the translation is not found", function() { - expect(Diaspora.I18n.t("missing.locale")).toEqual(""); + it("throws an error if the translation is not found", function() { + expect(function() { + return Diaspora.I18n.t("missing.locale"); + }).toThrowError("Missing translation: missing.locale"); }); it("falls back on missing key", function() { @@ -90,6 +96,7 @@ describe("Diaspora.I18n", function() { Diaspora.I18n.load(locale, "en", locale); Diaspora.I18n.reset(); expect(Diaspora.I18n.locale.data).toEqual({}); + expect(Diaspora.I18n.locale.fallback.data).toEqual({}); }); it("sets the locale to only a specific value", function() { @@ -97,6 +104,7 @@ describe("Diaspora.I18n", function() { Diaspora.I18n.load(locale, "en", locale); Diaspora.I18n.reset(data); expect(Diaspora.I18n.locale.data).toEqual(data); + expect(Diaspora.I18n.locale.fallback.data).toEqual(data); }); }); }); diff --git a/spec/javascripts/helpers/markdown_editor_spec.js b/spec/javascripts/helpers/markdown_editor_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..9c2ab4cff72d5e79640e39dd1ef676b6d2ab37bc --- /dev/null +++ b/spec/javascripts/helpers/markdown_editor_spec.js @@ -0,0 +1,237 @@ +describe("Diaspora.MarkdownEditor", function() { + beforeEach(function() { + spec.content().html("<textarea id='fake-textarea'></textarea>"); + this.$el = $("#fake-textarea"); + }); + + describe("constructor", function() { + it("calls initialize", function() { + spyOn(Diaspora.MarkdownEditor.prototype, "initialize"); + new Diaspora.MarkdownEditor(this.$el, {}); + expect(Diaspora.MarkdownEditor.prototype.initialize).toHaveBeenCalledWith(this.$el, {}); + }); + }); + + describe("initialize", function() { + beforeEach(function() { + this.target = new Diaspora.MarkdownEditor($("<textarea></textarea>"), {}); + }); + + it("calls localize", function() { + spyOn(Diaspora.MarkdownEditor.prototype, "localize"); + this.target.initialize(this.$el, {}); + expect(Diaspora.MarkdownEditor.prototype.localize).toHaveBeenCalled(); + }); + + it("calls onShow", function() { + spyOn(Diaspora.MarkdownEditor.prototype, "onShow"); + this.target.initialize(this.$el, {}); + expect(Diaspora.MarkdownEditor.prototype.onShow).toHaveBeenCalled(); + }); + + it("call $.fn.markdown with correct default options", function() { + spyOn($.fn, "markdown"); + this.target.initialize(this.$el, {}); + expect($.fn.markdown).toHaveBeenCalled(); + var args = $.fn.markdown.calls.mostRecent().args[0]; + expect(args.resize).toBe("none"); + expect(args.language).toBe("en"); + expect(args.onHidePreview).toBe($.noop); + expect(args.onPostPreview).toBe($.noop); + expect(args.fullscreen).toEqual({enable: false, icons: {}}); + expect(args.hiddenButtons).toEqual(["cmdPreview"]); + }); + + it("overrides fullscreen, hiddenButtons, language and onShow options", function() { + spyOn($.fn, "markdown").and.callThrough(); + spyOn(Diaspora.MarkdownEditor.prototype, "onShow"); + spyOn(Diaspora.MarkdownEditor.prototype, "localize").and.callThrough(); + this.target.initialize(this.$el, { + fullscreen: {enabled: true, icons: {somekey: "somevalue"}}, + hiddenButtons: [], + language: "fr", + onShow: $.noop + }); + var args = $.fn.markdown.calls.mostRecent().args[0]; + expect(args.fullscreen).toEqual({enable: false, icons: {}}); + expect(args.hiddenButtons).toEqual(["cmdPreview"]); + expect(args.language).toBe("en"); + expect(args.onShow).not.toBe($.noop); + expect(Diaspora.MarkdownEditor.prototype.onShow).toHaveBeenCalled(); + expect(Diaspora.MarkdownEditor.prototype.localize).toHaveBeenCalled(); + }); + }); + + describe("onShow", function() { + beforeEach(function() { + this.target = new Diaspora.MarkdownEditor(this.$el, {}); + this.$el.find(".md-header").remove(".write-preview-tabs"); + this.$el.find(".md-header").remove(".md-cancel"); + }); + + it("retreives the $.fn.markdown instance back", function() { + var fakeInstance = {$editor: $("body")}; + this.target.onShow(fakeInstance); + expect(this.target.instance).toBe(fakeInstance); + }); + + it("calls createTabsElement createCloseElement if preview and close functions are given", function() { + spyOn(Diaspora.MarkdownEditor.prototype, "createTabsElement"); + spyOn(Diaspora.MarkdownEditor.prototype, "createCloseElement"); + this.target.options.onPreview = $.noop; + this.target.options.onClose = $.noop; + this.target.onShow(this.target.instance); + expect(Diaspora.MarkdownEditor.prototype.createTabsElement).toHaveBeenCalled(); + expect(Diaspora.MarkdownEditor.prototype.createCloseElement).toHaveBeenCalled(); + }); + + it("does not call createTabsElement createCloseElement if no preview and close functions are given", function() { + spyOn(Diaspora.MarkdownEditor.prototype, "createTabsElement"); + spyOn(Diaspora.MarkdownEditor.prototype, "createCloseElement"); + delete this.target.options.onPreview; + delete this.target.options.onClose; + this.target.onShow(this.target.instance); + expect(Diaspora.MarkdownEditor.prototype.createCloseElement).not.toHaveBeenCalled(); + expect(Diaspora.MarkdownEditor.prototype.createTabsElement).not.toHaveBeenCalled(); + }); + + it("creates the preview and write tabs", function() { + this.target.options.onPreview = $.noop; + this.target.onShow(this.target.instance); + expect($(".md-header .write-preview-tabs").length).toBe(1); + }); + + it("removes preview tabs if already existing", function() { + this.target.options.onPreview = $.noop; + this.$el.find(".md-header").prepend("<div id='fake-write-preview-tabs' class='write-preview-tabs'/>"); + this.target.onShow(this.target.instance); + expect($(".md-header .write-preview-tabs").length).toBe(1); + expect($("#fake-write-preview-tabs").length).toBe(0); + }); + + it("creates the cancel button", function() { + this.target.options.onClose = $.noop; + this.target.onShow(this.target.instance); + expect($(".md-header .md-cancel").length).toBe(1); + }); + + it("removes cancel button if already existing", function() { + this.target.options.onClose = $.noop; + this.$el.find(".md-header").prepend("<div id='fake-md-cancel' class='md-cancel'/>"); + this.target.onShow(this.target.instance); + expect($(".md-header .md-cancel").length).toBe(1); + expect($("#fake-md-cancel").length).toBe(0); + }); + }); + + describe("createTabsElement", function() { + beforeEach(function() { + this.target = new Diaspora.MarkdownEditor(this.$el, {}); + }); + + it("correctly creates the preview tabs", function() { + var tabsElement = this.target.createTabsElement(); + expect(tabsElement).toHaveClass("write-preview-tabs"); + expect(tabsElement.find("> li > a.md-write-tab").attr("title")).toBe("Edit message"); + expect(tabsElement.find("> li > a.md-write-tab > i.diaspora-custom-compose").length).toBe(1); + expect(tabsElement.find("> li > a.md-write-tab > span.tab-help-text").length).toBe(1); + expect(tabsElement.find("> li > a.md-write-tab > span.tab-help-text").text()).toBe("Write"); + expect(tabsElement.find("> li > a.md-preview-tab").attr("title")).toBe("Preview message"); + expect(tabsElement.find("> li > a.md-preview-tab > i.entypo-search").length).toBe(1); + expect(tabsElement.find("> li > a.md-preview-tab > span.tab-help-text").length).toBe(1); + expect(tabsElement.find("> li > a.md-preview-tab > span.tab-help-text").text()).toBe("Preview"); + }); + + it("correctly binds onclick events", function() { + var tabsElement = this.target.createTabsElement(); + spyOn(Diaspora.MarkdownEditor.prototype, "hidePreview"); + spyOn(Diaspora.MarkdownEditor.prototype, "showPreview"); + tabsElement.find("> li > a.md-write-tab").click(); + expect(Diaspora.MarkdownEditor.prototype.hidePreview).toHaveBeenCalled(); + tabsElement.find("> li > a.md-preview-tab").click(); + expect(Diaspora.MarkdownEditor.prototype.showPreview).toHaveBeenCalled(); + }); + }); + + describe("createCloseElement", function() { + beforeEach(function() { + this.target = new Diaspora.MarkdownEditor(this.$el, {}); + }); + + it("correctly creates the close button", function() { + var closeElement = this.target.createCloseElement(); + expect(closeElement).toHaveClass("md-cancel"); + expect(closeElement.get(0).tagName).toBe("A"); + expect(closeElement.attr("title")).toBe("Cancel message"); + expect(closeElement.find("> i.entypo-cross").length).toBe(1); + }); + + it("correctly binds onclick events", function() { + this.target.options.onClose = jasmine.createSpy(); + var closeElement = this.target.createCloseElement(); + closeElement.click(); + expect(this.target.options.onClose).toHaveBeenCalled(); + }); + }); + + describe("hidePreview", function() { + beforeEach(function() { + this.target = new Diaspora.MarkdownEditor(this.$el, {onPreview: $.noop, onHidePreview: jasmine.createSpy()}); + spyOn(this.target.instance, "hidePreview"); + spyOn(this.target.writeLink, "tab"); + }); + + it("calls writeLink.tab", function() { + this.target.hidePreview(); + expect(this.target.writeLink.tab).toHaveBeenCalledWith("show"); + }); + + it("calls instance.hidePreview", function() { + this.target.hidePreview(); + expect(this.target.instance.hidePreview).toHaveBeenCalled(); + }); + + it("calls instance.onHidePreview", function() { + this.target.hidePreview(); + expect(this.target.options.onHidePreview).toHaveBeenCalled(); + }); + }); + + describe("showPreview", function() { + beforeEach(function() { + this.target = new Diaspora.MarkdownEditor(this.$el, {onPreview: $.noop, onPostPreview: jasmine.createSpy()}); + spyOn(this.target.instance, "showPreview"); + spyOn(this.target.previewLink, "tab"); + }); + + it("calls previewLink.tab", function() { + this.target.showPreview(); + expect(this.target.previewLink.tab).toHaveBeenCalledWith("show"); + }); + + it("calls instance.showPreview", function() { + this.target.showPreview(); + expect(this.target.instance.showPreview).toHaveBeenCalled(); + }); + + it("calls instance.onPostPreview", function() { + this.target.showPreview(); + expect(this.target.options.onPostPreview).toHaveBeenCalled(); + }); + }); + + describe("localize", function() { + beforeEach(function() { + this.target = new Diaspora.MarkdownEditor(this.$el, {}); + }); + + it("returns the correct locale", function() { + expect(this.target.localize()).toBe(Diaspora.I18n.language); + }); + + it("creates translation messages for the current locale", function() { + this.target.localize(); + expect($.fn.markdown.messages[Diaspora.I18n.language]).toBeDefined(); + }); + }); +}); diff --git a/spec/javascripts/jasmine_helpers/SpecHelper.js b/spec/javascripts/jasmine_helpers/SpecHelper.js index 9e7ac46cc9871bf07e6c7205900ce5a9fbd72f8c..5316752100a832e9e6ca58ecf790539ef612f884 100644 --- a/spec/javascripts/jasmine_helpers/SpecHelper.js +++ b/spec/javascripts/jasmine_helpers/SpecHelper.js @@ -3,15 +3,12 @@ var realXMLHttpRequest = window.XMLHttpRequest; // matches flash messages with success/error and contained text -var flashMatcher = function(flash, id, text) { +var flashMatcher = function(flash, klass, text) { var textContained = true; - if( text ) { - textContained = (flash.text().indexOf(text) !== -1); + if(text) { + textContained = (flash.text().trim().indexOf(text) !== -1); } - - return flash.is(id) && - flash.hasClass('expose') && - textContained; + return flash.hasClass(klass) && flash.parent().hasClass("expose") && textContained; }; // information for jshint @@ -24,7 +21,7 @@ var customMatchers = { return { compare: function(actual, expected) { var result = {}; - result.pass = flashMatcher(actual, '#flash_notice', expected); + result.pass = flashMatcher(actual, "alert-success", expected); return result; } }; @@ -33,17 +30,14 @@ var customMatchers = { return { compare: function(actual, expected) { var result = {}; - result.pass = flashMatcher(actual, '#flash_error', expected); + result.pass = flashMatcher(actual, "alert-danger", expected); return result; } }; } }; - beforeEach(function() { - $('#jasmine_content').html(spec.readFixture("underscore_templates")); - jasmine.clock().install(); jasmine.Ajax.install(); @@ -57,18 +51,26 @@ beforeEach(function() { var Page = Diaspora.Pages["TestPage"]; $.extend(Page.prototype, Diaspora.EventBroker.extend(Diaspora.BaseWidget)); - Diaspora.I18n.load({}, 'en', {}); - Diaspora.page = new Page(); Diaspora.page.publish("page/ready", [$(document.body)]); // add custom matchers for flash messages jasmine.addMatchers(customMatchers); + + // PhantomJS 1.9.8 doesn't support bind yet + // See https://github.com/ariya/phantomjs/issues/10522 + // and https://github.com/colszowka/phantomjs-gem + /* jshint -W121 */ + Function.prototype.bind = Function.prototype.bind || function (thisp) { + var fn = this; + return function () { + return fn.apply(thisp, arguments); + }; + }; + /* jshint +W121 */ }); afterEach(function() { - //spec.clearLiveEventBindings(); - jasmine.clock().uninstall(); jasmine.Ajax.uninstall(); @@ -100,49 +102,13 @@ window.logout = function logout(){ return app.currentUser; }; -window.hipsterIpsumFourParagraphs = "Mcsweeney's mumblecore irony fugiat, ex iphone brunch helvetica eiusmod retro" + - " sustainable mlkshk. Pop-up gentrify velit readymade ad exercitation 3 wolf moon. Vinyl aute laboris artisan irony, " + - "farm-to-table beard. Messenger bag trust fund pork belly commodo tempor street art, nihil excepteur PBR lomo laboris." + - " Cosby sweater american apparel occupy, locavore odio put a bird on it fixie kale chips. Pariatur semiotics flexitarian " + - "veniam, irure freegan irony tempor. Consectetur sriracha pour-over vice, umami exercitation farm-to-table master " + - "cleanse art party." + "\n" + - - "Quinoa nostrud street art helvetica et single-origin coffee, stumptown bushwick selvage skateboard enim godard " + - "before they sold out tumblr. Portland aesthetic freegan pork belly, truffaut occupy assumenda banksy 3 wolf moon " + - "irure forage terry richardson nulla. Anim nostrud selvage sartorial organic. Consequat pariatur aute fugiat qui, " + - "organic marfa sunt gluten-free mcsweeney's elit hella whatever wayfarers. Leggings pariatur chambray, ullamco " + - "flexitarian esse sed iphone pinterest messenger bag Austin cred DIY. Duis enim squid mcsweeney's, nisi lo-fi " + - "sapiente. Small batch vegan thundercats locavore williamsburg, non aesthetic trust fund put a bird on it gluten-free " + - "consectetur." + "\n" + - - "Viral reprehenderit iphone sapiente exercitation. Enim nostrud letterpress, tempor typewriter dreamcatcher tattooed." + - " Ex godard pariatur voluptate est, polaroid hoodie ea nulla umami pickled tempor portland. Nostrud food truck" + - "single-origin coffee skateboard. Fap enim tumblr retro, nihil twee trust fund pinterest non jean shorts veniam " + - "fingerstache small batch. Cred whatever photo booth sed, et dolore gastropub duis freegan. Authentic quis butcher, " + - "fanny pack art party cupidatat readymade semiotics kogi consequat polaroid shoreditch ad four loko." + "\n" + - - "PBR gluten-free ullamco exercitation narwhal in godard occaecat bespoke street art veniam aesthetic jean shorts " + - "mlkshk assumenda. Typewriter terry richardson pork belly, cupidatat tempor craft beer tofu sunt qui gentrify eiusmod " + - "id. Letterpress pitchfork wayfarers, eu sunt lomo helvetica pickled dreamcatcher bicycle rights. Aliqua banksy " + - "cliche, sapiente anim chambray williamsburg vinyl cardigan. Pork belly mcsweeney's anim aliqua. DIY vice portland " + - "thundercats est vegan etsy, gastropub helvetica aliqua. Artisan jean shorts american apparel duis esse trust fund."; - -spec.clearLiveEventBindings = function() { - var events = jQuery.data(document, "events"); - for (var prop in events) { - if(events.hasOwnProperty(prop)) { - delete events[prop]; - } - } -}; - spec.content = function() { - return $('#jasmine_content'); + return $("#jasmine_content"); }; // Loads fixure markup into the DOM as a child of the jasmine_content div spec.loadFixture = function(fixtureName) { - var $destination = $('#jasmine_content'); + var $destination = $("#jasmine_content"); // get the markup, inject it into the dom $destination.html(spec.fixtureHtml(fixtureName)); @@ -169,7 +135,7 @@ spec.fixtureHtml = function(fixtureName) { spec.retrieveFixture = function(fixtureName) { // construct a path to the fixture, including a cache-busting timestamp - var path = '/tmp/js_dom_fixtures/' + fixtureName + ".fixture.html?" + new Date().getTime(); + var path = "/tmp/js_dom_fixtures/" + fixtureName + ".fixture.html?" + new Date().getTime(); var xhr; // retrieve the fixture markup via xhr request to jasmine server @@ -188,6 +154,8 @@ spec.retrieveFixture = function(fixtureName) { return xhr.responseText; }; - spec.loadFixtureCount = 0; spec.cachedFixtures = {}; + +spec.defaultLocale = JSON.parse(spec.readFixture("locale_en_javascripts_json")); +Diaspora.I18n.reset(spec.defaultLocale); diff --git a/spec/javascripts/jasmine_helpers/factory.js b/spec/javascripts/jasmine_helpers/factory.js index 5b812a48ca40f0ca6260b99d6fb396ebb07a0fc0..d214356513d51f6480fcc1e75c176785a1873f02 100644 --- a/spec/javascripts/jasmine_helpers/factory.js +++ b/spec/javascripts/jasmine_helpers/factory.js @@ -21,6 +21,16 @@ var factory = { return _.extend(defaultAttrs, overrides); }, + aspectMembershipAttrs: function(overrides) { + var id = this.id.next(); + var defaultAttrs = { + "id": id, + "aspect": factory.aspectAttrs() + }; + + return _.extend(defaultAttrs, overrides); + }, + comment : function(overrides) { var defaultAttrs = { "created_at" : "2012-01-04T00:55:30Z", @@ -33,6 +43,18 @@ var factory = { return new app.models.Comment(_.extend(defaultAttrs, overrides)); }, + contact: function(overrides) { + var person = factory.personAttrs(); + var attrs = { + "id": this.id.next(), + "person_id": person.id, + "person": person, + "aspect_memberships": factory.aspectMembershipAttrs() + }; + + return new app.models.Contact(_.extend(attrs, overrides)); + }, + user : function(overrides) { return new app.models.User(factory.userAttrs(overrides)); }, @@ -54,18 +76,17 @@ var factory = { postAttrs : function(){ return { + "author": {}, "provider_display_name" : null, "created_at" : "2012-01-03T19:53:13Z", "interacted_at" : '2012-01-03T19:53:13Z', "public" : false, "guid" : this.guid(), - "image_url" : null, "o_embed_cache" : null, "open_graph_cache": null, "photos" : [], "text" : "jasmine is bomb", "id" : this.id.next(), - "object_url" : null, "root" : null, "post_type" : "StatusMessage", "interactions" : { @@ -148,6 +169,14 @@ var factory = { }, overrides); }, + location : function() { + return { + address: "Starco Mart, Mission Street, San Francisco, Kalifornien, 94103, Vereinigte Staaten von Amerika", + lat: 37.78, + lng: -122.41 + }; + }, + post : function(overrides) { var defaultAttrs = _.extend(factory.postAttrs(), {"author" : this.author()}); return new app.models.Post(_.extend(defaultAttrs, overrides)); @@ -181,6 +210,7 @@ var factory = { aspectAttrs: function(overrides) { var names = ['Work','School','Family','Friends','Just following','People','Interesting']; var defaultAttrs = { + id: this.id.next(), name: names[Math.floor(Math.random()*names.length)]+' '+Math.floor(Math.random()*100), selected: false }; @@ -203,6 +233,24 @@ var factory = { window.gon = { preloads: {} }; _.extend(window.gon.preloads, defaults, overrides); + }, + + pod: function(overrides) { + var defaultAttrs = { + "id": 4, + "host": "pod.example.org", + "port": null, + "ssl": true, + "status": "no_errors", + "checked_at": "2020-01-01T13:37:00.000Z", + "response_time": 100, + "offline": false, + "offline_since": null, + "created_at": "2010-01-01T13:37:00.000Z", + "software": "diaspora 1.2.3.0", + "error": "ConnectionTester::Failure: #<Faraday::TimeoutError>" + }; + return new app.models.Pod(_.extend(defaultAttrs, overrides)); } }; diff --git a/spec/javascripts/lib/charcounter_spec.js b/spec/javascripts/lib/charcounter_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..f0287afef6655b13faafcc558f4a6121c80726c8 --- /dev/null +++ b/spec/javascripts/lib/charcounter_spec.js @@ -0,0 +1,102 @@ +describe("$.fn.charCount", function() { + beforeEach(function() { + this.input = $("<textarea></textarea>"); + this.counter = $("<div class='charcounter'></div>"); + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat + this.repeat = function(str, count) { + var rpt = ""; + for (;;) { + if ((count & 1) === 1) { + rpt += str; + } + count >>>= 1; + if (count === 0) { + break; + } + str += str; + } + return rpt; + }; + }); + + context("on initialization", function() { + beforeEach(function() { + this.input.val(this.repeat("a", 10)); + }); + + it("shows the correct number of available chars", function() { + this.input.charCount({allowed: 12, warning: 1, counter: this.counter}); + expect(this.counter.text()).toEqual("2"); + }); + + it("shows the normal text if there are enough chars left", function() { + this.input.charCount({allowed: 12, warning: 2, counter: this.counter}); + expect(this.counter).not.toHaveClass("text-warning"); + expect(this.counter).not.toHaveClass("text-danger"); + }); + + it("shows a warning if there almost no chars left", function() { + this.input.charCount({allowed: 12, warning: 3, counter: this.counter}); + expect(this.counter).toHaveClass("text-warning"); + expect(this.counter).not.toHaveClass("text-danger"); + }); + + it("shows an error if the limit exceeded", function() { + this.input.charCount({allowed: 9, warning: 3, counter: this.counter}); + expect(this.counter).not.toHaveClass("text-warning"); + expect(this.counter).toHaveClass("text-danger"); + }); + }); + + context("on text changes", function() { + it("updates the number of available chars", function() { + this.input.val("a"); + this.input.charCount({allowed: 100, warning: 10, counter: this.counter}); + expect(this.counter.text()).toEqual("99"); + + this.input.val(this.repeat("a", 99)); + this.input.trigger("textchange"); + expect(this.counter.text()).toEqual("1"); + + this.input.val(this.repeat("a", 102)); + this.input.trigger("textchange"); + expect(this.counter.text()).toEqual("-2"); + + this.input.val(""); + this.input.trigger("textchange"); + expect(this.counter.text()).toEqual("100"); + }); + + it("updates the counter classes", function() { + this.input.val("a"); + this.input.charCount({allowed: 100, warning: 10, counter: this.counter}); + expect(this.counter).not.toHaveClass("text-warning"); + expect(this.counter).not.toHaveClass("text-danger"); + + this.input.val(this.repeat("a", 90)); + this.input.trigger("textchange"); + expect(this.counter).not.toHaveClass("text-warning"); + expect(this.counter).not.toHaveClass("text-danger"); + + this.input.val(this.repeat("a", 91)); + this.input.trigger("textchange"); + expect(this.counter).toHaveClass("text-warning"); + expect(this.counter).not.toHaveClass("text-danger"); + + this.input.val(this.repeat("a", 100)); + this.input.trigger("textchange"); + expect(this.counter).toHaveClass("text-warning"); + expect(this.counter).not.toHaveClass("text-danger"); + + this.input.val(this.repeat("a", 101)); + this.input.trigger("textchange"); + expect(this.counter).not.toHaveClass("text-warning"); + expect(this.counter).toHaveClass("text-danger"); + + this.input.val(""); + this.input.trigger("textchange"); + expect(this.counter).not.toHaveClass("text-warning"); + expect(this.counter).not.toHaveClass("text-danger"); + }); + }); +}); diff --git a/spec/javascripts/lib/keycodes_spec.js b/spec/javascripts/lib/keycodes_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..f3a0258ae70a6410b2180210bb889474f4e0cdb5 --- /dev/null +++ b/spec/javascripts/lib/keycodes_spec.js @@ -0,0 +1,13 @@ +describe("Keycodes", function() { + it("sets the correct keycode for letters", function() { + "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("").forEach(function(c) { + expect(String.fromCharCode(Keycodes[c])).toBe(c); + }); + }); + + it("sets the correct keycode for digits", function() { + "0123456789".split("").forEach(function(c) { + expect(String.fromCharCode(Keycodes[c])).toBe(c); + }); + }); +}); diff --git a/spec/javascripts/mobile/mobile_application_spec.js b/spec/javascripts/mobile/mobile_application_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..ee9655dda6623ff1cbdf9577c14b3919d75a32ad --- /dev/null +++ b/spec/javascripts/mobile/mobile_application_spec.js @@ -0,0 +1,22 @@ +describe("Diaspora.Mobile", function(){ + describe("initialize", function(){ + beforeEach(function(){ + spec.loadFixture("aspects_index_mobile_nsfw_post"); + spyOn(window, "autosize"); + }); + + it("calls autosize for textareas", function(){ + Diaspora.Mobile.initialize(); + expect(window.autosize).toHaveBeenCalled(); + expect(window.autosize.calls.mostRecent().args[0].selector).toBe("textarea"); + }); + + it("deactivates shield", function(){ + Diaspora.Mobile.initialize(); + var $shield = $(".stream_element").first(); + expect($shield).toHaveClass("shield-active"); + $shield.find(".shield a").click(); + expect($shield).not.toHaveClass("shield-active"); + }); + }); +}); diff --git a/spec/javascripts/mobile/mobile_comments_spec.js b/spec/javascripts/mobile/mobile_comments_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..e8fd7551a91edb39f76e6e1b77d6d5fa6c034ca3 --- /dev/null +++ b/spec/javascripts/mobile/mobile_comments_spec.js @@ -0,0 +1,164 @@ +describe("Diaspora.Mobile.Comments", function(){ + describe("toggleComments", function() { + beforeEach(function() { + spec.loadFixture("aspects_index_mobile_post_with_comments"); + this.link = $(".stream .show-comments").first(); + spyOn(Diaspora.Mobile.Comments, "showComments"); + spyOn(Diaspora.Mobile.Comments, "hideComments"); + }); + + it("calls showComments", function() { + Diaspora.Mobile.Comments.toggleComments(this.link); + expect(Diaspora.Mobile.Comments.showComments).toHaveBeenCalled(); + expect(Diaspora.Mobile.Comments.hideComments).not.toHaveBeenCalled(); + }); + + it("calls hideComments if the link class is 'active'", function() { + this.link.addClass("active"); + Diaspora.Mobile.Comments.toggleComments(this.link); + expect(Diaspora.Mobile.Comments.showComments).not.toHaveBeenCalled(); + expect(Diaspora.Mobile.Comments.hideComments).toHaveBeenCalled(); + }); + + it("doesn't call any function if the link class is 'loading'", function() { + this.link.addClass("loading"); + Diaspora.Mobile.Comments.toggleComments(this.link); + expect(Diaspora.Mobile.Comments.showComments).not.toHaveBeenCalled(); + expect(Diaspora.Mobile.Comments.hideComments).not.toHaveBeenCalled(); + }); + }); + + describe("showUnloadedComments", function() { + beforeEach(function() { + spec.loadFixture("aspects_index_mobile_post_with_comments"); + this.link = $(".stream .show-comments").first(); + this.bottomBar = this.link.closest(".bottom-bar").first(); + this.commentActionLink = this.bottomBar.find("a.comment-action"); + }); + + it("adds the 'loading' class to the link", function() { + Diaspora.Mobile.Comments.showUnloadedComments(this.link, this.bottomBar, this.commentActionLink); + expect($(".show-comments").first()).toHaveClass("loading"); + }); + + it("removes the 'loading' class if the request failed", function() { + Diaspora.Mobile.Comments.showUnloadedComments(this.link, this.bottomBar, this.commentActionLink); + jasmine.Ajax.requests.mostRecent().respondWith({status: 400}); + expect($(".show-comments").first()).not.toHaveClass("loading"); + }); + + it("adds the 'active' class if the request succeeded", function() { + Diaspora.Mobile.Comments.showUnloadedComments(this.link, this.bottomBar, this.commentActionLink); + jasmine.Ajax.requests.mostRecent().respondWith({status: 200, contentType: "text/plain", responseText: "test"}); + expect($(".show-comments").first()).toHaveClass("active"); + expect($(".show-comments").first()).not.toHaveClass("loading"); + }); + + it("calls showCommentBox", function() { + spyOn(Diaspora.Mobile.Comments, "showCommentBox"); + Diaspora.Mobile.Comments.showUnloadedComments(this.link, this.bottomBar, this.commentActionLink); + jasmine.Ajax.requests.mostRecent().respondWith({status: 200, contentType: "text/plain", responseText: "test"}); + expect(Diaspora.Mobile.Comments.showCommentBox).toHaveBeenCalledWith(this.commentActionLink); + }); + + it("adds the response text to the comments list", function() { + Diaspora.Mobile.Comments.showUnloadedComments(this.link, this.bottomBar, this.commentActionLink); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: "text/plain", + responseText: "<div class=\"commentContainerForTest\">new comments</div>" + }); + expect($(".stream .stream_element").first()).toContainElement(".commentContainerForTest"); + }); + + it("shows and hides the mobile spinner", function(){ + Diaspora.Mobile.Comments.showComments(this.link); + expect($(".ajax-loader").first()).toBeVisible(); + jasmine.Ajax.requests.mostRecent().respondWith({status: 200, contentType: "text/plain", responseText: "test"}); + expect($(".ajax-loader").first()).not.toBeVisible(); + }); + }); + + describe("createComment", function () { + beforeEach(function() { + spec.loadFixture("aspects_index_mobile_post_with_comments"); + var link = $(".stream .comment-action").first(); + Diaspora.Mobile.Comments.showCommentBox(link); + $(".stream .new_comment").submit(Diaspora.Mobile.Comments.submitComment); + }); + + it("doesn't submit an empty comment", function() { + var form = $(".stream .new_comment").first(); + spyOn(jQuery, "ajax"); + form.submit(); + expect(jQuery.ajax).not.toHaveBeenCalled(); + }); + }); + + describe("increaseReactionCount", function(){ + beforeEach(function() { + spec.loadFixture("aspects_index_mobile_post_with_comments"); + this.bottomBar = $(".bottom-bar").first(); + this.toggleReactionsLink = this.bottomBar.find(".show-comments").first(); + }); + + it("Increase reaction count from 1", function(){ + expect(this.toggleReactionsLink.text().trim()).toBe("5 reactions"); + Diaspora.Mobile.Comments.increaseReactionCount(this.bottomBar); + expect(this.toggleReactionsLink.text().trim()).toBe("6 reactions"); + }); + + it("Creates the reaction link when no reactions", function(){ + var parent = this.toggleReactionsLink.parent(); + var postGuid = this.bottomBar.parents(".stream_element").data("guid"); + this.toggleReactionsLink.remove(); + parent.prepend($("<span/>", {"class": "show-comments"}).text("No reaction")); + + Diaspora.Mobile.Comments.increaseReactionCount(this.bottomBar); + this.toggleReactionsLink = this.bottomBar.find(".show-comments").first(); + expect(this.toggleReactionsLink.text().trim()).toBe("1 reaction"); + expect(this.toggleReactionsLink.attr("href")).toBe("/posts/" + postGuid + "/comments.mobile"); + }); + }); + + describe("bottomBarLazy", function(){ + beforeEach(function() { + spec.loadFixture("aspects_index_mobile_post_with_comments"); + this.bottomBar = $(".bottom-bar").first(); + this.bottomBarLazy = Diaspora.Mobile.Comments.bottomBarLazy(this.bottomBar); + }); + + it("shows and hides the loader", function(){ + expect(this.bottomBarLazy.loader()).toHaveClass("hidden"); + this.bottomBarLazy.showLoader(); + expect(this.bottomBarLazy.loader()).not.toHaveClass("hidden"); + this.bottomBarLazy.hideLoader(); + expect(this.bottomBarLazy.loader()).toHaveClass("hidden"); + }); + + it("activates the bottom bar", function(){ + expect(this.bottomBar).toHaveClass("inactive"); + expect(this.bottomBar).not.toHaveClass("active"); + expect(this.bottomBarLazy.getShowCommentsLink()).not.toHaveClass("active"); + expect(this.bottomBarLazy.getShowCommentsLink().find("i")).toHaveClass("entypo-chevron-down"); + this.bottomBarLazy.activate(); + expect(this.bottomBar).not.toHaveClass("inactive"); + expect(this.bottomBar).toHaveClass("active"); + expect(this.bottomBarLazy.getShowCommentsLink()).toHaveClass("active"); + expect(this.bottomBarLazy.getShowCommentsLink().find("i")).toHaveClass("entypo-chevron-up"); + }); + + it("deactivates the bottom bar", function(){ + this.bottomBarLazy.activate(); + expect(this.bottomBar).not.toHaveClass("inactive"); + expect(this.bottomBar).toHaveClass("active"); + expect(this.bottomBarLazy.getShowCommentsLink()).toHaveClass("active"); + expect(this.bottomBarLazy.getShowCommentsLink().find("i")).toHaveClass("entypo-chevron-up"); + this.bottomBarLazy.deactivate(); + expect(this.bottomBar).toHaveClass("inactive"); + expect(this.bottomBar).not.toHaveClass("active"); + expect(this.bottomBarLazy.getShowCommentsLink()).not.toHaveClass("active"); + expect(this.bottomBarLazy.getShowCommentsLink().find("i")).toHaveClass("entypo-chevron-down"); + }); + }); +}); diff --git a/spec/javascripts/mobile/mobile_drawer_spec.js b/spec/javascripts/mobile/mobile_drawer_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..fe70a640a2021b3cd04d87c0574a8ce45170ab11 --- /dev/null +++ b/spec/javascripts/mobile/mobile_drawer_spec.js @@ -0,0 +1,47 @@ +describe("Diaspora.Mobile.Drawer", function(){ + describe("initialize", function(){ + beforeEach(function(){ + spec.loadFixture("aspects_index_mobile_post_with_comments"); + Diaspora.Mobile.Drawer.initialize(); + this.menuBadge = $("#menu-badge"); + this.followedTags = $("#followed_tags"); + this.allAspects = $("#all_aspects"); + }); + + it("correctly binds events", function(){ + expect($._data(this.allAspects[0], "events").tap.length).not.toBe(0); + expect($._data(this.allAspects[0], "events").click.length).not.toBe(0); + expect($._data(this.followedTags[0], "events").tap.length).not.toBe(0); + expect($._data(this.followedTags[0], "events").click.length).not.toBe(0); + expect($._data(this.menuBadge[0], "events").tap.length).not.toBe(0); + expect($._data(this.menuBadge[0], "events").click.length).not.toBe(0); + }); + + it("opens and closes the drawer", function(){ + var $app = $("#app"); + expect($app).not.toHaveClass("draw"); + this.menuBadge.click(); + expect($app).toHaveClass("draw"); + this.menuBadge.click(); + expect($app).not.toHaveClass("draw"); + }); + + it("shows and hides the aspects", function(){ + var $aspectList = this.allAspects.find("+ li"); + expect($aspectList).toHaveClass("hide"); + this.allAspects.click(); + expect($aspectList).not.toHaveClass("hide"); + this.allAspects.click(); + expect($aspectList).toHaveClass("hide"); + }); + + it("shows and hides the followed tags", function(){ + var $tagList = this.followedTags.find("+ li"); + expect($tagList).toHaveClass("hide"); + this.followedTags.click(); + expect($tagList).not.toHaveClass("hide"); + this.followedTags.click(); + expect($tagList).toHaveClass("hide"); + }); + }); +}); diff --git a/spec/javascripts/mobile/mobile_post_actions_spec.js b/spec/javascripts/mobile/mobile_post_actions_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..b2a2f570e8f8288db03ba48b3a91553e77138083 --- /dev/null +++ b/spec/javascripts/mobile/mobile_post_actions_spec.js @@ -0,0 +1,232 @@ +describe("Diaspora.Mobile.PostActions", function(){ + describe("initialize", function(){ + beforeEach(function(){ + spec.loadFixture("aspects_index_mobile_public_post"); + spyOn(Diaspora.Mobile.PostActions, "onLike"); + spyOn(Diaspora.Mobile.PostActions, "onReshare"); + Diaspora.Mobile.PostActions.initialize(); + }); + + it("binds the events", function(){ + $(".stream .like-action").trigger("tap"); + expect(Diaspora.Mobile.PostActions.onLike).toHaveBeenCalled(); + $(".stream .like-action").click(); + expect(Diaspora.Mobile.PostActions.onLike).toHaveBeenCalled(); + $(".stream .reshare-action").trigger("tap"); + expect(Diaspora.Mobile.PostActions.onReshare).toHaveBeenCalled(); + $(".stream .reshare-action").click(); + expect(Diaspora.Mobile.PostActions.onReshare).toHaveBeenCalled(); + }); + }); + + describe("toggleActive", function(){ + beforeEach(function(){ + spec.loadFixture("aspects_index_mobile_public_post"); + Diaspora.Mobile.PostActions.initialize(); + this.link = $(".stream .like-action").first(); + }); + + it("toggles active and inactive classes", function(){ + expect(this.link).toHaveClass("inactive"); + expect(this.link).not.toHaveClass("active"); + Diaspora.Mobile.PostActions.toggleActive(this.link); + expect(this.link).not.toHaveClass("inactive"); + expect(this.link).toHaveClass("active"); + Diaspora.Mobile.PostActions.toggleActive(this.link); + expect(this.link).toHaveClass("inactive"); + expect(this.link).not.toHaveClass("active"); + }); + }); + + describe("showLoader and hideLoader", function(){ + beforeEach(function(){ + spec.loadFixture("aspects_index_mobile_public_post"); + Diaspora.Mobile.PostActions.initialize(); + this.link = $(".stream .like-action").first(); + }); + + it("adds and removes loading class", function(){ + expect(this.link).not.toHaveClass("loading"); + Diaspora.Mobile.PostActions.showLoader(this.link); + expect(this.link).toHaveClass("loading"); + Diaspora.Mobile.PostActions.hideLoader(this.link); + expect(this.link).not.toHaveClass("loading"); + }); + }); + + describe("onLike", function(){ + beforeEach(function(){ + spec.loadFixture("aspects_index_mobile_public_post"); + spyOn(Diaspora.Mobile.PostActions, "like"); + spyOn(Diaspora.Mobile.PostActions, "unlike"); + Diaspora.Mobile.PostActions.initialize(); + this.link = $(".stream .like-action").first(); + }); + + it("doesn't activate the link if loading", function(){ + this.link.addClass("loading"); + this.link.click(); + expect(Diaspora.Mobile.PostActions.like).not.toHaveBeenCalled(); + expect(Diaspora.Mobile.PostActions.unlike).not.toHaveBeenCalled(); + }); + + it("calls like if like button is inactive", function(){ + this.link.removeClass("active").addClass("inactive"); + this.link.click(); + expect(Diaspora.Mobile.PostActions.like).toHaveBeenCalled(); + }); + + it("calls unlike if like button is active", function(){ + this.link.removeClass("inactive").addClass("active"); + this.link.click(); + expect(Diaspora.Mobile.PostActions.unlike).toHaveBeenCalled(); + }); + }); + + describe("like", function(){ + beforeEach(function(){ + spec.loadFixture("aspects_index_mobile_public_post"); + Diaspora.Mobile.PostActions.initialize(); + this.link = $(".stream .like-action").first(); + this.likeCounter = this.link.closest(".stream_element").find(".like-count"); + }); + + it("always calls showLoader before sending request", function(){ + spyOn(Diaspora.Mobile.PostActions, "showLoader"); + + Diaspora.Mobile.PostActions.like(this.likeCounter, this.link); + expect(Diaspora.Mobile.PostActions.showLoader).toHaveBeenCalled(); + }); + + it("always calls hideLoader after receiving response", function(){ + spyOn(Diaspora.Mobile.PostActions, "hideLoader"); + + Diaspora.Mobile.PostActions.like(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 400}); + expect(Diaspora.Mobile.PostActions.hideLoader).toHaveBeenCalled(); + Diaspora.Mobile.PostActions.like(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 201, responseText: "{\"id\": \"18\"}"}); + expect(Diaspora.Mobile.PostActions.hideLoader).toHaveBeenCalled(); + }); + + it("doesn't activate the link on error", function(){ + spyOn(Diaspora.Mobile.PostActions, "toggleActive"); + + Diaspora.Mobile.PostActions.like(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 400}); + expect(Diaspora.Mobile.PostActions.toggleActive).not.toHaveBeenCalled(); + expect(this.likeCounter.text()).toBe("0"); + }); + + it("activates link on success", function(){ + spyOn(Diaspora.Mobile.PostActions, "toggleActive"); + var data = this.link.data("url"); + + Diaspora.Mobile.PostActions.like(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 201, responseText: "{\"id\": \"18\"}"}); + expect(Diaspora.Mobile.PostActions.toggleActive).toHaveBeenCalled(); + expect(this.likeCounter.text()).toBe("1"); + expect(this.link.data("url")).toBe(data + "/18"); + }); + }); + + describe("unlike", function(){ + beforeEach(function(){ + spec.loadFixture("aspects_index_mobile_public_post"); + Diaspora.Mobile.PostActions.initialize(); + this.link = $(".stream .like-action").first(); + this.likeCounter = this.link.closest(".stream_element").find(".like-count"); + Diaspora.Mobile.PostActions.like(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 201, responseText: "{\"id\": \"18\"}"}); + }); + + it("always calls showLoader before sending request", function(){ + spyOn(Diaspora.Mobile.PostActions, "showLoader"); + Diaspora.Mobile.PostActions.unlike(this.likeCounter, this.link); + expect(Diaspora.Mobile.PostActions.showLoader).toHaveBeenCalled(); + }); + + it("always calls hideLoader after receiving response", function(){ + spyOn(Diaspora.Mobile.PostActions, "hideLoader"); + + Diaspora.Mobile.PostActions.unlike(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 400}); + expect(Diaspora.Mobile.PostActions.hideLoader).toHaveBeenCalled(); + Diaspora.Mobile.PostActions.unlike(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 204}); + expect(Diaspora.Mobile.PostActions.hideLoader).toHaveBeenCalled(); + }); + + it("doesn't unlike on error", function(){ + spyOn(Diaspora.Mobile.PostActions, "toggleActive"); + + Diaspora.Mobile.PostActions.unlike(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 400}); + expect(Diaspora.Mobile.PostActions.toggleActive).not.toHaveBeenCalled(); + expect(this.likeCounter.text()).toBe("1"); + }); + + it("deactivates link on success", function(){ + spyOn(Diaspora.Mobile.PostActions, "toggleActive"); + var data = this.link.data("url"); + + expect(this.likeCounter.text()).toBe("1"); + Diaspora.Mobile.PostActions.unlike(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 204}); + expect(Diaspora.Mobile.PostActions.toggleActive).toHaveBeenCalled(); + expect(this.likeCounter.text()).toBe("0"); + expect(this.link.data("url")).toBe(data.replace(/\/\d+$/, "")); + }); + + it("doesn't produce negative like count", function(){ + expect(this.likeCounter.text()).toBe("1"); + Diaspora.Mobile.PostActions.unlike(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 204}); + expect(this.likeCounter.text()).toBe("0"); + Diaspora.Mobile.PostActions.unlike(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 204}); + expect(this.likeCounter.text()).toBe("0"); + Diaspora.Mobile.PostActions.unlike(this.likeCounter, this.link); + jasmine.Ajax.requests.mostRecent().respondWith({status: 204}); + expect(this.likeCounter.text()).toBe("0"); + }); + }); + + describe("onReshare", function(){ + beforeEach(function(){ + spec.loadFixture("aspects_index_mobile_public_post"); + Diaspora.Mobile.PostActions.initialize(); + this.reshareLink = $(".stream .reshare-action"); + spyOn(window, "confirm").and.returnValue(true); + spyOn(window, "alert"); + }); + + it("always calls showLoader before sending request and hideLoader after receiving response", function(){ + spyOn(Diaspora.Mobile.PostActions, "hideLoader"); + spyOn(Diaspora.Mobile.PostActions, "showLoader"); + + this.reshareLink.click(); + expect(Diaspora.Mobile.PostActions.showLoader).toHaveBeenCalled(); + jasmine.Ajax.requests.mostRecent().respondWith({status: 400}); + expect(Diaspora.Mobile.PostActions.hideLoader).toHaveBeenCalled(); + this.reshareLink.click(); + expect(Diaspora.Mobile.PostActions.showLoader).toHaveBeenCalled(); + jasmine.Ajax.requests.mostRecent().respondWith({status: 201, responseText: "{}"}); + expect(Diaspora.Mobile.PostActions.hideLoader).toHaveBeenCalled(); + }); + + it("calls toggleActive on success", function(){ + spyOn(Diaspora.Mobile.PostActions, "toggleActive"); + + this.reshareLink.click(); + jasmine.Ajax.requests.mostRecent().respondWith({status: 201, responseText: "{}"}); + expect(Diaspora.Mobile.PostActions.toggleActive).toHaveBeenCalledWith(this.reshareLink); + }); + + it("pops an alert on error", function(){ + this.reshareLink.click(); + jasmine.Ajax.requests.mostRecent().respondWith({status: 400}); + expect(window.alert).toHaveBeenCalledWith(Diaspora.I18n.t("failed_to_reshare")); + }); + }); +}); diff --git a/spec/javascripts/support/jasmine.yml b/spec/javascripts/support/jasmine.yml index 9d4e0d3a8b9b597e98a67aeee118a9821c5ad526..87e516cca0572c94b3247c8c69281d9ee5353421 100644 --- a/spec/javascripts/support/jasmine.yml +++ b/spec/javascripts/support/jasmine.yml @@ -13,6 +13,7 @@ src_files: # Precompile all scripts together for the test environment - assets/jasmine-load-all.js - assets/jasmine-jquery.js + - assets/bookmarklet.js # stylesheets # @@ -26,9 +27,7 @@ src_files: # - stylesheets/*.css # stylesheets: - - assets/bootstrap.css - - assets/default.css - - assets/application.css + - assets/color_themes/original/desktop.css # helpers # diff --git a/spec/javascripts/widgets/flash-messages-spec.js b/spec/javascripts/widgets/flash-messages-spec.js deleted file mode 100644 index f2e02bd9c2ea01e070072d142ddd6b780c339311..0000000000000000000000000000000000000000 --- a/spec/javascripts/widgets/flash-messages-spec.js +++ /dev/null @@ -1,36 +0,0 @@ -describe("Diaspora", function() { - describe("Widgets", function() { - describe("FlashMessages", function() { - var flashMessages; - - describe("animateMessages", function() { - beforeEach(function() { - flashMessages = Diaspora.BaseWidget.instantiate("FlashMessages"); - $("#jasmine_content").html( - '<div id="flash_notice">' + - 'flash message' + - '</div>' - ); - }); - - it("is called when the DOM is ready", function() { - spyOn(flashMessages, "animateMessages").and.callThrough(); - flashMessages.publish("widget/ready"); - expect(flashMessages.animateMessages).toHaveBeenCalled(); - }); - }); - - describe("render", function() { - it("creates a new div for the message and calls flashes.animateMessages", function() { - spyOn(flashMessages, "animateMessages"); - flashMessages.render({ - success: true, - message: "success!" - }); - expect($("#flash_notice").length).toEqual(1); - expect(flashMessages.animateMessages).toHaveBeenCalled(); - }); - }); - }); - }); -}); diff --git a/spec/javascripts/widgets/lightbox-spec.js b/spec/javascripts/widgets/lightbox-spec.js deleted file mode 100644 index 52d5ee7f9a21a5812bc4471d8cabaa468ffabff3..0000000000000000000000000000000000000000 --- a/spec/javascripts/widgets/lightbox-spec.js +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (c) 2010-2012, Diaspora Inc. This file is - * licensed under the Affero General Public License version 3 or later. See - * the COPYRIGHT file. - */ - -describe("Diaspora.Widgets.Lightbox", function() { - var photos; - - var createDummyMarkup = function(opts){ - var defaults = { - linkClass: 'stream-photo-link', - imageParent: 'stream_element', - imageClass: 'stream-photo' - }; - - var classes = _.extend(defaults, opts); - - var output = $('<div/>').addClass(classes.imageParent); - _.each(photos, function(photo){ - output.append( - $('<a />') - .attr('href', '#') - .addClass(classes.linkClass) - .append( - $('<img />') - .attr('src', photo.sizes.large) - .addClass(classes.imageClass) - .data({ - 'small-photo': photo.sizes.small, - 'full-photo': photo.sizes.large - }) - ) - ); - }); - - return output; - }; - - beforeEach(function(){ - $("#jasmine_content").html( - '<div id="lightbox" style="display: none;">TESTCONTENT</div>' + - '<div id="lightbox-imageset"></div>' + - '<div id="lightbox-backdrop"></div>' + - '<div id="lightbox-close-link"></div>' - ); - - photos = $.parseJSON(spec.readFixture("photos_json"))["photos"]; - }); - - context("opens the lightbox correctly", function() { - var lightbox, photoElement; - - beforeEach(function() { - $("#jasmine_content").append(createDummyMarkup()); - photoElement = $('.stream-photo').first(); - - lightbox = Diaspora.BaseWidget.instantiate("Lightbox"); - $('.stream_element').delegate("a.stream-photo-link", "click", lightbox.lightboxImageClicked); - }); - - it("shows the lightbox when a photo is clicked", function() { - spyOn(lightbox, 'revealLightbox'); - photoElement.trigger('click'); - expect(lightbox.revealLightbox).toHaveBeenCalled(); - }); - - }); - - context("opens lightbox for differently named elements", function(){ - var lightbox, photoElement; - - beforeEach(function() { - $("#jasmine_content").append(createDummyMarkup({ - linkClass: 'photo-link', - imageParent: 'main_stream', - imageClass: 'photo' - })); - photoElement = $('.photo').first(); - - lightbox = Diaspora.BaseWidget.instantiate("Lightbox"); - lightbox.set({ - imageParent: '.main_stream', - imageSelector: 'img.photo' - }); - $('.main_stream').delegate("a.photo-link", "click", lightbox.lightboxImageClicked); - }); - - it("shows the lightbox when a photo is clicked", function() { - spyOn(lightbox, 'revealLightbox'); - photoElement.trigger('click'); - expect(lightbox.revealLightbox).toHaveBeenCalled(); - }); - }); - -}); diff --git a/spec/lib/account_deleter_spec.rb b/spec/lib/account_deleter_spec.rb index a8d525eb80a7e45634e800a065a6dbcac5fd6f8b..8ca011b2b14b52cee33e32a7a55ebb40cddad6b8 100644 --- a/spec/lib/account_deleter_spec.rb +++ b/spec/lib/account_deleter_spec.rb @@ -16,19 +16,18 @@ describe AccountDeleter do end describe '#perform' do - - - user_removal_methods = [:delete_standard_user_associations, - :disassociate_invitations, - :remove_share_visibilities_on_contacts_posts, - :disconnect_contacts, - :tombstone_user] - - person_removal_methods = [:delete_contacts_of_me, - :delete_standard_person_associations, - :tombstone_person_and_profile, - :remove_share_visibilities_on_persons_posts, - :remove_conversation_visibilities] + user_removal_methods = %i( + delete_standard_user_associations + remove_share_visibilities_on_contacts_posts + disconnect_contacts tombstone_user + ) + + person_removal_methods = %i( + delete_contacts_of_me + delete_standard_person_associations + tombstone_person_and_profile + remove_conversation_visibilities + ) context "user deletion" do after do @@ -111,15 +110,6 @@ describe AccountDeleter do end end - describe "#disassociate_invitations" do - it "sets invitations_from_me to be admin invitations" do - invites = [double] - allow(bob).to receive(:invitations_from_me).and_return(invites) - expect(invites.first).to receive(:convert_to_admin!) - @account_deletion.disassociate_invitations - end - end - context 'person associations' do describe '#disconnect_contacts' do it "deletes all of user's contacts" do @@ -158,21 +148,11 @@ describe AccountDeleter do end end - describe "#remove_person_share_visibilities" do - it 'removes the share visibilities for a person ' do - @s_vis = double - expect(ShareVisibility).to receive(:for_contacts_of_a_person).with(bob.person).and_return(@s_vis) - expect(@s_vis).to receive(:destroy_all) - - @account_deletion.remove_share_visibilities_on_persons_posts - end - end - describe "#remove_share_visibilities_by_contacts_of_user" do - it 'removes the share visibilities for a user' do - @s_vis = double - expect(ShareVisibility).to receive(:for_a_users_contacts).with(bob).and_return(@s_vis) - expect(@s_vis).to receive(:destroy_all) + it "removes the share visibilities for a user" do + s_vis = double + expect(ShareVisibility).to receive(:for_a_user).with(bob).and_return(s_vis) + expect(s_vis).to receive(:destroy_all) @account_deletion.remove_share_visibilities_on_contacts_posts end diff --git a/spec/lib/api/openid_connect/protected_resource_endpoint_spec.rb b/spec/lib/api/openid_connect/protected_resource_endpoint_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..4c9035ece4dac3c0a079f130314118c3663d9011 --- /dev/null +++ b/spec/lib/api/openid_connect/protected_resource_endpoint_spec.rb @@ -0,0 +1,86 @@ +require "spec_helper" + +describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do + let(:auth_with_read) { FactoryGirl.create(:auth_with_read) } + let!(:access_token_with_read) { auth_with_read.create_access_token.to_s } + let!(:expired_access_token) do + access_token = auth_with_read.o_auth_access_tokens.create! + access_token.expires_at = Time.zone.now - 100 + access_token.save + access_token.bearer_token.to_s + end + let(:invalid_token) { SecureRandom.hex(32).to_s } + + context "when valid access token is provided" do + before do + get api_openid_connect_user_info_path, access_token: access_token_with_read + end + + it "includes private in the cache-control header" do + expect(response.headers["Cache-Control"]).to include("private") + end + end + + context "when access token is expired" do + before do + get api_openid_connect_user_info_path, access_token: expired_access_token + end + + it "should respond with a 401 Unauthorized response" do + expect(response.status).to be(401) + end + it "should have an auth-scheme value of Bearer" do + expect(response.headers["WWW-Authenticate"]).to include("Bearer") + end + end + + context "when no access token is provided" do + before do + get api_openid_connect_user_info_path + end + + it "should respond with a 401 Unauthorized response" do + expect(response.status).to be(401) + end + it "should have an auth-scheme value of Bearer" do + expect(response.headers["WWW-Authenticate"]).to include("Bearer") + end + end + + context "when an invalid access token is provided" do + before do + get api_openid_connect_user_info_path, access_token: invalid_token + end + + it "should respond with a 401 Unauthorized response" do + expect(response.status).to be(401) + end + + it "should have an auth-scheme value of Bearer" do + expect(response.headers["WWW-Authenticate"]).to include("Bearer") + end + + it "should contain an invalid_token error" do + expect(response.body).to include("invalid_token") + end + end + + context "when authorization has been destroyed" do + before do + auth_with_read.destroy + get api_openid_connect_user_info_path, access_token: access_token_with_read + end + + it "should respond with a 401 Unauthorized response" do + expect(response.status).to be(401) + end + + it "should have an auth-scheme value of Bearer" do + expect(response.headers["WWW-Authenticate"]).to include("Bearer") + end + + it "should contain an invalid_token error" do + expect(response.body).to include("invalid_token") + end + end +end diff --git a/spec/lib/api/openid_connect/token_endpoint_spec.rb b/spec/lib/api/openid_connect/token_endpoint_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..37eba5380f0def94f09c72337ab2548b3fe6b0fc --- /dev/null +++ b/spec/lib/api/openid_connect/token_endpoint_spec.rb @@ -0,0 +1,246 @@ +require "spec_helper" + +describe Api::OpenidConnect::TokenEndpoint, type: :request do + let!(:client) { FactoryGirl.create(:o_auth_application_with_ppid) } + let!(:auth) { + Api::OpenidConnect::Authorization.find_or_create_by( + o_auth_application: client, user: bob, redirect_uri: "http://localhost:3000/", scopes: ["openid"]) + } + let!(:code) { auth.create_code } + let!(:client_with_specific_id) { FactoryGirl.create(:o_auth_application_with_ppid_with_specific_id) } + let!(:auth_with_specific_id) do + client_with_specific_id.client_id = "14d692cd53d9c1a9f46fd69e0e57443e" + client_with_specific_id.jwks = File.read(jwks_file_path) + client_with_specific_id.save! + Api::OpenidConnect::Authorization.find_or_create_by( + o_auth_application: client_with_specific_id, + user: bob, redirect_uri: "http://localhost:3000/", scopes: ["openid"]) + end + let!(:code_with_specific_id) { auth_with_specific_id.create_code } + + describe "the authorization code grant type" do + context "when the authorization code is valid" do + before do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + client_id: client.client_id, client_secret: client.client_secret, + redirect_uri: "http://localhost:3000/", code: code + end + + it "should return a valid id token" do + json = JSON.parse(response.body) + encoded_id_token = json["id_token"] + decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, + Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY + expected_guid = bob.pairwise_pseudonymous_identifiers.find_by(identifier: "https://example.com/uri").guid + expect(decoded_token.sub).to eq(expected_guid) + expect(decoded_token.exp).to be > Time.zone.now.utc.to_i + end + + it "should return an id token with a kid" do + json = JSON.parse(response.body) + encoded_id_token = json["id_token"] + kid = JSON::JWT.decode(encoded_id_token, :skip_verification).header[:kid] + expect(kid).to eq("default") + end + + it "should return a valid access token" do + json = JSON.parse(response.body) + encoded_id_token = json["id_token"] + decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, + Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY + access_token = json["access_token"] + access_token_check_num = UrlSafeBase64.encode64(OpenSSL::Digest::SHA256.digest(access_token)[0, 128 / 8]) + expect(decoded_token.at_hash).to eq(access_token_check_num) + end + + it "should not allow code to be reused" do + auth.reload + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + client_id: client.client_id, client_secret: client.client_secret, + redirect_uri: "http://localhost:3000/", code: code + expect(JSON.parse(response.body)["error"]).to eq("invalid_grant") + end + + it "should not allow a nil code" do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + client_id: client.client_id, client_secret: client.client_secret, + redirect_uri: "http://localhost:3000/", code: nil + expect(JSON.parse(response.body)["error"]).to eq("invalid_request") + end + end + + context "when the authorization code is valid with jwt bearer" do + before do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + redirect_uri: "http://localhost:3000/", code: code_with_specific_id, + client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + client_assertion: File.read(valid_client_assertion_path) + end + + it "should return a valid id token" do + json = JSON.parse(response.body) + encoded_id_token = json["id_token"] + decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, + Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY + expected_guid = bob.pairwise_pseudonymous_identifiers.find_by(identifier: "https://example.com/uri").guid + expect(decoded_token.sub).to eq(expected_guid) + expect(decoded_token.exp).to be > Time.zone.now.utc.to_i + end + + it "should return a valid access token" do + json = JSON.parse(response.body) + encoded_id_token = json["id_token"] + decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, + Api::OpenidConnect::IdTokenConfig::PUBLIC_KEY + access_token = json["access_token"] + access_token_check_num = UrlSafeBase64.encode64(OpenSSL::Digest::SHA256.digest(access_token)[0, 128 / 8]) + expect(decoded_token.at_hash).to eq(access_token_check_num) + end + + it "should not allow code to be reused" do + auth_with_specific_id.reload + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + client_id: client.client_id, client_secret: client.client_secret, + redirect_uri: "http://localhost:3000/", code: code_with_specific_id + expect(JSON.parse(response.body)["error"]).to eq("invalid_grant") + end + end + + context "when the authorization code is not valid" do + it "should return an invalid grant error" do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + client_id: client.client_id, client_secret: client.client_secret, code: "123456" + expect(response.body).to include "invalid_grant" + end + end + + context "when the client assertion is in an invalid format" do + before do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + redirect_uri: "http://localhost:3000/", code: code_with_specific_id, + client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + client_assertion: "invalid_client_assertion.random" + end + + it "should return an error" do + expect(response.body).to include "invalid_request" + end + end + + context "when the client assertion is not matching with jwks keys" do + before do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + redirect_uri: "http://localhost:3000/", code: code_with_specific_id, + client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + client_assertion: File.read(client_assertion_with_tampered_sig_path) + end + + it "should return an error" do + expect(response.body).to include "invalid_grant" + end + end + + context "when kid doesn't exist in jwks keys" do + before do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + redirect_uri: "http://localhost:3000/", code: code_with_specific_id, + client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + client_assertion: File.read(client_assertion_with_nonexistent_kid_path) + end + + it "should return an error" do + expect(response.body).to include "invalid_request" + end + end + + context "when the client is unregistered" do + it "should return an error" do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", code: auth.refresh_token, + client_id: SecureRandom.hex(16).to_s, client_secret: client.client_secret + expect(response.body).to include "invalid_client" + end + end + + context "when the client is unregistered with jwks keys" do + before do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + redirect_uri: "http://localhost:3000/", code: code_with_specific_id, + client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + client_assertion: File.read(client_assertion_with_nonexistent_client_id_path) + end + + it "should return an error" do + expect(response.body).to include "invalid_request" + end + end + + context "when the code field is missing" do + it "should return an invalid request error" do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", + client_id: client.client_id, client_secret: client.client_secret + expect(response.body).to include "invalid_request" + end + end + + context "when the client_secret doesn't match" do + it "should return an invalid client error" do + post api_openid_connect_access_tokens_path, grant_type: "authorization_code", code: auth.refresh_token, + client_id: client.client_id, client_secret: "client.client_secret" + expect(response.body).to include "invalid_client" + end + end + end + + describe "an unsupported grant type" do + it "should return an unsupported grant type error" do + post api_openid_connect_access_tokens_path, grant_type: "noexistgrant", username: "bob", + password: "bluepin7", client_id: client.client_id, client_secret: client.client_secret, scope: "read" + expect(response.body).to include "unsupported_grant_type" + end + end + + describe "the refresh token grant type" do + context "when the refresh token is valid" do + it "should return an access token" do + post api_openid_connect_access_tokens_path, grant_type: "refresh_token", + client_id: client.client_id, client_secret: client.client_secret, refresh_token: auth.refresh_token + json = JSON.parse(response.body) + expect(response.body).to include "expires_in" + expect(json["access_token"].length).to eq(64) + expect(json["token_type"]).to eq("bearer") + end + end + + context "when the refresh token is not valid" do + it "should return an invalid grant error" do + post api_openid_connect_access_tokens_path, grant_type: "refresh_token", + client_id: client.client_id, client_secret: client.client_secret, refresh_token: "123456" + expect(response.body).to include "invalid_grant" + end + end + + context "when the client is unregistered" do + it "should return an error" do + post api_openid_connect_access_tokens_path, grant_type: "refresh_token", refresh_token: auth.refresh_token, + client_id: SecureRandom.hex(16).to_s, client_secret: client.client_secret + expect(response.body).to include "invalid_client" + end + end + + context "when the refresh_token field is missing" do + it "should return an invalid request error" do + post api_openid_connect_access_tokens_path, grant_type: "refresh_token", + client_id: client.client_id, client_secret: client.client_secret + expect(response.body).to include "'refresh_token' required" + end + end + + context "when the client_secret doesn't match" do + it "should return an invalid client error" do + post api_openid_connect_access_tokens_path, grant_type: "refresh_token", refresh_token: auth.refresh_token, + client_id: client.client_id, client_secret: "client.client_secret" + expect(response.body).to include "invalid_client" + end + end + end +end diff --git a/spec/lib/configuration_methods_spec.rb b/spec/lib/configuration_methods_spec.rb index 452fbfe249af9c5a201e71b07fd5e0848724c777..8e474c381d3de665888ac791fd0c138ef36f4dc4 100644 --- a/spec/lib/configuration_methods_spec.rb +++ b/spec/lib/configuration_methods_spec.rb @@ -12,6 +12,7 @@ describe Configuration::Methods do describe "#pod_uri" do before do @settings.environment.url = nil + @settings.environment.require_ssl = false @settings.instance_variable_set(:@pod_uri, nil) end @@ -36,6 +37,18 @@ describe Configuration::Methods do expect(@settings.pod_uri.to_s).to eq("http://example.org/") end + it "adds https:// on the front if require_ssl is true" do + @settings.environment.require_ssl = true + @settings.environment.url = "example.org" + expect(@settings.pod_uri.to_s).to eq("https://example.org/") + end + + it "changes http to https if require_ssl is true" do + @settings.environment.require_ssl = true + @settings.environment.url = "http://example.org/" + expect(@settings.pod_uri.to_s).to eq("https://example.org/") + end + it "does not add a prefix if there already is https:// on the front" do @settings.environment.url = "https://example.org/" expect(@settings.pod_uri.to_s).to eq("https://example.org/") @@ -152,19 +165,8 @@ describe Configuration::Methods do end describe "#get_redis_options" do - context "with REDISTOGO_URL set" do - before do - ENV["REDISTOGO_URL"] = "redis://myserver" - end - - it "uses that" do - expect(@settings.get_redis_options[:url]).to match "myserver" - end - end - context "with REDIS_URL set" do before do - ENV["REDISTOGO_URL"] = nil ENV["REDIS_URL"] = "redis://yourserver" end @@ -175,7 +177,6 @@ describe Configuration::Methods do context "with redis set" do before do - ENV["REDISTOGO_URL"] = nil ENV["REDIS_URL"] = nil @settings.environment.redis = "redis://ourserver" end @@ -187,7 +188,6 @@ describe Configuration::Methods do context "with a unix socket set" do before do - ENV["REDISTOGO_URL"] = nil ENV["REDIS_URL"] = nil @settings.environment.redis = "unix:///tmp/redis.sock" end diff --git a/spec/lib/connection_tester_spec.rb b/spec/lib/connection_tester_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..22fc906bd932485cd92a63775ea59805352b24fb --- /dev/null +++ b/spec/lib/connection_tester_spec.rb @@ -0,0 +1,162 @@ + +require "spec_helper" + +describe ConnectionTester do + let(:url) { "https://pod.example.com" } + let(:result) { ConnectionTester::Result.new } + let(:tester) { ConnectionTester.new(url, result) } + + describe "::check" do + it "takes a http url and returns a result object" do + res = ConnectionTester.check("https://pod.example.com") + expect(res).to be_a(ConnectionTester::Result) + end + + it "still returns a result object, even for invalid urls" do + res = ConnectionTester.check("i:am/not)a+url") + expect(res).to be_a(ConnectionTester::Result) + expect(res.error).to be_a(ConnectionTester::Failure) + end + end + + describe "#initialize" do + it "accepts the http protocol" do + expect { + ConnectionTester.new("https://pod.example.com") + }.not_to raise_error + end + it "rejects unexpected protocols" do + expect { + ConnectionTester.new("xmpp:user@example.com") + }.to raise_error(ConnectionTester::AddressFailure) + end + end + + describe "#resolve" do + it "resolves the IP address" do + expect(IPSocket).to receive(:getaddress).with("pod.example.com").and_return("192.168.1.2") + + tester.resolve + expect(result.ip).to eq("192.168.1.2") + end + + it "raises DNSFailure if host is unknown" do + expect(IPSocket).to receive(:getaddress).with("pod.example.com").and_raise(SocketError.new("Error!")) + + expect { tester.resolve }.to raise_error(ConnectionTester::DNSFailure, "'pod.example.com' - Error!") + end + end + + describe "#request" do + it "performs a successful GET request on '/' and '/.well-known/host-meta'" do + stub_request(:get, url).to_return(status: 200, body: "Hello World!") + stub_request(:get, "#{url}/.well-known/host-meta").to_return(status: 200, body: "host-meta") + + tester.request + expect(result.rt).to be > -1 + expect(result.reachable).to be_truthy + expect(result.ssl).to be_truthy + end + + it "receives a 'normal' 301 redirect" do + stub_request(:get, url).to_return(status: 301, headers: {"Location" => "#{url}/redirect"}) + stub_request(:get, "#{url}/redirect").to_return(status: 200, body: "Hello World!") + stub_request(:get, "#{url}/.well-known/host-meta").to_return(status: 200, body: "host-meta") + + tester.request + end + + it "updates ssl after https redirect" do + tester = ConnectionTester.new("http://pod.example.com/", result) + stub_request(:get, "http://pod.example.com/").to_return(status: 200, body: "Hello World!") + stub_request(:get, "http://pod.example.com/.well-known/host-meta") + .to_return(status: 301, headers: {"Location" => "#{url}/.well-known/host-meta"}) + stub_request(:get, "#{url}/.well-known/host-meta").to_return(status: 200, body: "host-meta") + + tester.request + expect(result.ssl).to be_truthy + end + + it "rejects other hostname after redirect redirect" do + stub_request(:get, url).to_return(status: 200, body: "Hello World!") + stub_request(:get, "#{url}/.well-known/host-meta") + .to_return(status: 301, headers: {"Location" => "https://example.com/.well-known/host-meta"}) + stub_request(:get, "https://example.com/.well-known/host-meta").to_return(status: 200, body: "host-meta") + + expect { tester.request }.to raise_error(ConnectionTester::HTTPFailure) + end + + it "receives too many 301 redirects" do + stub_request(:get, url).to_return(status: 301, headers: {"Location" => "#{url}/redirect"}) + stub_request(:get, "#{url}/redirect").to_return(status: 301, headers: {"Location" => "#{url}/redirect1"}) + stub_request(:get, "#{url}/redirect1").to_return(status: 301, headers: {"Location" => "#{url}/redirect2"}) + stub_request(:get, "#{url}/redirect2").to_return(status: 301, headers: {"Location" => "#{url}/redirect3"}) + stub_request(:get, "#{url}/redirect3").to_return(status: 200, body: "Hello World!") + + expect { tester.request }.to raise_error(ConnectionTester::HTTPFailure) + end + + it "receives a 404 not found" do + stub_request(:get, url).to_return(status: 404, body: "Not Found!") + expect { tester.request }.to raise_error(ConnectionTester::HTTPFailure) + end + + it "cannot connect" do + stub_request(:get, url).to_raise(Faraday::ConnectionFailed.new("Error!")) + expect { tester.request }.to raise_error(ConnectionTester::NetFailure) + end + + it "encounters an invalid SSL setup" do + stub_request(:get, url).to_raise(Faraday::SSLError.new("Error!")) + expect { tester.request }.to raise_error(ConnectionTester::SSLFailure) + end + end + + describe "#nodeinfo" do + let(:ni_wellknown) { {links: [{rel: ConnectionTester::NODEINFO_SCHEMA, href: "/nodeinfo"}]} } + + it "reads the version from the nodeinfo document" do + ni_document = NodeInfo.build do |doc| + doc.version = "1.0" + doc.open_registrations = true + doc.protocols.inbound << "diaspora" + doc.protocols.outbound << "diaspora" + doc.software.name = "diaspora" + doc.software.version = "a.b.c.d" + end + + stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}") + .to_return(status: 200, body: JSON.generate(ni_wellknown)) + stub_request(:get, "#{url}/nodeinfo").to_return(status: 200, body: JSON.generate(ni_document.as_json)) + + tester.nodeinfo + expect(result.software_version).to eq("diaspora a.b.c.d") + end + + it "handles a missing nodeinfo document gracefully" do + stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}") + .to_return(status: 404, body: "Not Found") + expect { tester.nodeinfo }.to raise_error(ConnectionTester::NodeInfoFailure) + end + + it "handles a malformed document gracefully" do + stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}") + .to_return(status: 200, body: '{"json"::::"malformed"}') + expect { tester.nodeinfo }.to raise_error(ConnectionTester::NodeInfoFailure) + end + + it "handles a invalid jrd document gracefully" do + invalid_wellknown = {links: {rel: ConnectionTester::NODEINFO_SCHEMA, href: "/nodeinfo"}} + stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}") + .to_return(status: 200, body: JSON.generate(invalid_wellknown)) + expect { tester.nodeinfo }.to raise_error(ConnectionTester::NodeInfoFailure) + end + + it "handles a invalid nodeinfo document gracefully" do + stub_request(:get, "#{url}#{ConnectionTester::NODEINFO_FRAGMENT}") + .to_return(status: 200, body: JSON.generate(ni_wellknown)) + stub_request(:get, "#{url}/nodeinfo").to_return(status: 200, body: '{"software": "invalid nodeinfo"}') + expect { tester.nodeinfo }.to raise_error(ConnectionTester::NodeInfoFailure) + end + end +end diff --git a/spec/lib/diaspora/encryptable_spec.rb b/spec/lib/diaspora/encryptable_spec.rb deleted file mode 100644 index 7419b7f61c1b63ca7a1428c2c2a4ee8359b148b2..0000000000000000000000000000000000000000 --- a/spec/lib/diaspora/encryptable_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Diaspora::Encryptable do - before do - @comment = FactoryGirl.create(:comment, :author => bob.person) - end - describe '#sign_with_key' do - it 'signs the object with RSA256 signature' do - sig = @comment.sign_with_key bob.encryption_key - expect(bob.public_key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(sig), @comment.signable_string)).to be true - end - end - - describe '#verify_signature' do - it 'verifies SHA256 signatures' do - sig = @comment.sign_with_key bob.encryption_key - expect(@comment.verify_signature(sig, bob.person)).to be true - end - - it 'does not verify the fallback after rollout window' do - sig = Base64.strict_encode64(bob.encryption_key.sign( "SHA", @comment.signable_string )) - expect(@comment.verify_signature(sig, bob.person)).to be false - end - end -end diff --git a/spec/lib/diaspora/federated/base_spec.rb b/spec/lib/diaspora/federated/base_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..78b262dfde5ade23bbe9d04a084653663a591c1e --- /dev/null +++ b/spec/lib/diaspora/federated/base_spec.rb @@ -0,0 +1,25 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require "spec_helper" + +describe Diaspora::Federated::Base do + class Foo + include Diaspora::Federated::Base + end + + let(:foo) { Foo.new } + + describe "#object_to_receive" do + it "returns self" do + expect(foo.object_to_receive).to eq(foo) + end + end + + describe "#subscribers" do + it "throws an error if the including module does not redefine it" do + expect { foo.subscribers }.to raise_error(/override subscribers/) + end + end +end diff --git a/spec/lib/diaspora/federated/generator_spec.rb b/spec/lib/diaspora/federated/generator_spec.rb deleted file mode 100644 index a7859efc610bb3372ae75c99860a9ec99737d67c..0000000000000000000000000000000000000000 --- a/spec/lib/diaspora/federated/generator_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require "spec_helper" - -describe "adds root author on reshare" do - before do - @generator = Federated::Generator.new(double("user", id: 1), double) - @root_author = double("root_author") - root = double("root", author: @root_author) - parent = double("parent", root: root) - @relayable = double("relayable", parent: parent, class: "foo", guid: "123") - end - - it "adds root to additional subscribers" do - @generator.add_root_author(@relayable) - additional_subscribers = @generator.instance_variable_get(:@dispatcher_opts)[:additional_subscribers] - expect(additional_subscribers).to include(@root_author) - end - - it "calls add_root_author" do - allow(Postzord::Dispatcher).to receive(:defer_build_and_post).and_return(true) - allow(@generator).to receive(:build).and_return(@relayable) - allow(@relayable).to receive(:save!).and_return(true) - expect(@generator).to receive(:add_root_author) - @generator.create! - end -end diff --git a/spec/lib/diaspora/federated/relayable_retraction_spec.rb b/spec/lib/diaspora/federated/relayable_retraction_spec.rb deleted file mode 100644 index 6e8635a24819f0329b87a85067226e8f4e1546ad..0000000000000000000000000000000000000000 --- a/spec/lib/diaspora/federated/relayable_retraction_spec.rb +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' -require Rails.root.join("spec", "shared_behaviors", "relayable") - -describe RelayableRetraction do - before do - @local_luke, @local_leia, @remote_raphael = set_up_friends - @remote_parent = FactoryGirl.build(:status_message, :author => @remote_raphael) - @local_parent = @local_luke.post :status_message, :text => "hi", :to => @local_luke.aspects.first - end - - context "when retracting a comment" do - before do - @comment= @local_luke.comment!(@local_parent, "yo") - @retraction= @local_luke.retract(@comment) - end - - describe "#parent" do - it "delegates to to target" do - expect(@retraction.target).to receive(:parent) - @retraction.parent - end - end - - describe "#parent_author" do - it "delegates to target" do - expect(@retraction.target).to receive(:parent_author) - @retraction.parent_author - end - end - - describe '#subscribers' do - it 'delegates it to target' do - arg = double() - expect(@retraction.target).to receive(:subscribers).with(arg) - @retraction.subscribers(arg) - end - end - end - - describe '#receive' do - it 'discards a retraction with a nil target' do - @comment= @local_luke.comment!(@local_parent, "yo") - @retraction= @local_luke.retract(@comment) - - @retraction.instance_variable_set(:@target, nil) - @retraction.target_guid = '135245' - expect(@retraction).not_to receive(:perform) - @retraction.receive(@local_luke, @remote_raphael) - end - - context 'from the downstream author' do - before do - @comment = @local_leia.comment!(@local_parent, "yo") - @retraction = @local_leia.retract(@comment) - @recipient = @local_luke - end - - it 'signs' do - expect(@retraction).to receive(:sign_with_key) do |key| - expect(key.to_s).to eq(@recipient.encryption_key.to_s) - end - @retraction.receive(@recipient, @comment.author) - end - - it 'dispatches' do - zord = double() - expect(zord).to receive(:post) - expect(Postzord::Dispatcher).to receive(:build).with(@local_luke, @retraction).and_return zord - @retraction.receive(@recipient, @comment.author) - end - - it 'performs' do - expect(@retraction).to receive(:perform).with(@local_luke) - @retraction.receive(@recipient, @comment.author) - end - end - - context 'from the upstream owner' do - before do - @comment = @local_luke.comment!(@remote_parent, "Yeah, it was great") - @retraction = described_class.allocate - @retraction.sender = @remote_raphael - @retraction.target = @comment - allow(@retraction).to receive(:parent_author_signature_valid?).and_return(true) - @recipient = @local_luke - end - - it 'performs' do - expect(@retraction).to receive(:perform).with(@recipient) - @retraction.receive(@recipient, @remote_raphael) - end - - it 'does not dispatch' do - expect(Postzord::Dispatcher).not_to receive(:build) - @retraction.receive(@recipient, @remote_raphael) - end - - it 'performs through postzord' do - xml = Salmon::Slap.create_by_user_and_activity(@local_luke, @retraction.to_diaspora_xml).xml_for(nil) - expect { - Postzord::Receiver::Public.new(xml).perform! - }.to change(Comment, :count).by(-1) - end - end - end - - describe 'xml' do - before do - @comment = @local_leia.comment!(@local_parent, "yo") - @retraction = described_class.build(@local_leia, @comment) - @retraction.parent_author_signature = 'PARENTSIGNATURE' - @retraction.target_author_signature = 'TARGETSIGNATURE' - @xml = @retraction.to_xml.to_s - end - - describe '#to_xml' do - it 'serializes target_guid' do - expect(@xml).to include(@comment.guid) - end - - it 'serializes target_type' do - expect(@xml).to include(@comment.class.to_s) - end - - it 'serializes sender_handle' do - expect(@xml).to include(@local_leia.diaspora_handle) - end - - it 'serializes signatures' do - expect(@xml).to include('TARGETSIGNATURE') - expect(@xml).to include('PARENTSIGNATURE') - end - end - - describe '.from_xml' do - before do - @marshalled = described_class.from_xml(@xml) - end - - it 'marshals the target' do - expect(@marshalled.target).to eq(@comment) - end - - it 'marshals the sender' do - expect(@marshalled.sender).to eq(@local_leia.person) - end - - it 'marshals the signature' do - expect(@marshalled.target_author_signature).to eq('TARGETSIGNATURE') - expect(@marshalled.parent_author_signature).to eq('PARENTSIGNATURE') - end - end - end -end diff --git a/spec/lib/diaspora/federated/request_spec.rb b/spec/lib/diaspora/federated/request_spec.rb deleted file mode 100644 index 8a15f85062b46d673f933b0790af963608e38076..0000000000000000000000000000000000000000 --- a/spec/lib/diaspora/federated/request_spec.rb +++ /dev/null @@ -1,166 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Request do - before do - @aspect = alice.aspects.first - end - - describe 'validations' do - before do - @request = described_class.diaspora_initialize(:from => alice.person, :to => eve.person, :into => @aspect) - end - - it 'is valid' do - expect(@request.sender).to eq(alice.person) - expect(@request.recipient).to eq(eve.person) - expect(@request.aspect).to eq(@aspect) - expect(@request).to be_valid - end - - it 'is from a person' do - @request.sender = nil - expect(@request).not_to be_valid - end - - it 'is to a person' do - @request.recipient = nil - expect(@request).not_to be_valid - end - - it 'is not necessarily into an aspect' do - @request.aspect = nil - expect(@request).to be_valid - end - - it 'is not from an existing friend' do - Contact.create(:user => eve, :person => alice.person, :aspects => [eve.aspects.first]) - expect(@request).not_to be_valid - end - - it 'is not to yourself' do - @request = described_class.diaspora_initialize(:from => alice.person, :to => alice.person, :into => @aspect) - expect(@request).not_to be_valid - end - end - - describe '#notification_type' do - it 'returns request_accepted' do - person = FactoryGirl.build:person - - request = described_class.diaspora_initialize(:from => alice.person, :to => eve.person, :into => @aspect) - alice.contacts.create(:person_id => person.id) - - expect(request.notification_type(alice, person)).to eq(Notifications::StartedSharing) - end - end - - describe '#subscribers' do - it 'returns an array with to field on a request' do - request = described_class.diaspora_initialize(:from => alice.person, :to => eve.person, :into => @aspect) - expect(request.subscribers(alice)).to match_array([eve.person]) - end - end - - describe '#receive' do - it 'creates a contact' do - request = described_class.diaspora_initialize(:from => alice.person, :to => eve.person, :into => @aspect) - expect{ - request.receive(eve, alice.person) - }.to change{ - eve.contacts(true).size - }.by(1) - end - - it 'sets mutual if a contact already exists' do - alice.share_with(eve.person, alice.aspects.first) - - expect { - described_class.diaspora_initialize(:from => eve.person, :to => alice.person, - :into => eve.aspects.first).receive(alice, eve.person) - }.to change { - alice.contacts.find_by_person_id(eve.person.id).mutual? - }.from(false).to(true) - - end - - it 'sets sharing' do - described_class.diaspora_initialize(:from => eve.person, :to => alice.person, - :into => eve.aspects.first).receive(alice, eve.person) - expect(alice.contact_for(eve.person)).to be_sharing - end - - it 'shares back if auto_following is enabled' do - alice.auto_follow_back = true - alice.auto_follow_back_aspect = alice.aspects.first - alice.save - - described_class.diaspora_initialize(:from => eve.person, :to => alice.person, - :into => eve.aspects.first).receive(alice, eve.person) - - expect(eve.contact_for( alice.person )).to be_sharing - end - - it 'shares not back if auto_following is not enabled' do - alice.auto_follow_back = false - alice.auto_follow_back_aspect = alice.aspects.first - alice.save - - described_class.diaspora_initialize(:from => eve.person, :to => alice.person, - :into => eve.aspects.first).receive(alice, eve.person) - - expect(eve.contact_for(alice.person)).to be_nil - end - - it 'shares not back if already sharing' do - alice.auto_follow_back = true - alice.auto_follow_back_aspect = alice.aspects.first - alice.save - - contact = FactoryGirl.build:contact, :user => alice, :person => eve.person, - :receiving => true, :sharing => false - contact.save - - expect(alice).not_to receive(:share_with) - - described_class.diaspora_initialize(:from => eve.person, :to => alice.person, - :into => eve.aspects.first).receive(alice, eve.person) - end - - it "queue a job to fetch public posts" do - expect(Diaspora::Fetcher::Public).to receive(:queue_for).exactly(1).times - - described_class.diaspora_initialize(from: eve.person, to: alice.person, - into: eve.aspects.first).receive(alice, eve.person) - end - end - - context 'xml' do - before do - @request = described_class.diaspora_initialize(:from => alice.person, :to => eve.person, :into => @aspect) - @xml = @request.to_xml.to_s - end - - describe 'serialization' do - it 'produces valid xml' do - expect(@xml).to include alice.person.diaspora_handle - expect(@xml).to include eve.person.diaspora_handle - expect(@xml).not_to include alice.person.exported_key - expect(@xml).not_to include alice.person.profile.first_name - end - end - - context 'marshalling' do - it 'produces a request object' do - marshalled = described_class.from_xml @xml - - expect(marshalled.sender).to eq(alice.person) - expect(marshalled.recipient).to eq(eve.person) - expect(marshalled.aspect).to be_nil - end - end - end -end diff --git a/spec/lib/diaspora/federated/retraction_spec.rb b/spec/lib/diaspora/federated/retraction_spec.rb index 11b1c49f91f61cf0510e262e9881ba5ccff28ac4..450ff20c903fcd1ab4114f513fbf53737fa6c09e 100644 --- a/spec/lib/diaspora/federated/retraction_spec.rb +++ b/spec/lib/diaspora/federated/retraction_spec.rb @@ -2,59 +2,167 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' +require "spec_helper" describe Retraction do - before do - @aspect = alice.aspects.first - alice.contacts.create(:person => eve.person, :aspects => [@aspect]) - @post = alice.post(:status_message, :public => true, :text => "Destroy!", :to => @aspect.id) + let(:post) { alice.post(:status_message, text: "destroy!", public: true) } + let(:retraction) { Retraction.for(post, alice) } + + describe "#subscribers" do + it "contains all remote-subscribers of target object" do + post = local_luke.post(:status_message, text: "destroy!", public: true) + + retraction = Retraction.for(post, local_luke) + + expect(retraction.subscribers).to eq([remote_raphael]) + end end - describe 'serialization' do - it 'should have a post id after serialization' do - retraction = described_class.for(@post) - xml = retraction.to_xml.to_s - expect(xml.include?(@post.guid.to_s)).to eq(true) + describe "#data" do + it "contains the hash with all data from the federation-retraction" do + federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, alice) + + expect(retraction.data).to eq(federation_retraction.to_h) end end - describe '#subscribers' do - context 'posts' do - before do - @retraction = described_class.for(@post) - @obj = @retraction.instance_variable_get(:@object) - @wanted_subscribers = @obj.subscribers(alice) - end + describe ".for" do + it "creates a retraction for a post" do + expect(Diaspora::Federation::Entities).to receive(:signed_retraction).with(post, alice) - it 'returns the subscribers to the post for all objects other than person' do - expect(@retraction.subscribers(alice).map(&:id)).to match_array(@wanted_subscribers.map(&:id)) - end + Retraction.for(post, alice) + end - it 'does not return the authors of reshares' do - @post.reshares << FactoryGirl.build(:reshare, :root => @post, :author => bob.person) - @post.save! + it "creates a retraction for a relayable" do + comment = FactoryGirl.create(:comment, author: alice.person, post: post) - @wanted_subscribers -= [bob.person] - expect(@retraction.subscribers(alice).map(&:id)).to match_array(@wanted_subscribers.map(&:id)) - end + expect(Diaspora::Federation::Entities).to receive(:relayable_retraction).with(comment, alice) + + Retraction.for(comment, alice) + end + + it "creates a retraction for a contact" do + contact = FactoryGirl.create(:contact) + + expect(Diaspora::Federation::Entities).to receive(:retraction).with(contact) + + Retraction.for(contact, contact.user) + end + end + + describe ".defer_dispatch" do + it "queues a job to send the retraction later" do + post = local_luke.post(:status_message, text: "destroy!", public: true) + federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, local_luke) + + expect(Workers::DeferredRetraction).to receive(:perform_async).with( + local_luke.id, federation_retraction.to_h, [remote_raphael.id], service_types: [] + ) + + Retraction.for(post, local_luke).defer_dispatch(local_luke) + end + + it "adds service metadata to queued job for deletion" do + post.tweet_id = "123" + twitter = Services::Twitter.new(access_token: "twitter") + facebook = Services::Facebook.new(access_token: "facebook") + alice.services << twitter << facebook + + federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, alice) + + expect(Workers::DeferredRetraction).to receive(:perform_async).with( + alice.id, federation_retraction.to_h, [], service_types: ["Services::Twitter"], tweet_id: "123" + ) + + Retraction.for(post, alice).defer_dispatch(alice) + end + + it "queues also a job if subscribers is empty" do + federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, alice) + + expect(Workers::DeferredRetraction).to receive(:perform_async).with( + alice.id, federation_retraction.to_h, [], service_types: [] + ) + + Retraction.for(post, alice).defer_dispatch(alice) end - context 'setting subscribers' do - it 'barfs if the type is a person, and subscribers instance varabile is not set' do - retraction = described_class.for(alice) - obj = retraction.instance_variable_get(:@object) + it "queues a job with empty opts for non-StatusMessage" do + post = local_luke.post(:status_message, text: "hello", public: true) + comment = local_luke.comment!(post, "destroy!") + federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_luke) + + expect(Workers::DeferredRetraction).to receive(:perform_async).with( + local_luke.id, federation_retraction.to_h, [remote_raphael.id], {} + ) + + Retraction.for(comment, local_luke).defer_dispatch(local_luke) + end + + it "uses the author of the target parent as sender for a comment-retraction if the parent is local" do + post = local_luke.post(:status_message, text: "hello", public: true) + comment = local_leia.comment!(post, "destroy!") + federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_leia) + + expect(Workers::DeferredRetraction).to receive(:perform_async).with( + local_luke.id, federation_retraction.to_h, [remote_raphael.id], {} + ) - expect { - retraction.subscribers(alice) - }.to raise_error + Retraction.for(comment, local_leia).defer_dispatch(local_leia) + end + + context "relayable" do + let(:post) { local_luke.post(:status_message, text: "hello", public: true) } + let(:comment) { FactoryGirl.create(:comment, post: post, author: remote_raphael) } + + it "sends retraction to target author if deleted by parent author" do + federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_luke) + + expect(Workers::DeferredRetraction).to receive(:perform_async).with( + local_luke.id, federation_retraction.to_h, [remote_raphael.id], {} + ) + + Retraction.for(comment, local_luke).defer_dispatch(local_luke) end - it 'returns manually set subscribers' do - retraction = described_class.for(alice) - retraction.subscribers = "fooey" - expect(retraction.subscribers(alice)).to eq('fooey') + it "don't sends retraction back to target author if relayed by parent author" do + federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_luke) + + expect(Workers::DeferredRetraction).to receive(:perform_async).with( + local_luke.id, federation_retraction.to_h, [], {} + ) + + Retraction.for(comment, local_luke).defer_dispatch(local_luke, false) end end end + + describe "#perform" do + it "destroys the target object" do + expect(post).to receive(:destroy!) + Retraction.for(post, alice).perform + end + end + + describe "#public?" do + it "returns true for a public post" do + expect(Retraction.for(post, alice).public?).to be_truthy + end + + it "returns true for a public comment if parent post is local" do + comment = bob.comment!(post, "destroy!") + expect(Retraction.for(comment, bob).public?).to be_truthy + end + + it "returns false for a public comment if parent post is not local" do + remote_post = FactoryGirl.create(:status_message, author: remote_raphael) + comment = alice.comment!(remote_post, "destroy!") + expect(Retraction.for(comment, alice).public?).to be_falsey + end + + it "returns false for a private target" do + private_post = alice.post(:status_message, text: "destroy!", to: alice.aspects.first.id) + expect(Retraction.for(private_post, alice).public?).to be_falsey + end + end end diff --git a/spec/lib/diaspora/federated/signed_retraction_spec.rb b/spec/lib/diaspora/federated/signed_retraction_spec.rb deleted file mode 100644 index 332e9e9c45658a131aa77e91b2c5f719ee047c6d..0000000000000000000000000000000000000000 --- a/spec/lib/diaspora/federated/signed_retraction_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -require 'spec_helper' - -describe SignedRetraction do - before do - @post = FactoryGirl.create(:status_message, :author => bob.person, :public => true) - @resharer = FactoryGirl.create(:user) - @post.reshares << FactoryGirl.create(:reshare, :root => @post, :author => @resharer.person) - @post.save! - end - describe '#perform' do - it "dispatches the retraction onward to recipients of the recipient's reshare" do - retraction = described_class.build(bob, @post) - onward_retraction = retraction.dup - expect(retraction).to receive(:dup).and_return(onward_retraction) - - dis = double - expect(Postzord::Dispatcher).to receive(:build).with(@resharer, onward_retraction).and_return(dis) - expect(dis).to receive(:post) - - retraction.perform(@resharer) - end - it 'relays the retraction onward even if the post does not exist' do - remote_post = FactoryGirl.create(:status_message, :public => true) - bob.post(:reshare, :root_guid => remote_post.guid) - alice.post(:reshare, :root_guid => remote_post.guid) - - remote_retraction = described_class.new.tap{|r| - r.target_type = remote_post.type - r.target_guid = remote_post.guid - r.sender = remote_post.author - allow(r).to receive(:target_author_signature_valid?).and_return(true) - } - - remote_retraction.dup.perform(bob) - expect(Post.exists?(:id => remote_post.id)).to be false - - dis = double - expect(Postzord::Dispatcher).to receive(:build){ |sender, retraction| - expect(sender).to eq(alice) - expect(retraction.sender).to eq(alice.person) - dis - } - expect(dis).to receive(:post) - remote_retraction.perform(alice) - end - end -end diff --git a/spec/lib/diaspora/federated_base_spec.rb b/spec/lib/diaspora/federated_base_spec.rb deleted file mode 100644 index a2621e3c634b950d0ff8e2359fb110a11607b40d..0000000000000000000000000000000000000000 --- a/spec/lib/diaspora/federated_base_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Diaspora::Federated::Base do - describe '#subscribers' do - it 'throws an error if the including module does not redefine it' do - class Foo - include Diaspora::Federated::Base - end - - f = Foo.new - - expect{ f.subscribers(1)}.to raise_error /override subscribers/ - end - end -end diff --git a/spec/lib/diaspora/federation/dispatcher/private_spec.rb b/spec/lib/diaspora/federation/dispatcher/private_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..5ef6c108ec86aec5bf322f171ec5dbec737eff24 --- /dev/null +++ b/spec/lib/diaspora/federation/dispatcher/private_spec.rb @@ -0,0 +1,59 @@ +require "spec_helper" + +describe Diaspora::Federation::Dispatcher::Private do + let(:post) { FactoryGirl.create(:status_message, author: alice.person, text: "hello", public: false) } + let(:comment) { FactoryGirl.create(:comment, author: alice.person, post: post) } + + before do + alice.share_with(remote_raphael, alice.aspects.first) + alice.add_to_streams(post, [alice.aspects.first]) + end + + describe "#dispatch" do + context "deliver to remote user" do + let(:xml) { "<diaspora/>" } + it "queues a private send job" do + expect(Workers::SendPrivate).to receive(:perform_async) do |user_id, _entity_string, targets| + expect(user_id).to eq(alice.id) + expect(targets.size).to eq(1) + expect(targets).to have_key(remote_raphael.receive_url) + expect(targets[remote_raphael.receive_url]).to eq(xml) + end + + salmon = double + expect(DiasporaFederation::Salmon::EncryptedSlap).to receive(:prepare).and_return(salmon) + expect(salmon).to receive(:generate_xml).and_return(xml) + + Diaspora::Federation::Dispatcher.build(alice, post).dispatch + end + + it "does not queue a private send job when no remote recipients specified" do + bobs_post = FactoryGirl.create(:status_message, author: alice.person, text: "hello", public: false) + bob.add_to_streams(bobs_post, [bob.aspects.first]) + + expect(Workers::SendPrivate).not_to receive(:perform_async) + + Diaspora::Federation::Dispatcher.build(bob, bobs_post).dispatch + end + + it "queues private send job for a specific subscriber" do + remote_person = FactoryGirl.create(:person) + + expect(Workers::SendPrivate).to receive(:perform_async) do |user_id, _entity_string, targets| + expect(user_id).to eq(alice.id) + expect(targets.size).to eq(1) + expect(targets).to have_key(remote_person.receive_url) + expect(targets[remote_person.receive_url]).to eq(xml) + end + + salmon = double + expect(DiasporaFederation::Salmon::EncryptedSlap).to receive(:prepare).and_return(salmon) + expect(salmon).to receive(:generate_xml).and_return(xml) + + Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [remote_person]).dispatch + end + end + end + + it_behaves_like "a dispatcher" +end diff --git a/spec/lib/diaspora/federation/dispatcher/public_spec.rb b/spec/lib/diaspora/federation/dispatcher/public_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..5fb654f0215a376401f72ff0452527ed29a101d7 --- /dev/null +++ b/spec/lib/diaspora/federation/dispatcher/public_spec.rb @@ -0,0 +1,92 @@ +require "spec_helper" + +describe Diaspora::Federation::Dispatcher::Public do + let(:post) { FactoryGirl.create(:status_message, author: alice.person, text: "hello", public: true) } + let(:comment) { FactoryGirl.create(:comment, author: alice.person, post: post) } + + describe "#dispatch" do + context "pubsubhubbub" do + it "delivers public posts to pubsubhubbub" do + expect(Workers::PublishToHub).to receive(:perform_async).with(alice.atom_url) + Diaspora::Federation::Dispatcher.build(alice, post).dispatch + end + + it "does not call pubsubhubbub for comments" do + expect(Workers::PublishToHub).not_to receive(:perform_async) + Diaspora::Federation::Dispatcher.build(alice, comment).dispatch + end + end + + context "relay functionality" do + before do + AppConfig.relay.outbound.url = "https://relay.iliketoast.net/receive/public" + end + + it "delivers public post to relay when relay is enabled" do + AppConfig.relay.outbound.send = true + + expect(Workers::SendPublic).to receive(:perform_async) do |_user_id, _entity_string, urls, _xml| + expect(urls).to include("https://relay.iliketoast.net/receive/public") + end + + Diaspora::Federation::Dispatcher.build(alice, post).dispatch + end + + it "does not deliver post to relay when relay is disabled" do + AppConfig.relay.outbound.send = false + + expect(Workers::SendPublic).not_to receive(:perform_async) + + Diaspora::Federation::Dispatcher.build(alice, post).dispatch + end + + it "does not deliver comments to relay" do + AppConfig.relay.outbound.send = true + + expect(Workers::SendPublic).not_to receive(:perform_async) + + Diaspora::Federation::Dispatcher.build(alice, comment).dispatch + end + end + + context "deliver to remote user" do + let(:salmon_xml) { "<diaspora/>" } + + it "queues a public send job" do + alice.share_with(remote_raphael, alice.aspects.first) + + expect(Workers::SendPublic).to receive(:perform_async) do |user_id, _entity_string, urls, xml| + expect(user_id).to eq(alice.id) + expect(urls.size).to eq(1) + expect(urls[0]).to eq(remote_raphael.pod.url_to("/receive/public")) + expect(xml).to eq(salmon_xml) + end + + expect(DiasporaFederation::Salmon::Slap).to receive(:generate_xml).and_return(salmon_xml) + + Diaspora::Federation::Dispatcher.build(alice, post).dispatch + end + + it "does not queue a private send job when no remote recipients specified" do + expect(Workers::SendPublic).not_to receive(:perform_async) + + Diaspora::Federation::Dispatcher.build(alice, post).dispatch + end + + it "queues public send job for a specific subscriber" do + expect(Workers::SendPublic).to receive(:perform_async) do |user_id, _entity_string, urls, xml| + expect(user_id).to eq(alice.id) + expect(urls.size).to eq(1) + expect(urls[0]).to eq(remote_raphael.pod.url_to("/receive/public")) + expect(xml).to eq(salmon_xml) + end + + expect(DiasporaFederation::Salmon::Slap).to receive(:generate_xml).and_return(salmon_xml) + + Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [remote_raphael]).dispatch + end + end + end + + it_behaves_like "a dispatcher" +end diff --git a/spec/lib/diaspora/federation/dispatcher_spec.rb b/spec/lib/diaspora/federation/dispatcher_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..40ab01dc899dcf472c37458879bed06f6b5283b4 --- /dev/null +++ b/spec/lib/diaspora/federation/dispatcher_spec.rb @@ -0,0 +1,64 @@ +require "spec_helper" + +describe Diaspora::Federation::Dispatcher do + let(:post) { FactoryGirl.create(:status_message, author: alice.person, text: "hello", public: true) } + let(:opts) { {service_types: "Services::Twitter"} } + + describe ".build" do + it "creates a public dispatcher for a public post" do + expect(Diaspora::Federation::Dispatcher::Public).to receive(:new).with(alice, post, opts).and_call_original + + dispatcher = described_class.build(alice, post, opts) + + expect(dispatcher).to be_instance_of(Diaspora::Federation::Dispatcher::Public) + end + + it "creates a private dispatcher for a private post" do + private = FactoryGirl.create(:status_message, author: alice.person, text: "hello", public: false) + + expect(Diaspora::Federation::Dispatcher::Private).to receive(:new).with(alice, private, opts).and_call_original + + dispatcher = described_class.build(alice, private, opts) + + expect(dispatcher).to be_instance_of(Diaspora::Federation::Dispatcher::Private) + end + + it "creates a private dispatcher for object with no public flag" do + object = double + + expect(Diaspora::Federation::Dispatcher::Private).to receive(:new).with(alice, object, {}).and_call_original + + dispatcher = described_class.build(alice, object) + + expect(dispatcher).to be_instance_of(Diaspora::Federation::Dispatcher::Private) + end + + it "uses the parent author as sender for a comment if the parent is local" do + comment = FactoryGirl.create(:comment, author: bob.person, post: post) + + expect(Diaspora::Federation::Dispatcher::Public).to receive(:new).with(alice, comment, {}).and_call_original + + dispatcher = described_class.build(bob, comment) + + expect(dispatcher).to be_instance_of(Diaspora::Federation::Dispatcher::Public) + end + + it "uses the original sender for a comment if the parent is not local" do + remote_post = FactoryGirl.create(:status_message, author: remote_raphael, text: "hello", public: true) + comment = FactoryGirl.create(:comment, author: bob.person, post: remote_post) + + expect(Diaspora::Federation::Dispatcher::Public).to receive(:new).with(bob, comment, {}).and_call_original + + dispatcher = described_class.build(bob, comment) + + expect(dispatcher).to be_instance_of(Diaspora::Federation::Dispatcher::Public) + end + end + + describe ".defer_dispatch" do + it "queues a job for dispatch" do + expect(Workers::DeferredDispatch).to receive(:perform_async).with(alice.id, "StatusMessage", post.id, opts) + described_class.defer_dispatch(alice, post, opts) + end + end +end diff --git a/spec/lib/diaspora/federation/entities_spec.rb b/spec/lib/diaspora/federation/entities_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..8e97e6705b340cf9af3690e87eb96dad04f4e8b3 --- /dev/null +++ b/spec/lib/diaspora/federation/entities_spec.rb @@ -0,0 +1,364 @@ +require "spec_helper" + +describe Diaspora::Federation::Entities do + describe ".build" do + it "builds an account deletion" do + diaspora_entity = FactoryGirl.build(:account_deletion) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::AccountDeletion) + expect(federation_entity.author).to eq(diaspora_entity.person.diaspora_handle) + end + + it "builds a comment" do + diaspora_entity = FactoryGirl.build(:comment) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Comment) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.parent_guid).to eq(diaspora_entity.post.guid) + expect(federation_entity.text).to eq(diaspora_entity.text) + expect(federation_entity.author_signature).to be_nil + expect(federation_entity.xml_order).to be_nil + expect(federation_entity.additional_xml_elements).to be_empty + end + + it "builds a comment with signature" do + diaspora_entity = FactoryGirl.build(:comment, signature: FactoryGirl.build(:comment_signature)) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Comment) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.parent_guid).to eq(diaspora_entity.post.guid) + expect(federation_entity.text).to eq(diaspora_entity.text) + expect(federation_entity.author_signature).to eq(diaspora_entity.signature.author_signature) + expect(federation_entity.xml_order).to eq(diaspora_entity.signature.signature_order.order.split) + expect(federation_entity.additional_xml_elements).to eq(diaspora_entity.signature.additional_data) + end + + it "builds a contact (request)" do + diaspora_entity = FactoryGirl.build(:contact) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Request) + expect(federation_entity.author).to eq(diaspora_entity.user.diaspora_handle) + expect(federation_entity.recipient).to eq(diaspora_entity.person.diaspora_handle) + end + + context "Conversation" do + let(:participant) { FactoryGirl.create(:person) } + let(:diaspora_entity) { FactoryGirl.create(:conversation_with_message, participants: [participant]) } + let(:federation_entity) { described_class.build(diaspora_entity) } + + it "builds a conversation" do + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Conversation) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.subject).to eq(diaspora_entity.subject) + expect(federation_entity.created_at).to eq(diaspora_entity.created_at) + end + + it "adds the participants" do + expect(federation_entity.participants) + .to eq("#{participant.diaspora_handle};#{diaspora_entity.author.diaspora_handle}") + end + + it "includes the message" do + diaspora_message = diaspora_entity.messages.first + federation_message = federation_entity.messages.first + + expect(federation_message.author).to eq(diaspora_message.author.diaspora_handle) + expect(federation_message.guid).to eq(diaspora_message.guid) + expect(federation_message.conversation_guid).to eq(diaspora_entity.guid) + expect(federation_message.text).to eq(diaspora_message.text) + expect(federation_message.created_at).to eq(diaspora_message.created_at) + end + end + + it "builds a like" do + diaspora_entity = FactoryGirl.build(:like) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Like) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.parent_guid).to eq(diaspora_entity.target.guid) + expect(federation_entity.positive).to eq(diaspora_entity.positive) + expect(federation_entity.author_signature).to be_nil + expect(federation_entity.xml_order).to be_nil + expect(federation_entity.additional_xml_elements).to be_empty + end + + it "builds a like with signature" do + diaspora_entity = FactoryGirl.build(:like, signature: FactoryGirl.build(:like_signature)) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Like) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.parent_guid).to eq(diaspora_entity.target.guid) + expect(federation_entity.positive).to eq(diaspora_entity.positive) + expect(federation_entity.author_signature).to eq(diaspora_entity.signature.author_signature) + expect(federation_entity.xml_order).to eq(diaspora_entity.signature.signature_order.order.split) + expect(federation_entity.additional_xml_elements).to eq(diaspora_entity.signature.additional_data) + end + + it "builds a message" do + diaspora_entity = FactoryGirl.create(:message, author_signature: "abc") + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Message) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.conversation_guid).to eq(diaspora_entity.conversation.guid) + expect(federation_entity.text).to eq(diaspora_entity.text) + expect(federation_entity.created_at).to eq(diaspora_entity.created_at) + expect(federation_entity.author_signature).to eq(diaspora_entity.author_signature) + end + + it "builds a participation" do + diaspora_entity = FactoryGirl.build(:participation) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Participation) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.parent_guid).to eq(diaspora_entity.target.guid) + expect(federation_entity.parent_type).to eq(diaspora_entity.target.class.base_class.to_s) + end + + it "builds a photo" do + diaspora_entity = FactoryGirl.create(:photo) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Photo) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.public).to eq(diaspora_entity.public) + expect(federation_entity.created_at).to eq(diaspora_entity.created_at) + expect(federation_entity.remote_photo_path).to eq(diaspora_entity.remote_photo_path) + expect(federation_entity.remote_photo_name).to eq(diaspora_entity.remote_photo_name) + expect(federation_entity.text).to eq(diaspora_entity.text) + expect(federation_entity.height).to eq(diaspora_entity.height) + expect(federation_entity.width).to eq(diaspora_entity.width) + end + + it "builds a poll participation" do + diaspora_entity = FactoryGirl.build(:poll_participation) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::PollParticipation) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.parent_guid).to eq(diaspora_entity.poll_answer.poll.guid) + expect(federation_entity.poll_answer_guid).to eq(diaspora_entity.poll_answer.guid) + expect(federation_entity.author_signature).to be_nil + expect(federation_entity.xml_order).to be_nil + expect(federation_entity.additional_xml_elements).to be_empty + end + + it "builds a poll participation with signature" do + signature = FactoryGirl.build(:poll_participation_signature) + diaspora_entity = FactoryGirl.build(:poll_participation, signature: signature) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::PollParticipation) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.parent_guid).to eq(diaspora_entity.poll_answer.poll.guid) + expect(federation_entity.poll_answer_guid).to eq(diaspora_entity.poll_answer.guid) + expect(federation_entity.author_signature).to eq(signature.author_signature) + expect(federation_entity.xml_order).to eq(signature.signature_order.order.split) + expect(federation_entity.additional_xml_elements).to eq(signature.additional_data) + end + + it "builds a profile" do + diaspora_entity = FactoryGirl.build(:profile_with_image_url) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Profile) + expect(federation_entity.author).to eq(diaspora_entity.diaspora_handle) + expect(federation_entity.first_name).to eq(diaspora_entity.first_name) + expect(federation_entity.last_name).to eq(diaspora_entity.last_name) + expect(federation_entity.image_url).to eq(diaspora_entity.image_url) + expect(federation_entity.image_url_medium).to eq(diaspora_entity.image_url_medium) + expect(federation_entity.image_url_small).to eq(diaspora_entity.image_url_small) + expect(federation_entity.birthday).to eq(diaspora_entity.birthday) + expect(federation_entity.gender).to eq(diaspora_entity.gender) + expect(federation_entity.bio).to eq(diaspora_entity.bio) + expect(federation_entity.location).to eq(diaspora_entity.location) + expect(federation_entity.searchable).to eq(diaspora_entity.searchable) + expect(federation_entity.nsfw).to eq(diaspora_entity.nsfw) + expect(federation_entity.tag_string.split(" ")).to match_array(diaspora_entity.tag_string.split(" ")) + end + + it "builds a reshare" do + diaspora_entity = FactoryGirl.create(:reshare) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Reshare) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.root_author).to eq(diaspora_entity.root.author.diaspora_handle) + expect(federation_entity.root_guid).to eq(diaspora_entity.root.guid) + expect(federation_entity.public).to be_truthy + expect(federation_entity.created_at).to eq(diaspora_entity.created_at) + expect(federation_entity.provider_display_name).to eq(diaspora_entity.provider_display_name) + end + + context "StatusMessage" do + it "builds a status message" do + diaspora_entity = FactoryGirl.create(:status_message) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::StatusMessage) + expect(federation_entity.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_entity.guid).to eq(diaspora_entity.guid) + expect(federation_entity.text).to eq(diaspora_entity.text) + expect(federation_entity.public).to eq(diaspora_entity.public) + expect(federation_entity.created_at).to eq(diaspora_entity.created_at) + expect(federation_entity.provider_display_name).to eq(diaspora_entity.provider_display_name) + + expect(federation_entity.photos).to be_empty + expect(federation_entity.location).to be_nil + expect(federation_entity.poll).to be_nil + end + + it "includes the photos" do + diaspora_entity = FactoryGirl.create(:status_message_with_photo) + diaspora_photo = diaspora_entity.photos.first + federation_entity = described_class.build(diaspora_entity) + federation_photo = federation_entity.photos.first + + expect(federation_entity.photos.size).to eq(1) + expect(federation_photo.author).to eq(diaspora_entity.author.diaspora_handle) + expect(federation_photo.guid).to eq(diaspora_photo.guid) + expect(federation_photo.public).to eq(diaspora_photo.public) + expect(federation_photo.created_at).to eq(diaspora_photo.created_at) + expect(federation_photo.remote_photo_path).to eq(diaspora_photo.remote_photo_path) + expect(federation_photo.remote_photo_name).to eq(diaspora_photo.remote_photo_name) + expect(federation_photo.text).to eq(diaspora_photo.text) + expect(federation_photo.height).to eq(diaspora_photo.height) + expect(federation_photo.width).to eq(diaspora_photo.width) + end + + it "includes the location" do + diaspora_entity = FactoryGirl.create(:status_message_with_location) + diaspora_location = diaspora_entity.location + federation_entity = described_class.build(diaspora_entity) + federation_location = federation_entity.location + + expect(federation_location.address).to eq(diaspora_location.address) + expect(federation_location.lat).to eq(diaspora_location.lat) + expect(federation_location.lng).to eq(diaspora_location.lng) + end + + it "includes the poll" do + diaspora_entity = FactoryGirl.create(:status_message_with_poll) + diaspora_poll = diaspora_entity.poll + federation_entity = described_class.build(diaspora_entity) + federation_poll = federation_entity.poll + + expect(federation_poll.guid).to eq(diaspora_poll.guid) + expect(federation_poll.question).to eq(diaspora_poll.question) + + diaspora_answer1 = diaspora_poll.poll_answers.first + diaspora_answer2 = diaspora_poll.poll_answers.second + federation_answer1 = federation_poll.poll_answers.first + federation_answer2 = federation_poll.poll_answers.second + + expect(federation_answer1.guid).to eq(diaspora_answer1.guid) + expect(federation_answer1.answer).to eq(diaspora_answer1.answer) + expect(federation_answer2.guid).to eq(diaspora_answer2.guid) + expect(federation_answer2.answer).to eq(diaspora_answer2.answer) + end + end + end + + describe ".build_retraction" do + context "Retraction" do + it "builds a Retraction for a Photo" do + target = FactoryGirl.create(:photo, author: alice.person) + retraction = Retraction.for(target, alice) + federation_retraction = described_class.build_retraction(retraction) + + expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::Retraction) + expect(federation_retraction.author).to eq(target.author.diaspora_handle) + expect(federation_retraction.target_guid).to eq(target.guid) + expect(federation_retraction.target_type).to eq("Photo") + end + + it "builds a Retraction for a Contact" do + target = FactoryGirl.create(:contact) + retraction = Retraction.for(target, target.user) + federation_retraction = described_class.build_retraction(retraction) + + expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::Retraction) + expect(federation_retraction.author).to eq(target.user.diaspora_handle) + expect(federation_retraction.target_guid).to eq(target.user.guid) + expect(federation_retraction.target_type).to eq("Person") + end + end + + context "SignedRetraction" do + it "builds a SignedRetraction for a StatusMessage" do + target = FactoryGirl.create(:status_message, author: alice.person) + retraction = Retraction.for(target, alice) + federation_retraction = described_class.build_retraction(retraction) + + expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::SignedRetraction) + expect(federation_retraction.author).to eq(target.author.diaspora_handle) + expect(federation_retraction.target_guid).to eq(target.guid) + expect(federation_retraction.target_type).to eq("Post") + end + + it "builds a SignedRetraction for a Reshare" do + target = FactoryGirl.create(:reshare, author: alice.person) + retraction = Retraction.for(target, alice) + federation_retraction = described_class.build_retraction(retraction) + + expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::SignedRetraction) + expect(federation_retraction.author).to eq(target.author.diaspora_handle) + expect(federation_retraction.target_guid).to eq(target.guid) + expect(federation_retraction.target_type).to eq("Post") + end + end + + context "RelayableRetraction" do + it "builds a RelayableRetraction for a Comment" do + target = FactoryGirl.create(:comment, author: alice.person) + retraction = Retraction.for(target, alice) + federation_retraction = described_class.build_retraction(retraction) + + expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::RelayableRetraction) + expect(federation_retraction.author).to eq(alice.diaspora_handle) + expect(federation_retraction.target_guid).to eq(target.guid) + expect(federation_retraction.target_type).to eq("Comment") + end + + it "builds a RelayableRetraction for a Like" do + target = FactoryGirl.create(:like, author: alice.person) + retraction = Retraction.for(target, alice) + federation_retraction = described_class.build_retraction(retraction) + + expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::RelayableRetraction) + expect(federation_retraction.author).to eq(alice.diaspora_handle) + expect(federation_retraction.target_guid).to eq(target.guid) + expect(federation_retraction.target_type).to eq("Like") + end + + it "builds a RelayableRetraction for a PollParticipation" do + target = FactoryGirl.create(:poll_participation, author: alice.person) + retraction = Retraction.for(target, alice) + federation_retraction = described_class.build_retraction(retraction) + + expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::RelayableRetraction) + expect(federation_retraction.author).to eq(alice.diaspora_handle) + expect(federation_retraction.target_guid).to eq(target.guid) + expect(federation_retraction.target_type).to eq("PollParticipation") + end + end + end +end diff --git a/spec/lib/diaspora/federation/receive_spec.rb b/spec/lib/diaspora/federation/receive_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..df9e5da67762d4770010dc7b0f792651f34f5e76 --- /dev/null +++ b/spec/lib/diaspora/federation/receive_spec.rb @@ -0,0 +1,700 @@ +require "spec_helper" + +describe Diaspora::Federation::Receive do + let(:sender) { FactoryGirl.create(:person) } + let(:post) { FactoryGirl.create(:status_message, text: "hello", public: true, author: alice.person) } + + describe ".account_deletion" do + let(:account_deletion_entity) { FactoryGirl.build(:account_deletion_entity, author: sender.diaspora_handle) } + + it "saves the account deletion" do + Diaspora::Federation::Receive.account_deletion(account_deletion_entity) + + account_deletion = AccountDeletion.find_by!(diaspora_handle: sender.diaspora_handle) + + expect(account_deletion.person).to eq(sender) + end + end + + describe ".comment" do + let(:comment_data) { + FactoryGirl.attributes_for( + :comment_entity, + author: sender.diaspora_handle, + parent_guid: post.guid, + author_signature: "aa" + ) + } + let(:comment_entity) { + DiasporaFederation::Entities::Comment.new( + comment_data, [:author, :guid, :parent_guid, :text, "new_property"], "new_property" => "data" + ) + } + + it "saves the comment" do + received = Diaspora::Federation::Receive.perform(comment_entity) + + comment = Comment.find_by!(guid: comment_entity.guid) + + expect(received).to eq(comment) + expect(comment.author).to eq(sender) + expect(comment.text).to eq(comment_entity.text) + expect(comment.created_at.iso8601).to eq(comment_entity.created_at.iso8601) + end + + it "attaches the comment to the post" do + Diaspora::Federation::Receive.perform(comment_entity) + + comment = Comment.find_by!(guid: comment_entity.guid) + + expect(post.comments).to include(comment) + expect(comment.post).to eq(post) + end + + it "saves the signature data" do + Diaspora::Federation::Receive.perform(comment_entity) + + comment = Comment.find_by!(guid: comment_entity.guid) + + expect(comment.signature).not_to be_nil + expect(comment.signature.author_signature).to eq("aa") + expect(comment.signature.additional_data).to eq("new_property" => "data") + expect(comment.signature.order).to eq(%w(author guid parent_guid text new_property)) + end + + let(:entity) { comment_entity } + it_behaves_like "it ignores existing object received twice", Comment + it_behaves_like "it rejects if the parent author ignores the author", Comment + it_behaves_like "it relays relayables", Comment + end + + describe ".contact" do + let(:contact_entity) { + FactoryGirl.build(:contact_entity, author: sender.diaspora_handle, recipient: alice.diaspora_handle) + } + + it "creates the contact if it doesn't exist" do + received = Diaspora::Federation::Receive.perform(contact_entity) + + contact = alice.contacts.find_by!(person_id: sender.id) + + expect(received).to eq(contact) + expect(contact.sharing).to be_truthy + end + + it "updates the contact if it exists" do + alice.contacts.find_or_initialize_by(person_id: sender.id, receiving: true, sharing: false).save! + + received = Diaspora::Federation::Receive.perform(contact_entity) + + contact = alice.contacts.find_by!(person_id: sender.id) + + expect(received).to eq(contact) + expect(contact.sharing).to be_truthy + end + + it "does nothing, if already sharing" do + alice.contacts.find_or_initialize_by(person_id: sender.id, receiving: true, sharing: true).save! + + expect_any_instance_of(Contact).not_to receive(:save!) + + expect(Diaspora::Federation::Receive.perform(contact_entity)).to be_nil + end + + context "sharing=false" do + let(:unshare_contact_entity) { + FactoryGirl.build( + :contact_entity, + author: sender.diaspora_handle, + recipient: alice.diaspora_handle, + sharing: "false" + ) + } + + it "disconnects, if currently connected" do + alice.contacts.find_or_initialize_by(person_id: sender.id, receiving: true, sharing: true).save! + + received = Diaspora::Federation::Receive.perform(unshare_contact_entity) + expect(received).to be_nil + + contact = alice.contacts.find_by!(person_id: sender.id) + + expect(contact).not_to be_nil + expect(contact.sharing).to be_falsey + end + + it "does nothing, if already disconnected" do + received = Diaspora::Federation::Receive.perform(unshare_contact_entity) + expect(received).to be_nil + expect(alice.contacts.find_by(person_id: sender.id)).to be_nil + end + end + end + + describe ".conversation" do + let(:conv_guid) { FactoryGirl.generate(:guid) } + let(:message_entity) { + FactoryGirl.build( + :message_entity, + author: alice.diaspora_handle, + parent_guid: conv_guid, + conversation_guid: conv_guid + ) + } + let(:conversation_entity) { + FactoryGirl.build( + :conversation_entity, + guid: conv_guid, + author: alice.diaspora_handle, + messages: [message_entity], + participants: "#{alice.diaspora_handle};#{bob.diaspora_handle}" + ) + } + + it "saves the conversation" do + received = Diaspora::Federation::Receive.perform(conversation_entity) + + conv = Conversation.find_by!(guid: conversation_entity.guid) + + expect(received).to eq(conv) + expect(conv.author).to eq(alice.person) + expect(conv.subject).to eq(conversation_entity.subject) + end + + it "saves the message" do + Diaspora::Federation::Receive.perform(conversation_entity) + + conv = Conversation.find_by!(guid: conversation_entity.guid) + + expect(conv.messages.count).to eq(1) + expect(conv.messages.first.author).to eq(alice.person) + expect(conv.messages.first.text).to eq(message_entity.text) + expect(conv.messages.first.created_at.iso8601).to eq(message_entity.created_at.iso8601) + end + + it "creates appropriate visibilities" do + Diaspora::Federation::Receive.perform(conversation_entity) + + conv = Conversation.find_by!(guid: conversation_entity.guid) + + expect(conv.participants.count).to eq(2) + expect(conv.participants).to include(alice.person, bob.person) + end + + it_behaves_like "it ignores existing object received twice", Conversation do + let(:entity) { conversation_entity } + end + end + + describe ".like" do + let(:like_data) { + FactoryGirl.attributes_for( + :like_entity, + author: sender.diaspora_handle, + parent_guid: post.guid, + author_signature: "aa" + ) + } + let(:like_entity) { + DiasporaFederation::Entities::Like.new( + like_data, [:author, :guid, :parent_guid, :parent_type, :positive, "new_property"], "new_property" => "data" + ) + } + + it "saves the like" do + received = Diaspora::Federation::Receive.perform(like_entity) + + like = Like.find_by!(guid: like_entity.guid) + + expect(received).to eq(like) + expect(like.author).to eq(sender) + expect(like.positive).to be_truthy + end + + it "attaches the like to the post" do + Diaspora::Federation::Receive.perform(like_entity) + + like = Like.find_by!(guid: like_entity.guid) + + expect(post.likes).to include(like) + expect(like.target).to eq(post) + end + + it "saves the signature data" do + Diaspora::Federation::Receive.perform(like_entity) + + like = Like.find_by!(guid: like_entity.guid) + + expect(like.signature).not_to be_nil + expect(like.signature.author_signature).to eq("aa") + expect(like.signature.additional_data).to eq("new_property" => "data") + expect(like.signature.order).to eq(%w(author guid parent_guid parent_type positive new_property)) + end + + let(:entity) { like_entity } + it_behaves_like "it ignores existing object received twice", Like + it_behaves_like "it rejects if the parent author ignores the author", Like + it_behaves_like "it relays relayables", Like + end + + describe ".message" do + let(:conversation) { + FactoryGirl.build(:conversation, author: alice.person).tap do |conv| + conv.participants << sender + conv.save! + end + } + let(:message_entity) { + FactoryGirl.build( + :message_entity, + author: sender.diaspora_handle, + parent_guid: conversation.guid, + conversation_guid: conversation.guid + ) + } + + it "saves the message" do + received = Diaspora::Federation::Receive.perform(message_entity) + + msg = Message.find_by!(guid: message_entity.guid) + + expect(received).to eq(msg) + expect(msg.author).to eq(sender) + expect(msg.text).to eq(message_entity.text) + expect(msg.created_at.iso8601).to eq(message_entity.created_at.iso8601) + end + + it "attaches the message to the conversation" do + msg = Diaspora::Federation::Receive.perform(message_entity) + + conv = Conversation.find_by!(guid: conversation.guid) + + expect(conv.messages).to include(msg) + expect(msg.conversation).to eq(conv) + end + + let(:entity) { message_entity } + it_behaves_like "it ignores existing object received twice", Message + it_behaves_like "it relays relayables", Message + end + + describe ".participation" do + let(:participation_entity) { + FactoryGirl.build(:participation_entity, author: sender.diaspora_handle, parent_guid: post.guid) + } + + it "saves the participation" do + received = Diaspora::Federation::Receive.perform(participation_entity) + + participation = Participation.find_by!(guid: participation_entity.guid) + + expect(received).to eq(participation) + expect(participation.author).to eq(sender) + end + + it "attaches the participation to the post" do + Diaspora::Federation::Receive.perform(participation_entity) + + participation = Participation.find_by!(guid: participation_entity.guid) + + expect(post.participations).to include(participation) + expect(participation.target).to eq(post) + end + + it_behaves_like "it ignores existing object received twice", Participation do + let(:entity) { participation_entity } + end + end + + describe ".photo" do + let(:photo_entity) { FactoryGirl.build(:photo_entity, author: sender.diaspora_handle) } + + it "saves the photo if it does not already exist" do + received = Diaspora::Federation::Receive.perform(photo_entity) + + photo = Photo.find_by!(guid: photo_entity.guid) + + expect(received).to eq(photo) + expect(photo.author).to eq(sender) + expect(photo.remote_photo_name).to eq(photo_entity.remote_photo_name) + expect(photo.created_at.iso8601).to eq(photo_entity.created_at.iso8601) + end + + it "updates the photo if it is already persisted" do + Diaspora::Federation::Receive.perform(photo_entity) + + photo = Photo.find_by!(guid: photo_entity.guid) + photo.remote_photo_name = "foobar.jpg" + photo.save + + received = Diaspora::Federation::Receive.perform(photo_entity) + photo.reload + + expect(received).to eq(photo) + expect(photo.author).to eq(sender) + expect(photo.remote_photo_name).to eq(photo_entity.remote_photo_name) + end + + it "does not update the photo if the author mismatches" do + Diaspora::Federation::Receive.perform(photo_entity) + + photo = Photo.find_by!(guid: photo_entity.guid) + photo.remote_photo_name = "foobar.jpg" + photo.author = bob.person + photo.save + + expect { + Diaspora::Federation::Receive.perform(photo_entity) + }.to raise_error Diaspora::Federation::InvalidAuthor + + photo.reload + + expect(photo.author).to eq(bob.person) + expect(photo.remote_photo_name).to eq("foobar.jpg") + end + end + + describe ".poll_participation" do + let(:post_with_poll) { FactoryGirl.create(:status_message_with_poll, author: alice.person) } + let(:poll_participation_data) { + FactoryGirl.attributes_for( + :poll_participation_entity, + author: sender.diaspora_handle, + parent_guid: post_with_poll.poll.guid, + poll_answer_guid: post_with_poll.poll.poll_answers.first.guid, + author_signature: "aa" + ) + } + let(:poll_participation_entity) { + DiasporaFederation::Entities::PollParticipation.new( + poll_participation_data, + [:author, :guid, :parent_guid, :poll_answer_guid, "new_property"], + "new_property" => "data" + ) + } + + it "saves the poll participation" do + received = Diaspora::Federation::Receive.perform(poll_participation_entity) + + poll_participation = PollParticipation.find_by!(guid: poll_participation_entity.guid) + + expect(received).to eq(poll_participation) + expect(poll_participation.author).to eq(sender) + expect(poll_participation.poll_answer).to eq(post_with_poll.poll.poll_answers.first) + end + + it "attaches the poll participation to the poll" do + Diaspora::Federation::Receive.perform(poll_participation_entity) + + poll_participation = PollParticipation.find_by!(guid: poll_participation_entity.guid) + + expect(post_with_poll.poll.poll_participations).to include(poll_participation) + expect(poll_participation.poll).to eq(post_with_poll.poll) + end + + it "saves the signature data" do + Diaspora::Federation::Receive.perform(poll_participation_entity) + + poll_participation = PollParticipation.find_by!(guid: poll_participation_entity.guid) + + expect(poll_participation.signature).not_to be_nil + expect(poll_participation.signature.author_signature).to eq("aa") + expect(poll_participation.signature.additional_data).to eq("new_property" => "data") + expect(poll_participation.signature.order).to eq(%w(author guid parent_guid poll_answer_guid new_property)) + end + + let(:entity) { poll_participation_entity } + it_behaves_like "it ignores existing object received twice", PollParticipation + it_behaves_like "it rejects if the parent author ignores the author", PollParticipation + it_behaves_like "it relays relayables", PollParticipation + end + + describe ".profile" do + let(:profile_entity) { FactoryGirl.build(:profile_entity, author: sender.diaspora_handle) } + + it "updates the profile of the person" do + received = Diaspora::Federation::Receive.perform(profile_entity) + + profile = Profile.find(sender.profile.id) + + expect(received).to eq(profile) + expect(profile.first_name).to eq(profile_entity.first_name) + expect(profile.last_name).to eq(profile_entity.last_name) + expect(profile.gender).to eq(profile_entity.gender) + expect(profile.bio).to eq(profile_entity.bio) + expect(profile.location).to eq(profile_entity.location) + expect(profile.searchable).to eq(profile_entity.searchable) + expect(profile.nsfw).to eq(profile_entity.nsfw) + expect(profile.tag_string.split(" ")).to match_array(profile_entity.tag_string.split(" ")) + end + end + + describe ".reshare" do + let(:reshare_entity) { FactoryGirl.build(:reshare_entity, author: sender.diaspora_handle, root_guid: post.guid) } + + it "saves the reshare" do + received = Diaspora::Federation::Receive.perform(reshare_entity) + + reshare = Reshare.find_by!(guid: reshare_entity.guid) + + expect(received).to eq(reshare) + expect(reshare.author).to eq(sender) + end + + it "attaches the reshare to the post" do + Diaspora::Federation::Receive.perform(reshare_entity) + + reshare = Reshare.find_by!(guid: reshare_entity.guid) + + expect(post.reshares).to include(reshare) + expect(reshare.root).to eq(post) + expect(reshare.created_at.iso8601).to eq(reshare_entity.created_at.iso8601) + end + + it_behaves_like "it ignores existing object received twice", Reshare do + let(:entity) { reshare_entity } + end + end + + describe ".retraction" do + it "destroys the post" do + remote_post = FactoryGirl.create(:status_message, author: sender, public: true) + + retraction = FactoryGirl.build( + :retraction_entity, + author: sender.diaspora_handle, + target_guid: remote_post.guid, + target_type: "Post" + ) + + expect_any_instance_of(StatusMessage).to receive(:destroy!).and_call_original + + Diaspora::Federation::Receive.retraction(retraction, nil) + + expect(StatusMessage.exists?(guid: remote_post.guid)).to be_falsey + end + + it "raises when the post does not exist" do + retraction = FactoryGirl.build( + :retraction_entity, + author: sender.diaspora_handle, + target_guid: FactoryGirl.generate(:guid), + target_type: "Post" + ) + + expect { + Diaspora::Federation::Receive.retraction(retraction, nil) + }.to raise_error ActiveRecord::RecordNotFound + end + + it "disconnects on Person-Retraction" do + alice.contacts.find_or_initialize_by(person_id: sender.id, receiving: true, sharing: true).save! + + retraction = FactoryGirl.build( + :retraction_entity, + author: sender.diaspora_handle, + target_guid: sender.guid, + target_type: "Person" + ) + + Diaspora::Federation::Receive.retraction(retraction, alice.id) + + contact = alice.contacts.find_by!(person_id: sender.id) + + expect(contact).not_to be_nil + expect(contact.sharing).to be_falsey + end + + context "Relayable" do + it "relays the retraction and destroys the relayable when the parent-author is local" do + local_post = FactoryGirl.create(:status_message, author: alice.person, public: true) + remote_comment = FactoryGirl.create(:comment, author: sender, post: local_post) + + retraction = FactoryGirl.build( + :retraction_entity, + author: sender.diaspora_handle, + target_guid: remote_comment.guid, + target_type: "Comment" + ) + + comment_retraction = Retraction.for(remote_comment, alice) + + expect(Retraction).to receive(:for).with(instance_of(Comment), alice).and_return(comment_retraction) + expect(comment_retraction).to receive(:defer_dispatch).with(alice, false) + expect(comment_retraction).to receive(:perform).and_call_original + expect_any_instance_of(Comment).to receive(:destroy!).and_call_original + + Diaspora::Federation::Receive.retraction(retraction, nil) + + expect(StatusMessage.exists?(guid: remote_comment.guid)).to be_falsey + end + + it "destroys the relayable when the parent-author is not local" do + remote_post = FactoryGirl.create(:status_message, author: sender, public: true) + remote_comment = FactoryGirl.create(:comment, author: sender, post: remote_post) + + retraction = FactoryGirl.build( + :retraction_entity, + author: sender.diaspora_handle, + target_guid: remote_comment.guid, + target_type: "Comment" + ) + + expect_any_instance_of(Comment).to receive(:destroy!).and_call_original + + Diaspora::Federation::Receive.retraction(retraction, nil) + + expect(StatusMessage.exists?(guid: remote_comment.guid)).to be_falsey + end + end + end + + describe ".status_message" do + context "basic status message" do + let(:status_message_entity) { FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle) } + + it "saves the status message" do + received = Diaspora::Federation::Receive.perform(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + expect(status_message.text).to eq(status_message_entity.text) + expect(status_message.public).to eq(status_message_entity.public) + expect(status_message.created_at.iso8601).to eq(status_message_entity.created_at.iso8601) + expect(status_message.provider_display_name).to eq(status_message_entity.provider_display_name) + + expect(status_message.location).to be_nil + expect(status_message.poll).to be_nil + expect(status_message.photos).to be_empty + end + + it "returns the status message if it already exists" do + first = Diaspora::Federation::Receive.perform(status_message_entity) + second = Diaspora::Federation::Receive.perform(status_message_entity) + + expect(second).not_to be_nil + expect(first).to eq(second) + end + + it "does not change anything if the status message already exists" do + Diaspora::Federation::Receive.perform(status_message_entity) + + expect_any_instance_of(StatusMessage).not_to receive(:create_or_update) + + Diaspora::Federation::Receive.perform(status_message_entity) + end + + it "finds the correct author if the author is not lowercase" do + status_message_entity = FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle.upcase) + + received = Diaspora::Federation::Receive.perform(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + end + end + + context "with poll" do + let(:poll_entity) { FactoryGirl.build(:poll_entity) } + let(:status_message_entity) { + FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle, poll: poll_entity) + } + + it "saves the status message" do + received = Diaspora::Federation::Receive.perform(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + + expect(status_message.poll.question).to eq(poll_entity.question) + expect(status_message.poll.guid).to eq(poll_entity.guid) + expect(status_message.poll.poll_answers.count).to eq(poll_entity.poll_answers.count) + expect(status_message.poll.poll_answers.map(&:answer)).to eq(poll_entity.poll_answers.map(&:answer)) + end + end + + context "with location" do + let(:location_entity) { FactoryGirl.build(:location_entity) } + let(:status_message_entity) { + FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle, location: location_entity) + } + + it "saves the status message" do + received = Diaspora::Federation::Receive.perform(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + + expect(status_message.location.address).to eq(location_entity.address) + expect(status_message.location.lat).to eq(location_entity.lat) + expect(status_message.location.lng).to eq(location_entity.lng) + end + end + + context "with photos" do + let(:status_message_guid) { FactoryGirl.generate(:guid) } + let(:photo1) { + FactoryGirl.build(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid) + } + let(:photo2) { + FactoryGirl.build(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid) + } + let(:status_message_entity) { + FactoryGirl.build( + :status_message_entity, + author: sender.diaspora_handle, + guid: status_message_guid, + photos: [photo1, photo2] + ) + } + + it "saves the status message and photos" do + received = Diaspora::Federation::Receive.perform(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + + expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid) + end + + it "receives a status message only with photos and without text" do + entity = DiasporaFederation::Entities::StatusMessage.new(status_message_entity.to_h.merge(text: nil)) + received = Diaspora::Federation::Receive.perform(entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + + expect(status_message.text).to be_nil + expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid) + end + + it "does not overwrite the photos if they already exist" do + received_photo = Diaspora::Federation::Receive.photo(photo1) + received_photo.text = "foobar" + received_photo.save! + + received = Diaspora::Federation::Receive.perform(status_message_entity) + + status_message = StatusMessage.find_by!(guid: status_message_entity.guid) + + expect(received).to eq(status_message) + expect(status_message.author).to eq(sender) + + expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid) + expect(status_message.photos.map(&:text)).to include(received_photo.text, photo2.text) + end + end + end +end diff --git a/spec/lib/diaspora/fetcher/public_spec.rb b/spec/lib/diaspora/fetcher/public_spec.rb index fd0a7a824c7c5ecde0ce6cd47484e93de12ed8f8..6ad2fbebe7dec059b1c3bb1ef0b5ecdbc6ae186c 100644 --- a/spec/lib/diaspora/fetcher/public_spec.rb +++ b/spec/lib/diaspora/fetcher/public_spec.rb @@ -13,9 +13,9 @@ describe Diaspora::Fetcher::Public do # the guid of the person is "7445f9a0a6c28ebb" @fixture = File.open(Rails.root.join('spec', 'fixtures', 'public_posts.json')).read @fetcher = Diaspora::Fetcher::Public.new - @person = FactoryGirl.create(:person, {:guid => "7445f9a0a6c28ebb", - :url => "https://remote-testpod.net", - :diaspora_handle => "testuser@remote-testpod.net"}) + @person = FactoryGirl.create(:person, guid: "7445f9a0a6c28ebb", + pod: Pod.find_or_create_by(url: "https://remote-testpod.net"), + diaspora_handle: "testuser@remote-testpod.net") stub_request(:get, /remote-testpod.net\/people\/.*\/stream/) .with(headers: { @@ -122,10 +122,10 @@ describe Diaspora::Fetcher::Public do end end - it 'copied the text correctly' do + it "copied the text correctly" do @data.each do |post| - entry = StatusMessage.find_by_guid(post['guid']) - expect(entry.raw_message).to eql(post['text']) + entry = StatusMessage.find_by_guid(post["guid"]) + expect(entry.text).to eql(post["text"]) end end diff --git a/spec/lib/diaspora/markdownify_email_spec.rb b/spec/lib/diaspora/markdownify_email_spec.rb index 6c4b69e17274ddda9f85e484501b823683b3f7aa..5d4ae71868c3e6e5cf7369772c766eaa01390f50 100644 --- a/spec/lib/diaspora/markdownify_email_spec.rb +++ b/spec/lib/diaspora/markdownify_email_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe Diaspora::Markdownify::Email do + include Rails.application.routes.url_helpers + describe '#preprocess' do before do @html = Diaspora::Markdownify::Email.new @@ -8,12 +10,14 @@ describe Diaspora::Markdownify::Email do it 'should autolink a hashtag' do markdownified = @html.preprocess("#tag") - expect(markdownified).to eq("[#tag](http://localhost:9887/tags/tag)") + expect(markdownified).to eq("[#tag](#{AppConfig.url_to(tag_path('tag'))})") end it 'should autolink multiple hashtags' do markdownified = @html.preprocess("oh #l #loL") - expect(markdownified).to eq("oh [#l](http://localhost:9887/tags/l) [#loL](http://localhost:9887/tags/lol)") + expect(markdownified).to eq( + "oh [#l](#{AppConfig.url_to(tag_path('l'))}) [#loL](#{AppConfig.url_to(tag_path('lol'))})" + ) end it 'should not autolink headers' do @@ -30,7 +34,10 @@ describe Diaspora::Markdownify::Email do it 'should render the message' do rendered = @markdown.render(@sample_text).strip - expect(rendered).to eq("<h1>Header</h1>\n\n<p><a href=\"http://localhost:9887/tags/messages\">#messages</a> containing <a href=\"http://localhost:9887/tags/hashtags\">#hashtags</a> should render properly</p>") + expect(rendered).to eq( + "<h1>Header</h1>\n\n<p><a href=\"#{AppConfig.url_to(tag_path('messages'))}\">#messages</a>\ + containing <a href=\"#{AppConfig.url_to(tag_path('hashtags'))}\">#hashtags</a> should render properly</p>" + ) end end end diff --git a/spec/lib/diaspora/markdownify_spec.rb b/spec/lib/diaspora/markdownify_spec.rb index 143a62f31e9c4ecce25e386cbcf25199ecdc4796..161f88ff628420c3843026d43389fba76dd4eeee 100644 --- a/spec/lib/diaspora/markdownify_spec.rb +++ b/spec/lib/diaspora/markdownify_spec.rb @@ -1,12 +1,12 @@ -require 'spec_helper' +require "spec_helper" describe Diaspora::Markdownify::HTML do - describe '#autolink' do + describe "#autolink" do before do @html = Diaspora::Markdownify::HTML.new end - it 'should make all of the links open in a new tab' do + it "should make all of the links open in a new tab" do markdownified = @html.autolink("http://joindiaspora.com", nil) doc = Nokogiri.parse(markdownified) @@ -14,5 +14,14 @@ describe Diaspora::Markdownify::HTML do expect(link.attr("target").value).to eq("_blank") end + + it "should add noopener and noreferrer to autolinks' rel attributes" do + markdownified = @html.autolink("http://joindiaspora.com", nil) + doc = Nokogiri.parse(markdownified) + + link = doc.css("a") + + expect(link.attr("rel").value).to include("noopener", "noreferrer") + end end -end \ No newline at end of file +end diff --git a/spec/lib/diaspora/mentionable_spec.rb b/spec/lib/diaspora/mentionable_spec.rb index a328fe7cc7e295591fc317b1d849f2c6a29d32b5..552097a2ebf2d0e2223497efd7a33ba3ca2edf25 100644 --- a/spec/lib/diaspora/mentionable_spec.rb +++ b/spec/lib/diaspora/mentionable_spec.rb @@ -6,11 +6,12 @@ describe Diaspora::Mentionable do before do @people = [alice, bob, eve].map(&:person) + @names = %w(Alice\ A Bob\ B "Eve>\ E) @test_txt = <<-STR This post contains a lot of mentions -one @{Alice A; #{@people[0].diaspora_handle}}, -two @{Bob B; #{@people[1].diaspora_handle}} and finally -three @{"Eve> E; #{@people[2].diaspora_handle}}. +one @{#{@names[0]}; #{@people[0].diaspora_handle}}, +two @{#{@names[1]}; #{@people[1].diaspora_handle}} and finally +three @{#{@names[2]}; #{@people[2].diaspora_handle}}. STR @test_txt_plain = <<-STR This post contains a lot of mentions @@ -18,53 +19,50 @@ one Alice A, two Bob B and finally three "Eve> E. STR - @status_msg = FactoryGirl.build(:status_message, text: @test_txt) end describe "#format" do context "html output" do it "adds the links to the formatted message" do - fmt_msg = Diaspora::Mentionable.format(@status_msg.raw_message, @people) + fmt_msg = Diaspora::Mentionable.format(@test_txt, @people) - @people.each do |person| - expect(fmt_msg).to include person_link(person, class: "mention hovercardable") + [@people, @names].transpose.each do |person, name| + expect(fmt_msg).to include person_link(person, class: "mention hovercardable", display_name: name) end end it "should work correct when message is escaped html" do - raw_msg = @status_msg.raw_message - fmt_msg = Diaspora::Mentionable.format(CGI.escapeHTML(raw_msg), @people) + fmt_msg = Diaspora::Mentionable.format(CGI.escapeHTML(@test_txt), @people) - @people.each do |person| - expect(fmt_msg).to include person_link(person, class: "mention hovercardable") + [@people, @names].transpose.each do |person, name| + expect(fmt_msg).to include person_link(person, class: "mention hovercardable", display_name: name) end end it "escapes the link title (name)" do - p = @people[0].profile - p.first_name = "</a><script>alert('h')</script>" - p.save! + name = "</a><script>alert('h')</script>" + test_txt = "two @{#{name}; #{@people[0].diaspora_handle}} and finally" - fmt_msg = Diaspora::Mentionable.format(@status_msg.raw_message, @people) + fmt_msg = Diaspora::Mentionable.format(test_txt, @people) - expect(fmt_msg).not_to include(p.first_name) + expect(fmt_msg).not_to include(name) expect(fmt_msg).to include(">", "<", "'") # ">", "<", "'" end end context "plain text output" do it "removes mention markup and displays unformatted name" do - fmt_msg = Diaspora::Mentionable.format(@status_msg.raw_message, @people, plain_text: true) + fmt_msg = Diaspora::Mentionable.format(@test_txt, @people, plain_text: true) - @people.each do |person| - expect(fmt_msg).to include person.first_name + @names.each do |name| + expect(fmt_msg).to include CGI.escapeHTML(name) end expect(fmt_msg).not_to include "<a", "</a>", "hovercardable" end end - it "leaves the name of people that cannot be found" do - fmt_msg = Diaspora::Mentionable.format(@status_msg.raw_message, []) + it "leaves the names of people that cannot be found" do + fmt_msg = Diaspora::Mentionable.format(@test_txt, []) expect(fmt_msg).to eql @test_txt_plain end end @@ -72,7 +70,7 @@ STR describe "#people_from_string" do it "extracts the mentioned people from the text" do ppl = Diaspora::Mentionable.people_from_string(@test_txt) - expect(ppl).to include(*@people) + expect(ppl).to match_array(@people) end describe "returns an empty array if nobody was found" do @@ -82,7 +80,26 @@ STR end it "gets a post with invalid handles" do - ppl = Diaspora::Mentionable.people_from_string("@{a; xxx@xxx.xx} @{b; yyy@yyyy.yyy} @{...} @{bla; blubb}") + ppl = Diaspora::Mentionable.people_from_string("@{...} @{bla; blubb}") + expect(ppl).to be_empty + end + + it "filters duplicate handles" do + ppl = Diaspora::Mentionable.people_from_string("@{a; #{alice.diaspora_handle}} @{a; #{alice.diaspora_handle}}") + expect(ppl).to eq([alice.person]) + end + + it "fetches unknown handles" do + person = FactoryGirl.build(:person) + expect(Person).to receive(:find_or_fetch_by_identifier).with("xxx@xxx.xx").and_return(person) + ppl = Diaspora::Mentionable.people_from_string("@{a; xxx@xxx.xx}") + expect(ppl).to eq([person]) + end + + it "handles DiscoveryError" do + expect(Person).to receive(:find_or_fetch_by_identifier).with("yyy@yyy.yy") + .and_raise(DiasporaFederation::Discovery::DiscoveryError) + ppl = Diaspora::Mentionable.people_from_string("@{b; yyy@yyy.yy}") expect(ppl).to be_empty end end @@ -111,7 +128,7 @@ STR aspect_id = @user_a.aspects.where(name: "generic").first.id txt = Diaspora::Mentionable.filter_for_aspects(@test_txt_c, @user_a, aspect_id) - expect(txt).to include(@user_c.person.name) + expect(txt).to include("user C") expect(txt).to include(local_or_remote_person_path(@user_c.person)) expect(txt).not_to include("href") expect(txt).not_to include(@mention_c) diff --git a/spec/lib/diaspora/message_renderer_spec.rb b/spec/lib/diaspora/message_renderer_spec.rb index 5929480d44d4ab7d4751f19101ce74138805f713..9362c6fd076f1fcc31f8f003d6f69577fb588d9f 100644 --- a/spec/lib/diaspora/message_renderer_spec.rb +++ b/spec/lib/diaspora/message_renderer_spec.rb @@ -169,7 +169,7 @@ describe Diaspora::MessageRenderer do it 'should process text with both a hashtag and a link' do expect( message("Test #tag?\nhttps://joindiaspora.com\n").markdownified - ).to eq %{<p>Test <a class="tag" href="/tags/tag">#tag</a>?<br>\n<a href="https://joindiaspora.com" rel="nofollow" target="_blank">https://joindiaspora.com</a></p>\n} + ).to eq %{<p>Test <a class="tag" href="/tags/tag">#tag</a>?<br>\n<a href="https://joindiaspora.com" rel="nofollow noopener noreferrer" target="_blank">https://joindiaspora.com</a></p>\n} end it 'should process text with a header' do diff --git a/spec/lib/diaspora/parser_spec.rb b/spec/lib/diaspora/parser_spec.rb deleted file mode 100644 index c84ef4c17b169927417ef6545dd177c79568ad82..0000000000000000000000000000000000000000 --- a/spec/lib/diaspora/parser_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Diaspora::Parser do - before do - @user1 = alice - @user2 = bob - @user3 = eve - - @aspect1 = @user1.aspects.first - @aspect2 = @user2.aspects.first - @aspect3 = @user3.aspects.first - - @person = FactoryGirl.create(:person) - end - - describe "parsing compliant XML object" do - it 'should be able to correctly parse comment fields' do - post = @user1.post :status_message, :text => "hello", :to => @aspect1.id - comment = FactoryGirl.create(:comment, :post => post, :author => @person, :diaspora_handle => @person.diaspora_handle, :text => "Freedom!") - comment.delete - xml = comment.to_diaspora_xml - comment_from_xml = Diaspora::Parser.from_xml(xml) - expect(comment_from_xml.diaspora_handle).to eq(@person.diaspora_handle) - expect(comment_from_xml.post).to eq(post) - expect(comment_from_xml.text).to eq("Freedom!") - expect(comment_from_xml).not_to be comment - end - end -end - diff --git a/spec/lib/diaspora/shareable_spec.rb b/spec/lib/diaspora/shareable_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..4df87e80a47dec9bd0a85f5637d88671a9dfafae --- /dev/null +++ b/spec/lib/diaspora/shareable_spec.rb @@ -0,0 +1,30 @@ +require "spec_helper" + +describe Diaspora::Shareable do + describe "scopes" do + context "having multiple objects with equal db IDs" do + before do + # Determine the next database key ID, free on both Photo and StatusMessage + id = [Photo, StatusMessage].map {|model| model.maximum(:id).try(:next).to_i }.push(1).max + + alice.post(:status_message, id: id, text: "I'm #{alice.username}", to: alice.aspects.first.id, public: false) + alice.post(:photo, id: id, user_file: uploaded_photo, to: alice.aspects.first.id, public: false) + expect(StatusMessage.where(id: id)).to exist + expect(Photo.where(id: id)).to exist + end + + {with_visibility: ShareVisibility, with_aspects: AspectVisibility}.each do |method, visibility_class| + describe ".#{method}" do + it "includes only object of a right type" do + [Photo, Post].each do |klass| + expect(klass.send(method).where(visibility_class.arel_table[:shareable_type].eq(klass.to_s)).count) + .not_to eq(0) + expect(klass.send(method).where.not(visibility_class.arel_table[:shareable_type].eq(klass.to_s)).count) + .to eq(0) + end + end + end + end + end + end +end diff --git a/spec/lib/diaspora/taggable_spec.rb b/spec/lib/diaspora/taggable_spec.rb index bd4ab617f529eeb6089a4c3c6a227176826da0cf..bbc557d6e8b0474d1e8134d527d06b7c1fc43f14 100644 --- a/spec/lib/diaspora/taggable_spec.rb +++ b/spec/lib/diaspora/taggable_spec.rb @@ -1,6 +1,8 @@ require "spec_helper" describe Diaspora::Taggable do + include Rails.application.routes.url_helpers + describe "#format_tags" do context "when there are no tags in the text" do it "returns the input text" do @@ -40,19 +42,19 @@ describe Diaspora::Taggable do context "when there is a tag in the text" do it "autolinks and normalizes the hashtag" do text = Diaspora::Taggable.format_tags_for_mail("There is a #hashTag.") - expect(text).to eq("There is a [#hashTag](http://localhost:9887/tags/hashtag).") + expect(text).to eq("There is a [#hashTag](#{AppConfig.url_to(tag_path('hashtag'))}).") end it "autolinks #<3" do text = Diaspora::Taggable.format_tags_for_mail("#<3") - expect(text).to eq("[#<3](http://localhost:9887/tags/%3C3)") + expect(text).to eq("[#<3](#{AppConfig.url_to(tag_path('<3'))})") end end context "with multiple tags" do it "autolinks the hashtags" do text = Diaspora::Taggable.format_tags_for_mail("#l #lol") - expect(text).to eq("[#l](http://localhost:9887/tags/l) [#lol](http://localhost:9887/tags/lol)") + expect(text).to eq("[#l](#{AppConfig.url_to(tag_path('l'))}) [#lol](#{AppConfig.url_to(tag_path('lol'))})") end end end diff --git a/spec/lib/encryptor_spec.rb b/spec/lib/encryptor_spec.rb deleted file mode 100644 index a4d8a709a57075b733dfce50b8915077964fca83..0000000000000000000000000000000000000000 --- a/spec/lib/encryptor_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe 'user encryption' do - before do - @user = alice - @aspect = @user.aspects.first - end - - describe 'encryption' do - it 'should encrypt a string' do - string = "Secretsauce" - ciphertext = @user.person.encrypt string - expect(ciphertext.include?(string)).to be false - expect(@user.decrypt(ciphertext)).to eq(string) - end - end -end diff --git a/spec/lib/evil_query_spec.rb b/spec/lib/evil_query_spec.rb index 0e98c5c78202244eb8b10165bbe59ccc7c29e962..7448770341a4b1d1729f05a672a724ff324ca06f 100644 --- a/spec/lib/evil_query_spec.rb +++ b/spec/lib/evil_query_spec.rb @@ -1,19 +1,41 @@ require 'spec_helper' describe EvilQuery::MultiStream do - let(:evil_query) { EvilQuery::MultiStream.new(alice, 'created_at', Time.now-1.week, true) } + let(:evil_query) { EvilQuery::MultiStream.new(alice, "created_at", Time.zone.now, true) } + describe 'community_spotlight_posts!' do it 'does not raise an error' do expect { evil_query.community_spotlight_posts! }.to_not raise_error end end + + describe "make_relation!" do + it "includes public posts of someone you follow" do + alice.share_with(eve.person, alice.aspects.first) + public_post = eve.post(:status_message, text: "public post", to: "all", public: true) + expect(evil_query.make_relation!.map(&:id)).to include(public_post.id) + end + + it "includes private posts of contacts with a mutual relationship" do + alice.share_with(eve.person, alice.aspects.first) + eve.share_with(alice.person, eve.aspects.first) + private_post = eve.post(:status_message, text: "private post", to: eve.aspects.first.id, public: false) + expect(evil_query.make_relation!.map(&:id)).to include(private_post.id) + end + + it "doesn't include posts of followers that you don't follow back" do + eve.share_with(alice.person, eve.aspects.first) + public_post = eve.post(:status_message, text: "public post", to: "all", public: true) + private_post = eve.post(:status_message, text: "private post", to: eve.aspects.first.id, public: false) + expect(evil_query.make_relation!.map(&:id)).not_to include(public_post.id) + expect(evil_query.make_relation!.map(&:id)).not_to include(private_post.id) + end + end end describe EvilQuery::Participation do before do @status_message = FactoryGirl.create(:status_message, :author => bob.person) - # done in StatusMessagesController#create - bob.participate!(@status_message) end it "includes posts liked by the user" do @@ -65,4 +87,38 @@ describe EvilQuery::Participation do expect(posts.map(&:id)).to eq([@status_messageE.id, @status_messageA.id, @status_messageB.id]) end end + + describe "multiple participations" do + before do + @like = alice.like!(@status_message) + @comment = alice.comment!(@status_message, "party") + end + + let(:posts) { EvilQuery::Participation.new(alice).posts } + + it "includes Posts with multiple participations" do + expect(posts.map(&:id)).to eq([@status_message.id]) + end + + it "includes Posts with multiple participations only once" do + eve.like!(@status_message) + expect(posts.count).to be(1) + end + + it "includes Posts with multiple participations only once for the post author" do + eve.like!(@status_message) + expect(EvilQuery::Participation.new(bob).posts.count).to eq(1) + end + + it "includes Posts with multiple participation after removing one participation" do + @like.destroy + expect(posts.map(&:id)).to eq([@status_message.id]) + end + + it "doesn't includes Posts after removing all of their participations" do + @like.destroy + @comment.destroy + expect(posts.map(&:id)).not_to include(@status_message.id) + end + end end diff --git a/spec/lib/hydra_wrapper_spec.rb b/spec/lib/hydra_wrapper_spec.rb deleted file mode 100644 index 5a303052e5c2b8a121070a9928f2476c0af7dce2..0000000000000000000000000000000000000000 --- a/spec/lib/hydra_wrapper_spec.rb +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe HydraWrapper do - before do - @people = ["person", "person2", "person3"] - @wrapper = HydraWrapper.new double, @people, "<encoded_xml>", double - end - - describe 'initialize' do - it 'it sets the proper instance variables' do - user = "user" - encoded_object_xml = "encoded xml" - dispatcher_class = "Postzord::Dispatcher::Private" - - wrapper = HydraWrapper.new user, @people, encoded_object_xml, dispatcher_class - expect(wrapper.user).to eq(user) - expect(wrapper.people).to eq(@people) - expect(wrapper.encoded_object_xml).to eq(encoded_object_xml) - end - end - - describe '#run' do - it 'delegates #run to the @hydra' do - hydra = double.as_null_object - @wrapper.instance_variable_set :@hydra, hydra - expect(hydra).to receive :run - @wrapper.run - end - end - - describe '#xml_factory' do - it 'calls the salmon method on the dispatcher class (and memoizes)' do - allow(Base64).to receive(:decode64).and_return "#{@wrapper.encoded_object_xml} encoded" - decoded = Base64.decode64 @wrapper.encoded_object_xml - expect(@wrapper.dispatcher_class).to receive(:salmon).with(@wrapper.user, decoded).once.and_return true - @wrapper.send :xml_factory - @wrapper.send :xml_factory - end - end - - describe '#grouped_people' do - it 'groups people given their receive_urls' do - expect(@wrapper.dispatcher_class).to receive(:receive_url_for).and_return "foo.com", "bar.com", "bar.com" - - expect(@wrapper.send(:grouped_people)).to eq({"foo.com" => [@people[0]], "bar.com" => @people[1,2]}) - end - end - - describe '#enqueue_batch' do - it 'calls #grouped_people' do - expect(@wrapper).to receive(:grouped_people).and_return [] - @wrapper.enqueue_batch - end - - it 'inserts a job for every group of people' do - allow(Base64).to receive(:decode64) - @wrapper.dispatcher_class = double salmon: double(xml_for: "<XML>") - allow(@wrapper).to receive(:grouped_people).and_return('https://foo.com' => @wrapper.people) - expect(@wrapper.people).to receive(:first).once - expect(@wrapper).to receive(:insert_job).with('https://foo.com', "<XML>", @wrapper.people).once - @wrapper.enqueue_batch - end - - it 'does not insert a job for a person whos xml returns false' do - allow(Base64).to receive(:decode64) - allow(@wrapper).to receive(:grouped_people).and_return('https://foo.com' => [double]) - @wrapper.dispatcher_class = double salmon: double(xml_for: false) - expect(@wrapper).not_to receive :insert_job - @wrapper.enqueue_batch - end - - end - - describe '#redirecting_to_https?!' do - it 'does not execute unless response has a 3xx code' do - resp = double code: 200 - expect(@wrapper.send(:redirecting_to_https?, resp)).to be false - end - - it "returns true if just the protocol is different" do - host = "the-same.com/" - resp = double( - request: double(url: "http://#{host}"), - code: 302, - headers_hash: { - 'Location' => "https://#{host}" - } - ) - - expect(@wrapper.send(:redirecting_to_https?, resp)).to be true - end - - it "returns false if not just the protocol is different" do - host = "the-same.com/" - resp = double( - request: double(url: "http://#{host}"), - code: 302, - headers_hash: { - 'Location' => "https://not-the-same/" - } - ) - - expect(@wrapper.send(:redirecting_to_https?, resp)).to be false - end - end -end diff --git a/spec/lib/i18n_interpolation_fallbacks_spec.rb b/spec/lib/i18n_interpolation_fallbacks_spec.rb index d8569b05a116055070124b63c84fdd8d1dcbc97a..a93fe1f59306e67f3a7f7f7ebd8dd52fef069e17 100644 --- a/spec/lib/i18n_interpolation_fallbacks_spec.rb +++ b/spec/lib/i18n_interpolation_fallbacks_spec.rb @@ -7,23 +7,25 @@ require 'spec_helper' describe "i18n interpolation fallbacks" do describe "when string does not require interpolation arguments" do it "works normally" do - expect(I18n.t('user.invalid', - :resource_name => "user", - :scope => "devise.failure", - :default => [:invalid, "invalid"])).to eq("Invalid username or password.") + expect( + I18n.t("user.already_authenticated", + resource_name: "user", + scope: "devise.failure", + default: [:already_authenticated, "already_authenticated"]) + ).to eq("You are already signed in.") end end describe "when string requires interpolation arguments" do context "current locale has no fallbacks" do - # ago: "%{time} ago" (in en.yml) + # tags.show.follow: "Follow #%{tag}" (in en.yml) it "returns the translation when all arguments are provided" do - expect(I18n.t('ago', :time => "2 months")).to eq("2 months ago") + expect(I18n.t("tags.show.follow", tag: "cats")).to eq("Follow #cats") end it "returns the translation without substitution when all arguments are omitted" do - expect(I18n.t('ago')).to eq("%{time} ago") + expect(I18n.t("tags.show.follow")).to eq("Follow #%{tag}") end it "raises a MissingInterpolationArgument when arguments are wrong" do - expect { I18n.t('ago', :not_time => "2 months") }.to raise_exception(I18n::MissingInterpolationArgument) + expect { I18n.t("tags.show.follow", not_tag: "cats") }.to raise_exception(I18n::MissingInterpolationArgument) end end context "current locale falls back to English" do diff --git a/spec/lib/postzord/dispatcher/private_spec.rb b/spec/lib/postzord/dispatcher/private_spec.rb deleted file mode 100644 index 84b69769509b0474a4dc64ad15c7c65629c7641e..0000000000000000000000000000000000000000 --- a/spec/lib/postzord/dispatcher/private_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Postzord::Dispatcher::Private do - - describe '#salmon' do - end - - describe '#receive_url_for' do - end - - describe '#queue_remote_delivery_job' do - end -end diff --git a/spec/lib/postzord/dispatcher/public_spec.rb b/spec/lib/postzord/dispatcher/public_spec.rb deleted file mode 100644 index 11c0b655f3f75385a0a657e36e42e826f937dbb5..0000000000000000000000000000000000000000 --- a/spec/lib/postzord/dispatcher/public_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Postzord::Dispatcher::Public do - -end diff --git a/spec/lib/postzord/dispatcher_spec.rb b/spec/lib/postzord/dispatcher_spec.rb deleted file mode 100644 index a630ab1fa3495959f7ff0285a1d58012f21a1087..0000000000000000000000000000000000000000 --- a/spec/lib/postzord/dispatcher_spec.rb +++ /dev/null @@ -1,339 +0,0 @@ -# Copyright (c) 2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Postzord::Dispatcher do - before do - @sm = FactoryGirl.create(:status_message, :public => true, :author => alice.person) - @subscribers = [] - 5.times{@subscribers << FactoryGirl.create(:person)} - allow(@sm).to receive(:subscribers).and_return(@subscribers) - @xml = @sm.to_diaspora_xml - end - - describe '.initialize' do - it 'sets @sender, @object, @xml' do - zord = Postzord::Dispatcher.build(alice, @sm) - expect(zord.sender).to eq(alice) - expect(zord.object).to eq(@sm) - expect(zord.xml).to eq(@sm.to_diaspora_xml) - end - - context 'setting @subscribers' do - it 'sets @subscribers from object' do - expect(@sm).to receive(:subscribers).and_return(@subscribers) - zord = Postzord::Dispatcher.build(alice, @sm) - expect(zord.subscribers).to eq(@subscribers) - end - - it 'accepts additional subscribers from opts' do - new_person = FactoryGirl.create(:person) - - expect(@sm).to receive(:subscribers).and_return(@subscribers) - zord = Postzord::Dispatcher.build(alice, @sm, :additional_subscribers => new_person) - expect(zord.subscribers).to eq(@subscribers | [new_person]) - end - end - - it 'raises and gives you a helpful message if the object can not federate' do - expect { - Postzord::Dispatcher.build(alice, []) - }.to raise_error /Diaspora::Federated::Base/ - end - end - - context 'instance methods' do - before do - @subscribers << bob.person - @remote_people, @local_people = @subscribers.partition{ |person| person.owner_id.nil? } - - @zord = Postzord::Dispatcher.build(alice, @sm) - end - - describe '#post' do - it 'calls Array#partition on subscribers' do - @zord.instance_variable_set(:@subscribers, @subscribers) - expect(@subscribers).to receive(:partition).and_return([@remote_people, @local_people]) - @zord.post - end - - it 'calls #deliver_to_local with local people' do - expect(@zord).to receive(:deliver_to_local).with(@local_people) - @zord.post - end - - it 'calls #deliver_to_remote with remote people' do - expect(@zord).to receive(:deliver_to_remote).with(@remote_people) - @zord.post - end - end - - context "comments" do - before do - @local_luke, @local_leia, @remote_raphael = set_up_friends - end - - context "local luke's post is commented on by" do - before do - @post = @local_luke.post(:status_message, :text => "hello", :to => @local_luke.aspects.first) - end - context "local leia" do - before do - @comment = @local_leia.build_comment :text => "yo", :post => @post - @comment.save - end - context "local leia's mailman" do - before do - @mailman = Postzord::Dispatcher.build(@local_leia, @comment) - end - - it 'calls deliver_to_local with local_luke' do - expect(@mailman).to receive(:deliver_to_local).with([@local_luke.person]) - @mailman.post - end - - it 'calls deliver_to_remote with nobody' do - expect(@mailman).to receive(:deliver_to_remote).with([]) - @mailman.post - end - - it 'does not call notify_users' do - expect(@mailman).not_to receive(:notify_users) - @mailman.post - end - end - context "local luke's mailman" do - before do - @mailman = Postzord::Dispatcher.build(@local_luke, @comment) - end - - it 'does not call deliver_to_local' do - expect(@mailman).not_to receive(:deliver_to_local) - @mailman.post - end - - it 'calls deliver_to_remote with remote raphael' do - expect(@mailman).to receive(:deliver_to_remote).with([@remote_raphael]) - @mailman.post - end - - it 'calls notify_users' do - expect(@mailman).to receive(:notify_users).with([@local_leia]) - @mailman.post - end - end - end - - context "remote raphael" do - before do - @comment = FactoryGirl.create(:comment, :author => @remote_raphael, :post => @post) - @comment.save - @mailman = Postzord::Dispatcher.build(@local_luke, @comment) - end - - it 'does not call deliver_to_local' do - expect(@mailman).not_to receive(:deliver_to_local) - @mailman.post - end - - it 'calls deliver_to_remote with remote_raphael' do - expect(@mailman).to receive(:deliver_to_remote).with([@remote_raphael]) - @mailman.post - end - - it 'calls notify_users' do - expect(@mailman).to receive(:notify_users).with([@local_leia]) - @mailman.post - end - end - - context "local luke" do - before do - @comment = @local_luke.build_comment :text => "yo", :post => @post - @comment.save - @mailman = Postzord::Dispatcher.build(@local_luke, @comment) - end - - it 'does not call deliver_to_local' do - expect(@mailman).not_to receive(:deliver_to_local) - @mailman.post - end - - it 'calls deliver_to_remote with remote_raphael' do - expect(@mailman).to receive(:deliver_to_remote).with([@remote_raphael]) - @mailman.post - end - - it 'calls notify_users' do - expect(@mailman).to receive(:notify_users).with([@local_leia]) - @mailman.post - end - end - end - - context "remote raphael's post is commented on by local luke" do - before do - @post = FactoryGirl.create(:status_message, :author => @remote_raphael) - @comment = @local_luke.build_comment :text => "yo", :post => @post - @comment.save - @mailman = Postzord::Dispatcher.build(@local_luke, @comment) - end - - it 'calls deliver_to_remote with remote_raphael' do - expect(@mailman).to receive(:deliver_to_remote).with([@remote_raphael]) - @mailman.post - end - - it 'calls deliver_to_local with nobody' do - expect(@mailman).to receive(:deliver_to_local).with([]) - @mailman.post - end - - it 'does not call notify_users' do - expect(@mailman).not_to receive(:notify_users) - @mailman.post - end - end - end - - describe '#deliver_to_remote' do - before do - @remote_people = [] - @remote_people << alice.person - @mailman = Postzord::Dispatcher.build(alice, @sm) - @hydra = double() - allow(Typhoeus::Hydra).to receive(:new).and_return(@hydra) - end - - it 'should queue an HttpMultiJob for the remote people' do - allow_any_instance_of(Postzord::Dispatcher::Public).to receive(:deliver_to_remote).and_call_original - expect(Workers::HttpMulti).to receive(:perform_async).with(alice.id, anything, @remote_people.map{|p| p.id}, anything).once - @mailman.send(:deliver_to_remote, @remote_people) - - allow(Postzord::Dispatcher::Public).to receive(:deliver_to_remote) - end - end - - describe '#deliver_to_local' do - before do - @mailman = Postzord::Dispatcher.build(alice, @sm) - end - - it 'queues a batch receive' do - local_people = [] - local_people << alice.person - expect(Workers::ReceiveLocalBatch).to receive(:perform_async).with(@sm.class.to_s, @sm.id, [alice.id]).once - @mailman.send(:deliver_to_local, local_people) - end - - it 'returns if people are empty' do - expect(Workers::ReceiveLocalBatch).not_to receive(:perform_async) - @mailman.send(:deliver_to_local, []) - end - - it 'returns if the object is a profile' do - @mailman.instance_variable_set(:@object, Profile.new) - expect(Workers::ReceiveLocalBatch).not_to receive(:perform_async) - @mailman.send(:deliver_to_local, [1]) - end - end - - describe '#object_should_be_processed_as_public?' do - it 'returns true with a comment on a public post' do - f = FactoryGirl.create(:comment, :post => FactoryGirl.build(:status_message, :public => true)) - expect(Postzord::Dispatcher.object_should_be_processed_as_public?(f)).to be true - end - - it 'returns false with a comment on a private post' do - f = FactoryGirl.create(:comment, :post => FactoryGirl.build(:status_message, :public => false)) - expect(Postzord::Dispatcher.object_should_be_processed_as_public?(f)).to be false - end - - it 'returns true with a like on a comment on a public post' do - f = FactoryGirl.create(:like, :target => FactoryGirl.build(:comment, :post => FactoryGirl.build(:status_message, :public => true))) - expect(Postzord::Dispatcher.object_should_be_processed_as_public?(f)).to be true - end - - it 'returns false with a like on a comment on a private post' do - f = FactoryGirl.create(:like, :target => FactoryGirl.build(:comment, :post => FactoryGirl.build(:status_message, :public => false))) - expect(Postzord::Dispatcher.object_should_be_processed_as_public?(f)).to be false - end - - it 'returns false for a relayable_retraction' do - f = RelayableRetraction.new - f.target = FactoryGirl.create(:status_message, :public => true) - expect(Postzord::Dispatcher.object_should_be_processed_as_public?(f)).to be false - end - end - - - describe '#deliver_to_services' do - before do - alice.aspects.create(:name => "whatever") - @service = Services::Facebook.new(:access_token => "yeah") - alice.services << @service - end - - it 'queues a job to notify the hub' do - allow(Workers::PostToService).to receive(:perform_async).with(anything, anything, anything) - expect(Workers::PublishToHub).to receive(:perform_async).with(alice.atom_url) - @zord.send(:deliver_to_services, nil, []) - end - - it 'does not push to hub for non-public posts' do - @sm = FactoryGirl.create(:status_message) - mailman = Postzord::Dispatcher.build(alice, @sm, :url => "http://joindiaspora.com/p/123") - - expect(mailman).not_to receive(:deliver_to_hub) - mailman.post - end - - it 'only pushes to specified services' do - @s1 = FactoryGirl.create(:service, :user_id => alice.id) - alice.services << @s1 - @s2 = FactoryGirl.create(:service, :user_id => alice.id) - alice.services << @s2 - mailman = Postzord::Dispatcher.build(alice, FactoryGirl.create(:status_message), :url => "http://joindiaspora.com/p/123", :services => [@s1]) - - allow(Workers::PublishToHub).to receive(:perform_async).with(anything) - allow(Workers::HttpMulti).to receive(:perform_async).with(anything, anything, anything) - expect(Workers::PostToService).to receive(:perform_async).with(@s1.id, anything, anything) - mailman.post - end - - it 'does not push to services if none are specified' do - mailman = Postzord::Dispatcher.build(alice, FactoryGirl.create(:status_message), :url => "http://joindiaspora.com/p/123") - - allow(Workers::PublishToHub).to receive(:perform_async).with(anything) - expect(Workers::PostToService).not_to receive(:perform_async).with(anything, anything, anything) - mailman.post - end - - it 'queues a job to delete if given retraction' do - retraction = SignedRetraction.build(alice, FactoryGirl.create(:status_message)) - mailman = Postzord::Dispatcher.build(alice, retraction, :url => "http://joindiaspora.com/p/123", :services => [@service]) - - expect(Workers::DeletePostFromService).to receive(:perform_async).with(anything, anything) - mailman.post - end - - end - - describe '#and_notify_local_users' do - it 'calls notifiy_users' do - expect(@zord).to receive(:notify_users).with([bob]) - @zord.send(:notify_local_users, [bob.person]) - end - end - - describe '#notify_users' do - it 'enqueues a NotifyLocalUsers job' do - expect(Workers::NotifyLocalUsers).to receive(:perform_async).with([bob.id], @zord.object.class.to_s, @zord.object.id, @zord.object.author.id) - @zord.send(:notify_users, [bob]) - end - end - end -end - diff --git a/spec/lib/postzord/receiver/local_batch_spec.rb b/spec/lib/postzord/receiver/local_batch_spec.rb deleted file mode 100644 index 1a6c8e2fe61df12c768f46eb7224af28b8b4421d..0000000000000000000000000000000000000000 --- a/spec/lib/postzord/receiver/local_batch_spec.rb +++ /dev/null @@ -1,93 +0,0 @@ -require 'spec_helper' - -describe Postzord::Receiver::LocalBatch do - before do - @object = FactoryGirl.create(:status_message, :author => alice.person) - @ids = [bob.id.to_s] - end - - let(:receiver) { Postzord::Receiver::LocalBatch.new(@object, @ids) } - - describe '.initialize' do - it 'sets @post, @recipient_user_ids, and @user' do - [:object, :recipient_user_ids, :users].each do |instance_var| - expect(receiver.send(instance_var)).not_to be_nil - end - end - end - - describe '#receive!' do - it 'calls .create_share_visibilities' do - expect(receiver).to receive(:create_share_visibilities) - receiver.receive! - end - - it 'notifies mentioned users' do - expect(receiver).to receive(:notify_mentioned_users) - receiver.receive! - end - - it 'notifies users' do - expect(receiver).to receive(:notify_users) - receiver.receive! - end - end - - describe '#create_share_visibilities' do - it 'calls sharevisibility.batch_import with hashes' do - expect(ShareVisibility).to receive(:batch_import).with(instance_of(Array), @object) - receiver.create_share_visibilities - end - end - - describe '#notify_mentioned_users' do - it 'calls notify person for a mentioned person' do - sm = FactoryGirl.create(:status_message, - :author => alice.person, - :text => "Hey @{Bob; #{bob.diaspora_handle}}") - - receiver2 = Postzord::Receiver::LocalBatch.new(sm, @ids) - expect(Notification).to receive(:notify).with(bob, anything, alice.person) - receiver2.notify_mentioned_users - end - - it 'does not call notify person for a non-mentioned person' do - expect(Notification).not_to receive(:notify) - receiver.notify_mentioned_users - end - end - - describe '#notify_users' do - it 'calls notify for posts with notification type' do - reshare = FactoryGirl.create(:reshare) - expect(Notification).to receive(:notify) - receiver = Postzord::Receiver::LocalBatch.new(reshare, @ids) - receiver.notify_users - end - - it 'calls notify for posts with notification type' do - sm = FactoryGirl.create(:status_message, :author => alice.person) - receiver = Postzord::Receiver::LocalBatch.new(sm, @ids) - expect(Notification).not_to receive(:notify) - receiver.notify_users - end - end - - context 'integrates with a comment' do - before do - sm = FactoryGirl.create(:status_message, :author => alice.person) - @object = FactoryGirl.create(:comment, :author => bob.person, :post => sm) - end - - it 'calls notify_users' do - expect(receiver).to receive(:notify_users) - receiver.perform! - end - - it 'does not call create_visibilities and notify_mentioned_users' do - expect(receiver).not_to receive(:notify_mentioned_users) - expect(receiver).not_to receive(:create_share_visibilities) - receiver.perform! - end - end -end diff --git a/spec/lib/postzord/receiver/private_spec.rb b/spec/lib/postzord/receiver/private_spec.rb deleted file mode 100644 index 088df5ecf835fdc255766c6dd4b4fa52a94670dc..0000000000000000000000000000000000000000 --- a/spec/lib/postzord/receiver/private_spec.rb +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Postzord::Receiver::Private do - - before do - @alices_post = alice.build_post(:status_message, :text => "hey", :aspect_ids => [alice.aspects.first.id]) - @salmon_xml = alice.salmon(@alices_post).xml_for(bob.person) - end - - describe '.initialize' do - it 'valid for local' do - expect(Person).not_to receive(:find_or_fetch_by_identifier) - expect(Salmon::EncryptedSlap).not_to receive(:from_xml) - - zord = Postzord::Receiver::Private.new(bob, :person => alice.person, :object => @alices_post) - expect(zord.instance_variable_get(:@user)).not_to be_nil - expect(zord.instance_variable_get(:@author)).not_to be_nil - expect(zord.instance_variable_get(:@object)).not_to be_nil - end - - it 'valid for remote' do - salmon_double = double() - expect(salmon_double).to receive(:author_id).and_return(true) - expect(Salmon::EncryptedSlap).to receive(:from_xml).with(@salmon_xml, bob).and_return(salmon_double) - expect(Person).to receive(:find_or_fetch_by_identifier).and_return(true) - - zord = Postzord::Receiver::Private.new(bob, :salmon_xml => @salmon_xml) - expect(zord.instance_variable_get(:@user)).not_to be_nil - expect(zord.instance_variable_get(:@author)).not_to be_nil - expect(zord.instance_variable_get(:@salmon_xml)).not_to be_nil - end - end - - describe '#receive!' do - before do - @zord = Postzord::Receiver::Private.new(bob, :salmon_xml => @salmon_xml) - @salmon = @zord.instance_variable_get(:@salmon) - end - - context "does not parse and receive" do - it "if the salmon author does not exist" do - @zord.instance_variable_set(:@author, nil) - expect(@zord).not_to receive(:parse_and_receive) - @zord.receive! - end - - it "if the author does not match the signature" do - @zord.instance_variable_set(:@author, FactoryGirl.create(:person)) - expect(@zord).not_to receive(:parse_and_receive) - @zord.receive! - end - end - - it 'parses the salmon object' do - expect(Diaspora::Parser).to receive(:from_xml).with(@salmon.parsed_data).and_return(@alices_post) - @zord.receive! - end - end - - describe 'receive_object' do - before do - @zord = Postzord::Receiver::Private.new(bob, :person => alice.person, :object => @alices_post) - @salmon = @zord.instance_variable_get(:@salmon) - end - - it 'calls Notification.notify if object responds to notification_type' do - cm = Comment.new - allow(cm).to receive(:receive).and_return(cm) - - expect(Notification).to receive(:notify).with(bob, cm, alice.person) - zord = Postzord::Receiver::Private.new(bob, :person => alice.person, :object => cm) - zord.receive_object - end - - it 'does not call Notification.notify if object does not respond to notification_type' do - expect(Notification).not_to receive(:notify) - @zord.receive_object - end - - it 'calls receive on @object' do - obj = expect(@zord.instance_variable_get(:@object)).to receive(:receive) - @zord.receive_object - end - end -end diff --git a/spec/lib/postzord/receiver/public_spec.rb b/spec/lib/postzord/receiver/public_spec.rb deleted file mode 100644 index 090d67358aac5ca75a0b7b64eb76a4a59859a4d9..0000000000000000000000000000000000000000 --- a/spec/lib/postzord/receiver/public_spec.rb +++ /dev/null @@ -1,134 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Postzord::Receiver::Public do - before do - @post = FactoryGirl.build(:status_message, :author => alice.person, :public => true) - @created_salmon = Salmon::Slap.create_by_user_and_activity(alice, @post.to_diaspora_xml) - @xml = @created_salmon.xml_for(nil) - end - - context 'round trips works with' do - it 'a comment' do - sm = FactoryGirl.create(:status_message, :author => alice.person) - - comment = bob.build_comment(:text => 'yo', :post => sm) - comment.save - #bob signs his comment, and then sends it up - xml = Salmon::Slap.create_by_user_and_activity(bob, comment.to_diaspora_xml).xml_for(nil) - bob.destroy - comment.destroy - expect{ - receiver = Postzord::Receiver::Public.new(xml) - receiver.perform! - }.to change(Comment, :count).by(1) - end - end - - describe '#initialize' do - it 'creates a Salmon instance variable' do - receiver = Postzord::Receiver::Public.new(@xml) - expect(receiver.salmon).not_to be_nil - end - end - - describe '#perform!' do - before do - @receiver = Postzord::Receiver::Public.new(@xml) - end - - it 'calls verify_signature' do - expect(@receiver).to receive(:verified_signature?) - @receiver.perform! - end - - it "does not save the object if signature is not verified" do - expect(@receiver).to receive(:verified_signature?).and_return(false) - expect(@receiver).not_to receive(:parse_and_receive) - @receiver.perform! - end - - context 'if signature is valid' do - it 'calls recipient_user_ids' do - expect(@receiver).to receive(:recipient_user_ids) - @receiver.perform! - end - - it 'saves the parsed object' do - expect(@receiver).to receive(:parse_and_receive).and_call_original - @receiver.perform! - end - - it 'enqueues a Workers::ReceiveLocalBatch' do - expect(Workers::ReceiveLocalBatch).to receive(:perform_async).with(anything, anything, anything) - @receiver.perform! - end - - it 'intergrates' do - inlined_jobs do - @receiver.perform! - end - end - end - end - - describe '#verify_signature?' do - it 'calls Slap#verified_for_key?' do - receiver = Postzord::Receiver::Public.new(@xml) - expect(receiver.salmon).to receive(:verified_for_key?).with(instance_of(OpenSSL::PKey::RSA)) - receiver.verified_signature? - end - end - - describe '#recipient_user_ids' do - it 'calls User.all_sharing_with_person' do - expect(User).to receive(:all_sharing_with_person).and_return(double(:pluck => [])) - receiver = Postzord::Receiver::Public.new(@xml) - receiver.perform! - end - end - - describe '#receive_relayable' do - before do - @comment = bob.build_comment(:text => 'yo', :post => FactoryGirl.create(:status_message)) - @comment.save - created_salmon = Salmon::Slap.create_by_user_and_activity(alice, @comment.to_diaspora_xml) - xml = created_salmon.xml_for(nil) - @comment.delete - @receiver = Postzord::Receiver::Public.new(xml) - end - - it 'receives only for the parent author if he is local to the pod' do - comment = double.as_null_object - @receiver.instance_variable_set(:@object, comment) - - expect(comment).to receive(:receive) - @receiver.receive_relayable - end - - it 'calls notifiy_users' do - comment = double.as_null_object - @receiver.instance_variable_set(:@object, comment) - - local_batch_receiver = double.as_null_object - allow(Postzord::Receiver::LocalBatch).to receive(:new).and_return(local_batch_receiver) - expect(local_batch_receiver).to receive(:notify_users) - @receiver.receive_relayable - end - end - - describe "#parse_and_receive" do - before do - @receiver = Postzord::Receiver::Public.new(@xml) - @parsed_salmon = Salmon::Slap.from_xml(@xml) - end - - it "should raise a Diaspora::XMLNotParseable when the parsed object is nil" do - expect(Diaspora::Parser).to receive(:from_xml).and_return(nil) - expect { @receiver.parse_and_receive(@parsed_salmon.parsed_data) }.to raise_error(Diaspora::XMLNotParseable) - end - end -end diff --git a/spec/lib/postzord/receiver_spec.rb b/spec/lib/postzord/receiver_spec.rb deleted file mode 100644 index 9dc2ceac714acf98319f2b8017aa0a0e72eb197f..0000000000000000000000000000000000000000 --- a/spec/lib/postzord/receiver_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (c) 2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require "spec_helper" - -describe Postzord::Receiver do - before do - @receiver = Postzord::Receiver.new - end - - describe "#perform!" do - before do - allow(@receiver).to receive(:receive!).and_return(true) - end - - it "calls receive!" do - expect(@receiver).to receive(:receive!) - @receiver.perform! - end - end - - describe "#author_does_not_match_xml_author?" do - before do - @receiver.instance_variable_set(:@author, alice.person) - allow(@receiver).to receive(:xml_author).and_return(alice.diaspora_handle) - end - - it "should return false if the author matches" do - allow(@receiver).to receive(:xml_author).and_return(alice.diaspora_handle) - expect(@receiver.send(:author_does_not_match_xml_author?)).to be_falsey - end - - it "should return true if the author does not match" do - allow(@receiver).to receive(:xml_author).and_return(bob.diaspora_handle) - expect(@receiver.send(:author_does_not_match_xml_author?)).to be_truthy - end - end - - describe "#relayable_without_parent?" do - before do - @receiver.instance_variable_set(:@author, alice.person) - end - - it "should return false if object is not relayable" do - @receiver.instance_variable_set(:@object, nil) - expect(@receiver.send(:relayable_without_parent?)).to be_falsey - end - - context "if object is relayable" do - before do - @comment = bob.build_comment(text: "yo", post: FactoryGirl.create(:status_message)) - @receiver.instance_variable_set(:@object, @comment) - end - - it "should return false if object has parent" do - expect(@receiver.send(:relayable_without_parent?)).to be_falsey - end - - it "should return true if object has no parent" do - @comment.parent = nil - expect(@receiver.send(:relayable_without_parent?)).to be_truthy - end - end - end -end diff --git a/spec/lib/publisher_spec.rb b/spec/lib/publisher_spec.rb index 7bb7a7c5d935a742dbd3de05367c6fe5e0824a33..0094f8f496bc01a9f3fb75a70994d7245f6c75a4 100644 --- a/spec/lib/publisher_spec.rb +++ b/spec/lib/publisher_spec.rb @@ -18,19 +18,19 @@ describe Publisher do describe '#text' do it 'is a formatted version of the prefill' do - p = Publisher.new(alice, :prefill => "@{alice; alice@pod.com}") + p = Publisher.new(alice, prefill: "@{alice; #{alice.diaspora_handle}}") expect(p.text).to eq("alice") end end ["open", "public", "explain"].each do |property| - describe "##{property}?" do + describe "##{property}" do it 'defaults to closed' do - expect(@publisher.send("#{property}?".to_sym)).to be_falsey + expect(@publisher.send("#{property}".to_sym)).to be_falsey end it 'listens to the opts' do - expect(Publisher.new(alice, {property.to_sym => true}).send("#{property}?".to_sym)).to be true + expect(Publisher.new(alice, property.to_sym => true).send("#{property}".to_sym)).to be true end end end diff --git a/spec/lib/salmon/encrypted_slap_spec.rb b/spec/lib/salmon/encrypted_slap_spec.rb deleted file mode 100644 index ba297edcfe03dd5eb28e5a36c484776f37b50985..0000000000000000000000000000000000000000 --- a/spec/lib/salmon/encrypted_slap_spec.rb +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Salmon::EncryptedSlap do - before do - @post = alice.post(:status_message, :text => "hi", :to => alice.aspects.create(:name => "abcd").id) - @created_salmon = Salmon::EncryptedSlap.create_by_user_and_activity(alice, @post.to_diaspora_xml) - end - - describe '#create' do - it 'makes the data in the signature encrypted with that key' do - key_hash = {'key' => @created_salmon.aes_key, 'iv' => @created_salmon.iv} - decoded_string = Salmon::EncryptedSlap.decode64url(@created_salmon.magic_sig.data) - expect(alice.aes_decrypt(decoded_string, key_hash)).to eq(@post.to_diaspora_xml) - end - - it 'sets aes and iv key' do - expect(@created_salmon.aes_key).not_to be_nil - expect(@created_salmon.iv).not_to be_nil - end - end - - describe "#process_header" do - before do - @new_slap = Salmon::EncryptedSlap.new - @new_slap.process_header(Nokogiri::XML(@created_salmon.plaintext_header)) - end - - it 'sets the author id' do - expect(@new_slap.author_id).to eq(alice.diaspora_handle) - end - - it 'sets the aes_key' do - expect(@new_slap.aes_key).to eq(@created_salmon.aes_key) - end - - it 'sets the aes_key' do - expect(@new_slap.iv).to eq(@created_salmon.iv) - end - end - - context 'marshalling' do - let(:xml) {@created_salmon.xml_for(eve.person)} - let(:parsed_salmon) { Salmon::EncryptedSlap.from_xml(xml, alice)} - - it 'should parse out the aes key' do - expect(parsed_salmon.aes_key).to eq(@created_salmon.aes_key) - end - - it 'should parse out the iv' do - expect(parsed_salmon.iv).to eq(@created_salmon.iv) - end - - it 'contains the original data' do - expect(parsed_salmon.parsed_data).to eq(@post.to_diaspora_xml) - end - end - - describe '#xml_for' do - before do - @xml = @created_salmon.xml_for eve.person - end - - it 'has a encrypted header field' do - doc = Nokogiri::XML(@xml) - expect(doc.find("encrypted_header")).not_to be_blank - end - - context "encrypted header" do - before do - doc = Nokogiri::XML(@xml) - decrypted_header = eve.decrypt(doc.search('encrypted_header').text) - @dh_doc = Nokogiri::XML(decrypted_header) - end - - it 'contains the aes key' do - expect(@dh_doc.search('aes_key').map(&:text)).to eq([@created_salmon.aes_key]) - end - - it 'contains the initialization vector' do - expect(@dh_doc.search('iv').map(&:text)).to eq([@created_salmon.iv]) - end - - it 'contains the author id' do - expect(@dh_doc.search('author_id').map(&:text)).to eq([alice.diaspora_handle]) - end - end - end -end - diff --git a/spec/lib/salmon/magic_sig_envelope_spec.rb b/spec/lib/salmon/magic_sig_envelope_spec.rb deleted file mode 100644 index 1c1236a58a3d6d40d03efe40e56219cbbebb41bc..0000000000000000000000000000000000000000 --- a/spec/lib/salmon/magic_sig_envelope_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'spec_helper' - -describe Salmon::MagicSigEnvelope do - -end diff --git a/spec/lib/salmon/slap_spec.rb b/spec/lib/salmon/slap_spec.rb deleted file mode 100644 index d3a6851af82ccf0927c81296c699be14d149822f..0000000000000000000000000000000000000000 --- a/spec/lib/salmon/slap_spec.rb +++ /dev/null @@ -1,110 +0,0 @@ -require 'spec_helper' - -describe Salmon::Slap do - before do - @post = alice.post(:status_message, :text => "hi", :to => alice.aspects.create(:name => "abcd").id) - @created_salmon = Salmon::Slap.create_by_user_and_activity(alice, @post.to_diaspora_xml) - end - - describe '#create' do - it 'has data in the magic envelope' do - expect(@created_salmon.magic_sig.data).not_to be nil - end - - it 'has no parsed_data' do - expect(@created_salmon.parsed_data).to be nil - end - - end - - it 'works' do - salmon_string = @created_salmon.xml_for(nil) - salmon = Salmon::Slap.from_xml(salmon_string) - expect(salmon.author).to eq(alice.person) - expect(salmon.parsed_data).to eq(@post.to_diaspora_xml) - end - - describe '#from_xml' do - it 'procsses the header' do - expect_any_instance_of(Salmon::Slap).to receive(:process_header) - Salmon::Slap.from_xml(@created_salmon.xml_for(eve.person)) - end - end - - describe "#process_header" do - it 'sets the author id' do - slap = Salmon::Slap.new - slap.process_header(Nokogiri::XML(@created_salmon.plaintext_header)) - expect(slap.author_id).to eq(alice.diaspora_handle) - end - end - - describe '#author' do - let(:xml) {@created_salmon.xml_for(eve.person)} - let(:parsed_salmon) { Salmon::Slap.from_xml(xml, alice)} - - it 'should reference a local author' do - expect(parsed_salmon.author).to eq(alice.person) - end - - it 'should fail if no author is found' do - parsed_salmon.author_id = 'tom@tom.joindiaspora.com' - expect { - parsed_salmon.author.public_key - }.to raise_error "did you remember to async webfinger?" - end - end - - context 'marshaling' do - let(:xml) {@created_salmon.xml_for(eve.person)} - let(:parsed_salmon) { Salmon::Slap.from_xml(xml)} - - it 'should parse out the authors diaspora_handle' do - expect(parsed_salmon.author_id).to eq(alice.person.diaspora_handle) - end - - it 'verifies the signature for the sender' do - expect(parsed_salmon.verified_for_key?(alice.public_key)).to be true - end - - it 'verifies the signature for the sender' do - expect(parsed_salmon.verified_for_key?(FactoryGirl.create(:person).public_key)).to be false - end - - it 'contains the original data' do - expect(parsed_salmon.parsed_data).to eq(@post.to_diaspora_xml) - end - end - - describe "#xml_for" do - before do - @xml = @created_salmon.xml_for(eve.person) - end - - it "has diaspora as the root" do - doc = Nokogiri::XML(@xml) - expect(doc.root.name).to eq("diaspora") - end - - it "it has the descrypted header" do - doc = Nokogiri::XML(@xml) - expect(doc.search("header")).not_to be_blank - end - - context "header" do - - it "it has author_id node " do - doc = Nokogiri::XML(@xml) - search = doc.search("header").search("author_id") - expect(search.map(&:text)).to eq([alice.diaspora_handle]) - end - - end - - it "it has the magic envelope " do - doc = Nokogiri::XML(@xml) - expect(doc.find("/me:env")).not_to be_blank - end - end -end - diff --git a/spec/lib/stream/multi_spec.rb b/spec/lib/stream/multi_spec.rb index 2f77fc180ddcc5061c621b6d8bf7853f87b8fea9..5c1df2468505983e53437f4b96339c0487010cb3 100644 --- a/spec/lib/stream/multi_spec.rb +++ b/spec/lib/stream/multi_spec.rb @@ -26,9 +26,7 @@ describe Stream::Multi do prefill_text = "sup?" allow(@stream).to receive(:welcome?).and_return(true) allow(@stream).to receive(:publisher_prefill).and_return(prefill_text) - expect(@stream.send(:publisher_opts)).to eq({:open => true, - :prefill => prefill_text, - :public => true}) + expect(@stream.send(:publisher_opts)).to eq(open: true, prefill: prefill_text, public: true, explain: true) end it 'provides no opts if welcome? is not set' do diff --git a/spec/lib/stream/person_spec.rb b/spec/lib/stream/person_spec.rb index f5eb10224dda98d8c752b1ab028a8a6df8104caa..a320f800ebc53289116fc2eac1643927f78c5d1e 100644 --- a/spec/lib/stream/person_spec.rb +++ b/spec/lib/stream/person_spec.rb @@ -2,19 +2,26 @@ require 'spec_helper' require Rails.root.join('spec', 'shared_behaviors', 'stream') describe Stream::Person do - before do - @stream = Stream::Person.new(alice, bob.person, :max_time => Time.now, :order => 'updated_at') + describe "shared behaviors" do + before do + @stream = Stream::Person.new(alice, bob.person, max_time: Time.zone.now, order: "updated_at") + end + + it_should_behave_like "it is a stream" end - describe 'shared behaviors' do - it_should_behave_like 'it is a stream' + describe "#posts" do + it "calls user#posts_from if the user is present" do + stream = Stream::Person.new(alice, bob.person, max_time: Time.zone.now, order: "updated_at") + expect(alice).to receive(:posts_from).with(bob.person) + stream.posts + end end it "returns the most recent posts" do - skip # this randomly fails on postgres posts = [] fetched_posts = [] - + aspect = bob.aspects.first.id Timecop.scale(600) do 16.times do |n| @@ -30,5 +37,4 @@ describe Stream::Person do expect(fetched_posts).to eq(posts) end - end diff --git a/spec/lib/stream/public_spec.rb b/spec/lib/stream/public_spec.rb index 976a9439b55dfaad7ddba0a68e64ca0362a83ef7..a17348cef7902800c77a595b1121304fc22e619b 100644 --- a/spec/lib/stream/public_spec.rb +++ b/spec/lib/stream/public_spec.rb @@ -9,4 +9,11 @@ describe Stream::Public do describe 'shared behaviors' do it_should_behave_like 'it is a stream' end + + describe "#posts" do + it "calls Post#all_public" do + expect(Post).to receive(:all_public) + @stream.posts + end + end end diff --git a/spec/lib/stream/tag_spec.rb b/spec/lib/stream/tag_spec.rb index 5e1205c83f09de108e65468e32020153ed54406b..75952680a0aa71f3add2746f0d8f7de4319331af 100644 --- a/spec/lib/stream/tag_spec.rb +++ b/spec/lib/stream/tag_spec.rb @@ -80,11 +80,30 @@ describe Stream::Tag do describe 'shared behaviors' do before do - @stream = Stream::Tag.new(FactoryGirl.create(:user), "test") + @stream = Stream::Tag.new(FactoryGirl.create(:user), FactoryGirl.create(:tag).name) end it_should_behave_like 'it is a stream' end + describe '#stream_posts' do + it "returns an empty array if the tag does not exist" do + stream = Stream::Tag.new(FactoryGirl.create(:user), "test") + expect(stream.stream_posts).to eq([]) + end + + it "returns an empty array if there are no visible posts for the tag" do + alice.post(:status_message, text: "#what", public: false, to: "all") + stream = Stream::Tag.new(nil, "what") + expect(stream.stream_posts).to eq([]) + end + + it "returns the post containing the tag" do + post = alice.post(:status_message, text: "#what", public: true) + stream = Stream::Tag.new(FactoryGirl.create(:user), "what") + expect(stream.stream_posts).to eq([post]) + end + end + describe '#tag_name=' do it 'downcases the tag' do stream = Stream::Tag.new(nil, "WHAT") diff --git a/spec/mailers/notifier_spec.rb b/spec/mailers/notifier_spec.rb index 7ba777de88b63e0d28f4d6570866dfc482769fce..1fa2837e6761f1a8303509ab5b1101d7f2e13fed 100644 --- a/spec/mailers/notifier_spec.rb +++ b/spec/mailers/notifier_spec.rb @@ -212,15 +212,12 @@ describe Notifier, type: :mailer do expect(@mail["From"].to_s).to eq("\"#{@cnv.author.name} (diaspora*)\" <#{AppConfig.mail.sender_address}>") end - it "SUBJECT: has a snippet of the post contents" do - expect(@mail.subject).to eq(@cnv.subject) + it "should use a generic subject" do + expect(@mail.subject).to eq(I18n.translate("notifier.private_message.subject")) end - it "SUBJECT: has 'Re:' if not the first message in a conversation" do - @cnv.messages << Message.new(text: "yo", author: eve.person) - @mail = Notifier.private_message(bob.id, @cnv.author.id, @cnv.messages.last.id) - - expect(@mail.subject).to eq("Re: #{@cnv.subject}") + it "SUBJECT: should not has a snippet of the private message contents" do + expect(@mail.subject).not_to include(@cnv.subject) end it "BODY: does not contain the message text" do @@ -444,7 +441,9 @@ describe Notifier, type: :mailer do mails = Notifier.admin("#Welcome to bureaucracy!", [bob]) expect(mails.length).to eq(1) mail = mails.first - expect(mail.body.encoded).to match "<p><a href=\"http://localhost:9887/tags/welcome\">#Welcome</a> to bureaucracy!</p>" + expect(mail.body.encoded).to match( + "<p><a href=\"#{AppConfig.url_to(tag_path('welcome'))}\">#Welcome</a> to bureaucracy!</p>" + ) end end diff --git a/spec/mailers/report_spec.rb b/spec/mailers/report_spec.rb index 32c2afdb1cde0587a923465862ae490408c5e6a2..5ecb669235f74828918867eb068ee1ca8ce15b43 100644 --- a/spec/mailers/report_spec.rb +++ b/spec/mailers/report_spec.rb @@ -7,6 +7,17 @@ require "spec_helper" describe Report, type: :mailer do describe "#make_notification" do before do + @reported_user = bob + @post = @reported_user.post(:status_message, text: "hello", to: @reported_user.aspects.first.id) + @comment = @reported_user.comment!(@post, "welcome") + @post_report = @reported_user.reports.create( + item_id: @post.id, item_type: "Post", + text: "offensive content" + ) + @comment_report = @reported_user.reports.create( + item_id: @comment.id, item_type: "Comment", + text: "offensive comment" + ) @remote = FactoryGirl.create(:person, diaspora_handle: "remote@remote.net") @user = FactoryGirl.create(:user_with_aspect, username: "local", language: "de") @user2 = FactoryGirl.create(:user_with_aspect, username: "locally") @@ -16,26 +27,36 @@ describe Report, type: :mailer do it "should deliver successfully" do expect { - ReportMailer.new_report("post", 666).each(&:deliver_now) + ReportMailer.new_report(@post_report.id).each(&:deliver_now) }.to_not raise_error end it "should be added to the delivery queue" do expect { - ReportMailer.new_report("post", 666).each(&:deliver_now) + ReportMailer.new_report(@post_report.id).each(&:deliver_now) }.to change(ActionMailer::Base.deliveries, :size).by(2) end it "should include correct recipient" do - ReportMailer.new_report("post", 666).each(&:deliver_now) + ReportMailer.new_report(@post_report.id).each(&:deliver_now) expect(ActionMailer::Base.deliveries[0].to[0]).to include(@user.email) expect(ActionMailer::Base.deliveries[1].to[0]).to include(@user2.email) end it "should send mail in recipent's prefered language" do - ReportMailer.new_report("post", 666).each(&:deliver_now) + ReportMailer.new_report(@post_report.id).each(&:deliver_now) expect(ActionMailer::Base.deliveries[0].subject).to match("Ein neuer post wurde als anstößig markiert") expect(ActionMailer::Base.deliveries[1].subject).to match("A new post was marked as offensive") end + + it "should find correct post translation" do + ReportMailer.new_report(@post_report.id).each(&:deliver_now) + expect(ActionMailer::Base.deliveries[0].subject).not_to match("translation missing") + end + + it "should find correct comment translation" do + ReportMailer.new_report(@comment_report.id).each(&:deliver_now) + expect(ActionMailer::Base.deliveries[0].subject).not_to match("translation missing") + end end end diff --git a/spec/misc_spec.rb b/spec/misc_spec.rb index e714d839dabee6523990275eec5e7184e652c583..721b4ddce2502a032d5dded6d672d540650e8ab1 100644 --- a/spec/misc_spec.rb +++ b/spec/misc_spec.rb @@ -17,7 +17,7 @@ describe 'making sure the spec runner works' do end end - describe '#connect_users' do + describe "#connect_users" do before do @user1 = User.where(:username => 'alice').first @user2 = User.where(:username => 'eve').first @@ -50,9 +50,29 @@ describe 'making sure the spec runner works' do end end - describe '#post' do - it 'creates a notification with a mention' do - expect{ + describe "#add_contact_to_aspect" do + let(:contact) { alice.contact_for(bob.person) } + + it "adds the contact to the aspect" do + new_aspect = alice.aspects.create(name: "two") + + expect { + alice.add_contact_to_aspect(contact, new_aspect) + }.to change(new_aspect.contacts, :count).by(1) + end + + it "does nothing if they are already in the aspect" do + original_aspect = alice.aspects.where(name: "generic").first + + expect { + alice.add_contact_to_aspect(contact, original_aspect) + }.not_to change(contact.aspect_memberships, :count) + end + end + + describe "#post" do + it "creates a notification with a mention" do + expect { alice.post(:status_message, :text => "@{Bob Grimn; #{bob.person.diaspora_handle}} you are silly", :to => alice.aspects.find_by_name('generic')) }.to change(Notification, :count).by(1) end diff --git a/spec/models/account_deletion_spec.rb b/spec/models/account_deletion_spec.rb index 0126edb77ac9c7b221505888eef80612af7b5427..4b0734b1948fc271086e99af80dd59d5687d9bd6 100644 --- a/spec/models/account_deletion_spec.rb +++ b/spec/models/account_deletion_spec.rb @@ -4,46 +4,42 @@ require "spec_helper" -describe AccountDeletion, :type => :model do - let(:account_deletion_new) { AccountDeletion.new(person: alice.person) } - let(:account_deletion_create) { AccountDeletion.create(person: alice.person) } +describe AccountDeletion, type: :model do + let(:account_deletion) { AccountDeletion.new(person: alice.person) } it "assigns the diaspora_handle from the person object" do - expect(account_deletion_new.diaspora_handle).to eq(alice.person.diaspora_handle) + expect(account_deletion.diaspora_handle).to eq(alice.person.diaspora_handle) end - it "fires a job after creation"do + it "fires a job after creation" do expect(Workers::DeleteAccount).to receive(:perform_async).with(anything) - account_deletion_create + AccountDeletion.create(person: alice.person) end describe "#perform!" do it "creates a deleter" do expect(AccountDeleter).to receive(:new).with(alice.person.diaspora_handle).and_return(double(perform!: true)) - account_deletion_new.perform! + account_deletion.perform! end it "dispatches the account deletion if the user exists" do - expect(account_deletion_new).to receive(:dispatch) - account_deletion_new.perform! + dispatcher = double + expect(Diaspora::Federation::Dispatcher::Public).to receive(:new).and_return(dispatcher) + expect(dispatcher).to receive(:dispatch) + + account_deletion.perform! end it "does not dispatch an account deletion for non-local people" do deletion = AccountDeletion.new(person: remote_raphael) - expect(deletion).not_to receive(:dispatch) + expect(Diaspora::Federation::Dispatcher).not_to receive(:build) deletion.perform! end it "marks an AccountDeletion as completed when successful" do - account_deletion_create.perform! - expect(account_deletion_create.reload.completed_at).not_to be_nil - end - end - - describe "#dispatch" do - it "creates a public postzord" do - expect(Postzord::Dispatcher::Public).to receive(:new).and_return(double.as_null_object) - account_deletion_new.dispatch + deletion = AccountDeletion.create(person: alice.person) + deletion.perform! + expect(deletion.reload.completed_at).not_to be_nil end end @@ -51,7 +47,7 @@ describe AccountDeletion, :type => :model do it "includes all remote contacts" do alice.share_with(remote_raphael, alice.aspects.first) - expect(account_deletion_new.subscribers(alice)).to eq([remote_raphael]) + expect(account_deletion.subscribers).to eq([remote_raphael]) end it "includes remote resharers" do @@ -59,19 +55,7 @@ describe AccountDeletion, :type => :model do FactoryGirl.create(:reshare, author: remote_raphael, root: status_message) FactoryGirl.create(:reshare, author: local_luke.person, root: status_message) - expect(account_deletion_new.subscribers(alice)).to eq([remote_raphael]) - end - end - - describe "serialization" do - let(:xml) { account_deletion_new.to_xml.to_s } - - it "should have a diaspora_handle" do - expect(xml.include?(alice.person.diaspora_handle)).to eq(true) - end - - it "marshals the xml" do - expect(AccountDeletion.from_xml(xml)).to be_valid + expect(account_deletion.subscribers).to eq([remote_raphael]) end end end diff --git a/spec/models/aspect_visibility_spec.rb b/spec/models/aspect_visibility_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..b27b2e984986ec87d7dead58d7b0363bde479493 --- /dev/null +++ b/spec/models/aspect_visibility_spec.rb @@ -0,0 +1,32 @@ +require "spec_helper" + +describe AspectVisibility, type: :model do + let(:status_message) { FactoryGirl.create(:status_message) } + let(:aspect) { FactoryGirl.create(:aspect) } + let(:status_message_in_aspect) { FactoryGirl.create(:status_message_in_aspect) } + let(:photo_with_same_id) { + Photo.find_by_id(status_message_in_aspect.id) || FactoryGirl.create(:photo, id: status_message_in_aspect.id) + } + + describe ".create" do + it "creates object when attributes are fine" do + expect { + AspectVisibility.create(shareable: status_message, aspect: aspect) + }.to change(AspectVisibility, :count).by(1) + end + + it "doesn't allow duplicating objects" do + expect { + AspectVisibility + .create(shareable: status_message_in_aspect, aspect: status_message_in_aspect.aspects.first) + .save! + }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "makes difference between shareable types" do + expect { + AspectVisibility.create(shareable: photo_with_same_id, aspect: status_message_in_aspect.aspects.first).save! + }.not_to raise_error + end + end +end diff --git a/spec/models/comment_signature_spec.rb b/spec/models/comment_signature_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..396dbb9038f7d86217485321b86e0686d5685e46 --- /dev/null +++ b/spec/models/comment_signature_spec.rb @@ -0,0 +1,11 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require "spec_helper" + +describe CommentSignature, type: :model do + it_behaves_like "signature data" do + let(:relayable_type) { :comment } + end +end diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index 1ba80fba8d6ab4ce7fa0818c259fb265070e29b7..135e0174b65d7cfc6956f271db1e5d647b859c89 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -3,41 +3,23 @@ # the COPYRIGHT file. require "spec_helper" -require Rails.root.join("spec", "shared_behaviors", "relayable") -describe Comment, :type => :model do +describe Comment, type: :model do let(:alices_aspect) { alice.aspects.first } let(:status_bob) { bob.post(:status_message, text: "hello", to: bob.aspects.first.id) } let(:comment_alice) { alice.comment!(status_bob, "why so formal?") } - describe 'comment#notification_type' do - it "returns 'comment_on_post' if the comment is on a post you own" do - expect(comment_alice.notification_type(bob, alice.person)).to eq(Notifications::CommentOnPost) - end - - it "returns 'also_commented' if the comment is on a post you participate to" do - eve.participate! status_bob - expect(comment_alice.notification_type(eve, alice.person)).to eq(Notifications::AlsoCommented) - end - - it "returns false if the comment is not on a post you own and no one 'also_commented'" do - expect(comment_alice.notification_type(eve, alice.person)).to be false + describe "#destroy" do + it "should delete a participation" do + comment_alice + expect { comment_alice.destroy }.to change { Participation.count }.by(-1) end - context "also commented" do - let(:comment_eve) { eve.comment!(status_bob, "I also commented on the first user's post") } - - before do - comment_alice - end - - it "does not return also commented if the user commented" do - expect(comment_eve.notification_type(eve, alice.person)).to eq(false) - end - - it "returns 'also_commented' if another person commented on a post you commented on" do - expect(comment_eve.notification_type(alice, alice.person)).to eq(Notifications::AlsoCommented) - end + it "should decrease count participation" do + alice.comment!(status_bob, "Are you there?") + comment_alice.destroy + participations = Participation.where(target_id: comment_alice.commentable_id, author_id: comment_alice.author_id) + expect(participations.first.count).to eq(1) end end @@ -58,6 +40,12 @@ describe Comment, :type => :model do }.to change { Comment.count }.by(1) end + it "should create a participation" do + comment_alice + participations = Participation.where(target_id: comment_alice.commentable_id, author_id: comment_alice.author_id) + expect(participations.count).to eq(1) + end + it "does not create a participation if comment validation failed" do begin alice.comment!(status_bob, " ") @@ -78,65 +66,13 @@ describe Comment, :type => :model do end end - describe "xml" do - let(:commenter) { create(:user) } - let(:commenter_aspect) { commenter.aspects.create(name: "bruisers") } - let(:post) { alice.post :status_message, text: "hello", to: alices_aspect.id } - let(:comment) { commenter.comment!(post, "Fool!") } - let(:xml) { comment.to_xml.to_s } - - before do - connect_users(alice, alices_aspect, commenter, commenter_aspect) - end - - it "serializes the sender handle" do - expect(xml.include?(commenter.diaspora_handle)).to be true - end - - it "serializes the post_guid" do - expect(xml).to include(post.guid) - end - - describe "marshalling" do - let(:marshalled_comment) { Comment.from_xml(xml) } - - it "marshals the author" do - expect(marshalled_comment.author).to eq(commenter.person) - end - - it "marshals the post" do - expect(marshalled_comment.post).to eq(post) - end - - it "tries to fetch a missing parent" do - guid = post.guid - marshalled_comment - post.destroy - expect_any_instance_of(Comment).to receive(:fetch_parent).with(guid).and_return(nil) - Comment.from_xml(xml) - end - end - end - - describe "it is relayable" do - let(:remote_parent) { build(:status_message, author: remote_raphael) } - let(:local_parent) { local_luke.post :status_message, text: "hi", to: local_luke.aspects.first } - let(:object_by_parent_author) { local_luke.comment!(local_parent, "yo!") } - let(:object_by_recipient) { local_leia.build_comment(text: "yo", post: local_parent) } - let(:dup_object_by_parent_author) { object_by_parent_author.dup } + it_behaves_like "it is relayable" do + let(:remote_parent) { FactoryGirl.create(:status_message, author: remote_raphael) } + let(:local_parent) { local_luke.post(:status_message, text: "hi", to: local_luke.aspects.first) } + let(:object_on_local_parent) { local_luke.comment!(local_parent, "yo!") } let(:object_on_remote_parent) { local_luke.comment!(remote_parent, "Yeah, it was great") } - - before do - # shared_behaviors/relayable.rb is still using instance variables, so we need to define them here. - # Suggestion: refactor all specs using shared_behaviors/relayable.rb to use "let" - @object_by_parent_author = object_by_parent_author - @object_by_recipient = object_by_recipient - @dup_object_by_parent_author = dup_object_by_parent_author - @object_on_remote_parent = object_on_remote_parent - end - - let(:build_object) { alice.build_comment(post: status_bob, text: "why so formal?") } - it_should_behave_like "it is relayable" + let(:remote_object_on_local_parent) { FactoryGirl.create(:comment, post: local_parent, author: remote_raphael) } + let(:relayable) { Comment::Generator.new(alice, status_bob, "why so formal?").build } end describe "tags" do diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb index b5efa37e1a00639c649b3fcde9126f70727c5ef9..0245d1ab09f0368a000c137a215c9004d550c8e1 100644 --- a/spec/models/contact_spec.rb +++ b/spec/models/contact_spec.rb @@ -4,7 +4,7 @@ require "spec_helper" -describe Contact, :type => :model do +describe Contact, type: :model do describe "aspect_memberships" do it "deletes dependent aspect memberships" do expect { @@ -16,6 +16,10 @@ describe Contact, :type => :model do context "validations" do let(:contact) { Contact.new } + it "is valid" do + expect(alice.contact_for(bob.person)).to be_valid + end + it "requires a user" do contact.valid? expect(contact.errors.full_messages).to include "User can't be blank" @@ -26,31 +30,53 @@ describe Contact, :type => :model do expect(contact.errors.full_messages).to include "Person can't be blank" end - it "ensures user is not making a contact for himself" do - contact.person = alice.person - contact.user = alice - - contact.valid? - expect(contact.errors.full_messages).to include "Cannot create self-contact" - end - it "validates uniqueness" do person = FactoryGirl.create(:person) + contact1 = alice.contacts.create(person: person) + expect(contact1).to be_valid + contact2 = alice.contacts.create(person: person) - expect(contact2).to be_valid + expect(contact2).not_to be_valid + end + + describe "#not_contact_with_closed_account" do + it "adds error if the person's account is closed" do + person = FactoryGirl.create(:person, closed_account: true) + bad_contact = alice.contacts.create(person: person) - contact.user = alice - contact.person = person - expect(contact).not_to be_valid + expect(bad_contact).not_to be_valid + expect(bad_contact.errors.full_messages.count).to eq(1) + expect(bad_contact.errors.full_messages.first).to eq("Cannot be in contact with a closed account") + end + end + + describe "#not_contact_for_self" do + it "adds error contacting self" do + bad_contact = alice.contacts.create(person: alice.person) + + expect(bad_contact).not_to be_valid + expect(bad_contact.errors.full_messages.count).to eq(1) + expect(bad_contact.errors.full_messages.first).to eq("Cannot create self-contact") + end end - it "validates that the person's account is not closed" do - person = FactoryGirl.create(:person, :closed_account => true) - contact = alice.contacts.new(person: person) + describe "#not_blocked_user" do + it "adds an error when start sharing with a blocked person" do + alice.blocks.create(person: eve.person) + bad_contact = alice.contacts.create(person: eve.person, receiving: true) - expect(contact).not_to be_valid - expect(contact.errors.full_messages).to include "Cannot be in contact with a closed account" + expect(bad_contact).not_to be_valid + expect(bad_contact.errors.full_messages.count).to eq(1) + expect(bad_contact.errors.full_messages.first).to eq("Cannot connect to an ignored user") + end + + it "is valid when a blocked person starts sharing with the user" do + alice.blocks.create(person: eve.person) + bad_contact = alice.contacts.create(person: eve.person, receiving: false, sharing: true) + + expect(bad_contact).to be_valid + end end end @@ -59,10 +85,15 @@ describe Contact, :type => :model do it "returns contacts with sharing true" do expect { alice.contacts.create!(sharing: true, person: FactoryGirl.create(:person)) - alice.contacts.create!(sharing: false, person: FactoryGirl.create(:person)) - }.to change{ + }.to change { Contact.sharing.count }.by(1) + + expect { + alice.contacts.create!(sharing: false, person: FactoryGirl.create(:person)) + }.to change { + Contact.sharing.count + }.by(0) end end @@ -70,33 +101,61 @@ describe Contact, :type => :model do it "returns contacts with sharing true" do expect { alice.contacts.create!(receiving: true, person: FactoryGirl.build(:person)) + }.to change { + Contact.receiving.count + }.by(1) + + expect { alice.contacts.create!(receiving: false, person: FactoryGirl.build(:person)) - }.to change{ + }.to change { Contact.receiving.count + }.by(0) + end + end + + describe "mutual" do + it "returns contacts with sharing true and receiving true" do + expect { + alice.contacts.create!(receiving: true, sharing: true, person: FactoryGirl.build(:person)) + }.to change { + Contact.mutual.count }.by(1) + + expect { + alice.contacts.create!(receiving: false, sharing: true, person: FactoryGirl.build(:person)) + alice.contacts.create!(receiving: true, sharing: false, person: FactoryGirl.build(:person)) + }.to change { + Contact.mutual.count + }.by(0) end end describe "only_sharing" do it "returns contacts with sharing true and receiving false" do expect { - alice.contacts.create!(receiving: true, sharing: true, person: FactoryGirl.build(:person)) alice.contacts.create!(receiving: false, sharing: true, person: FactoryGirl.build(:person)) alice.contacts.create!(receiving: false, sharing: true, person: FactoryGirl.build(:person)) - alice.contacts.create!(receiving: true, sharing: false, person: FactoryGirl.build(:person)) - }.to change{ - Contact.receiving.count + }.to change { + Contact.only_sharing.count }.by(2) + + expect { + alice.contacts.create!(receiving: true, sharing: true, person: FactoryGirl.build(:person)) + alice.contacts.create!(receiving: true, sharing: false, person: FactoryGirl.build(:person)) + }.to change { + Contact.only_sharing.count + }.by(0) end end describe "all_contacts_of_person" do it "returns all contacts where the person is the passed in person" do person = FactoryGirl.create(:person) + contact1 = FactoryGirl.create(:contact, person: person) - contact2 = FactoryGirl.create(:contact) - contacts = Contact.all_contacts_of_person(person) - expect(contacts).to eq([contact1]) + FactoryGirl.create(:contact) # contact2 + + expect(Contact.all_contacts_of_person(person)).to eq([contact1]) end end end @@ -122,7 +181,7 @@ describe Contact, :type => :model do bob.contacts.create(person: person, aspects: [@new_aspect]) @people2 << person end - #eve <-> bob <-> alice + # eve <-> bob <-> alice end context "on a contact for a local user" do @@ -158,50 +217,52 @@ describe Contact, :type => :model do end end - context "requesting" do - let(:contact) { Contact.new user: user, person: person } - let(:user) { build(:user) } - let(:person) { build(:person) } + describe "#receive" do + it "shares back if auto_following is enabled" do + alice.auto_follow_back = true + alice.auto_follow_back_aspect = alice.aspects.first + alice.save - describe "#generate_request" do - it "makes a request" do - allow(contact).to receive(:user).and_return(user) - request = contact.generate_request + expect(alice).to receive(:share_with).with(eve.person, alice.aspects.first) - expect(request.sender).to eq(user.person) - expect(request.recipient).to eq(person) - end + described_class.new(user: alice, person: eve.person, sharing: true).receive([alice.id]) end - describe "#dispatch_request" do - it "pushes to people" do - allow(contact).to receive(:user).and_return(user) - m = double() - expect(m).to receive(:post) - expect(Postzord::Dispatcher).to receive(:build).and_return(m) - contact.dispatch_request - end - end - end + it "shares not back if auto_following is not enabled" do + alice.auto_follow_back = false + alice.auto_follow_back_aspect = alice.aspects.first + alice.save - describe "#not_blocked_user" do - let(:contact) { alice.contact_for(bob.person) } + expect(alice).not_to receive(:share_with) - it "is called on validate" do - expect(contact).to receive(:not_blocked_user) - contact.valid? + described_class.new(user: alice, person: eve.person, sharing: true).receive([alice.id]) end - it "adds to errors if potential contact is blocked by user" do - person = eve.person - alice.blocks.create(person: person) - bad_contact = alice.contacts.create(person: person) + it "shares not back if already sharing" do + alice.auto_follow_back = true + alice.auto_follow_back_aspect = alice.aspects.first + alice.save + + expect(alice).not_to receive(:share_with) + + described_class.new(user: alice, person: eve.person, sharing: true, receiving: true).receive([alice.id]) + end + end - expect(bad_contact.send(:not_blocked_user)).to be false + describe "#object_to_receive" do + it "returns the contact for the recipient" do + user = FactoryGirl.create(:user) + contact = alice.contacts.create(person: user.person) + receive = contact.object_to_receive + expect(receive.user).to eq(user) + expect(receive.person).to eq(alice.person) end + end - it "does not add to errors" do - expect(contact.send(:not_blocked_user)).to be true + describe "#subscribers" do + it "returns an array with recipient of the contact" do + contact = alice.contacts.create(person: eve.person) + expect(contact.subscribers).to match_array([eve.person]) end end end diff --git a/spec/models/conversation_spec.rb b/spec/models/conversation_spec.rb index fe44e463df7dde2bcdc647575d9852b7464285d1..5bb08c2c1628ee2d2208d5959581f39fc9f9b56f 100644 --- a/spec/models/conversation_spec.rb +++ b/spec/models/conversation_spec.rb @@ -70,67 +70,6 @@ describe Conversation, :type => :model do end end - context "transport" do - let(:conversation_message) { conversation.messages.first } - let(:xml) { conversation.to_diaspora_xml } - - before do - conversation - end - - describe "serialization" do - it "serializes the message" do - expect(xml.gsub(/\s/, "")).to include(conversation_message.to_xml.to_s.gsub(/\s/, "")) - end - - it "serializes the participants" do - create_hash[:participant_ids].each do |id| - expect(xml).to include(Person.find(id).diaspora_handle) - end - end - - it "serializes the created_at time" do - expect(xml).to include(conversation_message.created_at.to_s) - end - end - - describe "#subscribers" do - it "returns the recipients for the post owner" do - expect(conversation.subscribers(user1)).to eq(user1.contacts.map(&:person)) - end - end - - describe "#receive" do - before do - Message.destroy_all - Conversation.destroy_all - end - - it "creates a message" do - expect { - Diaspora::Parser.from_xml(xml).receive(user1, user2.person) - }.to change(Message, :count).by(1) - end - it "creates a conversation" do - expect { - Diaspora::Parser.from_xml(xml).receive(user1, user2.person) - }.to change(Conversation, :count).by(1) - end - it "creates appropriate visibilities" do - expect { - Diaspora::Parser.from_xml(xml).receive(user1, user2.person) - }.to change(ConversationVisibility, :count).by(participant_ids.size) - end - it "does not save before receive" do - expect(Diaspora::Parser.from_xml(xml).persisted?).to be false - end - it "notifies for the message" do - expect(Notification).to receive(:notify).once - Diaspora::Parser.from_xml(xml).receive(user1, user2.person) - end - end - end - describe "#invalid parameters" do context "local author" do let(:invalid_hash) { diff --git a/spec/models/invitation_spec.rb b/spec/models/invitation_spec.rb deleted file mode 100644 index 539b6158285cb26b58abb76b3eb88e53c0a30e01..0000000000000000000000000000000000000000 --- a/spec/models/invitation_spec.rb +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Invitation, :type => :model do - let(:user) { alice } - - before do - @email = 'maggie@example.com' - Devise.mailer.deliveries = [] - end - describe 'validations' do - before do - @invitation = FactoryGirl.build(:invitation, :sender => user, :recipient => nil, :aspect => user.aspects.first, :language => "de") - end - - it 'is valid' do - expect(@invitation.sender).to eq(user) - expect(@invitation.recipient).to eq(nil) - expect(@invitation.aspect).to eq(user.aspects.first) - expect(@invitation.language).to eq("de") - expect(@invitation).to be_valid - end - - it 'ensures the sender is placing the recipient into one of his aspects' do - @invitation.aspect = FactoryGirl.build(:aspect) - expect(@invitation).not_to be_valid - end - end - - describe '#language' do - it 'returns the correct language if the language is set' do - @invitation = FactoryGirl.build(:invitation, :sender => user, :recipient => eve, :aspect => user.aspects.first, :language => "de") - expect(@invitation.language).to eq("de") - end - - it 'returns en if no language is set' do - @invitation = FactoryGirl.build(:invitation, :sender => user, :recipient => eve, :aspect => user.aspects.first) - expect(@invitation.language).to eq("en") - end - end - - it 'has a message' do - @invitation = FactoryGirl.build(:invitation, :sender => user, :recipient => eve, :aspect => user.aspects.first, :language => user.language) - @invitation.message = "!" - expect(@invitation.message).to eq("!") - end - - - describe '.batch_invite' do - before do - @emails = ['max@foo.com', 'bob@mom.com'] - @opts = {:aspect => eve.aspects.first, :sender => eve, :service => 'email', :language => eve.language} - end - - it 'returns an array of invites based on the emails passed in' do - invites = Invitation.batch_invite(@emails, @opts) - expect(invites.count).to be 2 - expect(invites.all?{|x| x.persisted?}).to be true - end - - it 'shares with people who are already on the pod' do - FactoryGirl.create(:user, :email => @emails.first) - invites = nil - expect{ - invites = Invitation.batch_invite(@emails, @opts) - }.to change(eve.contacts, :count).by(1) - expect(invites.count).to be 2 - - end - end -end diff --git a/lib/postzord.rb b/spec/models/like_signature_spec.rb similarity index 53% rename from lib/postzord.rb rename to spec/models/like_signature_spec.rb index 438da2b28cf9feaf01a6aa3457734f374dd9eabf..d31a374333960a7f4c15bdf0916fffa23636a3fa 100644 --- a/lib/postzord.rb +++ b/spec/models/like_signature_spec.rb @@ -2,7 +2,10 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -module Postzord - require 'postzord/receiver' - require 'postzord/dispatcher' +require "spec_helper" + +describe LikeSignature, type: :model do + it_behaves_like "signature data" do + let(:relayable_type) { :like } + end end diff --git a/spec/models/like_spec.rb b/spec/models/like_spec.rb index 11532bff69022d0874d3a3720d84968a99969fb1..64f3d79dbc29627eb0b099f7539bd966546bea41 100644 --- a/spec/models/like_spec.rb +++ b/spec/models/like_spec.rb @@ -2,95 +2,53 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' -require Rails.root.join("spec", "shared_behaviors", "relayable") +require "spec_helper" -describe Like, :type => :model do - before do - @status = bob.post(:status_message, :text => "hello", :to => bob.aspects.first.id) - end +describe Like, type: :model do + let(:status) { bob.post(:status_message, text: "hello", to: bob.aspects.first.id) } - it 'has a valid factory' do + it "has a valid factory" do expect(FactoryGirl.build(:like)).to be_valid end - describe '#notification_type' do + describe "#destroy" do before do - @like = alice.like!(@status) - end - - it 'should be notifications liked if you are the post owner' do - expect(@like.notification_type(bob, alice.person)).to be Notifications::Liked + @like = alice.like!(status) end - it 'should not notify you if you are the like-r' do - expect(@like.notification_type(alice, alice.person)).to be_nil + it "should delete a participation" do + expect { @like.destroy }.to change { Participation.count }.by(-1) end - it 'should not notify you if you did not create the post' do - expect(@like.notification_type(eve, alice.person)).to be_nil + it "should decrease count participation" do + alice.comment!(status, "Are you there?") + @like.destroy + participations = Participation.where(target_id: @like.target_id, author_id: @like.author_id) + expect(participations.first.count).to eq(1) end end - describe 'counter cache' do - it 'increments the counter cache on its post' do + describe "counter cache" do + it "increments the counter cache on its post" do expect { - alice.like!(@status) - }.to change{ @status.reload.likes_count }.by(1) + alice.like!(status) + }.to change { status.reload.likes_count }.by(1) end - it 'increments the counter cache on its comment' do - comment = FactoryGirl.create(:comment, :post => @status) + it "increments the counter cache on its comment" do + comment = FactoryGirl.create(:comment, post: status) expect { alice.like!(comment) - }.to change{ comment.reload.likes_count }.by(1) - end - end - - describe 'xml' do - before do - alices_aspect = alice.aspects.first - - @liker = FactoryGirl.create(:user) - @liker_aspect = @liker.aspects.create(:name => "dummies") - connect_users(alice, alices_aspect, @liker, @liker_aspect) - @post = alice.post(:status_message, :text => "huhu", :to => alices_aspect.id) - @like = @liker.like!(@post) - @xml = @like.to_xml.to_s - end - it 'serializes the sender handle' do - expect(@xml.include?(@liker.diaspora_handle)).to be true - end - it' serializes the post_guid' do - expect(@xml).to include(@post.guid) - end - describe 'marshalling' do - before do - @marshalled_like = Like.from_xml(@xml) - end - it 'marshals the author' do - expect(@marshalled_like.author).to eq(@liker.person) - end - it 'marshals the post' do - expect(@marshalled_like.target).to eq(@post) - end + }.to change { comment.reload.likes_count }.by(1) end end - describe 'it is relayable' do - before do - @local_luke, @local_leia, @remote_raphael = set_up_friends - @remote_parent = FactoryGirl.create(:status_message, :author => @remote_raphael) - @local_parent = @local_luke.post :status_message, :text => "foobar", :to => @local_luke.aspects.first - - @object_by_parent_author = @local_luke.like!(@local_parent) - @object_by_recipient = @local_leia.like!(@local_parent) - @dup_object_by_parent_author = @object_by_parent_author.dup - - @object_on_remote_parent = @local_luke.like!(@remote_parent) - end - - let(:build_object) { Like::Generator.new(alice, @status).build } - it_should_behave_like 'it is relayable' + it_behaves_like "it is relayable" do + let(:remote_parent) { FactoryGirl.create(:status_message, author: remote_raphael) } + let(:local_parent) { local_luke.post(:status_message, text: "hi", to: local_luke.aspects.first) } + let(:object_on_local_parent) { local_luke.like!(local_parent) } + let(:object_on_remote_parent) { local_luke.like!(remote_parent) } + let(:remote_object_on_local_parent) { FactoryGirl.create(:like, target: local_parent, author: remote_raphael) } + let(:relayable) { Like::Generator.new(alice, status).build } end end diff --git a/spec/models/mention_spec.rb b/spec/models/mention_spec.rb index a3eaa103bcefca011436c72a874660c51f7a4c75..5ea19fcfdf7e8c7ae787b4b0400b35546aa4fbdf 100644 --- a/spec/models/mention_spec.rb +++ b/spec/models/mention_spec.rb @@ -2,47 +2,19 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' +require "spec_helper" -describe Mention, :type => :model do - describe "#notify_recipient" do - before do - @user = alice - @aspect1 = @user.aspects.create(:name => 'second_aspect') - end - - it 'notifies the person being mentioned' do - sm = @user.build_post(:status_message, :text => "hi @{#{bob.name}; #{bob.diaspora_handle}}", :to => @user.aspects.first) - expect(Notification).to receive(:notify).with(bob, anything(), sm.author) - sm.receive(bob, alice.person) - end +describe Mention, type: :model do + describe "after destroy" do + it "destroys a notification" do + sm = alice.post(:status_message, text: "hi", to: alice.aspects.first) + mention = Mention.create!(person: bob.person, post: sm) - it 'should not notify a user if they do not see the message' do - expect(Notification).not_to receive(:notify).with(alice, anything(), bob.person) - sm2 = bob.build_post(:status_message, :text => "stuff @{#{alice.name}; #{alice.diaspora_handle}}", :to => bob.aspects.first) - sm2.receive(eve, bob.person) - end - end + Notifications::Mentioned.notify(sm, [bob.id]) - describe '#notification_type' do - it "returns 'mentioned'" do - expect(Mention.new.notification_type).to eq(Notifications::Mentioned) - end - end - - describe 'after destroy' do - it 'destroys a notification' do - @user = alice - @mentioned_user = bob - - @sm = @user.post(:status_message, :text => "hi", :to => @user.aspects.first) - @m = Mention.create!(:person => @mentioned_user.person, :post => @sm) - @m.notify_recipient - - expect{ - @m.destroy + expect { + mention.destroy }.to change(Notification, :count).by(-1) end end end - diff --git a/spec/models/message_spec.rb b/spec/models/message_spec.rb index 327348125cb4f4282410c6d30676e3eb64d0ec8c..ec853498ce9d6076eba73ecdeabe0bf846c969a1 100644 --- a/spec/models/message_spec.rb +++ b/spec/models/message_spec.rb @@ -2,109 +2,59 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' -require Rails.root.join("spec", "shared_behaviors", "relayable") - -describe Message, :type => :model do - before do - @create_hash = { - :author => bob.person, - :participant_ids => [bob.person.id, alice.person.id], - :subject => "cool stuff", - :messages_attributes => [ {:author => bob.person, :text => 'stuff'} ] +require "spec_helper" + +describe Message, type: :model do + let(:create_hash) { + { + author: bob.person, + participant_ids: [bob.person.id, alice.person.id], + subject: "cool stuff", + messages_attributes: [{author: bob.person, text: "stuff"}] } + } + let(:conversation) { Conversation.create!(create_hash) } + let(:message) { conversation.messages.first } - @conversation = Conversation.create!(@create_hash) - @message = @conversation.messages.first - @xml = @message.to_diaspora_xml - end - - it 'validates that the author is a participant in the conversation' do - message = Message.new(:text => 'yo', :author => eve.person, :conversation_id => @conversation.id) + it "validates that the author is a participant in the conversation" do + message = Message.new(text: "yo", author: eve.person, conversation_id: conversation.id) expect(message).not_to be_valid end - describe '#notification_type' do - it 'does not return anything for the author' do - expect(@message.notification_type(bob, bob.person)).to be_nil - end - - it 'returns private mesage for an actual receiver' do - expect(@message.notification_type(alice, bob.person)).to eq(Notifications::PrivateMessage) - end - end - - describe '#before_create' do - it 'signs the message' do - expect(@message.author_signature).not_to be_blank - end - - it 'signs the message author if author of conversation' do - expect(@message.parent_author_signature).not_to be_blank - end - end - - describe 'serialization' do - it 'serializes the text' do - expect(@xml).to include(@message.text) - end + describe "#subscribers" do + let(:cnv_hash) { + { + participant_ids: [local_luke.person, local_leia.person, remote_raphael].map(&:id), + subject: "cool story, bro", + messages_attributes: [{author: remote_raphael, text: "hey"}] + } + } + let(:local_conv) { Conversation.create(cnv_hash.merge(author: local_luke.person)) } + let(:remote_conv) { Conversation.create(cnv_hash.merge(author: remote_raphael)) } - it 'serializes the author_handle' do - expect(@xml).to include(@message.author.diaspora_handle) + it "returns all participants, if the conversation and the author is local" do + message = Message.create(author: local_luke.person, text: "yo", conversation: local_conv) + expect(message.subscribers).to match_array([local_luke.person, local_leia.person, remote_raphael]) end - it 'serializes the created_at time' do - expect(@xml).to include(@message.created_at.to_s) + it "returns all participants, if the author is local and the conversation is remote" do + message = Message.create(author: local_luke.person, text: "yo", conversation: remote_conv) + expect(message.subscribers).to match_array([local_luke.person, local_leia.person, remote_raphael]) end - it 'serializes the conversation_guid time' do - expect(@xml).to include(@message.conversation.guid) + it "returns only remote participants, if the conversation is local, but the author is remote" do + message = Message.create(author: remote_raphael, text: "yo", conversation: local_conv) + expect(message.subscribers).to match_array([remote_raphael]) end end - describe 'it is relayable' do - before do - @local_luke, @local_leia, @remote_raphael = set_up_friends - - cnv_hash = { - :author => @remote_raphael, - :participant_ids => [@local_luke.person, @local_leia.person, @remote_raphael].map(&:id), - :subject => 'cool story, bro', - :messages_attributes => [ {:author => @remote_raphael, :text => 'hey'} ] - } - - @remote_parent = Conversation.create(cnv_hash.dup) - - cnv_hash[:author] = @local_luke.person - @local_parent = Conversation.create(cnv_hash) - - msg_hash = {:author => @local_luke.person, :text => 'yo', :conversation => @local_parent} - @object_by_parent_author = Message.create(msg_hash.dup) - Postzord::Dispatcher.build(@local_luke, @object_by_parent_author).post - - msg_hash[:author] = @local_leia.person - @object_by_recipient = Message.create(msg_hash.dup) - - @dup_object_by_parent_author = @object_by_parent_author.dup - - msg_hash[:author] = @local_luke.person - msg_hash[:conversation] = @remote_parent - @object_on_remote_parent = Message.create(msg_hash) - Postzord::Dispatcher.build(@local_luke, @object_on_remote_parent).post - end - - let(:build_object) { Message.new(:author => @alice.person, :text => "ohai!", :conversation => @conversation) } - it_should_behave_like 'it is relayable' - - describe '#increase_unread' do - it 'increments the conversation visiblity for the conversation' do - expect(ConversationVisibility.where(:conversation_id => @object_by_recipient.reload.conversation.id, - :person_id => @local_luke.person.id).first.unread).to eq(0) + describe "#increase_unread" do + it "increments the conversation visibility for the conversation" do + conf = ConversationVisibility.find_by(conversation_id: conversation.id, person_id: alice.person.id) + expect(conf.unread).to eq(0) - @object_by_recipient.increase_unread(@local_luke) - expect(ConversationVisibility.where(:conversation_id => @object_by_recipient.reload.conversation.id, - :person_id => @local_luke.person.id).first.unread).to eq(1) - end + message.increase_unread(alice) + expect(conf.reload.unread).to eq(1) end end end diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 34317494bee8f44b369f17098dbf55a83ee1d10b..6008ac5f595b678de1c0eb01e0b44920a61fab47 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -54,87 +54,33 @@ describe Notification, :type => :model do end end + describe ".concatenate_or_create" do + it "creates a new notification if the notification does not exist" do + Notification.concatenate_or_create(alice, @sm, eve.person) + notification = Notification.find_by(recipient: alice, target: @sm) + expect(notification.actors).to eq([eve.person]) + end - describe '.concatenate_or_create' do - it 'creates a new notificiation if the notification does not exist, or if it is unread' do + it "creates a new notification if the notification is unread" do @note.unread = false @note.save expect(Notification.count).to eq(1) - Notification.concatenate_or_create(@note.recipient, @note.target, @note.actors.first, Notifications::CommentOnPost) + Notification.concatenate_or_create(@note.recipient, @note.target, eve.person) expect(Notification.count).to eq(2) end - end - describe '.notify' do - context 'with a request' do - before do - @request = Request.diaspora_initialize(:from => @user.person, :to => @user2.person, :into => @aspect) - end - - it 'calls Notification.create if the object has a notification_type' do - expect(Notification).to receive(:make_notification).once - Notification.notify(@user, @request, @person) - end - - it "does nothing if told to notify oneself" do - notification = Notification.notify(@user, @request, @user.person) - expect(notification).to eq(nil) - end - - describe '#emails_the_user' do - it 'calls mail' do - opts = { - :actors => [@person], - :recipient_id => @user.id} - - n = Notifications::StartedSharing.new(opts) - allow(n).to receive(:recipient).and_return @user - expect(@user).to receive(:mail) - n.email_the_user(@request, @person) - end - end - - context 'multiple likes' do - it 'concatinates the like notifications' do - p = FactoryGirl.build(:status_message, :author => @user.person) - person2 = FactoryGirl.build(:person) - notification = Notification.notify(@user, FactoryGirl.build(:like, :author => @person, :target => p), @person) - earlier_updated_at = notification.updated_at - notification2 = Notification.notify(@user, FactoryGirl.build(:like, :author => person2, :target => p), person2) - expect(notification.id).to eq(notification2.id) - expect(earlier_updated_at).to_not eq(notification.reload.updated_at) - end - end - - context 'multiple comments' do - it 'concatinates the comment notifications' do - p = FactoryGirl.build(:status_message, :author => @user.person) - person2 = FactoryGirl.build(:person) - notification = Notification.notify(@user, FactoryGirl.build(:comment, :author => @person, :post => p), @person) - earlier_updated_at = notification.updated_at - notification2 = Notification.notify(@user, FactoryGirl.build(:comment, :author => person2, :post => p), person2) - expect(notification.id).to eq(notification2.id) - expect(earlier_updated_at).to_not eq(notification.reload.updated_at) - end - end - - context 'multiple people' do - before do - @user3 = bob - @sm = @user3.post(:status_message, :text => "comment!", :to => :all) - Postzord::Receiver::Private.new(@user3, :person => @user2.person, :object => @user2.comment!(@sm, "hey")).receive_object - Postzord::Receiver::Private.new(@user3, :person => @user.person, :object => @user.comment!(@sm, "hey")).receive_object - end - - it "updates the notification with a more people if one already exists" do - expect(Notification.where(:recipient_id => @user3.id, :target_type => @sm.class.base_class, :target_id => @sm.id).first.actors.count).to eq(2) - end + it "appends the actors to the already existing notification" do + notification = Notification.create_notification(alice, @sm, @person) + expect { + Notification.concatenate_or_create(alice, @sm, eve.person) + }.to change(notification.actors, :count).by(1) + end - it 'handles double comments from the same person without raising' do - Postzord::Receiver::Private.new(@user3, :person => @user2.person, :object => @user2.comment!(@sm, "hey")).receive_object - expect(Notification.where(:recipient_id => @user3.id, :target_type => @sm.class.base_class, :target_id => @sm.id).first.actors.count).to eq(2) - end - end + it "doesn't append the actor to an existing notification if it is already there" do + notification = Notification.create_notification(alice, @sm, @person) + expect { + Notification.concatenate_or_create(alice, @sm, @person) + }.not_to change(notification.actors, :count) end end end diff --git a/spec/models/notifications/also_commented_spec.rb b/spec/models/notifications/also_commented_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..72361bf030a0425c47fb8b9901bfa69f28c7f618 --- /dev/null +++ b/spec/models/notifications/also_commented_spec.rb @@ -0,0 +1,67 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require "spec_helper" + +describe Notifications::AlsoCommented, type: :model do + let(:sm) { FactoryGirl.build(:status_message, author: alice.person, public: true) } + let(:comment) { FactoryGirl.create(:comment, commentable: sm) } + let(:notification) { Notifications::AlsoCommented.new(recipient: bob) } + + describe ".notify" do + it "does not notify the commentable author" do + expect(Notifications::AlsoCommented).not_to receive(:concatenate_or_create) + + Notifications::AlsoCommented.notify(comment, []) + end + + it "notifies a local participant" do + bob.participate!(sm) + + expect(Notifications::AlsoCommented).to receive(:concatenate_or_create).with( + bob, sm, comment.author + ).and_return(notification) + expect(bob).to receive(:mail).with(Workers::Mail::AlsoCommented, bob.id, comment.author.id, comment.id) + + Notifications::AlsoCommented.notify(comment, []) + end + + it "does not notify the a remote participant" do + FactoryGirl.create(:participation, target: sm) + + expect(Notifications::AlsoCommented).not_to receive(:concatenate_or_create) + + Notifications::AlsoCommented.notify(comment, []) + end + + it "does not notify the author of the comment" do + bob.participate!(sm) + comment = FactoryGirl.create(:comment, commentable: sm, author: bob.person) + + expect(Notifications::AlsoCommented).not_to receive(:concatenate_or_create) + + Notifications::AlsoCommented.notify(comment, []) + end + + it "does not notify if the commentable is hidden" do + bob.participate!(sm) + bob.add_hidden_shareable(sm.class.base_class.to_s, sm.id.to_s) + + expect(Notifications::AlsoCommented).not_to receive(:concatenate_or_create) + + Notifications::AlsoCommented.notify(comment, []) + end + + it "does not notify if the author of the comment is ignored" do + bob.participate!(sm) + bob.blocks.create(person: comment.author) + + expect_any_instance_of(Notifications::AlsoCommented).not_to receive(:email_the_user) + + Notifications::AlsoCommented.notify(comment, []) + + expect(Notifications::AlsoCommented.where(target: sm)).not_to exist + end + end +end diff --git a/spec/models/notifications/mentioned_spec.rb b/spec/models/notifications/mentioned_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..cb63bb9ffb77b36fcb4e8921aab369a29e8097ce --- /dev/null +++ b/spec/models/notifications/mentioned_spec.rb @@ -0,0 +1,72 @@ +require "spec_helper" + +describe Notifications::Mentioned, type: :model do + let(:sm) { + FactoryGirl.create(:status_message, author: alice.person, text: "hi @{bob; #{bob.diaspora_handle}}", public: true) + } + let(:mentioned_notification) { Notifications::Mentioned.new(recipient: bob) } + + describe ".notify" do + it "calls create_notification with mention" do + expect(Notifications::Mentioned).to receive(:create_notification).with( + bob, sm.mentions.first, sm.author + ).and_return(mentioned_notification) + + Notifications::Mentioned.notify(sm, []) + end + + it "sends an email to the mentioned person" do + allow(Notifications::Mentioned).to receive(:create_notification).and_return(mentioned_notification) + expect(bob).to receive(:mail).with(Workers::Mail::Mentioned, bob.id, sm.author.id, sm.mentions.first.id) + + Notifications::Mentioned.notify(sm, []) + end + + it "does nothing if the mentioned person is not local" do + sm = FactoryGirl.create( + :status_message, + author: alice.person, + text: "hi @{raphael; #{remote_raphael.diaspora_handle}}", + public: true + ) + expect(Notifications::Mentioned).not_to receive(:create_notification) + + Notifications::Mentioned.notify(sm, []) + end + + it "does not notify if the author of the post is ignored" do + bob.blocks.create(person: sm.author) + + expect_any_instance_of(Notifications::Mentioned).not_to receive(:email_the_user) + + Notifications::Mentioned.notify(sm, []) + + expect(Notifications::Mentioned.where(target: sm.mentions.first)).not_to exist + end + + context "with private post" do + let(:private_sm) { + FactoryGirl.create( + :status_message, + author: remote_raphael, + text: "hi @{bob; #{bob.diaspora_handle}}", + public: false + ) + } + + it "calls create_notification if the mentioned person is a recipient of the post" do + expect(Notifications::Mentioned).to receive(:create_notification).with( + bob, private_sm.mentions.first, private_sm.author + ).and_return(mentioned_notification) + + Notifications::Mentioned.notify(private_sm, [bob.id]) + end + + it "does not call create_notification if the mentioned person is not a recipient of the post" do + expect(Notifications::Mentioned).not_to receive(:create_notification) + + Notifications::Mentioned.notify(private_sm, [alice.id]) + end + end + end +end diff --git a/spec/models/notifications/private_message_spec.rb b/spec/models/notifications/private_message_spec.rb index 60c62b8aa05e9b22fcf5a33fd3fc19b3cc0cb592..07916220cd4135080bf4bf84669d1f9ab6fee834 100644 --- a/spec/models/notifications/private_message_spec.rb +++ b/spec/models/notifications/private_message_spec.rb @@ -2,69 +2,64 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' +require "spec_helper" -describe Notifications::PrivateMessage, :type => :model do - before do - @user1 = alice - @user2 = bob +describe Notifications::PrivateMessage, type: :model do + let(:conversation) { + conv_guid = FactoryGirl.generate(:guid) - @create_hash = { - :author => @user1.person, - :participant_ids => [@user1.contacts.first.person.id, @user1.person.id], - :subject => 'cool stuff', - :messages_attributes => [ {:author => @user1.person, :text => 'stuff'} ] - } + Conversation.create( + guid: conv_guid, + author: alice.person, + participant_ids: [alice.person.id, bob.person.id], + subject: "cool stuff", + messages_attributes: [{author: alice.person, text: "stuff", conversation_guid: conv_guid}] + ) + } + let(:msg) { conversation.messages.first } - @cnv = Conversation.create(@create_hash) - @msg = @cnv.messages.first + describe ".notify" do + it "does not save the notification" do + expect { + Notifications::PrivateMessage.notify(msg, [alice.id]) + }.not_to change(Notification, :count) end - describe '#make_notifiaction' do - it 'does not save the notification' do - expect{ - Notification.notify(@user2, @msg, @user1.person) - }.not_to change(Notification, :count) + it "does email the user when receiving a conversation" do + expect(Notifications::PrivateMessage).to receive(:new).and_wrap_original do |m, *args| + expect(args.first[:recipient].id).to eq(bob.id) + m.call(recipient: bob) end + expect(bob).to receive(:mail).with(Workers::Mail::PrivateMessage, bob.id, alice.person.id, msg.id) - it 'does email the user' do - opts = { - :actors => [@user1.person], - :recipient_id => @user2.id} - - n = Notifications::PrivateMessage.new(opts) - allow(Notifications::PrivateMessage).to receive(:make_notification).and_return(n) - Notification.notify(@user2, @msg, @user1.person) - allow(n).to receive(:recipient).and_return @user2 + Notifications::PrivateMessage.notify(conversation, [bob.id]) + end - expect(@user2).to receive(:mail) - n.email_the_user(@msg, @user1.person) - end - - it 'increases user unread count - author user 1' do - message = @cnv.messages.build( - :text => "foo bar", - :author => @user1.person - ) - message.save - n = Notifications::PrivateMessage.make_notification(@user2, message, @user1.person, Notifications::PrivateMessage) - - expect(ConversationVisibility.where(:conversation_id => message.reload.conversation.id, - :person_id => @user2.person.id).first.unread).to eq(1) + it "does email the user when receiving a message" do + expect(Notifications::PrivateMessage).to receive(:new).and_wrap_original do |m, *args| + expect(args.first[:recipient].id).to eq(bob.id) + m.call(recipient: bob) end - - it 'increases user unread count - author user 2' do - message = @cnv.messages.build( - :text => "foo bar", - :author => @user2.person - ) - message.save - n = Notifications::PrivateMessage.make_notification(@user1, message, @user2.person, Notifications::PrivateMessage) - - expect(ConversationVisibility.where(:conversation_id => message.reload.conversation.id, - :person_id => @user1.person.id).first.unread).to eq(1) - end - + expect(bob).to receive(:mail).with(Workers::Mail::PrivateMessage, bob.id, alice.person.id, msg.id) + + Notifications::PrivateMessage.notify(msg, [bob.id]) + end + + it "increases user unread count" do + Notifications::PrivateMessage.notify(msg, [bob.id]) + + expect(ConversationVisibility.where(conversation_id: conversation.id, + person_id: bob.person.id).first.unread).to eq(1) + end + + it "increases user unread count on response" do + message = conversation.messages.build(text: "foo bar", author: bob.person) + message.save + + Notifications::PrivateMessage.notify(message, [alice.id]) + + expect(ConversationVisibility.where(conversation_id: conversation.id, + person_id: alice.person.id).first.unread).to eq(1) end + end end - diff --git a/spec/models/notifications/reshared_spec.rb b/spec/models/notifications/reshared_spec.rb index 58836069c6284d3528b87473a6131e277b7df40d..203ed5230b2ea27f9f884c7ac9ec939f2d9206a9 100644 --- a/spec/models/notifications/reshared_spec.rb +++ b/spec/models/notifications/reshared_spec.rb @@ -2,42 +2,51 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' +require "spec_helper" -describe Notifications::Reshared, :type => :model do - before do - @sm = FactoryGirl.build(:status_message, :author => alice.person, :public => true) - @reshare1 = FactoryGirl.build(:reshare, :root => @sm) - @reshare2 = FactoryGirl.build(:reshare, :root => @sm) - end +describe Notifications::Reshared, type: :model do + let(:sm) { FactoryGirl.build(:status_message, author: alice.person, public: true) } + let(:reshare) { FactoryGirl.build(:reshare, root: sm) } + let(:reshared_notification) { Notifications::Reshared.new(recipient: alice) } - describe 'Notification.notify' do - it 'calls concatenate_or_create with root post' do - expect(Notifications::Reshared).to receive(:concatenate_or_create).with(alice, @reshare1.root, @reshare1.author, Notifications::Reshared) + describe ".notify" do + it "calls concatenate_or_create with root post" do + expect(Notifications::Reshared).to receive(:concatenate_or_create).with( + alice, reshare.root, reshare.author + ).and_return(reshared_notification) - Notification.notify(alice, @reshare1, @reshare1.author) + Notifications::Reshared.notify(reshare, []) end - end - describe '#mail_job' do - it "does not raise" do - expect{ - Notifications::Reshared.new.mail_job - }.not_to raise_error + it "sends an email to the root author" do + allow(Notifications::Reshared).to receive(:concatenate_or_create).and_return(reshared_notification) + expect(alice).to receive(:mail).with(Workers::Mail::Reshared, alice.id, reshare.author.id, reshare.id) + + Notifications::Reshared.notify(reshare, []) end - end - describe '#concatenate_or_create' do - it 'creates a new notification if one does not already exist' do - expect(Notifications::Reshared).to receive(:make_notification).with(alice, @reshare1.root, @reshare1.author, Notifications::Reshared) - Notifications::Reshared.concatenate_or_create(alice, @reshare1.root, @reshare1.author, Notifications::Reshared) + it "does nothing if the root was deleted" do + reshare.root = nil + expect(Notifications::Reshared).not_to receive(:concatenate_or_create) + + Notifications::Reshared.notify(reshare, []) end - it "appends the actors to the aldeady existing notification" do - note = Notifications::Reshared.make_notification(alice, @reshare1.root, @reshare1.author, Notifications::Reshared) - expect{ - Notifications::Reshared.concatenate_or_create(alice, @reshare2.root, @reshare2.author, Notifications::Reshared) - }.to change(note.actors, :count).by(1) + it "does nothing if the root author is not local" do + sm.author = remote_raphael + expect(Notifications::Reshared).not_to receive(:concatenate_or_create) + + Notifications::Reshared.notify(reshare, []) + end + + it "does not notify if the author of the reshare is ignored" do + alice.blocks.create(person: reshare.author) + + expect_any_instance_of(Notifications::Reshared).not_to receive(:email_the_user) + + Notifications::Reshared.notify(reshare, []) + + expect(Notifications::Reshared.where(target: sm)).not_to exist end end end diff --git a/spec/models/notifications/started_sharing_spec.rb b/spec/models/notifications/started_sharing_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..29fb2d4e7cfa8b6f2cefddd7f0948089faa5b36c --- /dev/null +++ b/spec/models/notifications/started_sharing_spec.rb @@ -0,0 +1,33 @@ +require "spec_helper" + +describe Notifications::StartedSharing, type: :model do + let(:contact) { alice.contact_for(bob.person) } + let(:started_sharing_notification) { Notifications::StartedSharing.new(recipient: alice) } + + describe ".notify" do + it "calls create_notification with sender" do + expect(Notifications::StartedSharing).to receive(:create_notification).with( + alice, bob.person, bob.person + ).and_return(started_sharing_notification) + + Notifications::StartedSharing.notify(contact, []) + end + + it "sends an email to the contacted user" do + allow(Notifications::StartedSharing).to receive(:create_notification).and_return(started_sharing_notification) + expect(alice).to receive(:mail).with(Workers::Mail::StartedSharing, alice.id, bob.person.id, bob.person.id) + + Notifications::StartedSharing.notify(contact, []) + end + + it "does not notify if the sender of the contact is ignored" do + alice.blocks.create(person: contact.person) + + expect_any_instance_of(Notifications::StartedSharing).not_to receive(:email_the_user) + + Notifications::StartedSharing.notify(contact, []) + + expect(Notifications::StartedSharing.where(target: bob.person)).not_to exist + end + end +end diff --git a/spec/models/participation_spec.rb b/spec/models/participation_spec.rb index 658c0cc8ef8447e420d3e1e092617c2b79c6fe40..806c7e6819ae91298f29af3be0b4ade2d7836edf 100644 --- a/spec/models/participation_spec.rb +++ b/spec/models/participation_spec.rb @@ -1,23 +1,46 @@ require "spec_helper" -describe Participation, :type => :model do - describe 'it is relayable' do - before do - @status = bob.post(:status_message, :text => "hello", :to => bob.aspects.first.id) +describe Participation, type: :model do + let(:status) { bob.post(:status_message, text: "hello", to: bob.aspects.first.id) } - @local_luke, @local_leia, @remote_raphael = set_up_friends - @remote_parent = FactoryGirl.create(:status_message, :author => @remote_raphael) - @local_parent = @local_luke.post :status_message, :text => "foobar", :to => @local_luke.aspects.first + describe "#subscribers" do + it "returns the parent author on local parent" do + local_parent = local_luke.post(:status_message, text: "hi", to: local_luke.aspects.first) + participation = local_luke.participate!(local_parent) + expect(participation.subscribers).to match_array([local_luke.person]) + end - @object_by_parent_author = @local_luke.participate!(@local_parent) - @object_by_recipient = @local_leia.participate!(@local_parent) - @dup_object_by_parent_author = @object_by_parent_author.dup + it "returns the parent author on remote parent" do + remote_parent = FactoryGirl.create(:status_message, author: remote_raphael) + participation = local_luke.participate!(remote_parent) + expect(participation.subscribers).to match_array([remote_raphael]) + end + end - @object_on_remote_parent = @local_luke.participate!(@remote_parent) + describe "#unparticipate" do + before do + @like = alice.like!(status) end - let(:build_object) { Participation::Generator.new(alice, @status).build } + it "retract participation" do + @like.author.participations.first.unparticipate! + participations = Participation.where(target_id: @like.target_id, author_id: @like.author_id) + expect(participations.count).to eq(0) + end + + it "retract one of multiple participations" do + comment = alice.comment!(status, "bro") + comment.author.participations.first.unparticipate! + participations = Participation.where(target_id: @like.target_id, author_id: @like.author_id) + expect(participations.count).to eq(1) + expect(participations.first.count).to eq(1) + end - it_should_behave_like 'it is relayable' + it "retract all of multiple participations" do + alice.comment!(status, "bro") + alice.participations.first.unparticipate! + alice.participations.first.unparticipate! + expect(Participation.where(target_id: @like.target_id, author_id: @like.author_id).count).to eq(0) + end end end diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index b060569035eae14e515d598523a4aaaad7b1dc4a..a941d5e0be306df11cb58671d3331f0436a09e6f 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -109,7 +109,7 @@ describe Person, :type => :model do describe "valid url" do context "https urls" do - let(:person) { FactoryGirl.build(:person, url: "https://example.com") } + let(:person) { FactoryGirl.build(:person, pod: Pod.find_or_create_by(url: "https://example.com")) } it "should add trailing slash" do expect(person.url).to eq("https://example.com/") @@ -129,7 +129,9 @@ describe Person, :type => :model do end context "messed up urls" do - let(:person) { FactoryGirl.build(:person, url: "https://example.com/a/bit/messed/up") } + let(:person) { + FactoryGirl.build(:person, pod: Pod.find_or_create_by(url: "https://example.com/a/bit/messed/up")) + } it "should return the correct url" do expect(person.url).to eq("https://example.com/") @@ -149,12 +151,12 @@ describe Person, :type => :model do end it "should allow ports in the url" do - person = FactoryGirl.build(:person, url: "https://example.com:3000/") + person = FactoryGirl.build(:person, pod: Pod.find_or_create_by(url: "https://example.com:3000/")) expect(person.url).to eq("https://example.com:3000/") end it "should remove https port in the url" do - person = FactoryGirl.build(:person, url: "https://example.com:443/") + person = FactoryGirl.build(:person, pod: Pod.find_or_create_by(url: "https://example.com:443/")) expect(person.url).to eq("https://example.com/") end end @@ -238,21 +240,6 @@ describe Person, :type => :model do end end - describe 'XML' do - before do - @xml = @person.to_xml.to_s - end - - it 'should serialize to xml' do - expect(@xml.include?("person")).to eq(true) - end - - it 'should have a profile in its xml' do - expect(@xml.include?("first_name")).to eq(true) - - end - end - it '#owns? posts' do person_message = FactoryGirl.create(:status_message, :author => @person) person_two = FactoryGirl.create(:person) @@ -307,10 +294,11 @@ describe Person, :type => :model do user_profile.last_name = "asdji" user_profile.save - @robert_grimm = FactoryGirl.build(:searchable_person) - @eugene_weinstein = FactoryGirl.build(:searchable_person) - @yevgeniy_dodis = FactoryGirl.build(:searchable_person) - @casey_grippi = FactoryGirl.build(:searchable_person) + @robert_grimm = FactoryGirl.build(:person) + @eugene_weinstein = FactoryGirl.build(:person) + @yevgeniy_dodis = FactoryGirl.build(:person) + @casey_grippi = FactoryGirl.build(:person) + @invisible_person = FactoryGirl.build(:person) @robert_grimm.profile.first_name = "Robert" @robert_grimm.profile.last_name = "Grimm" @@ -331,7 +319,14 @@ describe Person, :type => :model do @casey_grippi.profile.last_name = "Grippi" @casey_grippi.profile.save @casey_grippi.reload + + @invisible_person.profile.first_name = "Johnson" + @invisible_person.profile.last_name = "Invisible" + @invisible_person.profile.searchable = false + @invisible_person.profile.save + @invisible_person.reload end + it 'orders results by last name' do @robert_grimm.profile.first_name = "AAA" @robert_grimm.profile.save! @@ -380,10 +375,15 @@ describe Person, :type => :model do expect(people.first).to eq(@casey_grippi) end - it 'only displays searchable people' do - invisible_person = FactoryGirl.build(:person, :profile => FactoryGirl.build(:profile, :searchable => false, :first_name => "johnson")) - expect(Person.search("johnson", @user)).not_to include invisible_person - expect(Person.search("", @user)).not_to include invisible_person + it "doesn't display people that are neither searchable nor contacts" do + expect(Person.search("Johnson", @user)).to be_empty + end + + it "displays contacts that are not searchable" do + @user.contacts.create(person: @invisible_person, aspects: [@user.aspects.first]) + people = Person.search("Johnson", @user) + expect(people.count).to eq(1) + expect(people.first).to eq(@invisible_person) end it 'returns results for Diaspora handles' do @@ -409,6 +409,65 @@ describe Person, :type => :model do people = Person.search("AAA", @user) expect(people.map { |p| p.name }).to eq([@casey_grippi, @yevgeniy_dodis, @robert_grimm, @eugene_weinstein].map { |p| p.name }) end + + context "only contacts" do + before do + @robert_contact = @user.contacts.create(person: @robert_grimm, aspects: [@user.aspects.first]) + @eugene_contact = @user.contacts.create(person: @eugene_weinstein, aspects: [@user.aspects.first]) + @invisible_contact = @user.contacts.create(person: @invisible_person, aspects: [@user.aspects.first]) + end + + it "orders results by last name" do + @robert_grimm.profile.first_name = "AAA" + @robert_grimm.profile.save! + + @eugene_weinstein.profile.first_name = "AAA" + @eugene_weinstein.profile.save! + + @casey_grippi.profile.first_name = "AAA" + @casey_grippi.profile.save! + + people = Person.search("AAA", @user, only_contacts: true) + expect(people.map(&:name)).to eq([@robert_grimm, @eugene_weinstein].map(&:name)) + end + + it "returns nothing on an empty query" do + people = Person.search("", @user, only_contacts: true) + expect(people).to be_empty + end + + it "returns nothing on a one-character query" do + people = Person.search("i", @user, only_contacts: true) + expect(people).to be_empty + end + + it "returns results for partial names" do + people = Person.search("Eug", @user, only_contacts: true) + expect(people.count).to eq(1) + expect(people.first).to eq(@eugene_weinstein) + + people = Person.search("wEi", @user, only_contacts: true) + expect(people.count).to eq(1) + expect(people.first).to eq(@eugene_weinstein) + + @user.contacts.create(person: @casey_grippi, aspects: [@user.aspects.first]) + people = Person.search("gri", @user, only_contacts: true) + expect(people.count).to eq(2) + expect(people.first).to eq(@robert_grimm) + expect(people.second).to eq(@casey_grippi) + end + + it "returns results for full names" do + people = Person.search("Robert Grimm", @user, only_contacts: true) + expect(people.count).to eq(1) + expect(people.first).to eq(@robert_grimm) + end + + it "returns results for Diaspora handles" do + people = Person.search(@robert_grimm.diaspora_handle, @user, only_contacts: true) + expect(people).to eq([@robert_grimm]) + end + end end context 'people finders for webfinger' do @@ -443,55 +502,17 @@ describe Person, :type => :model do expect(person).to eq(user1.person) end - it 'should only find people who are exact matches (1/2)' do - user = FactoryGirl.create(:user, :username => "SaMaNtHa") - person = FactoryGirl.create(:person, :diaspora_handle => "tomtom@tom.joindiaspora.com") - user.person.diaspora_handle = "tom@tom.joindiaspora.com" - user.person.save - expect(Person.by_account_identifier("tom@tom.joindiaspora.com").diaspora_handle).to eq("tom@tom.joindiaspora.com") + it "should only find people who are exact matches (1/2)" do + FactoryGirl.create(:person, diaspora_handle: "tomtom@tom.joindiaspora.com") + FactoryGirl.create(:person, diaspora_handle: "tom@tom.joindiaspora.com") + expect(Person.by_account_identifier("tom@tom.joindiaspora.com").diaspora_handle) + .to eq("tom@tom.joindiaspora.com") end - it 'should only find people who are exact matches (2/2)' do - person = FactoryGirl.create(:person, :diaspora_handle => "tomtom@tom.joindiaspora.com") - person1 = FactoryGirl.create(:person, :diaspora_handle => "tom@tom.joindiaspora.comm") - f = Person.by_account_identifier("tom@tom.joindiaspora.com") - expect(f).to be nil - end - end - - describe ".find_local_by_diaspora_handle" do - it "should find local users person" do - person = Person.find_local_by_diaspora_handle(user.diaspora_handle) - expect(person).to eq(user.person) - end - - it "should not find a remote person" do - person = Person.find_local_by_diaspora_handle(@person.diaspora_handle) - expect(person).to be nil - end - - it "should not find a person with closed account" do - user.person.lock_access! - person = Person.find_local_by_diaspora_handle(user.diaspora_handle) - expect(person).to be nil - end - end - - describe ".find_local_by_guid" do - it "should find local users person" do - person = Person.find_local_by_guid(user.guid) - expect(person).to eq(user.person) - end - - it "should not find a remote person" do - person = Person.find_local_by_guid(@person.guid) - expect(person).to be nil - end - - it "should not find a person with closed account" do - user.person.lock_access! - person = Person.find_local_by_guid(user.guid) - expect(person).to be nil + it "should only find people who are exact matches (2/2)" do + FactoryGirl.create(:person, diaspora_handle: "tomtom@tom.joindiaspora.com") + FactoryGirl.create(:person, diaspora_handle: "tom@tom.joindiaspora.comm") + expect(Person.by_account_identifier("tom@tom.joindiaspora.com")).to be_nil end end end @@ -538,32 +559,6 @@ describe Person, :type => :model do end end - context 'updating urls' do - before do - @url = "http://new-url.com/" - end - - describe '.url_batch_update' do - it "calls #update_person_url given an array of users and a url" do - people = [double.as_null_object, double.as_null_object, double.as_null_object] - people.each do |person| - expect(person).to receive(:update_url).with(@url) - end - Person.url_batch_update(people, @url) - end - end - - describe '#update_url' do - it "updates a given person's url" do - expect { - alice.person.update_url(@url) - }.to change { - alice.person.reload.url - }.from(anything).to(@url) - end - end - end - describe '#lock_access!' do it 'sets the closed_account flag' do @person.lock_access! @@ -581,4 +576,14 @@ describe Person, :type => :model do @person.clear_profile! end end + + context "validation" do + it "validates that no other person with same guid exists" do + person = FactoryGirl.build(:person) + person.guid = alice.guid + + expect(person.valid?).to be_falsey + expect(person.errors.full_messages).to include("Person with same GUID already exists: #{alice.diaspora_handle}") + end + end end diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index 863864c2edb52ff2d702dd731754f8932797879d..e6b9a169bffcaafbe11665422b0361b59ce4d63c 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -34,10 +34,6 @@ describe Photo, :type => :model do end end - it 'is mutable' do - expect(@photo.mutable?).to eq(true) - end - it 'has a random string key' do expect(@photo2.random_string).not_to be nil end @@ -189,53 +185,23 @@ describe Photo, :type => :model do end - describe 'serialization' do - before do - @saved_photo = with_carrierwave_processing do - @user.build_post(:photo, :user_file => File.open(@fixture_name), :to => @aspect.id) - end - @xml = @saved_photo.to_xml.to_s - end - - it 'serializes the url' do - expect(@xml.include?(@saved_photo.remote_photo_path)).to be true - expect(@xml.include?(@saved_photo.remote_photo_name)).to be true - end - - it 'serializes the diaspora_handle' do - expect(@xml.include?(@user.diaspora_handle)).to be true - end - - it 'serializes the height and width' do - expect(@xml).to include 'height' - expect(@xml.include?('width')).to be true - expect(@xml.include?('40')).to be true - end - end - - describe 'remote photos' do - before do - Workers::ProcessPhoto.new.perform(@saved_photo.id) - end - - it 'should set the remote_photo on marshalling' do - user2 = FactoryGirl.create(:user) - aspect2 = user2.aspects.create(:name => "foobars") - connect_users(@user, @aspect, user2, aspect2) - + describe "remote photos" do + it "should set the remote_photo on marshalling" do url = @saved_photo.url thumb_url = @saved_photo.url :thumb_medium - xml = @saved_photo.to_diaspora_xml + @saved_photo.height = 42 + @saved_photo.width = 23 + + federation_photo = Diaspora::Federation::Entities.photo(@saved_photo) @saved_photo.destroy - zord = Postzord::Receiver::Private.new(user2, :person => @photo.author) - zord.parse_and_receive(xml) - new_photo = Photo.where(:guid => @saved_photo.guid).first - expect(new_photo.url.nil?).to be false - expect(new_photo.url.include?(url)).to be true - expect(new_photo.url(:thumb_medium).include?(thumb_url)).to be true + Diaspora::Federation::Receive.photo(federation_photo) + + new_photo = Photo.find_by(guid: @saved_photo.guid) + expect(new_photo.url).to eq(url) + expect(new_photo.url(:thumb_medium)).to eq(thumb_url) end end @@ -284,27 +250,17 @@ describe Photo, :type => :model do end end - describe "#receive_public" do - it "updates the photo if it is already persisted" do - allow(@photo).to receive(:persisted_shareable).and_return(@photo2) - expect(@photo2).to receive(:update_attributes) - @photo.receive_public - end - - it "does not update the photo if the author mismatches" do - @photo.author = bob.person - allow(@photo).to receive(:persisted_shareable).and_return(@photo2) - expect(@photo).not_to receive(:update_existing_sharable) - @photo.receive_public - end - end - describe "#visible" do context "with a current user" do it "calls photos_from" do expect(@user).to receive(:photos_from).with(@user.person, limit: :all, max_time: nil).and_call_original Photo.visible(@user, @user.person) end + + it "does not contain pending photos" do + pending_photo = @user.post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: @aspect) + expect(Photo.visible(@user, @user.person).ids).not_to include(pending_photo.id) + end end context "without a current user" do diff --git a/spec/models/pod_spec.rb b/spec/models/pod_spec.rb index 7aee2dfa2efa8e3e81926f4f7bbae6dc7dd73bde..1624b562b6969aff37af82ab251b4e4cdce5c7fb 100644 --- a/spec/models/pod_spec.rb +++ b/spec/models/pod_spec.rb @@ -1,15 +1,174 @@ -require 'spec_helper' +require "spec_helper" -describe Pod, :type => :model do - describe '.find_or_create_by' do - it 'takes a url, and makes one by host' do - pod = Pod.find_or_create_by(url: 'https://joindiaspora.com/maxwell') - expect(pod.host).to eq('joindiaspora.com') +describe Pod, type: :model do + describe ".find_or_create_by" do + it "takes a url, and makes one by host" do + pod = Pod.find_or_create_by(url: "https://example.org/u/maxwell") + expect(pod.host).to eq("example.org") end - it 'sets ssl boolean(side-effect)' do - pod = Pod.find_or_create_by(url: 'https://joindiaspora.com/maxwell') + it "saves the port" do + pod = Pod.find_or_create_by(url: "https://example.org:3000/") + expect(pod.host).to eq("example.org") + expect(pod.port).to eq(3000) + end + + it "ignores default ports" do + pod = Pod.find_or_create_by(url: "https://example.org:443/") + expect(pod.host).to eq("example.org") + expect(pod.port).to be_nil + end + + it "sets ssl boolean" do + pod = Pod.find_or_create_by(url: "https://example.org/") + expect(pod.ssl).to be true + end + + it "updates ssl boolean if upgraded to https" do + pod = Pod.find_or_create_by(url: "http://example.org/") + expect(pod.ssl).to be false + pod = Pod.find_or_create_by(url: "https://example.org/") expect(pod.ssl).to be true end + + it "does not update ssl boolean if downgraded to http" do + pod = Pod.find_or_create_by(url: "https://example.org/") + expect(pod.ssl).to be true + pod = Pod.find_or_create_by(url: "http://example.org/") + expect(pod.ssl).to be true + end + + context "validation" do + it "is valid" do + pod = Pod.find_or_create_by(url: "https://example.org/") + expect(pod).to be_valid + end + + it "doesn't allow own pod" do + pod = Pod.find_or_create_by(url: AppConfig.url_to("/")) + expect(pod).not_to be_valid + end + + it "doesn't allow own pod with default port" do + uri = URI.parse("https://example.org/") + allow(AppConfig).to receive(:pod_uri).and_return(uri) + + pod = Pod.find_or_create_by(url: AppConfig.url_to("/")) + expect(pod).not_to be_valid + end + + it "doesn't allow own pod with other scheme" do + uri = URI.parse("https://example.org/") + allow(AppConfig).to receive(:pod_uri).and_return(uri) + + pod = Pod.find_or_create_by(url: "http://example.org/") + expect(pod).not_to be_valid + end + end + end + + describe ".check_all!" do + before do + @pods = (0..4).map do + double("pod").tap do |pod| + expect(pod).to receive(:test_connection!) + end + end + allow(Pod).to receive(:find_in_batches).and_yield(@pods) + end + + it "calls #test_connection! on every pod" do + Pod.check_all! + end + end + + describe "#test_connection!" do + before do + @pod = FactoryGirl.create(:pod) + @result = double("result") + + allow(@result).to receive(:rt) { 123 } + allow(@result).to receive(:software_version) { "diaspora a.b.c.d" } + allow(@result).to receive(:failure_message) { "hello error!" } + + expect(ConnectionTester).to receive(:check).at_least(:once).and_return(@result) + end + + it "updates the connectivity values" do + allow(@result).to receive(:error) + allow(@result).to receive(:error?) + @pod.test_connection! + + expect(@pod.status).to eq("no_errors") + expect(@pod.offline?).to be_falsy + expect(@pod.response_time).to eq(123) + expect(@pod.checked_at).to be_within(1.second).of Time.zone.now + end + + it "handles a failed check" do + expect(@result).to receive(:error?).at_least(:once) { true } + expect(@result).to receive(:error).at_least(:once) { ConnectionTester::NetFailure.new } + @pod.test_connection! + + expect(@pod.offline?).to be_truthy + expect(@pod.offline_since).to be_within(1.second).of Time.zone.now + end + + it "preserves the original offline timestamp" do + expect(@result).to receive(:error?).at_least(:once) { true } + expect(@result).to receive(:error).at_least(:once) { ConnectionTester::NetFailure.new } + @pod.test_connection! + + now = Time.zone.now + expect(@pod.offline_since).to be_within(1.second).of now + + Timecop.travel(Time.zone.today + 30.days) do + @pod.test_connection! + expect(@pod.offline_since).to be_within(1.second).of now + expect(Time.zone.now).to be_within(1.day).of(now + 30.days) + end + end + end + + describe "#url_to" do + it "appends the path to the pod-url" do + pod = FactoryGirl.create(:pod) + expect(pod.url_to("/receive/public")).to eq("https://#{pod.host}/receive/public") + end + end + + describe "#update_offline_since" do + let(:pod) { FactoryGirl.create(:pod) } + + it "handles a successful status" do + pod.status = :no_errors + pod.update_offline_since + + expect(pod.offline?).to be_falsey + expect(pod.offline_since).to be_nil + end + + it "handles a failed status" do + pod.status = :unknown_error + pod.update_offline_since + + expect(pod.offline?).to be_truthy + expect(pod.offline_since).to be_within(1.second).of Time.zone.now + end + + it "preserves the original offline timestamp" do + pod.status = :unknown_error + pod.update_offline_since + pod.save + + now = Time.zone.now + expect(pod.offline_since).to be_within(1.second).of now + + Timecop.travel(Time.zone.today + 30.days) do + pod.update_offline_since + expect(pod.offline_since).to be_within(1.second).of now + expect(Time.zone.now).to be_within(1.day).of(now + 30.days) + end + end end end diff --git a/spec/models/poll_participation_signature_spec.rb b/spec/models/poll_participation_signature_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..6427d40fbaea01db94be92c432a20ba6e1250134 --- /dev/null +++ b/spec/models/poll_participation_signature_spec.rb @@ -0,0 +1,11 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require "spec_helper" + +describe PollParticipationSignature, type: :model do + it_behaves_like "signature data" do + let(:relayable_type) { :poll_participation } + end +end diff --git a/spec/models/poll_participation_spec.rb b/spec/models/poll_participation_spec.rb index d56d25e27a2b1d032024990547f1d4cd94f6ccf5..7d79a09a51239586ef81f3a59c2c9d965a31788e 100644 --- a/spec/models/poll_participation_spec.rb +++ b/spec/models/poll_participation_spec.rb @@ -1,7 +1,6 @@ -require 'spec_helper' -require Rails.root.join("spec", "shared_behaviors", "relayable") +require "spec_helper" -describe PollParticipation, :type => :model do +describe PollParticipation, type: :model do before do @alices_aspect = alice.aspects.first @status = bob.post(:status_message, :text => "hello", :to => bob.aspects.first.id) @@ -17,7 +16,7 @@ describe PollParticipation, :type => :model do 2.times do |run| bob.participate_in_poll!(@status, @poll.poll_answers.first) end - }.to raise_error + }.to raise_error ActiveRecord::RecordInvalid end it 'allows a one time participation in a poll' do @@ -25,103 +24,22 @@ describe PollParticipation, :type => :model do bob.participate_in_poll!(@status, @poll.poll_answers.first) }.to_not raise_error end - end - describe 'xml' do - before do - @poll_participant = FactoryGirl.create(:user) - @poll_participant_aspect = @poll_participant.aspects.create(:name => "bruisers") - connect_users(alice, @alices_aspect, @poll_participant, @poll_participant_aspect) - @poll = Poll.new(:question => "hi") - @poll.poll_answers.build(:answer => "a") - @poll.poll_answers.build(:answer => "b") - @post = alice.post :status_message, :text => "hello", :to => @alices_aspect.id - @post.poll = @poll - @poll_participation = @poll_participant.participate_in_poll!(@post, @poll.poll_answers.first) - @xml = @poll_participation.to_xml.to_s - end - - it 'serializes the class name' do - expect(@xml.include?(PollParticipation.name.underscore.to_s)).to be true - end - - it 'serializes the sender handle' do - expect(@xml.include?(@poll_participation.diaspora_handle)).to be true - end - - it 'serializes the poll_guid' do - expect(@xml).to include(@poll.guid) - end - - it 'serializes the poll_answer_guid' do - expect(@xml).to include(@poll_participation.poll_answer.guid) - end - - describe 'marshalling' do - before do - @marshalled_poll_participation = PollParticipation.from_xml(@xml) - end - - it 'marshals the author' do - expect(@marshalled_poll_participation.author).to eq(@poll_participant.person) - end - - it 'marshals the answer' do - expect(@marshalled_poll_participation.poll_answer).to eq(@poll_participation.poll_answer) + it_behaves_like "it is relayable" do + let(:remote_parent) { FactoryGirl.create(:status_message_with_poll, author: remote_raphael) } + let(:local_parent) { + FactoryGirl.create(:status_message_with_poll, author: local_luke.person).tap do |status_message| + local_luke.add_to_streams(status_message, [local_luke.aspects.first]) end - - it 'marshals the poll' do - expect(@marshalled_poll_participation.poll).to eq(@poll) - end - end - end - - describe 'federation' do - before do - #Alice is on pod A and another person is on pod B. Alice posts a poll and participates in the poll. - @poll_participant = FactoryGirl.create(:user) - @poll_participant_aspect = @poll_participant.aspects.create(:name => "bruisers") - connect_users(alice, @alices_aspect, @poll_participant, @poll_participant_aspect) - @poll = Poll.new(:question => "hi") - @poll.poll_answers.build(:answer => "a") - @poll.poll_answers.build(:answer => "b") - @post = alice.post :status_message, :text => "hello", :to => @alices_aspect.id - @post.poll = @poll - @poll_participation_alice = alice.participate_in_poll!(@post, @poll.poll_answers.first) - end - - it 'is saved without errors in a simulated A-B node environment' do - #stubs needed because the poll participation is already saved in the test db. This is just a simulated federation! - allow_any_instance_of(PollParticipation).to receive(:save!).and_return(true) - allow_any_instance_of(Person).to receive(:local?).and_return(false) - expect{ - salmon = Salmon::Slap.create_by_user_and_activity(alice, @poll_participation_alice.to_diaspora_xml).xml_for(@poll_participant) - parsed_salmon = Salmon::Slap.from_xml(salmon) - Postzord::Receiver::Public.new(salmon).parse_and_receive(parsed_salmon.parsed_data) - }.to_not raise_error - end - end - - describe 'it is relayable' do - before do - @local_luke, @local_leia, @remote_raphael = set_up_friends - @remote_parent = FactoryGirl.build(:status_message_with_poll, :author => @remote_raphael) - - @local_parent = @local_luke.post :status_message, :text => "hi", :to => @local_luke.aspects.first - @poll2 = Poll.new(:question => 'Who is now in charge?') - @poll2.poll_answers.build(:answer => "a") - @poll2.poll_answers.build(:answer => "b") - @local_parent.poll = @poll2 - - @object_by_parent_author = @local_luke.participate_in_poll!(@local_parent, @poll2.poll_answers.first) - @object_by_recipient = @local_leia.participate_in_poll!(@local_parent, @poll2.poll_answers.first) - @dup_object_by_parent_author = @object_by_parent_author.dup - - @object_on_remote_parent = @local_luke.participate_in_poll!(@remote_parent, @remote_parent.poll.poll_answers.first) - end - - let(:build_object) { PollParticipation::Generator.new(alice, @status, @poll.poll_answers.first).build } - it_should_behave_like 'it is relayable' + } + let(:object_on_local_parent) { local_luke.participate_in_poll!(local_parent, local_parent.poll.poll_answers.first) } + let(:object_on_remote_parent) { + local_luke.participate_in_poll!(remote_parent, remote_parent.poll.poll_answers.first) + } + let(:remote_object_on_local_parent) { + FactoryGirl.create(:poll_participation, poll_answer: local_parent.poll.poll_answers.first, author: remote_raphael) + } + let(:relayable) { PollParticipation::Generator.new(alice, @status, @poll.poll_answers.first).build } end end diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index d35d4d19ff434d2fad641dfa6d36600baa2e2e08..afd1546940a5f179024562f18df837d99f951677 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -5,11 +5,6 @@ require 'spec_helper' describe Post, :type => :model do - before do - @user = alice - @aspect = @user.aspects.create(:name => "winners") - end - describe 'scopes' do describe '.owned_or_visible_by_user' do before do @@ -47,6 +42,21 @@ describe Post, :type => :model do end end + describe ".all_public" do + it "includes all public posts" do + post1 = FactoryGirl.create(:status_message, author: alice.person, public: true) + post2 = FactoryGirl.create(:status_message, author: bob.person, public: true) + post3 = FactoryGirl.create(:status_message, author: eve.person, public: true) + expect(Post.all_public.ids).to match_array([post1.id, post2.id, post3.id]) + end + + it "doesn't include any private posts" do + FactoryGirl.create(:status_message, author: alice.person, public: false) + FactoryGirl.create(:status_message, author: bob.person, public: false) + FactoryGirl.create(:status_message, author: eve.person, public: false) + expect(Post.all_public.ids).to eq([]) + end + end describe '.for_a_stream' do it 'calls #for_visible_shareable_sql' do @@ -148,6 +158,22 @@ describe Post, :type => :model do Post.for_visible_shareable_sql(Time.now + 1, "created_at") end + context "with two posts with the same timestamp" do + before do + aspect_id = alice.aspects.where(name: "generic").first.id + Timecop.freeze Time.now do + alice.post(:status_message, text: "first", to: aspect_id) + alice.post(:status_message, text: "second", to: aspect_id) + end + end + + it "returns them in reverse creation order" do + posts = Post.for_visible_shareable_sql(Time.now + 1, "created_at") + expect(posts.first.text).to eq("second") + expect(posts.at(1).text).to eq("first") + expect(posts.last.text).to eq("alice - 5") + end + end end end end @@ -168,24 +194,14 @@ describe Post, :type => :model do describe 'deletion' do it 'should delete a posts comments on delete' do - post = FactoryGirl.create(:status_message, :author => @user.person) - @user.comment!(post, "hey") + post = FactoryGirl.create(:status_message, author: alice.person) + alice.comment!(post, "hey") post.destroy expect(Post.where(:id => post.id).empty?).to eq(true) expect(Comment.where(:text => "hey").empty?).to eq(true) end end - describe 'serialization' do - it 'should serialize the handle and not the sender' do - post = @user.post :status_message, :text => "hello", :to => @aspect.id - xml = post.to_diaspora_xml - - expect(xml.include?("person_id")).to be false - expect(xml.include?(@user.person.diaspora_handle)).to be true - end - end - describe '.diaspora_initialize' do it 'takes provider_display_name' do sm = FactoryGirl.create(:status_message, :provider_display_name => 'mobile') @@ -193,168 +209,98 @@ describe Post, :type => :model do end end - describe '#mutable?' do - it 'should be false by default' do - post = @user.post :status_message, :text => "hello", :to => @aspect.id - expect(post.mutable?).to eq(false) - end - end - - describe '#subscribers' do - it 'returns the people contained in the aspects the post appears in' do - post = @user.post :status_message, :text => "hello", :to => @aspect.id - - expect(post.subscribers(@user)).to eq([]) - end - - it 'returns all a users contacts if the post is public' do - post = @user.post :status_message, :text => "hello", :to => @aspect.id, :public => true - - expect(post.subscribers(@user).to_set).to eq(@user.contact_people.to_set) - end - end + describe "#subscribers" do + let(:user) { FactoryGirl.create(:user_with_aspect) } - describe 'Likeable#update_likes_counter' do before do - @post = bob.post :status_message, :text => "hello", :to => 'all' - bob.like!(@post) - end - it 'does not update updated_at' do - old_time = Time.zone.now - 10000 - Post.where(:id => @post.id).update_all(:updated_at => old_time) - expect(@post.reload.updated_at.to_i).to eq(old_time.to_i) - @post.update_likes_counter - expect(@post.reload.updated_at.to_i).to eq(old_time.to_i) + user.share_with(alice.person, user.aspects.first) end - end - describe "#receive" do - it "does not receive if the post does not verify" do - @post = FactoryGirl.create(:status_message, author: bob.person) - @known_post = FactoryGirl.create(:status_message, author: eve.person) - allow(@post).to receive(:persisted_shareable).and_return(@known_post) - expect(@post).not_to receive(:receive_persisted) - @post.receive(bob, eve.person) - end - - it "receives an update if the post is known" do - @post = FactoryGirl.create(:status_message, author: bob.person) - expect(@post).to receive(:receive_persisted) - @post.receive(bob, eve.person) - end + context "private" do + it "returns the people contained in the aspects the post appears in" do + post = user.post(:status_message, text: "hello", to: user.aspects.first.id) - it "receives a new post if the post is unknown" do - @post = FactoryGirl.create(:status_message, author: bob.person) - allow(@post).to receive(:persisted_shareable).and_return(nil) - expect(@post).to receive(:receive_non_persisted) - @post.receive(bob, eve.person) - end - end - - describe "#receive_persisted" do - before do - @post = FactoryGirl.create(:status_message, author: bob.person) - @known_post = Post.new - allow(bob).to receive(:contact_for).with(eve.person).and_return(double(receive_shareable: true)) - end - - context "user knows about the post" do - before do - allow(bob).to receive(:find_visible_shareable_by_id).and_return(@known_post) + expect(post.subscribers).to eq([alice.person]) end - it "updates attributes only if mutable" do - allow(@known_post).to receive(:mutable?).and_return(true) - expect(@known_post).to receive(:update_attributes) - expect(@post.send(:receive_persisted, bob, eve.person, @known_post)).to eq(true) - end + it "returns empty if posted to an empty aspect" do + empty_aspect = user.aspects.create(name: "empty") + + post = user.post(:status_message, text: "hello", to: empty_aspect.id) - it "does not update attributes if trying to update a non-mutable object" do - allow(@known_post).to receive(:mutable?).and_return(false) - expect(@known_post).not_to receive(:update_attributes) - @post.send(:receive_persisted, bob, eve.person, @known_post) + expect(post.subscribers).to eq([]) end end - context "the user does not know about the post" do - before do - allow(bob).to receive(:find_visible_shareable_by_id).and_return(nil) - allow(bob).to receive(:notify_if_mentioned).and_return(true) - end + context "public" do + let(:post) { user.post(:status_message, text: "hello", public: true) } - it "receives the post from the contact of the author" do - expect(@post.send(:receive_persisted, bob, eve.person, @known_post)).to eq(true) + it "returns the author to ensure local delivery" do + lonely_user = FactoryGirl.create(:user) + lonely_post = lonely_user.post(:status_message, text: "anyone?", public: true) + expect(lonely_post.subscribers).to match_array([lonely_user.person]) end - it "notifies the user if they are mentioned" do - allow(bob).to receive(:contact_for).with(eve.person).and_return(double(receive_shareable: true)) - expect(bob).to receive(:notify_if_mentioned).and_return(true) + it "returns all a users contacts if the post is public" do + second_aspect = user.aspects.create(name: "winners") + user.share_with(bob.person, second_aspect) - expect(@post.send(:receive_persisted, bob, eve.person, @known_post)).to eq(true) + expect(post.subscribers).to match_array([alice.person, bob.person, user.person]) end - end - end - describe "#receive_non_persisted" do - context "the user does not know about the post" do - before do - @post = FactoryGirl.create(:status_message, author: bob.person) - allow(bob).to receive(:find_visible_shareable_by_id).and_return(nil) - allow(bob).to receive(:notify_if_mentioned).and_return(true) - end + it "adds resharers to subscribers" do + FactoryGirl.create(:reshare, root: post, author: eve.person) - it "it receives the post from the contact of the author" do - expect(bob).to receive(:contact_for).with(eve.person).and_return(double(receive_shareable: true)) - expect(@post.send(:receive_non_persisted, bob, eve.person)).to eq(true) + expect(post.subscribers).to match_array([alice.person, eve.person, user.person]) end - it "notifies the user if they are mentioned" do - allow(bob).to receive(:contact_for).with(eve.person).and_return(double(receive_shareable: true)) - expect(bob).to receive(:notify_if_mentioned).and_return(true) - - expect(@post.send(:receive_non_persisted, bob, eve.person)).to eq(true) - end + it "adds participants to subscribers" do + eve.participate!(post) - it "does not create shareable visibility if the post does not save" do - allow(@post).to receive(:save).and_return(false) - expect(@post).not_to receive(:receive_shareable_visibility) - @post.send(:receive_non_persisted, bob, eve.person) + expect(post.subscribers).to match_array([alice.person, eve.person, user.person]) end + end + end - it "retries if saving fails with RecordNotUnique error" do - allow(@post).to receive(:save).and_raise(ActiveRecord::RecordNotUnique.new("Duplicate entry ...")) - expect(bob).to receive(:contact_for).with(eve.person).and_return(double(receive_shareable: true)) - expect(@post.send(:receive_non_persisted, bob, eve.person)).to eq(true) - end + describe "Likeable#update_likes_counter" do + before do + @post = bob.post(:status_message, text: "hello", public: true) + bob.like!(@post) + end - it "retries if saving fails with RecordNotUnique error and raise again if no persisted shareable found" do - allow(@post).to receive(:save).and_raise(ActiveRecord::RecordNotUnique.new("Duplicate entry ...")) - allow(@post).to receive(:persisted_shareable).and_return(nil) - expect(bob).not_to receive(:contact_for).with(eve.person) - expect { @post.send(:receive_non_persisted, bob, eve.person) }.to raise_error(ActiveRecord::RecordNotUnique) - end + it "does not update updated_at" do + old_time = Time.zone.now - 100 + Post.where(id: @post.id).update_all(updated_at: old_time) + expect(@post.reload.updated_at.to_i).to eq(old_time.to_i) + @post.update_likes_counter + expect(@post.reload.updated_at.to_i).to eq(old_time.to_i) end end - describe "#receive_public" do - it "saves the post if the post is unknown" do - @post = FactoryGirl.create(:status_message, author: bob.person) - allow(@post).to receive(:persisted_shareable).and_return(nil) - expect(@post).to receive(:save!) - @post.receive_public + describe "#receive" do + it "creates a share visibility for the user" do + user_ids = [alice.id, eve.id] + post = FactoryGirl.create(:status_message, author: bob.person) + expect(ShareVisibility).to receive(:batch_import).with(user_ids, post) + post.receive(user_ids) end - it "does not update the post because not mutable" do - @post = FactoryGirl.create(:status_message, author: bob.person) - expect(@post).to receive(:update_existing_sharable).and_call_original - expect(@post).not_to receive(:update_attributes) - @post.receive_public + it "does nothing for public post" do + post = FactoryGirl.create(:status_message, author: bob.person, public: true) + expect(ShareVisibility).not_to receive(:batch_import) + post.receive([alice.id]) + end + + it "does nothing if no recipients provided" do + post = FactoryGirl.create(:status_message, author: bob.person) + expect(ShareVisibility).not_to receive(:batch_import) + post.receive([]) end end describe '#reshares_count' do before :each do - @post = @user.post :status_message, :text => "hello", :to => @aspect.id, :public => true + @post = alice.post(:status_message, text: "hello", public: true) expect(@post.reshares.size).to eq(0) end @@ -399,56 +345,4 @@ describe Post, :type => :model do expect(post.interacted_at).not_to be_blank end end - - describe "#find_public" do - it "succeeds with an id" do - post = FactoryGirl.create :status_message, public: true - expect(Post.find_public post.id).to eq(post) - end - - it "succeeds with an guid" do - post = FactoryGirl.create :status_message, public: true - expect(Post.find_public post.guid).to eq(post) - end - - it "raises ActiveRecord::RecordNotFound for a non-existing id without a user" do - allow(Post).to receive_messages where: double(includes: double(first: nil)) - expect { - Post.find_public 123 - }.to raise_error ActiveRecord::RecordNotFound - end - - it "raises Diaspora::NonPublic for a private post without a user" do - post = FactoryGirl.create :status_message - expect { - Post.find_public post.id - }.to raise_error Diaspora::NonPublic - end - end - - describe "#find_non_public_by_guid_or_id_with_user" do - it "succeeds with an id" do - post = FactoryGirl.create :status_message_in_aspect - expect(Post.find_non_public_by_guid_or_id_with_user(post.id, post.author.owner)).to eq(post) - end - - it "succeeds with an guid" do - post = FactoryGirl.create :status_message_in_aspect - expect(Post.find_non_public_by_guid_or_id_with_user(post.guid, post.author.owner)).to eq(post) - end - - it "looks up on the passed user object if it's non-nil" do - post = FactoryGirl.create :status_message - user = double - expect(user).to receive(:find_visible_shareable_by_id).with(Post, post.id, key: :id).and_return(post) - Post.find_non_public_by_guid_or_id_with_user(post.id, user) - end - - it "raises ActiveRecord::RecordNotFound with a non-existing id and a user" do - user = double(find_visible_shareable_by_id: nil) - expect { - Post.find_non_public_by_guid_or_id_with_user(123, user) - }.to raise_error ActiveRecord::RecordNotFound - end - end end diff --git a/spec/models/profile_spec.rb b/spec/models/profile_spec.rb index d1087a6e8e6da9db7742d610f230e9a9f9f4f30e..f29d8da26e8be52b2ada2ddb87b4c264a181e6cf 100644 --- a/spec/models/profile_spec.rb +++ b/spec/models/profile_spec.rb @@ -161,42 +161,6 @@ describe Profile, :type => :model do end end - describe '#from_xml' do - it 'should make a valid profile object' do - @profile = FactoryGirl.build(:profile) - @profile.tag_string = '#big #rafi #style' - xml = @profile.to_xml - - new_profile = Profile.from_xml(xml.to_s) - expect(new_profile.tag_string).not_to be_blank - expect(new_profile.tag_string).to include('#rafi') - end - end - - describe 'serialization' do - let(:person) {FactoryGirl.build(:person,:diaspora_handle => "foobar" )} - - it 'should include persons diaspora handle' do - xml = person.profile.to_diaspora_xml - expect(xml).to include "foobar" - end - - it 'includes tags' do - person.profile.tag_string = '#one' - person.profile.build_tags - person.profile.save - xml = person.profile.to_diaspora_xml - expect(xml).to include "#one" - end - - it 'includes location' do - person.profile.location = 'Dark Side, Moon' - person.profile.save - xml = person.profile.to_diaspora_xml - expect(xml).to include "Dark Side, Moon" - end - end - describe '#image_url' do before do @profile = FactoryGirl.build(:profile) @@ -219,7 +183,7 @@ describe Profile, :type => :model do describe '#subscribers' do it 'returns all non-pending contacts for a user' do - expect(bob.profile.subscribers(bob).map{|s| s.id}).to match_array([alice.person, eve.person].map{|s| s.id}) + expect(bob.profile.subscribers.map(&:id)).to match_array([alice.person, eve.person].map(&:id)) end end @@ -319,18 +283,6 @@ describe Profile, :type => :model do end - describe '#receive' do - it 'updates the profile in place' do - local_luke, local_leia, remote_raphael = set_up_friends - new_profile = FactoryGirl.build :profile - expect{ - new_profile.receive(local_leia, remote_raphael) - }.not_to change(Profile, :count) - expect(remote_raphael.last_name).to eq(new_profile.last_name) - end - - end - describe "#tombstone!" do before do @profile = bob.person.profile @@ -356,18 +308,19 @@ describe Profile, :type => :model do profile = FactoryGirl.build :profile expect(profile.send(:clearable_fields).sort).to eq( ["diaspora_handle", - "first_name", - "last_name", - "image_url", - "image_url_small", - "image_url_medium", - "birthday", - "gender", - "bio", - "searchable", - "nsfw", - "location", - "full_name"].sort + "first_name", + "last_name", + "image_url", + "image_url_small", + "image_url_medium", + "birthday", + "gender", + "bio", + "searchable", + "nsfw", + "location", + "public_details", + "full_name"].sort ) end end diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb index bdfc17d382b02e712b91a156e2ab5380ba9df4b4..04e4bc85a8d1dd9753bc12a5326c4392cda2942b 100644 --- a/spec/models/report_spec.rb +++ b/spec/models/report_spec.rb @@ -12,14 +12,12 @@ describe Report, :type => :model do @bob_comment = @user.comment!(@bob_post, "welcome") @valid_post_report = { - :item_id => @bob_post.id, - :item_type => 'post', - :text => 'offensive content' + item_id: @bob_post.id, item_type: "Post", + text: "offensive content" } @valid_comment_report = { - :item_id => @bob_comment.id, - :item_type => 'comment', - :text => 'offensive content' + item_id: @bob_comment.id, item_type: "Comment", + text: "offensive content" } end diff --git a/spec/models/reshare_spec.rb b/spec/models/reshare_spec.rb index 6a5f2cd451a6310482a4f199312376386fa81b6e..cc436de9aad92483880db3cdd71e8c984c766311 100644 --- a/spec/models/reshare_spec.rb +++ b/spec/models/reshare_spec.rb @@ -1,307 +1,150 @@ -require 'spec_helper' +require "spec_helper" -describe Reshare, :type => :model do - it 'has a valid Factory' do +describe Reshare, type: :model do + it "has a valid Factory" do expect(FactoryGirl.build(:reshare)).to be_valid end - it 'requires root' do - reshare = FactoryGirl.build(:reshare, :root => nil) + it "requires root" do + reshare = FactoryGirl.build(:reshare, root: nil) expect(reshare).not_to be_valid end - it 'require public root' do - reshare = FactoryGirl.build(:reshare, :root => FactoryGirl.create(:status_message, :public => false)) + it "require public root" do + reshare = FactoryGirl.build(:reshare, root: FactoryGirl.create(:status_message, public: false)) expect(reshare).not_to be_valid - expect(reshare.errors[:base]).to include('Only posts which are public may be reshared.') + expect(reshare.errors[:base]).to include("Only posts which are public may be reshared.") end - it 'forces public' do - expect(FactoryGirl.create(:reshare, :public => false).public).to be true + it "forces public" do + expect(FactoryGirl.create(:reshare, public: false).public).to be true end describe "#root_diaspora_id" do + let(:reshare) { create(:reshare, root: FactoryGirl.build(:status_message, author: bob.person, public: true)) } + it "should return the root diaspora id" do - reshare = FactoryGirl.create(:reshare, root: FactoryGirl.build(:status_message, author: bob.person, public: true)) expect(reshare.root_diaspora_id).to eq(bob.person.diaspora_handle) end it "should be nil if no root found" do - reshare = FactoryGirl.create(:reshare, root: FactoryGirl.build(:status_message, author: bob.person, public: true)) reshare.root = nil expect(reshare.root_diaspora_id).to be_nil end end describe "#receive" do - let(:receive_reshare) { @reshare.receive(@root.author.owner, @reshare.author) } - - before do - @reshare = FactoryGirl.create(:reshare, :root => FactoryGirl.build(:status_message, :author => bob.person, :public => true)) - @root = @reshare.root - end - - it 'increments the reshare count' do - receive_reshare - expect(@root.resharers.count).to eq(1) - end - - it 'adds the resharer to the re-sharers of the post' do - receive_reshare - expect(@root.resharers).to include(@reshare.author) - end - - it "does not error if the root author has a contact for the resharer" do - bob.share_with @reshare.author, bob.aspects.first - expect { - Timeout.timeout(5) do - receive_reshare #This doesn't ever terminate on my machine before it was fixed. - end - }.not_to raise_error - end + let(:reshare) { create(:reshare, root: FactoryGirl.build(:status_message, author: bob.person, public: true)) } it "participates root author in the reshare" do - receive_reshare - participations = Participation.where(target_id: @reshare.id, author_id: @root.author_id) - expect(participations.count).to eq(1) + reshare.receive([]) + expect(Participation.where(target_id: reshare.id, author_id: bob.person.id).count).to eq(1) end end - describe '#nsfw' do - before do - sfw = FactoryGirl.build(:status_message, :author => alice.person, :public => true) - nsfw = FactoryGirl.build(:status_message, :author => alice.person, :public => true, :text => "This is #nsfw") - @sfw_reshare = FactoryGirl.build(:reshare, :root => sfw) - @nsfw_reshare = FactoryGirl.build(:reshare, :root => nsfw) - end + describe "#nsfw" do + let(:sfw) { build(:status_message, author: alice.person, public: true) } + let(:nsfw) { build(:status_message, author: alice.person, public: true, text: "This is #nsfw") } + let(:sfw_reshare) { build(:reshare, root: sfw) } + let(:nsfw_reshare) { build(:reshare, root: nsfw) } - it 'deletates #nsfw to the root post' do - expect(@sfw_reshare.nsfw).not_to be true - expect(@nsfw_reshare.nsfw).to be_truthy + it "deletates #nsfw to the root post" do + expect(sfw_reshare.nsfw).not_to be true + expect(nsfw_reshare.nsfw).to be_truthy end end - describe '#poll' do - before do - @root_post = FactoryGirl.create(:status_message_with_poll, public: true) - @reshare = FactoryGirl.create(:reshare, root: @root_post) - end - - it 'contains root poll' do - expect(@reshare.poll).to eq @root_post.poll - end - end - - describe '#notification_type' do - before do - sm = FactoryGirl.build(:status_message, :author => alice.person, :public => true) - @reshare = FactoryGirl.build(:reshare, :root => sm) - end - it 'does not return anything for non-author of the original post' do - expect(@reshare.notification_type(bob, @reshare.author)).to be_nil - end - - it 'returns "Reshared" for the original post author' do - expect(@reshare.notification_type(alice, @reshare.author)).to eq(Notifications::Reshared) - end + describe "#poll" do + let(:root_post) { create(:status_message_with_poll, public: true) } + let(:reshare) { create(:reshare, root: root_post) } - it 'does not error out if the root was deleted' do - @reshare.root = nil - expect { - @reshare.notification_type(alice, @reshare.author) - }.to_not raise_error + it "contains root poll" do + expect(reshare.poll).to eq root_post.poll end end - describe '#absolute_root' do + describe "#absolute_root" do before do - @sm = FactoryGirl.build(:status_message, :author => alice.person, :public => true) - rs1 = FactoryGirl.build(:reshare, :root=>@sm) - rs2 = FactoryGirl.build(:reshare, :root=>rs1) - @rs3 = FactoryGirl.build(:reshare, :root=>rs2) + @status_message = FactoryGirl.build(:status_message, author: alice.person, public: true) + reshare_1 = FactoryGirl.build(:reshare, root: @status_message) + reshare_2 = FactoryGirl.build(:reshare, root: reshare_1) + @reshare_3 = FactoryGirl.build(:reshare, root: reshare_2) - sm = FactoryGirl.create(:status_message, :author => alice.person, :public => true) - rs1 = FactoryGirl.create(:reshare, :root => sm) - @of_deleted = FactoryGirl.build(:reshare, :root => rs1) - sm.destroy - rs1.reload + status_message = FactoryGirl.create(:status_message, author: alice.person, public: true) + reshare_1 = FactoryGirl.create(:reshare, root: status_message) + @of_deleted = FactoryGirl.build(:reshare, root: reshare_1) + status_message.destroy + reshare_1.reload end - it 'resolves root posts to the top level' do - expect(@rs3.absolute_root).to eq(@sm) + it "resolves root posts to the top level" do + expect(@reshare_3.absolute_root).to eq(@status_message) end - it 'can handle deleted reshares' do + it "can handle deleted reshares" do expect(@of_deleted.absolute_root).to be_nil end - it 'is used everywhere' do - expect(@rs3.message).to eq @sm.message + it "is used everywhere" do + expect(@reshare_3.message).to eq @status_message.message expect(@of_deleted.message).to be_nil - expect(@rs3.photos).to eq @sm.photos + expect(@reshare_3.photos).to eq @status_message.photos expect(@of_deleted.photos).to be_empty - expect(@rs3.o_embed_cache).to eq @sm.o_embed_cache + expect(@reshare_3.o_embed_cache).to eq @status_message.o_embed_cache expect(@of_deleted.o_embed_cache).to be_nil - expect(@rs3.open_graph_cache).to eq @sm.open_graph_cache + expect(@reshare_3.open_graph_cache).to eq @status_message.open_graph_cache expect(@of_deleted.open_graph_cache).to be_nil - expect(@rs3.mentioned_people).to eq @sm.mentioned_people + expect(@reshare_3.mentioned_people).to eq @status_message.mentioned_people expect(@of_deleted.mentioned_people).to be_empty - expect(@rs3.nsfw).to eq @sm.nsfw + expect(@reshare_3.nsfw).to eq @status_message.nsfw expect(@of_deleted.nsfw).to be_nil - expect(@rs3.address).to eq @sm.location.try(:address) + expect(@reshare_3.address).to eq @status_message.location.try(:address) expect(@of_deleted.address).to be_nil end end - describe "XML" do - before do - @reshare = FactoryGirl.build(:reshare) - @xml = @reshare.to_xml.to_s - end + describe "#post_location" do + let(:status_message) { build(:status_message, text: "This is a status_message", author: bob.person, public: true) } + let(:reshare) { create(:reshare, root: status_message) } - context 'serialization' do - it 'serializes root_diaspora_id' do - expect(@xml).to include("root_diaspora_id") - expect(@xml).to include(@reshare.author.diaspora_handle) - end + context "with location" do + let(:location) { build(:location) } - it 'serializes root_guid' do - expect(@xml).to include("root_guid") - expect(@xml).to include(@reshare.root.guid) + it "should deliver address and coordinates" do + status_message.location = location + expect(reshare.post_location).to include(address: location.address, lat: location.lat, lng: location.lng) end end - context 'marshalling' do - context 'local' do - before do - @original_author = @reshare.root.author - @root_object = @reshare.root - end - - it 'marshals the guid' do - expect(Reshare.from_xml(@xml).root_guid).to eq(@root_object.guid) - end - - it 'fetches the root post from root_guid' do - expect(Reshare.from_xml(@xml).root).to eq(@root_object) - end - - it 'fetches the root author from root_diaspora_id' do - expect(Reshare.from_xml(@xml).root.author).to eq(@original_author) - end - end - - describe 'destroy' do - it 'allows you to destroy the reshare if the root post is missing' do - reshare = FactoryGirl.build(:reshare) - reshare.root = nil - - expect{ - reshare.destroy - }.to_not raise_error - end + context "without location" do + it "should deliver empty address and coordinates" do + expect(reshare.post_location[:address]).to be_nil + expect(reshare.post_location[:lat]).to be_nil + expect(reshare.post_location[:lng]).to be_nil end + end + end - context 'remote' do - before do - @root_object = @reshare.root - @root_object.delete - @response = double - allow(@response).to receive(:status).and_return(200) - allow(@response).to receive(:success?).and_return(true) - end - - it 'fetches the root author from root_diaspora_id' do - @original_profile = @reshare.root.author.profile.dup - @reshare.root.author.profile.delete - @original_author = @reshare.root.author.dup - @reshare.root.author.delete - - @original_author.profile = @original_profile - - expect(Person).to receive(:find_or_fetch_by_identifier).and_return(@original_author) - - allow(@response).to receive(:body).and_return(@root_object.to_diaspora_xml) - - expect(Faraday.default_connection).to receive(:get).with( - URI.join( - @original_author.url, - Rails.application.routes.url_helpers.short_post_path( - @root_object.guid, - format: "xml" - ) - ) - ).and_return(@response) - Reshare.from_xml(@xml) - end - - context "fetching post" do - it "raises if the post is not found" do - allow(@response).to receive(:status).and_return(404) - expect(Faraday.default_connection).to receive(:get).and_return(@response) - - expect { - Reshare.from_xml(@xml) - }.to raise_error(Diaspora::PostNotFetchable) - end - - it "raises if there's another error receiving the post" do - allow(@response).to receive(:status).and_return(500) - allow(@response).to receive(:success?).and_return(false) - expect(Faraday.default_connection).to receive(:get).and_return(@response) - - expect { - Reshare.from_xml(@xml) - }.to raise_error RuntimeError - end - end - - context 'saving the post' do - before do - allow(@response).to receive(:body).and_return(@root_object.to_diaspora_xml) - allow(Faraday.default_connection).to receive(:get).with( - URI.join( - @reshare.root.author.url, - Rails.application.routes.url_helpers.short_post_path( - @root_object.guid, - format: "xml" - ) - ) - ).and_return(@response) - end - - it 'fetches the root post from root_guid' do - root = Reshare.from_xml(@xml).root - - [:text, :guid, :diaspora_handle, :type, :public].each do |attr| - expect(root.send(attr)).to eq(@reshare.root.send(attr)) - end - end - - it 'correctly saves the type' do - expect(Reshare.from_xml(@xml).root.reload.type).to eq("StatusMessage") - end + describe "#subscribers" do + it "adds root author to subscribers" do + user = FactoryGirl.create(:user_with_aspect) + user.share_with(alice.person, user.aspects.first) - it 'correctly sets the author' do - @original_author = @reshare.root.author - expect(Reshare.from_xml(@xml).root.reload.author.reload).to eq(@original_author) - end + post = eve.post(:status_message, text: "hello", public: true) + reshare = FactoryGirl.create(:reshare, root: post, author: user.person) - it 'verifies that the author of the post received is the same as the author in the reshare xml' do - @original_author = @reshare.root.author.dup - @xml = @reshare.to_xml.to_s + expect(reshare.subscribers).to match_array([alice.person, eve.person, user.person]) + end - different_person = FactoryGirl.build(:person) - expect(Person).to receive(:find_or_fetch_by_identifier).and_return(different_person) + it "does not add the root author if the root post was deleted" do + user = FactoryGirl.create(:user_with_aspect) + user.share_with(alice.person, user.aspects.first) - allow(different_person).to receive(:url).and_return(@original_author.url) + post = eve.post(:status_message, text: "hello", public: true) + reshare = FactoryGirl.create(:reshare, root: post, author: user.person) + post.destroy - expect{ - Reshare.from_xml(@xml) - }.to raise_error /^Diaspora ID \(.+\) in the root does not match the Diaspora ID \(.+\) specified in the reshare!$/ - end - end - end + expect(reshare.reload.subscribers).to match_array([alice.person, user.person]) end end end diff --git a/spec/models/services/facebook_spec.rb b/spec/models/services/facebook_spec.rb index 022a42e2472672a84502e6728dcbbb6127b24c7d..162e72ef0bff0b0cf67755787e672d0f8693a914 100644 --- a/spec/models/services/facebook_spec.rb +++ b/spec/models/services/facebook_spec.rb @@ -16,14 +16,6 @@ describe Services::Facebook, :type => :model do @service.post(@post) end - it 'swallows exception raised by facebook always being down' do - skip "temporarily disabled to figure out while some requests are failing" - - stub_request(:post,"https://graph.facebook.com/me/feed"). - to_raise(StandardError) - @service.post(@post) - end - it 'removes text formatting markdown from post text' do message = double(urls: []) expect(message).to receive(:plain_text_without_markdown).and_return("") @@ -78,14 +70,25 @@ describe Services::Facebook, :type => :model do end end - describe '#delete_post' do - it 'removes a post from facebook' do + describe "#post_opts" do + it "returns the facebook_id of the post" do @post.facebook_id = "2345" - url="https://graph.facebook.com/#{@post.facebook_id}/" - stub_request(:delete, "#{url}?access_token=#{@service.access_token}").to_return(:status => 200) - expect(@service).to receive(:delete_from_facebook).with(url, {access_token: @service.access_token}) + expect(@service.post_opts(@post)).to eq(facebook_id: "2345") + end + + it "returns nil when the post has no facebook_id" do + expect(@service.post_opts(@post)).to be_nil + end + end + + describe "#delete_from_service" do + it "removes a post from facebook" do + facebook_id = "2345" + url = "https://graph.facebook.com/#{facebook_id}/" + stub_request(:delete, "#{url}?access_token=#{@service.access_token}").to_return(status: 200) + expect(@service).to receive(:delete_from_facebook).with(url, access_token: @service.access_token) - @service.delete_post(@post) + @service.delete_from_service(facebook_id: facebook_id) end end end diff --git a/spec/models/services/tumblr_spec.rb b/spec/models/services/tumblr_spec.rb index ea0c7e756010843cabeebd6e97f73d0d613b704d..2a8f0d71b88ec2c1bd3586feecb72bfc720c7004 100644 --- a/spec/models/services/tumblr_spec.rb +++ b/spec/models/services/tumblr_spec.rb @@ -25,7 +25,7 @@ describe Services::Tumblr, type: :model do it "posts a status message to the primary blog and stores the id" do stub = stub_request(:post, "http://api.tumblr.com/v2/blog/bar.tumblr.com/post") - .with(post_request).to_return(post_response) + .with(post_request).to_return(post_response) expect(post).to receive(:tumblr_ids=).with({"bar.tumblr.com" => post_id}.to_json) @@ -40,7 +40,7 @@ describe Services::Tumblr, type: :model do it "posts a status message to the returned blog" do stub = stub_request(:post, "http://api.tumblr.com/v2/blog/foo.tumblr.com/post") - .with(post_request).to_return(post_response) + .with(post_request).to_return(post_response) service.post(post) @@ -49,13 +49,24 @@ describe Services::Tumblr, type: :model do end end - describe "#delete_post" do - it "removes posts from tumblr" do + describe "#post_opts" do + it "returns the tumblr_ids of the post" do post.tumblr_ids = {"foodbar.tumblr.com" => post_id}.to_json + expect(service.post_opts(post)).to eq(tumblr_ids: post.tumblr_ids) + end + + it "returns nil when the post has no tumblr_ids" do + expect(service.post_opts(post)).to be_nil + end + end + + describe "#delete_from_service" do + it "removes posts from tumblr" do + tumblr_ids = {"foodbar.tumblr.com" => post_id}.to_json stub = stub_request(:post, "http://api.tumblr.com/v2/blog/foodbar.tumblr.com/post/delete") - .with(body: {"id" => post_id}).to_return(status: 200) + .with(body: {"id" => post_id}).to_return(status: 200) - service.delete_post(post) + service.delete_from_service(tumblr_ids: tumblr_ids) expect(stub).to have_been_requested end diff --git a/spec/models/services/twitter_spec.rb b/spec/models/services/twitter_spec.rb index 982b42afa47aa821ad3aa39ac911d473ccb554e9..b2d09cae3ebdaebfe9e5d2c78869114624090b37 100644 --- a/spec/models/services/twitter_spec.rb +++ b/spec/models/services/twitter_spec.rb @@ -25,12 +25,6 @@ describe Services::Twitter, :type => :model do expect(@post.tweet_id).to match "1234" end - it 'swallows exception raised by twitter always being down' do - skip - expect_any_instance_of(Twitter::REST::Client).to receive(:update).and_raise(StandardError) - @service.post(@post) - end - it 'should call build_twitter_post' do url = "foo" expect(@service).to receive(:build_twitter_post).with(@post, 0) @@ -147,4 +141,15 @@ describe Services::Twitter, :type => :model do expect(@service.profile_photo_url).to eq("http://a2.twimg.com/profile_images/uid/avatar.png") end end + + describe "#post_opts" do + it "returns the tweet_id of the post" do + @post.tweet_id = "2345" + expect(@service.post_opts(@post)).to eq(tweet_id: "2345") + end + + it "returns nil when the post has no tweet_id" do + expect(@service.post_opts(@post)).to be_nil + end + end end diff --git a/spec/models/share_visibility_spec.rb b/spec/models/share_visibility_spec.rb index fe2674fe3a525c4dff464470ad816d0f3bbcba34..39698feabf68ed95afb9fb5cf4b948db017a5d4d 100644 --- a/spec/models/share_visibility_spec.rb +++ b/spec/models/share_visibility_spec.rb @@ -2,55 +2,45 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' +require "spec_helper" describe ShareVisibility, :type => :model do - describe '.batch_import' do - before do - @post = FactoryGirl.create(:status_message, :author => alice.person) - @contact = bob.contact_for(alice.person) - end + describe ".batch_import" do + let(:post) { FactoryGirl.create(:status_message, author: alice.person) } - it 'returns false if share is public' do - @post.public = true - @post.save - expect(ShareVisibility.batch_import([@contact.id], @post)).to be false + it "returns false if share is public" do + post.public = true + post.save + expect(ShareVisibility.batch_import([bob.id], post)).to be false end - it 'creates a visibility for each user' do + it "creates a visibility for each user" do expect { - ShareVisibility.batch_import([@contact.id], @post) + ShareVisibility.batch_import([bob.id], post) }.to change { - ShareVisibility.exists?(:contact_id => @contact.id, :shareable_id => @post.id, :shareable_type => 'Post') + ShareVisibility.exists?(user_id: bob.id, shareable_id: post.id, shareable_type: "Post") }.from(false).to(true) end - it 'does not raise if a visibility already exists' do - ShareVisibility.create!(:contact_id => @contact.id, :shareable_id => @post.id, :shareable_type => 'Post') + it "does not raise if a visibility already exists" do + ShareVisibility.create!(user_id: bob.id, shareable_id: post.id, shareable_type: "Post") expect { - ShareVisibility.batch_import([@contact.id], @post) + ShareVisibility.batch_import([bob.id], post) }.not_to raise_error end context "scopes" do - describe '.for_a_users_contacts' do - before do - alice.post(:status_message, :text => "Hey", :to => alice.aspects.first) - end + before do + alice.post(:status_message, text: "Hey", to: alice.aspects.first) - it 'searches for share visibilies for all users contacts' do - contact_ids = alice.contacts.map(&:id) - expect(ShareVisibility.for_a_users_contacts(alice)).to eq(ShareVisibility.where(:contact_id => contact_ids).to_a) - end + photo_path = File.join(File.dirname(__FILE__), "..", "fixtures", "button.png") + alice.post(:photo, user_file: File.open(photo_path), text: "Photo", to: alice.aspects.first) end - describe '.for_contacts_of_a_person' do - it 'searches for share visibilties generated by a person' do - - contact_ids = alice.person.contacts.map(&:id) - - ShareVisibility.for_contacts_of_a_person(alice.person) == ShareVisibility.where(:contact_id => contact_ids).to_a - + describe ".for_a_user" do + it "searches for share visibilies for a user" do + expect(ShareVisibility.for_a_user(bob).count).to eq(2) + expect(ShareVisibility.for_a_user(bob)).to eq(ShareVisibility.where(user_id: bob.id).to_a) end end end diff --git a/spec/models/signature_order_spec.rb b/spec/models/signature_order_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..646bbcd2e86694d8104f2abf9c83a041771dd073 --- /dev/null +++ b/spec/models/signature_order_spec.rb @@ -0,0 +1,25 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require "spec_helper" + +describe SignatureOrder, type: :model do + context "validation" do + it "requires an order" do + order = SignatureOrder.new + expect(order).not_to be_valid + + order.order = "author guid" + expect(order).to be_valid + end + + it "doesn't allow the same order twice" do + first = SignatureOrder.create!(order: "author guid") + expect(first).to be_valid + + second = SignatureOrder.new(order: first.order) + expect(second).not_to be_valid + end + end +end diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index 0f37390a4659d1abf19ec51837c55be235ec3092..31901380b05238a7b0a49c7063a8fd1500578976 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -2,56 +2,54 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' +require "spec_helper" -describe StatusMessage, :type => :model do +describe StatusMessage, type: :model do include PeopleHelper - before do - @user = alice - @aspect = @user.aspects.first - end - - describe 'scopes' do - describe '.where_person_is_mentioned' do - it 'returns status messages where the given person is mentioned' do - @bo = bob.person - @test_string = "@{Daniel; #{@bo.diaspora_handle}} can mention people like Raph" + let!(:user) { alice } + let!(:aspect) { user.aspects.first } + let(:status) { build(:status_message) } - FactoryGirl.create(:status_message, :text => @test_string ) - FactoryGirl.create(:status_message, :text => @test_string ) - FactoryGirl.create(:status_message) + describe "scopes" do + describe ".where_person_is_mentioned" do + it "returns status messages where the given person is mentioned" do + @bob = bob.person + @test_string = "@{Daniel; #{@bob.diaspora_handle}} can mention people like Raph" + FactoryGirl.create(:status_message, text: @test_string) + FactoryGirl.create(:status_message, text: @test_string) + FactoryGirl.create(:status_message) - expect(StatusMessage.where_person_is_mentioned(@bo).count).to eq(2) + expect(StatusMessage.where_person_is_mentioned(bob).count).to eq(2) end end context "tag_streams" do before do - @sm1 = FactoryGirl.create(:status_message, :text => "#hashtag" , :public => true) - @sm2 = FactoryGirl.create(:status_message, :text => "#hashtag" ) - @sm3 = FactoryGirl.create(:status_message, :text => "hashtags are #awesome", :public => true ) - @sm4 = FactoryGirl.create(:status_message, :text => "hashtags are #awesome" ) + @status_message_1 = FactoryGirl.create(:status_message, text: "#hashtag", public: true) + @status_message_2 = FactoryGirl.create(:status_message, text: "#hashtag") + @status_message_3 = FactoryGirl.create(:status_message, text: "hashtags are #awesome", public: true) + @status_message_4 = FactoryGirl.create(:status_message, text: "hashtags are #awesome") - @tag_id = ActsAsTaggableOn::Tag.where(:name => "hashtag").first.id + @tag_id = ActsAsTaggableOn::Tag.where(name: "hashtag").first.id end - describe '.tag_steam' do - it 'returns status messages tagged with the tag' do + describe ".tag_steam" do + it "returns status messages tagged with the tag" do tag_stream = StatusMessage.send(:tag_stream, [@tag_id]) - expect(tag_stream).to include @sm1 - expect(tag_stream).to include @sm2 + expect(tag_stream).to include @status_message_1 + expect(tag_stream).to include @status_message_2 end end - describe '.public_tag_stream' do - it 'returns public status messages tagged with the tag' do - expect(StatusMessage.public_tag_stream([@tag_id])).to eq([@sm1]) + describe ".public_tag_stream" do + it "returns public status messages tagged with the tag" do + expect(StatusMessage.public_tag_stream([@tag_id])).to eq([@status_message_1]) end end - describe '.user_tag_stream' do - it 'returns tag stream thats owned or visible by' do + describe ".user_tag_stream" do + it "returns tag stream thats owned or visible by" do relation = double expect(StatusMessage).to receive(:owned_or_visible_by_user).with(bob).and_return(relation) expect(relation).to receive(:tag_stream).with([@tag_id]) @@ -63,392 +61,245 @@ describe StatusMessage, :type => :model do end describe ".guids_for_author" do - it 'returns an array of the status_message guids' do - sm1 = FactoryGirl.create(:status_message, :author => alice.person) - sm2 = FactoryGirl.create(:status_message, :author => bob.person) + it "returns an array of the status_message guids" do + status_message_1 = FactoryGirl.create(:status_message, author: alice.person) + FactoryGirl.create(:status_message, author: bob.person) guids = StatusMessage.guids_for_author(alice.person) - expect(guids).to eq([sm1.guid]) + expect(guids).to eq([status_message_1.guid]) end end - describe '.before_validation' do - it 'calls build_tags' do - status = FactoryGirl.build(:status_message) + describe ".before_validation" do + it "calls build_tags" do expect(status).to receive(:build_tags) status.save end end - describe '.before_create' do - it 'calls build_tags' do - status = FactoryGirl.build(:status_message) + describe ".before_create" do + it "calls build_tags" do expect(status).to receive(:build_tags) status.save end - - it 'calls filter_mentions' do - status = FactoryGirl.build(:status_message) - expect(status).to receive(:filter_mentions) - status.save - end end - describe '.after_create' do - it 'calls create_mentions' do + describe ".after_create" do + it "calls create_mentions" do status = FactoryGirl.build(:status_message, text: "text @{Test; #{alice.diaspora_handle}}") expect(status).to receive(:create_mentions).and_call_original status.save end end - describe '#diaspora_handle=' do - it 'sets #author' do - person = FactoryGirl.create(:person) - post = FactoryGirl.build(:status_message, :author => @user.person) - post.diaspora_handle = person.diaspora_handle - expect(post.author).to eq(person) - end - end - - context "emptyness" do + context "emptiness" do it "needs either a message or at least one photo" do - n = @user.build_post(:status_message, :text => nil) - expect(n).not_to be_valid + post = user.build_post(:status_message, text: nil) + expect(post).not_to be_valid - n.text = "" - expect(n).not_to be_valid + post.text = "" + expect(post).not_to be_valid - n.text = "wales" - expect(n).to be_valid - n.text = nil + post.text = "wales" + expect(post).to be_valid + post.text = nil - photo = @user.build_post(:photo, :user_file => uploaded_photo, :to => @aspect.id) + photo = user.build_post(:photo, user_file: uploaded_photo, to: aspect.id) photo.save! - n.photos << photo - expect(n).to be_valid - expect(n.errors.full_messages).to eq([]) + post.photos << photo + expect(post).to be_valid + expect(post.message.to_s).to be_empty + expect(post.text).to be_nil + expect(post.nsfw).to be_falsey + expect(post.errors.full_messages).to eq([]) end - it "doesn't check for content when author is remote (federation...)" do - p = FactoryGirl.build(:status_message, text: nil) - expect(p).to be_valid + it "also checks for content when author is remote" do + post = FactoryGirl.build(:status_message, text: nil) + expect(post).not_to be_valid end end - it 'should be postable through the user' do + it "should be postable through the user" do message = "Users do things" - status = @user.post(:status_message, :text => message, :to => @aspect.id) + status = user.post(:status_message, text: message, to: aspect.id) db_status = StatusMessage.find(status.id) expect(db_status.text).to eq(message) end - it 'should require status messages not be more than 65535 characters long' do - message = 'a' * (65535+1) - status_message = FactoryGirl.build(:status_message, :text => message) + it "should require status messages not be more than 65535 characters long" do + message = "a" * (65_535 + 1) + status_message = FactoryGirl.build(:status_message, text: message) expect(status_message).not_to be_valid end - describe 'mentions' do - before do - @people = [alice, bob, eve].map{|u| u.person} - @test_string = <<-STR -@{Raphael; #{@people[0].diaspora_handle}} can mention people like Raphael @{Ilya; #{@people[1].diaspora_handle}} -can mention people like Raphaellike Raphael @{Daniel; #{@people[2].diaspora_handle}} can mention people like Raph -STR - @sm = FactoryGirl.create(:status_message, :text => @test_string ) - end - - describe '#create_mentions' do - it 'creates a mention for everyone mentioned in the message' do - expect(Diaspora::Mentionable).to receive(:people_from_string).and_return(@people) - @sm.mentions.delete_all - @sm.create_mentions - expect(@sm.mentions(true).map{|m| m.person}.to_set).to eq(@people.to_set) + describe "mentions" do + let(:people) { [alice, bob, eve].map(&:person) } + let(:test_string) { + "@{Raphael; #{people[0].diaspora_handle}} can mention people like Raphael @{Ilya; #{people[1].diaspora_handle}} + can mention people like Raphaellike Raphael @{Daniel; #{people[2].diaspora_handle}} can mention people like Raph" + } + let(:status_message) { create(:status_message, text: test_string) } + + describe "#create_mentions" do + it "creates a mention for everyone mentioned in the message" do + status_message + expect(Diaspora::Mentionable).to receive(:people_from_string).and_return(people) + status_message.mentions.delete_all + status_message.create_mentions + expect(status_message.mentions(true).map(&:person).to_set).to eq(people.to_set) end - it 'does not barf if it gets called twice' do - @sm.create_mentions + it "does not barf if it gets called twice" do + status_message.create_mentions - expect{ - @sm.create_mentions + expect { + status_message.create_mentions }.to_not raise_error end end - describe '#mentioned_people' do - it 'calls create_mentions if there are no mentions in the db' do - @sm.mentions.delete_all - expect(@sm).to receive(:create_mentions) - @sm.mentioned_people + describe "#mentioned_people" do + it "does not call create_mentions if there are no mentions in the db" do + status_message.mentions.delete_all + expect(status_message).not_to receive(:create_mentions) + status_message.mentioned_people end - it 'returns the mentioned people' do - @sm.mentions.delete_all - expect(@sm.mentioned_people.to_set).to eq(@people.to_set) - end - it 'does not call create_mentions if there are mentions in the db' do - expect(@sm).not_to receive(:create_mentions) - @sm.mentioned_people - end - end - describe "#mentions?" do - it 'returns true if the person was mentioned' do - expect(@sm.mentions?(@people[0])).to be true + it "returns the mentioned people" do + expect(status_message.mentioned_people.to_set).to eq(people.to_set) end - it 'returns false if the person was not mentioned' do - expect(@sm.mentions?(FactoryGirl.build(:person))).to be false + it "does not call create_mentions if there are mentions in the db" do + expect(status_message).not_to receive(:create_mentions) + status_message.mentioned_people end end - describe "#notify_person" do - it 'notifies the person mentioned' do - expect(Notification).to receive(:notify).with(alice, anything, anything) - @sm.notify_person(alice.person) + describe "#mentions?" do + it "returns true if the person was mentioned" do + expect(status_message.mentions?(people[0])).to be true end - end - describe "#filter_mentions" do - it 'calls Diaspora::Mentionable#filter_for_aspects' do - msg = FactoryGirl.build(:status_message_in_aspect) - - msg_txt = msg.raw_message - author_usr = msg.author.owner - aspect_id = author_usr.aspects.first.id - - expect(Diaspora::Mentionable).to receive(:filter_for_aspects) - .with(msg_txt, author_usr, aspect_id) - - msg.send(:filter_mentions) - end - - it "doesn't do anything when public" do - msg = FactoryGirl.build(:status_message, public: true) - expect(Diaspora::Mentionable).not_to receive(:filter_for_aspects) - - msg.send(:filter_mentions) + it "returns false if the person was not mentioned" do + expect(status_message.mentions?(FactoryGirl.build(:person))).to be false end end end describe "#nsfw" do - it 'returns MatchObject (true) if the post contains #nsfw (however capitalised)' do - status = FactoryGirl.build(:status_message, :text => "This message is #nSFw") + it "returns MatchObject (true) if the post contains #nsfw (however capitalised)" do + status = FactoryGirl.build(:status_message, text: "This message is #nSFw") expect(status.nsfw).to be_truthy end - it 'returns nil (false) if the post does not contain #nsfw' do - status = FactoryGirl.build(:status_message, :text => "This message is #sFW") + it "returns nil (false) if the post does not contain #nsfw" do + status = FactoryGirl.build(:status_message, text: "This message is #sFW") expect(status.nsfw).to be false end end - describe 'tags' do + describe "tags" do before do @object = FactoryGirl.build(:status_message) end - it_should_behave_like 'it is taggable' + it_should_behave_like "it is taggable" - it 'associates different-case tags to the same tag entry' do + it "associates different-case tags to the same tag entry" do assert_equal ActsAsTaggableOn.force_lowercase, true - msg_lc = FactoryGirl.build(:status_message, :text => '#newhere') - msg_uc = FactoryGirl.build(:status_message, :text => '#NewHere') - msg_cp = FactoryGirl.build(:status_message, :text => '#NEWHERE') + msg_lc = FactoryGirl.build(:status_message, text: "#newhere") + msg_uc = FactoryGirl.build(:status_message, text: "#NewHere") + msg_cp = FactoryGirl.build(:status_message, text: "#NEWHERE") - msg_lc.save; msg_uc.save; msg_cp.save + msg_lc.save + msg_uc.save + msg_cp.save tag_array = msg_lc.tags expect(msg_uc.tags).to match_array(tag_array) expect(msg_cp.tags).to match_array(tag_array) end - it 'should require tag name not be more than 255 characters long' do - message = "##{'a' * (255+1)}" - status_message = FactoryGirl.build(:status_message, :text => message) + it "should require tag name not be more than 255 characters long" do + message = "##{'a' * (255 + 1)}" + status_message = FactoryGirl.build(:status_message, text: message) expect(status_message).not_to be_valid end end - describe "XML" do - let(:message) { FactoryGirl.build(:status_message, text: "I hate WALRUSES!", author: @user.person) } - let(:xml) { message.to_xml.to_s } - let(:marshalled) { StatusMessage.from_xml(xml) } - - it 'serializes the escaped, unprocessed message' do - text = "[url](http://example.org)<script> alert('xss should be federated');</script>" - message.text = text - expect(xml).to include Builder::XChar.encode(text) - end - - it 'serializes the message' do - expect(xml).to include "<raw_message>I hate WALRUSES!</raw_message>" - end + describe "oembed" do + let(:youtube_url) { "https://www.youtube.com/watch?v=3PtFwlKfvHI" } + let(:message_text) { "#{youtube_url} is so cool. so is this link -> https://joindiaspora.com" } + let(:status_message) { FactoryGirl.build(:status_message, text: message_text) } - it 'serializes the author address' do - expect(xml).to include(@user.person.diaspora_handle) + it "should queue a GatherOembedData if it includes a link" do + status_message + expect(Workers::GatherOEmbedData).to receive(:perform_async).with(instance_of(Fixnum), instance_of(String)) + status_message.save end - describe '.from_xml' do - it 'marshals the message' do - expect(marshalled.text).to eq("I hate WALRUSES!") - end - - it 'marshals the guid' do - expect(marshalled.guid).to eq(message.guid) - end - - it 'marshals the author' do - expect(marshalled.author).to eq(message.author) - end - - it 'marshals the diaspora_handle' do - expect(marshalled.diaspora_handle).to eq(message.diaspora_handle) - end - end - - context 'with some photos' do - before do - message.photos << FactoryGirl.build(:photo) - message.photos << FactoryGirl.build(:photo) - end - - it 'serializes the photos' do - expect(xml).to include "photo" - expect(xml).to include message.photos.first.remote_photo_path - end - - describe '.from_xml' do - it 'marshals the photos' do - expect(marshalled.photos.size).to eq(2) - end - - it 'handles existing photos' do - message.photos.each(&:save!) - expect(marshalled).to be_valid - end + describe "#contains_oembed_url_in_text?" do + it "returns the oembed urls found in the raw message" do + expect(status_message.contains_oembed_url_in_text?).not_to be_nil + expect(status_message.oembed_url).to eq(youtube_url) end end + end - context 'with a location' do - before do - message.location = FactoryGirl.build(:location) - end + describe "opengraph" do + let(:ninegag_url) { "http://9gag.com/gag/a1AMW16" } + let(:youtube_url) { "https://www.youtube.com/watch?v=3PtFwlKfvHI" } + let(:message_text) { "#{ninegag_url} is so cool. so is this link -> https://joindiaspora.com" } + let(:oemessage_text) { "#{youtube_url} is so cool. so is this link -> https://joindiaspora.com" } + let(:status_message) { build(:status_message, text: message_text) } - it 'serializes the location' do - expect(xml).to include "location" - expect(xml).to include "lat" - expect(xml).to include "lng" - end - - describe ".from_xml" do - it 'marshals the location' do - expect(marshalled.location).to be_present - end - end + it "should queue a GatherOpenGraphData if it includes a link" do + status_message + expect(Workers::GatherOpenGraphData).to receive(:perform_async).with(instance_of(Fixnum), instance_of(String)) + status_message.save end - context 'with a poll' do - before do - message.poll = FactoryGirl.build(:poll) + describe "#contains_open_graph_url_in_text?" do + it "returns the opengraph urls found in the raw message" do + expect(status_message.contains_open_graph_url_in_text?).not_to be_nil + expect(status_message.open_graph_url).to eq(ninegag_url) end - - it 'serializes the poll' do - expect(xml).to include "poll" - expect(xml).to include "question" - expect(xml).to include "poll_answer" - end - - describe ".from_xml" do - it 'marshals the poll' do - expect(marshalled.poll).to be_present - end - - it 'marshals the poll answers' do - expect(marshalled.poll.poll_answers.size).to eq(2) - end + it "returns nil if the link is from trusted oembed provider" do + status_message = FactoryGirl.build(:status_message, text: oemessage_text) + expect(status_message.contains_open_graph_url_in_text?).to be_nil + expect(status_message.open_graph_url).to be_nil end end end - describe '#after_dispatch' do - before do - @photos = [alice.build_post(:photo, :pending => true, :user_file=> File.open(photo_fixture_name)), - alice.build_post(:photo, :pending => true, :user_file=> File.open(photo_fixture_name))] - - @photos.each(&:save!) - - @status_message = alice.build_post(:status_message, :text => "the best pebble.") - @status_message.photos << @photos + describe "validation" do + let(:status_message) { build(:status_message, text: @message_text) } - @status_message.save! - alice.add_to_streams(@status_message, alice.aspects) - end - it 'sets pending to false on any attached photos' do - @status_message.after_dispatch(alice) - expect(@photos.all?{|p| p.reload.pending}).to be false - end - it 'dispatches any attached photos' do - expect(alice).to receive(:dispatch_post).twice - @status_message.after_dispatch(alice) + it "should not be valid if the author is missing" do + status_message.author = nil + expect(status_message).not_to be_valid end end - describe 'oembed' do - before do - @youtube_url = "https://www.youtube.com/watch?v=3PtFwlKfvHI" - @message_text = "#{@youtube_url} is so cool. so is this link -> https://joindiaspora.com" - end + describe "#coordinates" do + let(:status_message) { build(:status_message, text: @message_text) } - it 'should queue a GatherOembedData if it includes a link' do - sm = FactoryGirl.build(:status_message, :text => @message_text) - expect(Workers::GatherOEmbedData).to receive(:perform_async).with(instance_of(Fixnum), instance_of(String)) - sm.save - end + context "with location" do + let(:location) { build(:location) } - describe '#contains_oembed_url_in_text?' do - it 'returns the oembed urls found in the raw message' do - sm = FactoryGirl.build(:status_message, :text => @message_text) - expect(sm.contains_oembed_url_in_text?).not_to be_nil - expect(sm.oembed_url).to eq(@youtube_url) + it "should deliver address and coordinates" do + status_message.location = location + expect(status_message.post_location).to include(address: location.address, lat: location.lat, lng: location.lng) end end - end - describe 'opengraph' do - before do - @ninegag_url = "http://9gag.com/gag/a1AMW16" - @youtube_url = "https://www.youtube.com/watch?v=3PtFwlKfvHI" - @message_text = "#{@ninegag_url} is so cool. so is this link -> https://joindiaspora.com" - @oemessage_text = "#{@youtube_url} is so cool. so is this link -> https://joindiaspora.com" - end - - it 'should queue a GatherOpenGraphData if it includes a link' do - sm = FactoryGirl.build(:status_message, :text => @message_text) - expect(Workers::GatherOpenGraphData).to receive(:perform_async).with(instance_of(Fixnum), instance_of(String)) - sm.save - end - - describe '#contains_open_graph_url_in_text?' do - it 'returns the opengraph urls found in the raw message' do - sm = FactoryGirl.build(:status_message, :text => @message_text) - expect(sm.contains_open_graph_url_in_text?).not_to be_nil - expect(sm.open_graph_url).to eq(@ninegag_url) - end - it 'returns nil if the link is from trusted oembed provider' do - sm = FactoryGirl.build(:status_message, :text => @oemessage_text) - expect(sm.contains_open_graph_url_in_text?).to be_nil - expect(sm.open_graph_url).to be_nil + context "without location" do + it "should deliver empty address and coordinates" do + expect(status_message.post_location[:address]).to be_nil + expect(status_message.post_location[:lat]).to be_nil + expect(status_message.post_location[:lng]).to be_nil end end end - - describe "validation" do - it "should not be valid if the author is missing" do - sm = FactoryGirl.build(:status_message, text: @message_text) - sm.author = nil - expect(sm).not_to be_valid - end - end end diff --git a/spec/models/user/connecting_spec.rb b/spec/models/user/connecting_spec.rb index 155dff64b12a0cdb617c79d457828a7d3ecfc12f..8b8262dd28aa91182659d6630fe1d75d998615e0 100644 --- a/spec/models/user/connecting_spec.rb +++ b/spec/models/user/connecting_spec.rb @@ -2,78 +2,102 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' +require "spec_helper" -describe User::Connecting, :type => :model do +describe User::Connecting, type: :model do + let(:aspect1) { alice.aspects.first } + let(:aspect2) { alice.aspects.create(name: "other") } - let(:aspect) { alice.aspects.first } - let(:aspect1) { alice.aspects.create(:name => 'other') } let(:person) { FactoryGirl.create(:person) } - let(:aspect2) { eve.aspects.create(:name => "aspect two") } + describe "disconnecting" do + describe "#disconnected_by" do + it "removes contact sharing flag" do + expect(bob.contacts.find_by(person_id: alice.person.id)).to be_sharing + bob.disconnected_by(alice.person) + expect(bob.contacts.find_by(person_id: alice.person.id)).not_to be_sharing + end - let(:person_one) { FactoryGirl.create :person } - let(:person_two) { FactoryGirl.create :person } - let(:person_three) { FactoryGirl.create :person } + it "removes contact if not receiving" do + eve.contacts.create(person: alice.person) - describe 'disconnecting' do - describe '#remove_contact' do - it 'removed non mutual contacts' do - alice.share_with(eve.person, alice.aspects.first) expect { - alice.remove_contact alice.contact_for(eve.person) - }.to change { - alice.contacts(true).count - }.by(-1) + eve.disconnected_by(alice.person) + }.to change(eve.contacts(true), :count).by(-1) end - it 'removes a contacts receiving flag' do - expect(bob.contacts.find_by_person_id(alice.person.id)).to be_receiving - bob.remove_contact(bob.contact_for(alice.person)) - expect(bob.contacts(true).find_by_person_id(alice.person.id)).not_to be_receiving - end - end + it "does not remove contact if disconnect twice" do + contact = bob.contact_for(alice.person) + expect(contact).to be_receiving - describe '#disconnected_by' do - it 'calls remove contact' do - expect(bob).to receive(:remove_contact).with(bob.contact_for(alice.person), :retracted => true) - bob.disconnected_by(alice.person) - end + expect { + bob.disconnected_by(alice.person) + bob.disconnected_by(alice.person) + }.not_to change(bob.contacts(true), :count) - it 'removes contact sharing flag' do - expect(bob.contacts.find_by_person_id(alice.person.id)).to be_sharing - bob.disconnected_by(alice.person) - expect(bob.contacts.find_by_person_id(alice.person.id)).not_to be_sharing + contact.reload + expect(contact).not_to be_sharing + expect(contact).to be_receiving end - it 'removes notitications' do + it "removes notitications" do alice.share_with(eve.person, alice.aspects.first) - expect(Notifications::StartedSharing.where(:recipient_id => eve.id).first).not_to be_nil + expect(Notifications::StartedSharing.where(recipient_id: eve.id).first).not_to be_nil eve.disconnected_by(alice.person) - expect(Notifications::StartedSharing.where(:recipient_id => eve.id).first).to be_nil + expect(Notifications::StartedSharing.where(recipient_id: eve.id).first).to be_nil end end - describe '#disconnect' do - it 'calls remove contact' do + describe "#disconnect" do + it "removes a contacts receiving flag" do + expect(bob.contacts.find_by(person_id: alice.person.id)).to be_receiving + bob.disconnect(bob.contact_for(alice.person)) + expect(bob.contacts(true).find_by(person_id: alice.person.id)).not_to be_receiving + end + + it "removes contact if not sharing" do + contact = alice.share_with(eve.person, alice.aspects.first) + + expect { + alice.disconnect(contact) + }.to change(alice.contacts(true), :count).by(-1) + end + + it "does not remove contact if disconnect twice" do contact = bob.contact_for(alice.person) + expect(contact).to be_sharing + + expect { + alice.disconnect(contact) + alice.disconnect(contact) + }.not_to change(bob.contacts(true), :count) + + contact.reload + expect(contact).not_to be_receiving + expect(contact).to be_sharing + end + + it "dispatches a retraction for local person" do + contact = bob.contact_for(eve.person) + + expect(contact.person.owner).to receive(:disconnected_by).with(bob.person) - expect(bob).to receive(:remove_contact).with(contact, {}) bob.disconnect(contact) end - it 'dispatches a retraction' do - p = double() - expect(Postzord::Dispatcher).to receive(:build).and_return(p) - expect(p).to receive(:post) + it "dispatches a retraction for remote person" do + contact = local_leia.contact_for(remote_raphael) + retraction = double - bob.disconnect bob.contact_for(eve.person) + expect(Retraction).to receive(:for).with(contact).and_return(retraction) + expect(retraction).to receive(:defer_dispatch).with(local_leia) + + local_leia.disconnect(contact) end - it 'should remove the contact from all aspects they are in' do + it "should remove the contact from all aspects they are in" do contact = alice.contact_for(bob.person) - new_aspect = alice.aspects.create(:name => 'new') - alice.add_contact_to_aspect(contact, new_aspect) + alice.add_contact_to_aspect(contact, aspect2) expect { alice.disconnect(contact) @@ -82,37 +106,27 @@ describe User::Connecting, :type => :model do end end - describe '#register_share_visibilities' do - it 'creates post visibilites for up to 100 posts' do - allow(Post).to receive_message_chain(:where, :limit).and_return([FactoryGirl.create(:status_message)]) - c = Contact.create!(:user_id => alice.id, :person_id => eve.person.id) - expect{ - alice.register_share_visibilities(c) - }.to change(ShareVisibility, :count).by(1) - end - end - - describe '#share_with' do - it 'finds or creates a contact' do + describe "#share_with" do + it "finds or creates a contact" do expect { alice.share_with(eve.person, alice.aspects.first) }.to change(alice.contacts, :count).by(1) end - it 'does not set mutual on intial share request' do + it "does not set mutual on intial share request" do alice.share_with(eve.person, alice.aspects.first) - expect(alice.contacts.find_by_person_id(eve.person.id)).not_to be_mutual + expect(alice.contacts.find_by(person_id: eve.person.id)).not_to be_mutual end - it 'does set mutual on share-back request' do + it "does set mutual on share-back request" do eve.share_with(alice.person, eve.aspects.first) alice.share_with(eve.person, alice.aspects.first) - expect(alice.contacts.find_by_person_id(eve.person.id)).to be_mutual + expect(alice.contacts.find_by(person_id: eve.person.id)).to be_mutual end - it 'adds a contact to an aspect' do - contact = alice.contacts.create(:person => eve.person) + it "adds a contact to an aspect" do + contact = alice.contacts.create(person: eve.person) allow(alice.contacts).to receive(:find_or_initialize_by).and_return(contact) expect { @@ -120,59 +134,66 @@ describe User::Connecting, :type => :model do }.to change(contact.aspects, :count).by(1) end - it 'calls #register_share_visibilities with a contact' do - expect(eve).to receive(:register_share_visibilities) - eve.share_with(alice.person, eve.aspects.first) - end + context "dispatching" do + it "dispatches a request on initial request" do + contact = alice.contacts.new(person: eve.person) + expect(alice.contacts).to receive(:find_or_initialize_by).and_return(contact) - context 'dispatching' do - it 'dispatches a request on initial request' do - contact = alice.contacts.new(:person => eve.person) - allow(alice.contacts).to receive(:find_or_initialize_by).and_return(contact) + allow(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch) + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, contact) - expect(contact).to receive(:dispatch_request) alice.share_with(eve.person, alice.aspects.first) end - it 'dispatches a request on a share-back' do + it "dispatches a request on a share-back" do eve.share_with(alice.person, eve.aspects.first) contact = alice.contact_for(eve.person) - allow(alice.contacts).to receive(:find_or_initialize_by).and_return(contact) + expect(alice.contacts).to receive(:find_or_initialize_by).and_return(contact) + + allow(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch) + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, contact) - expect(contact).to receive(:dispatch_request) alice.share_with(eve.person, alice.aspects.first) end - it 'does not dispatch a request if contact already marked as receiving' do - a2 = alice.aspects.create(:name => "two") - - contact = alice.contacts.create(:person => eve.person, :receiving => true) + it "does not dispatch a request if contact already marked as receiving" do + contact = alice.contacts.create(person: eve.person, receiving: true) allow(alice.contacts).to receive(:find_or_initialize_by).and_return(contact) - expect(contact).not_to receive(:dispatch_request) - alice.share_with(eve.person, a2) + allow(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, instance_of(Profile)) + expect(Diaspora::Federation::Dispatcher).not_to receive(:defer_dispatch).with(alice, instance_of(Contact)) + + alice.share_with(eve.person, aspect2) end - it 'posts profile' do - m = double() - expect(Postzord::Dispatcher).to receive(:build).twice.and_return(m) - expect(m).to receive(:post).twice + it "delivers profile for remote persons" do + allow(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch) + expect(Diaspora::Federation::Dispatcher) + .to receive(:defer_dispatch).with(alice, alice.profile, subscriber_ids: [remote_raphael.id]) + + alice.share_with(remote_raphael, alice.aspects.first) + end + + it "does not deliver profile for remote persons" do + allow(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch) + expect(Diaspora::Federation::Dispatcher).not_to receive(:defer_dispatch).with(alice, alice.profile, anything) + alice.share_with(eve.person, alice.aspects.first) end end - it 'sets receiving' do + it "sets receiving" do alice.share_with(eve.person, alice.aspects.first) expect(alice.contact_for(eve.person)).to be_receiving end it "should mark the corresponding notification as 'read'" do - notification = FactoryGirl.create(:notification, :target => eve.person) + FactoryGirl.create(:notification, target: eve.person, recipient: alice, type: "Notifications::StartedSharing") + expect(Notifications::StartedSharing.find_by(recipient_id: alice.id, target: eve.person).unread).to be_truthy - expect(Notification.where(:target_id => eve.person.id).first.unread).to be true - alice.share_with(eve.person, aspect) - expect(Notification.where(:target_id => eve.person.id).first.unread).to be false + alice.share_with(eve.person, aspect1) + expect(Notifications::StartedSharing.find_by(recipient_id: alice.id, target: eve.person).unread).to be_falsey end end end diff --git a/spec/models/user/querying_spec.rb b/spec/models/user/querying_spec.rb index 9d8a0ff1467aa56ed5063ef6c1563f5dd7e10f61..1a54d996a92297ce188ea55165b2f65d173860f8 100644 --- a/spec/models/user/querying_spec.rb +++ b/spec/models/user/querying_spec.rb @@ -45,22 +45,11 @@ describe User::Querying, :type => :model do expect(alice.visible_shareable_ids(Post)).not_to include(invisible_post.id) end - it "does not contain pending posts" do - pending_post = bob.post(:status_message, :text => "hey", :public => true, :to => @bobs_aspect.id, :pending => true) - expect(pending_post).to be_pending - expect(alice.visible_shareable_ids(Post)).not_to include pending_post.id - end - - it "does not contain pending photos" do - pending_photo = bob.post(:photo, :pending => true, :user_file=> File.open(photo_fixture_name), :to => @bobs_aspect) - expect(alice.visible_shareable_ids(Photo)).not_to include pending_photo.id - end - it "respects the :type option" do - post = bob.post(:status_message, :text => "hey", :public => true, :to => @bobs_aspect.id, :pending => false) - reshare = bob.post(:reshare, :pending => false, :root_guid => post.guid, :to => @bobs_aspect) - expect(alice.visible_shareable_ids(Post, :type => "Reshare")).to include(reshare.id) - expect(alice.visible_shareable_ids(Post, :type => 'StatusMessage')).not_to include(reshare.id) + post = bob.post(:status_message, text: "hey", public: true, to: @bobs_aspect.id) + reshare = bob.post(:reshare, root_guid: post.guid, to: @bobs_aspect) + expect(alice.visible_shareable_ids(Post, type: "Reshare")).to include(reshare.id) + expect(alice.visible_shareable_ids(Post, type: "StatusMessage")).not_to include(reshare.id) end it "does not contain duplicate posts" do @@ -85,8 +74,7 @@ describe User::Querying, :type => :model do end it "does not pull back hidden posts" do - visibility = @status.share_visibilities(Post).where(:contact_id => alice.contact_for(bob.person).id).first - visibility.update_attributes(:hidden => true) + @status.share_visibilities(Post).where(user_id: alice.id).first.update_attributes(hidden: true) expect(alice.visible_shareable_ids(Post).include?(@status.id)).to be false end end @@ -114,21 +102,6 @@ describe User::Querying, :type => :model do expect(bob.visible_shareables(Post).count(:all)).to eq(0) end - context 'with two posts with the same timestamp' do - before do - aspect_id = alice.aspects.where(:name => "generic").first.id - Timecop.freeze Time.now do - alice.post :status_message, :text => "first", :to => aspect_id - alice.post :status_message, :text => "second", :to => aspect_id - end - end - - it "returns them in reverse creation order" do - expect(bob.visible_shareables(Post).first.text).to eq("second") - expect(bob.visible_shareables(Post).last.text).to eq("first") - end - end - context 'with many posts' do before do time_interval = 1000 @@ -202,27 +175,21 @@ describe User::Querying, :type => :model do expect(alice.people_in_aspects([@alices_aspect])).to eq([bob.person]) end - it 'returns local/remote people objects for a users contact in each aspect' do + it "returns local/remote people objects for a users contact in each aspect" do local_user1 = FactoryGirl.create(:user) local_user2 = FactoryGirl.create(:user) - remote_user = FactoryGirl.create(:user) + remote_person = FactoryGirl.create(:person) - asp1 = local_user1.aspects.create(:name => "lol") - asp2 = local_user2.aspects.create(:name => "brb") - asp3 = remote_user.aspects.create(:name => "ttyl") + asp1 = local_user1.aspects.create(name: "lol") + asp2 = local_user2.aspects.create(name: "brb") connect_users(alice, @alices_aspect, local_user1, asp1) connect_users(alice, @alices_aspect, local_user2, asp2) - connect_users(alice, @alices_aspect, remote_user, asp3) - - local_person = remote_user.person - local_person.owner_id = nil - local_person.save - local_person.reload + alice.contacts.create!(person: remote_person, aspects: [@alices_aspect], sharing: true) expect(alice.people_in_aspects([@alices_aspect]).count).to eq(4) - expect(alice.people_in_aspects([@alices_aspect], :type => 'remote').count).to eq(1) - expect(alice.people_in_aspects([@alices_aspect], :type => 'local').count).to eq(3) + expect(alice.people_in_aspects([@alices_aspect], type: "remote").count).to eq(1) + expect(alice.people_in_aspects([@alices_aspect], type: "local").count).to eq(3) end it 'does not return people not connected to user on same pod' do diff --git a/spec/models/user/social_actions_spec.rb b/spec/models/user/social_actions_spec.rb index 74a67608be1a8b931ba89469ec365a37d63b5eaa..244f0f183dfd65201411ad349918f2e8ad24c41f 100644 --- a/spec/models/user/social_actions_spec.rb +++ b/spec/models/user/social_actions_spec.rb @@ -1,113 +1,111 @@ require "spec_helper" -describe User::SocialActions, :type => :model do - before do - @bobs_aspect = bob.aspects.where(:name => "generic").first - @status = bob.post(:status_message, :text => "hello", :to => @bobs_aspect.id) - end +describe User::SocialActions, type: :model do + let(:status) { FactoryGirl.create(:status_message, public: true, author: bob.person) } - describe 'User#comment!' do + describe "User#comment!" do it "sets the comment text" do - expect(alice.comment!(@status, "unicorn_mountain").text).to eq("unicorn_mountain") - end - - it "creates a partcipation" do - expect{ alice.comment!(@status, "bro") }.to change(Participation, :count).by(1) - expect(alice.participations.last.target).to eq(@status) - end - - it "creates the comment" do - expect{ alice.comment!(@status, "bro") }.to change(Comment, :count).by(1) + expect(alice.comment!(status, "unicorn_mountain").text).to eq("unicorn_mountain") end - it "federates" do - allow_any_instance_of(Participation::Generator).to receive(:create!) - expect(Postzord::Dispatcher).to receive(:defer_build_and_post) - alice.comment!(@status, "omg") + it "creates a participation" do + expect { alice.comment!(status, "bro") }.to change(Participation, :count).by(1) + expect(alice.participations.last.target).to eq(status) + expect(alice.participations.last.count).to eq(1) end - end - describe 'User#like!' do - it "creates a partcipation" do - expect{ alice.like!(@status) }.to change(Participation, :count).by(1) - expect(alice.participations.last.target).to eq(@status) + it "does not create a participation for the post author" do + expect { bob.comment!(status, "bro") }.not_to change(Participation, :count) end - it "creates the like" do - expect{ alice.like!(@status) }.to change(Like, :count).by(1) + it "creates the comment" do + expect { alice.comment!(status, "bro") }.to change(Comment, :count).by(1) end it "federates" do - #participation and like allow_any_instance_of(Participation::Generator).to receive(:create!) - expect(Postzord::Dispatcher).to receive(:defer_build_and_post) - alice.like!(@status) + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch) + alice.comment!(status, "omg") end end - describe 'User#like!' do - before do - @bobs_aspect = bob.aspects.where(:name => "generic").first - @status = bob.post(:status_message, :text => "hello", :to => @bobs_aspect.id) + describe "User#like!" do + it "creates a participation" do + expect { alice.like!(status) }.to change(Participation, :count).by(1) + expect(alice.participations.last.target).to eq(status) end - it "creates a partcipation" do - expect{ alice.like!(@status) }.to change(Participation, :count).by(1) + it "does not create a participation for the post author" do + expect { bob.like!(status) }.not_to change(Participation, :count) end it "creates the like" do - expect{ alice.like!(@status) }.to change(Like, :count).by(1) + expect { alice.like!(status) }.to change(Like, :count).by(1) end it "federates" do - #participation and like - expect(Postzord::Dispatcher).to receive(:defer_build_and_post).twice - alice.like!(@status) + allow_any_instance_of(Participation::Generator).to receive(:create!) + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch) + alice.like!(status) end it "should be able to like on one's own status" do - like = alice.like!(@status) - expect(@status.reload.likes.first).to eq(like) + like = bob.like!(status) + expect(status.reload.likes.first).to eq(like) end it "should be able to like on a contact's status" do - like = bob.like!(@status) - expect(@status.reload.likes.first).to eq(like) + like = alice.like!(status) + expect(status.reload.likes.first).to eq(like) end it "does not allow multiple likes" do - alice.like!(@status) - likes = @status.likes - expect { alice.like!(@status) }.to raise_error + alice.like!(status) + likes = status.likes + expect { alice.like!(status) }.to raise_error ActiveRecord::RecordInvalid - expect(@status.reload.likes).to eq(likes) + expect(status.reload.likes).to eq(likes) end end - describe 'User#participate_in_poll!' do - before do - @bobs_aspect = bob.aspects.where(:name => "generic").first - @status = bob.post(:status_message, :text => "hello", :to => @bobs_aspect.id) - @poll = FactoryGirl.create(:poll, :status_message => @status) - @answer = @poll.poll_answers.first - end + describe "User#participate_in_poll!" do + let(:poll) { FactoryGirl.create(:poll, status_message: status) } + let(:answer) { poll.poll_answers.first } it "federates" do allow_any_instance_of(Participation::Generator).to receive(:create!) - expect(Postzord::Dispatcher).to receive(:defer_build_and_post) - alice.participate_in_poll!(@status, @answer) + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch) + alice.participate_in_poll!(status, answer) + end + + it "creates a participation" do + expect { alice.participate_in_poll!(status, answer) }.to change(Participation, :count).by(1) end - it "creates a partcipation" do - expect{ alice.participate_in_poll!(@status, @answer) }.to change(Participation, :count).by(1) + it "does not create a participation for the post author" do + expect { bob.participate_in_poll!(status, answer) }.not_to change(Participation, :count) end it "creates the poll participation" do - expect{ alice.participate_in_poll!(@status, @answer) }.to change(PollParticipation, :count).by(1) + expect { alice.participate_in_poll!(status, answer) }.to change(PollParticipation, :count).by(1) end it "sets the poll answer id" do - expect(alice.participate_in_poll!(@status, @answer).poll_answer).to eq(@answer) + expect(alice.participate_in_poll!(status, answer).poll_answer).to eq(answer) + end + end + + describe "many actions" do + it "two comments" do + alice.comment!(status, "bro...") + alice.comment!(status, "...ther") + expect(alice.participations.last.count).to eq(2) + end + + it "like and comment" do + alice.comment!(status, "bro...") + alice.like!(status) + expect(alice.participations.last.count).to eq(2) end end -end \ No newline at end of file +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 489c1ac450b2c7ed93e1ca990db16acfd51b9930..2d636647f948bde074e2d33d670f958fd1a592e4 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -111,21 +111,6 @@ describe User, :type => :model do end end - context 'callbacks' do - describe '#save_person!' do - it 'saves the corresponding user if it has changed' do - alice.person.url = "http://stuff.com" - expect_any_instance_of(Person).to receive(:save) - alice.save - end - - it 'does not save the corresponding user if it has not changed' do - expect_any_instance_of(Person).not_to receive(:save) - alice.save - end - end - end - describe 'hidden_shareables' do before do @sm = FactoryGirl.create(:status_message) @@ -317,9 +302,16 @@ describe User, :type => :model do end it "requires a valid email address" do - alice.email = "somebody@anywhere" + alice.email = "somebodyanywhere" expect(alice).not_to be_valid end + + it "resets a matching unconfirmed_email on save" do + eve.update_attribute :unconfirmed_email, "new@example.com" + alice.update_attribute :email, "new@example.com" + eve.reload + expect(eve.unconfirmed_email).to eql(nil) + end end describe "of unconfirmed_email" do @@ -331,13 +323,18 @@ describe User, :type => :model do end it "does NOT require a unique unconfirmed_email address" do - eve.update_attribute :unconfirmed_email, "new@email.com" - alice.unconfirmed_email = "new@email.com" + eve.update_attribute :unconfirmed_email, "new@example.com" + alice.unconfirmed_email = "new@example.com" expect(alice).to be_valid end + it "requires an unconfirmed_email address which is not another user's email address" do + alice.unconfirmed_email = eve.email + expect(alice).not_to be_valid + end + it "requires a valid unconfirmed_email address" do - alice.unconfirmed_email = "somebody@anywhere" + alice.unconfirmed_email = "somebodyanywhere" expect(alice).not_to be_valid end end @@ -364,6 +361,13 @@ describe User, :type => :model do expect(user.language).to eq('de') end end + + describe "of color_theme" do + it "requires availability" do + alice.color_theme = "some invalid theme" + expect(alice).not_to be_valid + end + end end @@ -490,12 +494,6 @@ describe User, :type => :model do it "does not preserve case" do expect(User.find_for_database_authentication(:username => alice.username.upcase)).to eq(alice) end - - it 'errors out when passed a non-hash' do - expect { - User.find_for_database_authentication(alice.username) - }.to raise_error - end end describe '#update_profile' do @@ -506,16 +504,14 @@ describe User, :type => :model do } end - it 'dispatches the profile when tags are set' do - @params = {:tag_string => '#what #hey'} - mailman = Postzord::Dispatcher.build(alice, Profile.new) - expect(Postzord::Dispatcher).to receive(:build).and_return(mailman) + it "dispatches the profile when tags are set" do + @params = {tag_string: '#what #hey'} + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, alice.profile, {}) expect(alice.update_profile(@params)).to be true end - it 'sends a profile to their contacts' do - mailman = Postzord::Dispatcher.build(alice, Profile.new) - expect(Postzord::Dispatcher).to receive(:build).and_return(mailman) + it "sends a profile to their contacts" do + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, alice.profile, {}) expect(alice.update_profile(@params)).to be true end @@ -568,50 +564,8 @@ describe User, :type => :model do end end - describe '#notify_if_mentioned' do - before do - @post = FactoryGirl.build(:status_message, :author => bob.person) - end - - it 'notifies the user if the incoming post mentions them' do - expect(@post).to receive(:mentions?).with(alice.person).and_return(true) - expect(@post).to receive(:notify_person).with(alice.person) - - alice.notify_if_mentioned(@post) - end - - it 'does not notify the user if the incoming post does not mention them' do - expect(@post).to receive(:mentions?).with(alice.person).and_return(false) - expect(@post).not_to receive(:notify_person) - - alice.notify_if_mentioned(@post) - end - - it 'does not notify the user if the post author is not a contact' do - @post = FactoryGirl.build(:status_message, :author => eve.person) - allow(@post).to receive(:mentions?).and_return(true) - expect(@post).not_to receive(:notify_person) - - alice.notify_if_mentioned(@post) - end - end - describe 'account deletion' do describe '#destroy' do - it 'removes invitations from the user' do - FactoryGirl.create(:invitation, :sender => alice) - expect { - alice.destroy - }.to change {alice.invitations_from_me(true).count }.by(-1) - end - - it 'removes invitations to the user' do - Invitation.new(:sender => eve, :recipient => alice, :identifier => alice.email, :aspect => eve.aspects.first).save(:validate => false) - expect { - alice.destroy - }.to change {alice.invitations_to_me(true).count }.by(-1) - end - it 'removes all service connections' do Services::Facebook.create(:access_token => 'what', :user_id => alice.id) expect { @@ -647,26 +601,6 @@ describe User, :type => :model do end end - context "aspect management" do - before do - @contact = alice.contact_for(bob.person) - @original_aspect = alice.aspects.where(:name => "generic").first - @new_aspect = alice.aspects.create(:name => 'two') - end - - describe "#add_contact_to_aspect" do - it 'adds the contact to the aspect' do - expect { - alice.add_contact_to_aspect(@contact, @new_aspect) - }.to change(@new_aspect.contacts, :count).by(1) - end - - it 'returns true if they are already in the aspect' do - expect(alice.add_contact_to_aspect(@contact, @original_aspect)).to be true - end - end - end - context 'likes' do before do alices_aspect = alice.aspects.where(:name => "generic").first @@ -839,36 +773,17 @@ describe User, :type => :model do end - describe '#retract' do - before do - @retraction = double - @post = FactoryGirl.build(:status_message, :author => bob.person, :public => true) - end + describe "#retract" do + let(:retraction) { double } + let(:post) { FactoryGirl.build(:status_message, author: bob.person, public: true) } context "posts" do - before do - allow(SignedRetraction).to receive(:build).and_return(@retraction) - allow(@retraction).to receive(:perform) - end - - it 'sends a retraction' do - dispatcher = double - expect(Postzord::Dispatcher).to receive(:build).with(bob, @retraction, anything()).and_return(dispatcher) - expect(dispatcher).to receive(:post) + it "sends a retraction" do + expect(Retraction).to receive(:for).with(post, bob).and_return(retraction) + expect(retraction).to receive(:defer_dispatch).with(bob) + expect(retraction).to receive(:perform) - bob.retract(@post) - end - - it 'adds resharers of target post as additional subsctibers' do - person = FactoryGirl.create(:person) - reshare = FactoryGirl.create(:reshare, :root => @post, :author => person) - @post.reshares << reshare - - dispatcher = double - expect(Postzord::Dispatcher).to receive(:build).with(bob, @retraction, {:additional_subscribers => [person], :services => anything}).and_return(dispatcher) - expect(dispatcher).to receive(:post) - - bob.retract(@post) + bob.retract(post) end end end @@ -1031,10 +946,8 @@ describe User, :type => :model do describe "#clearable_attributes" do it 'returns the clearable fields' do user = FactoryGirl.create :user - expect(user.send(:clearable_fields).sort).to eq(%w{ + expect(user.send(:clearable_fields).sort).to eq(%w( language - invitation_token - invitation_sent_at reset_password_sent_at reset_password_token remember_created_at @@ -1044,18 +957,15 @@ describe User, :type => :model do current_sign_in_ip hidden_shareables last_sign_in_ip - invitation_service - invitation_identifier - invitation_limit invited_by_id - invited_by_type authentication_token auto_follow_back auto_follow_back_aspect_id unconfirmed_email confirm_email_token last_seen - }.sort) + color_theme + ).sort) end end end @@ -1180,12 +1090,8 @@ describe User, :type => :model do describe "active" do before do - invited_user = FactoryGirl.build(:user, username: nil) - invited_user.save(validate: false) - closed_account = FactoryGirl.create(:user) - closed_account.person.closed_account = true - closed_account.save + closed_account.person.lock_access! end it "returns total_users excluding closed accounts & users without usernames" do diff --git a/spec/presenters/contact_presenter_spec.rb b/spec/presenters/contact_presenter_spec.rb index 9f2d2724508ea1f3a49854edd83f50eda8088ee9..7ac959606a999cb2fd7d50269b3ee6bc090f3415 100644 --- a/spec/presenters/contact_presenter_spec.rb +++ b/spec/presenters/contact_presenter_spec.rb @@ -25,5 +25,13 @@ describe ContactPresenter do it "has relationship information" do expect(@presenter.full_hash_with_person[:person][:relationship]).to be(:mutual) end + + it "doesn't have redundant contact object in person hash" do + expect(@presenter.full_hash_with_person[:person]).not_to have_key(:contact) + end + + it "has avatar links in person profile hash" do + expect(@presenter.full_hash_with_person[:person][:profile]).to have_key(:avatar) + end end end diff --git a/spec/presenters/node_info_presenter_spec.rb b/spec/presenters/node_info_presenter_spec.rb index 028cfc5c70d7dc804f969a4bc1581c99c4454529..de10d4e3118b62ad8fb0b30dbd1de4b32948b989 100644 --- a/spec/presenters/node_info_presenter_spec.rb +++ b/spec/presenters/node_info_presenter_spec.rb @@ -31,7 +31,7 @@ describe NodeInfoPresenter do }, "services" => { "inbound" => [], - "outbound" => ["facebook"] + "outbound" => AppConfig.configured_services.map(&:to_s) }, "openRegistrations" => AppConfig.settings.enable_registrations?, "usage" => { diff --git a/spec/presenters/person_presenter_spec.rb b/spec/presenters/person_presenter_spec.rb index 110f1955c6250e5a468fea99fad83d362844d39a..3dab714d1b84d2f04c7f6e1ce7586cb072b2e3f6 100644 --- a/spec/presenters/person_presenter_spec.rb +++ b/spec/presenters/person_presenter_spec.rb @@ -4,44 +4,84 @@ describe PersonPresenter do let(:profile_user) { FactoryGirl.create(:user_with_aspect) } let(:person) { profile_user.person } - let(:mutual_contact) { double(id: 1, mutual?: true, sharing?: true, receiving?: true) } - let(:receiving_contact) { double(id: 1, mutual?: false, sharing?: false, receiving?: true) } - let(:sharing_contact) { double(id: 1, mutual?: false, sharing?: true, receiving?: false) } - let(:non_contact) { double(id: 1, mutual?: false, sharing?: false, receiving?: false) } + let(:mutual_contact) { + FactoryGirl.create(:contact, user: current_user, person: person, sharing: true, receiving: true) + } + let(:receiving_contact) { + FactoryGirl.create(:contact, user: current_user, person: person, sharing: false, receiving: true) + } + let(:sharing_contact) { + FactoryGirl.create(:contact, user: current_user, person: person, sharing: true, receiving: false) + } + let(:non_contact) { + FactoryGirl.create(:contact, user: current_user, person: person, sharing: false, receiving: false) + } describe "#as_json" do context "with no current_user" do - it "returns the user's public information if a user is not logged in" do + it "returns the user's basic profile" do expect(PersonPresenter.new(person, nil).as_json).to include(person.as_api_response(:backbone).except(:avatar)) end + + it "returns the user's additional profile if the user has set additional profile public" do + person.profile.public_details = true + expect(PersonPresenter.new(person, nil).as_json[:profile]).to include(*%i(location bio gender birthday)) + end + + it "doesn't return user's additional profile if the user hasn't set additional profile public" do + person.profile.public_details = false + expect(PersonPresenter.new(person, nil).as_json[:profile]).not_to include(*%i(location bio gender birthday)) + end end context "with a current_user" do - let(:current_user) { FactoryGirl.create(:user)} + let(:current_user) { FactoryGirl.create(:user) } let(:presenter){ PersonPresenter.new(person, current_user) } + # here private information == addtional user profile, because additional profile by default is private it "doesn't share private information when the users aren't connected" do allow(current_user).to receive(:contact_for) { non_contact } - expect(presenter.full_hash_with_profile[:profile]).not_to have_key(:location) + expect(person.profile.public_details).to be_falsey + expect(presenter.as_json[:show_profile_info]).to be_falsey + expect(presenter.as_json[:profile]).not_to have_key(:location) end it "doesn't share private information when the current user is sharing with the person" do allow(current_user).to receive(:contact_for) { receiving_contact } - expect(presenter.full_hash_with_profile[:profile]).not_to have_key(:location) + expect(person.profile.public_details).to be_falsey + expect(presenter.as_json[:show_profile_info]).to be_falsey + expect(presenter.as_json[:profile]).not_to have_key(:location) + end + + it "shares private information when the users aren't connected, but profile is public" do + allow(current_user).to receive(:contact_for) { non_contact } + person.profile.public_details = true + expect(presenter.as_json[:show_profile_info]).to be_truthy + expect(presenter.as_json[:relationship]).to be(:not_sharing) + expect(presenter.as_json[:profile]).to have_key(:location) end it "has private information when the person is sharing with the current user" do allow(current_user).to receive(:contact_for) { sharing_contact } - expect(presenter.full_hash_with_profile[:profile]).to have_key(:location) + expect(person.profile.public_details).to be_falsey + pr_json = presenter.as_json + expect(pr_json[:show_profile_info]).to be_truthy + expect(pr_json[:profile]).to have_key(:location) end it "has private information when the relationship is mutual" do allow(current_user).to receive(:contact_for) { mutual_contact } - expect(presenter.full_hash_with_profile[:profile]).to have_key(:location) + expect(person.profile.public_details).to be_falsey + pr_json = presenter.as_json + expect(pr_json[:show_profile_info]).to be_truthy + expect(pr_json[:profile]).to have_key(:location) end it "returns the user's private information if a user is logged in as herself" do - expect(PersonPresenter.new(current_user.person, current_user).as_json).to have_key(:location) + current_person_presenter = PersonPresenter.new(current_user.person, current_user) + expect(current_user.person.profile.public_details).to be_falsey + expect(current_person_presenter.as_json[:show_profile_info]).to be_truthy + expect(current_person_presenter.as_json[:profile]).to have_key(:location) end end end @@ -81,4 +121,18 @@ describe PersonPresenter do end end end + + describe "#hovercard" do + let(:current_user) { FactoryGirl.create(:user) } + let(:presenter) { PersonPresenter.new(person, current_user) } + + it "contains data required for hovercard" do + mutual_contact + expect(presenter.hovercard).to have_key(:profile) + expect(presenter.hovercard[:profile]).to have_key(:avatar) + expect(presenter.hovercard[:profile]).to have_key(:tags) + expect(presenter.hovercard).to have_key(:contact) + expect(presenter.hovercard[:contact]).to have_key(:aspect_memberships) + end + end end diff --git a/spec/presenters/post_presenter_spec.rb b/spec/presenters/post_presenter_spec.rb index 07a4b2d8411407fda7cac100c946f9b968954e56..5c9c527287fa85812b2d3afb9bb253a0f66250b3 100644 --- a/spec/presenters/post_presenter_spec.rb +++ b/spec/presenters/post_presenter_spec.rb @@ -75,7 +75,7 @@ describe PostPresenter do end context "with posts without text" do - it " displays a messaage with the post class" do + it "displays a messaage with the post class" do @sm = double(message: double(present?: false), author: bob.person, author_name: bob.person.name) @presenter.post = @sm expect(@presenter.send(:title)).to eq("A post from #{@sm.author.name}") @@ -89,4 +89,48 @@ describe PostPresenter do expect(presenter.as_json).to be_a(Hash) end end + + describe "#tags" do + it "returns the tag of the post" do + post = FactoryGirl.create(:status_message, text: "#hello #world", public: true) + + expect(PostPresenter.new(post).send(:tags)).to match_array(%w(hello world)) + end + + it "returns the tag of the absolute_root of a Reshare" do + post = FactoryGirl.create(:status_message, text: "#hello #world", public: true) + first_reshare = FactoryGirl.create(:reshare, root: post) + second_reshare = FactoryGirl.create(:reshare, root: first_reshare) + + expect(PostPresenter.new(second_reshare).send(:tags)).to match_array(%w(hello world)) + end + + it "does not raise if the root of a reshare does not exist anymore" do + reshare = FactoryGirl.create(:reshare) + reshare.root = nil + + expect(PostPresenter.new(reshare).send(:tags)).to eq([]) + end + end + + describe "#description" do + it "returns the first 1000 chars of the text" do + post = FactoryGirl.create(:status_message, text: "a" * 1001, public: true) + + expect(PostPresenter.new(post).send(:description)).to eq("#{'a' * 997}...") + end + + it "does not change the message if less or equal 1000 chars" do + post = FactoryGirl.create(:status_message, text: "a" * 1000, public: true) + + expect(PostPresenter.new(post).send(:description)).to eq("a" * 1000) + end + + it "does not raise if the root of a reshare does not exist anymore" do + reshare = FactoryGirl.create(:reshare) + reshare.root = nil + + expect(PostPresenter.new(reshare).send(:description)).to eq(nil) + end + end end diff --git a/spec/presenters/profile_presenter_spec.rb b/spec/presenters/profile_presenter_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..61829ab4086de3d3fcd4a040e743edadf14cc4b3 --- /dev/null +++ b/spec/presenters/profile_presenter_spec.rb @@ -0,0 +1,13 @@ +require "spec_helper" + +describe ProfilePresenter do + let(:profile) { FactoryGirl.create(:profile_with_image_url, person: alice.person) } + + describe "#for_hovercard" do + it "contains tags and avatar" do + hash = ProfilePresenter.new(profile).for_hovercard + expect(hash[:avatar]).to eq(profile.image_url_medium) + expect(hash[:tags]).to match_array(%w(one two)) + end + end +end diff --git a/spec/presenters/social_relay_presenter_spec.rb b/spec/presenters/social_relay_presenter_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..aa2f4339560b736ad4ec56dea535690b7bd18cf0 --- /dev/null +++ b/spec/presenters/social_relay_presenter_spec.rb @@ -0,0 +1,122 @@ +require "spec_helper" + +describe SocialRelayPresenter do + before do + @presenter = SocialRelayPresenter.new + end + + describe "#as_json" do + it "works" do + expect(@presenter.as_json).to be_present + expect(@presenter.as_json).to be_a Hash + end + end + + describe "#social relay well-known contents" do + describe "defaults" do + it "provides valid detault data" do + expect(@presenter.as_json).to eq( + "subscribe" => false, + "scope" => "tags", + "tags" => [] + ) + end + end + + describe "pod tags" do + before do + AppConfig.relay.inbound.pod_tags = "foo, bar" + AppConfig.relay.inbound.include_user_tags = false + end + + it "provides pod tags" do + expect(@presenter.as_json).to match( + "subscribe" => false, + "scope" => "tags", + "tags" => a_collection_containing_exactly("foo", "bar") + ) + end + end + + describe "user tags" do + before do + AppConfig.relay.inbound.pod_tags = "" + AppConfig.relay.inbound.include_user_tags = true + ceetag = FactoryGirl.create(:tag, name: "cee") + lootag = FactoryGirl.create(:tag, name: "loo") + FactoryGirl.create(:tag_following, user: alice, tag: ceetag) + FactoryGirl.create(:tag_following, user: alice, tag: lootag) + alice.last_seen = Time.zone.now - 2.months + alice.save + end + + it "provides user tags" do + expect(@presenter.as_json).to match( + "subscribe" => false, + "scope" => "tags", + "tags" => a_collection_containing_exactly("cee", "loo") + ) + end + end + + describe "pod tags combined with user tags" do + before do + AppConfig.relay.inbound.pod_tags = "foo, bar" + AppConfig.relay.inbound.include_user_tags = true + ceetag = FactoryGirl.create(:tag, name: "cee") + lootag = FactoryGirl.create(:tag, name: "loo") + FactoryGirl.create(:tag_following, user: alice, tag: ceetag) + FactoryGirl.create(:tag_following, user: alice, tag: lootag) + alice.last_seen = Time.zone.now - 2.months + alice.save + end + + it "provides combined pod and user tags" do + expect(@presenter.as_json).to match( + "subscribe" => false, + "scope" => "tags", + "tags" => a_collection_containing_exactly("foo", "bar", "cee", "loo") + ) + end + end + + describe "user tags for inactive user" do + before do + AppConfig.relay.inbound.pod_tags = "" + AppConfig.relay.inbound.include_user_tags = true + ceetag = FactoryGirl.create(:tag, name: "cee") + lootag = FactoryGirl.create(:tag, name: "loo") + FactoryGirl.create(:tag_following, user: alice, tag: ceetag) + FactoryGirl.create(:tag_following, user: alice, tag: lootag) + alice.last_seen = Time.zone.now - 8.months + alice.save + end + + it "ignores user tags" do + expect(@presenter.as_json).to eq( + "subscribe" => false, + "scope" => "tags", + "tags" => [] + ) + end + end + + describe "when scope is all" do + before do + AppConfig.relay.inbound.scope = "all" + AppConfig.relay.inbound.pod_tags = "foo,bar" + AppConfig.relay.inbound.include_user_tags = true + ceetag = FactoryGirl.create(:tag, name: "cee") + FactoryGirl.create(:tag_following, user: alice, tag: ceetag) + end + + it "provides empty tags list" do + expect(@presenter.as_json).to eq( + "subscribe" => false, + "scope" => "all", + "tags" => [] + ) + end + end + end +end diff --git a/spec/presenters/statistics_presenter_spec.rb b/spec/presenters/statistics_presenter_spec.rb index 31273cdec2e4a9fb65ade49f045cd07436f48078..b76350c56bf6f2d8a9de90f3f71b59c350e9cf0d 100644 --- a/spec/presenters/statistics_presenter_spec.rb +++ b/spec/presenters/statistics_presenter_spec.rb @@ -25,11 +25,7 @@ describe StatisticsPresenter do "network" => "Diaspora", "version" => AppConfig.version_string, "registrations_open" => AppConfig.settings.enable_registrations?, - "services" => ["facebook"], - "facebook" => true, - "tumblr" => false, - "twitter" => false, - "wordpress" => false + "services" => AppConfig.configured_services.map(&:to_s) ) end @@ -55,11 +51,7 @@ describe StatisticsPresenter do "network" => "Diaspora", "version" => AppConfig.version_string, "registrations_open" => AppConfig.settings.enable_registrations?, - "services" => %w(twitter facebook), - "facebook" => true, - "twitter" => true, - "tumblr" => false, - "wordpress" => false + "services" => %w(twitter facebook) ) end end @@ -89,11 +81,7 @@ describe StatisticsPresenter do "network" => "Diaspora", "version" => AppConfig.version_string, "registrations_open" => AppConfig.settings.enable_registrations?, - "services" => ["twitter"], - "facebook" => false, - "twitter" => true, - "tumblr" => false, - "wordpress" => false + "services" => ["twitter"] ) end end @@ -116,11 +104,7 @@ describe StatisticsPresenter do "active_users_monthly" => User.monthly_actives.count, "local_posts" => @presenter.local_posts, "local_comments" => @presenter.local_comments, - "services" => ["facebook"], - "facebook" => true, - "twitter" => false, - "tumblr" => false, - "wordpress" => false + "services" => AppConfig.configured_services.map(&:to_s) ) end end diff --git a/spec/requests_helper.rb b/spec/requests_helper.rb deleted file mode 100644 index fdae9a95da530103e43a1c054db2a268fc9a64fe..0000000000000000000000000000000000000000 --- a/spec/requests_helper.rb +++ /dev/null @@ -1,5 +0,0 @@ -include Warden::Test::Helpers - -def login(user) - login_as user, scope: :user -end diff --git a/spec/serializers/notification_serializer_spec.rb b/spec/serializers/notification_serializer_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..c771ad2b4e791fd8527adbac4eca33c30b18c6de --- /dev/null +++ b/spec/serializers/notification_serializer_spec.rb @@ -0,0 +1,53 @@ +require "spec_helper" + +describe NotificationSerializer do + let(:notifications_controller) { NotificationsController.new } + + before do + allow(notifications_controller).to receive(:current_user).and_return(notification.recipient) + notifications_controller.request = ActionController::TestRequest.new(host: AppConfig.pod_uri) + end + + let(:notification) { FactoryGirl.create(:notification) } + let(:json_output) { + NotificationSerializer.new(notification, context: notifications_controller).to_json + } + + subject(:parsed_hash) { + JSON.parse json_output + } + + it { is_expected.to have_key(notification.type.demodulize.underscore.to_s) } + + context "typed object" do + let(:object) { + parsed_hash[notification.type.demodulize.underscore] + } + + it "have all properties set" do + %w(id target_id recipient_id unread target_type).each do |key| + expect(object[key]).to eq(notification.send(key)) + end + + %w(created_at updated_at).each do |key| + expect(object[key]).to eq(notification.send(key).strftime("%FT%T.%LZ")) + end + + expect(object).to have_key("note_html") + end + + context "note_html" do + before do + # Nokogiri issue, see https://github.com/sparklemotion/nokogiri/issues/800 + # TODO: remove when the above issue is fixed + expect_any_instance_of(ApplicationHelper).to receive(:timeago).and_return("") + end + + let(:note_html) { object["note_html"] } + + it "contains valid html" do + expect(Nokogiri::HTML(note_html).errors).to eq([]) + end + end + end +end diff --git a/spec/serializers/post_serializer_spec.rb b/spec/serializers/post_serializer_spec.rb index b891f2b5dbcbe7a33de2a3997502968467987c66..924fe6c71b57fe8897ef57818a1d02ed9a05dec6 100644 --- a/spec/serializers/post_serializer_spec.rb +++ b/spec/serializers/post_serializer_spec.rb @@ -9,9 +9,6 @@ describe Export::PostSerializer do it { is_expected.to include %("public":#{post.public}) } it { is_expected.to include %("diaspora_handle":"#{post.diaspora_handle}") } it { is_expected.to include %("type":"#{post.type}") } - it { is_expected.to include %("image_url":#{post.image_url}) } - it { is_expected.to include %("image_height":#{post.image_height}) } - it { is_expected.to include %("image_width":#{post.image_width}) } it { is_expected.to include %("likes_count":#{post.likes_count}) } it { is_expected.to include %("comments_count":#{post.comments_count}) } it { is_expected.to include %("reshares_count":#{post.reshares_count}) } diff --git a/spec/services/comment_service_spec.rb b/spec/services/comment_service_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..7717f456189ed38ec9d698407445371c05f29f94 --- /dev/null +++ b/spec/services/comment_service_spec.rb @@ -0,0 +1,102 @@ +require "spec_helper" + +describe CommentService do + let(:post) { alice.post(:status_message, text: "hello", to: alice.aspects.first) } + + describe "#create" do + it "creates a comment on my own post" do + comment = CommentService.new(alice).create(post.id, "hi") + expect(comment.text).to eq("hi") + end + + it "creates a comment on post of a contact" do + comment = CommentService.new(bob).create(post.id, "hi") + expect(comment.text).to eq("hi") + end + + it "attaches the comment to the post" do + comment = CommentService.new(alice).create(post.id, "hi") + expect(post.comments.first.text).to eq("hi") + expect(post.comments.first.id).to eq(comment.id) + end + + it "fail if the post does not exist" do + expect { + CommentService.new(alice).create("unknown id", "hi") + }.to raise_error ActiveRecord::RecordNotFound + end + + it "fail if the user can not see the post" do + expect { + CommentService.new(eve).create("unknown id", "hi") + }.to raise_error ActiveRecord::RecordNotFound + end + end + + describe "#destroy" do + let(:comment) { CommentService.new(bob).create(post.id, "hi") } + + it "lets the user destroy his own comment" do + result = CommentService.new(bob).destroy(comment.id) + expect(result).to be_truthy + end + + it "lets the parent author destroy others comment" do + result = CommentService.new(alice).destroy(comment.id) + expect(result).to be_truthy + end + + it "does not let someone destroy others comment" do + result = CommentService.new(eve).destroy(comment.id) + expect(result).to be_falsey + end + + it "fails if the comment does not exist" do + expect { + CommentService.new(bob).destroy("unknown id") + }.to raise_error ActiveRecord::RecordNotFound + end + end + + describe "#find_for_post" do + context "with user" do + it "returns comments for a public post" do + post = alice.post(:status_message, text: "hello", public: true) + comment = CommentService.new(alice).create(post.id, "hi") + expect(CommentService.new(eve).find_for_post(post.id)).to include(comment) + end + + it "returns comments for a visible private post" do + comment = CommentService.new(alice).create(post.id, "hi") + expect(CommentService.new(bob).find_for_post(post.id)).to include(comment) + end + + it "does not return comments for private post the user can not see" do + expect { + CommentService.new(eve).find_for_post(post.id) + }.to raise_error ActiveRecord::RecordNotFound + end + end + + context "without user" do + it "returns comments for a public post" do + post = alice.post(:status_message, text: "hello", public: true) + comment = CommentService.new(alice).create(post.id, "hi") + expect(CommentService.new.find_for_post(post.id)).to include(comment) + end + + it "does not return comments for private post" do + expect { + CommentService.new.find_for_post(post.id) + }.to raise_error Diaspora::NonPublic + end + end + + it "returns all comments of a post" do + post = alice.post(:status_message, text: "hello", public: true) + comments = [alice, bob, eve].map {|user| CommentService.new(user).create(post.id, "hi") } + + expect(CommentService.new.find_for_post(post.id)).to match_array(comments) + end + end +end diff --git a/spec/services/post_service_spec.rb b/spec/services/post_service_spec.rb index 47f57d750c0734a3f510c18f80b7bdb81480cb77..2f2d4764f7840ea0ed682844b45bd4b45ba7e648 100644 --- a/spec/services/post_service_spec.rb +++ b/spec/services/post_service_spec.rb @@ -1,127 +1,188 @@ require "spec_helper" describe PostService do - before do - aspect = alice.aspects.first - @message = alice.build_post :status_message, text: "ohai", to: aspect.id - @message.save! + let(:post) { alice.post(:status_message, text: "ohai", to: alice.aspects.first) } + let(:public) { alice.post(:status_message, text: "hey", public: true) } - alice.add_to_streams(@message, [aspect]) - alice.dispatch_post @message, to: aspect.id + describe "#find" do + context "with user" do + it "returns the post, if it is the users post" do + expect(PostService.new(alice).find(post.id)).to eq(post) + end + + it "returns the post, if the user can see the it" do + expect(PostService.new(bob).find(post.id)).to eq(post) + end + + it "returns the post, if it is public" do + expect(PostService.new(eve).find(public.id)).to eq(public) + end + + it "does not return the post, if the post cannot be found" do + expect(PostService.new(alice).find("unknown")).to be_nil + end + + it "does not return the post, if user cannot see the post" do + expect(PostService.new(eve).find(post.id)).to be_nil + end + end + + context "without user" do + it "returns the post, if it is public" do + expect(PostService.new.find(public.id)).to eq(public) + end + + it "does not return the post, if the post is private" do + expect(PostService.new.find(post.id)).to be_nil + end + + it "does not return the post, if the post cannot be found" do + expect(PostService.new.find("unknown")).to be_nil + end + end end - describe "#assign_post" do - context "when the post is private" do - it "RecordNotFound if the post cannot be found" do - expect { PostService.new(id: 1_234_567, user: alice) }.to raise_error(ActiveRecord::RecordNotFound) + describe "#find!" do + context "with user" do + it "returns the post, if it is the users post" do + expect(PostService.new(alice).find!(post.id)).to eq(post) end - it "NonPublic if there is no user" do - expect { PostService.new(id: @message.id) }.to raise_error(Diaspora::NonPublic) + + it "works with guid" do + expect(PostService.new(alice).find!(post.guid)).to eq(post) end - it "RecordNotFound if user cannot see post" do - expect { PostService.new(id: @message.id, user: eve) }.to raise_error(ActiveRecord::RecordNotFound) + + it "returns the post, if the user can see the it" do + expect(PostService.new(bob).find!(post.id)).to eq(post) + end + + it "returns the post, if it is public" do + expect(PostService.new(eve).find!(public.id)).to eq(public) + end + + it "RecordNotFound if the post cannot be found" do + expect { + PostService.new(alice).find!("unknown") + }.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id unknown for user #{alice.id}" + end + + it "RecordNotFound if user cannot see the post" do + expect { + PostService.new(eve).find!(post.id) + }.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id #{post.id} for user #{eve.id}" end end - context "when the post is public" do + context "without user" do + it "returns the post, if it is public" do + expect(PostService.new.find!(public.id)).to eq(public) + end + + it "works with guid" do + expect(PostService.new.find!(public.guid)).to eq(public) + end + + it "NonPublic if the post is private" do + expect { + PostService.new.find!(post.id) + }.to raise_error Diaspora::NonPublic + end + it "RecordNotFound if the post cannot be found" do - expect { PostService.new(id: 1_234_567) }.to raise_error(ActiveRecord::RecordNotFound) + expect { + PostService.new.find!("unknown") + }.to raise_error ActiveRecord::RecordNotFound, "could not find a post with id unknown" end end - # We want to be using guids from now on for this post route, but do not want to break - # pre-exisiting permalinks. We can assume a guid is 8 characters long as we have - # guids set to hex(8) since we started using them. context "id/guid switch" do - before do - @status = alice.post(:status_message, text: "hello", public: true, to: "all") - end + let(:public) { alice.post(:status_message, text: "ohai", public: true) } - it "assumes guids less than 8 chars are ids and not guids" do - post = Post.where(id: @status.id.to_s) - expect(Post).to receive(:where).with(hash_including(id: @status.id)).and_return(post).at_least(:once) - PostService.new(id: @status.id, user: alice) + it "assumes ids less than 16 chars are ids and not guids" do + post = Post.where(id: public.id) + expect(Post).to receive(:where).with(hash_including(id: "123456789012345")).and_return(post).at_least(:once) + PostService.new(alice).find!("123456789012345") end - it "assumes guids more than (or equal to) 8 chars are actually guids" do - post = Post.where(guid: @status.guid) - expect(Post).to receive(:where).with(hash_including(guid: @status.guid)).and_return(post).at_least(:once) - PostService.new(id: @status.guid, user: alice) + it "assumes ids more than (or equal to) 16 chars are actually guids" do + post = Post.where(guid: public.guid) + expect(Post).to receive(:where).with(hash_including(guid: "1234567890123456")).and_return(post).at_least(:once) + PostService.new(alice).find!("1234567890123456") end end end describe "#mark_user_notifications" do it "marks a corresponding notifications as read" do - FactoryGirl.create(:notification, recipient: alice, target: @message, unread: true) - FactoryGirl.create(:notification, recipient: alice, target: @message, unread: true) - post_service = PostService.new(id: @message.id, user: alice) - expect { post_service.mark_user_notifications }.to change(Notification.where(unread: true), :count).by(-2) + FactoryGirl.create(:notification, recipient: alice, target: post, unread: true) + FactoryGirl.create(:notification, recipient: alice, target: post, unread: true) + + expect { + PostService.new(alice).mark_user_notifications(post.id) + }.to change(Notification.where(unread: true), :count).by(-2) end it "marks a corresponding mention notification as read" do status_text = "this is a text mentioning @{Mention User ; #{alice.diaspora_handle}} ... have fun testing!" - status_msg = - bob.post(:status_message, text: status_text, public: true, to: "all") - mention = status_msg.mentions.where(person_id: alice.person.id).first - FactoryGirl.create(:notification, recipient: alice, target_type: "Mention", target_id: mention.id, unread: true) - post_service = PostService.new(id: status_msg.id, user: alice) - expect { post_service.mark_user_notifications }.to change(Notification.where(unread: true), :count).by(-1) - end - end + mention_post = bob.post(:status_message, text: status_text, public: true) - describe "#present_json" do - it "works for a private post" do - post_service = PostService.new(id: @message.id, user: alice) - expect(post_service.present_json.to_json).to match(/\"text\"\:\"ohai\"/) + expect { + PostService.new(alice).mark_user_notifications(mention_post.id) + }.to change(Notification.where(unread: true), :count).by(-1) end - it "works for a public post " do - status = alice.post(:status_message, text: "hello", public: true, to: "all") - post_service = PostService.new(id: status.id) - expect(post_service.present_json.to_json).to match(/\"text\"\:\"hello\"/) + it "does not change the update_at date/time for post notifications" do + notification = Timecop.travel(1.minute.ago) do + FactoryGirl.create(:notification, recipient: alice, target: post, unread: true) + end + + expect { + PostService.new(alice).mark_user_notifications(post.id) + }.not_to change { Notification.where(id: notification.id).pluck(:updated_at) } end - end - describe "#present_oembed" do - it "works for a private post" do - post_service = PostService.new(id: @message.id, user: alice) - expect(post_service.present_oembed.to_json).to match(/iframe/) + it "does not change the update_at date/time for mention notifications" do + status_text = "this is a text mentioning @{Mention User ; #{alice.diaspora_handle}} ... have fun testing!" + mention_post = Timecop.travel(1.minute.ago) do + bob.post(:status_message, text: status_text, public: true) + end + mention = mention_post.mentions.where(person_id: alice.person.id).first + + expect { + PostService.new(alice).mark_user_notifications(post.id) + }.not_to change { Notification.where(target_type: "Mention", target_id: mention.id).pluck(:updated_at) } end - it "works for a public post" do - status = alice.post(:status_message, text: "hello", public: true, to: "all") - post_service = PostService.new(id: status.id) - expect(post_service.present_oembed.to_json).to match(/iframe/) + it "does nothing without a user" do + expect_any_instance_of(PostService).not_to receive(:mark_comment_reshare_like_notifications_read).with(post.id) + expect_any_instance_of(PostService).not_to receive(:mark_mention_notifications_read).with(post.id) + PostService.new.mark_user_notifications(post.id) end end - describe "#retract_post" do + describe "#destroy" do it "let a user delete his message" do - message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id) - post_service = PostService.new(id: message.id, user: alice) - post_service.retract_post - expect(StatusMessage.find_by_id(message.id)).to be_nil + PostService.new(alice).destroy(post.id) + expect(StatusMessage.find_by_id(post.id)).to be_nil end it "sends a retraction on delete" do - message = alice.post(:status_message, text: "hey", to: alice.aspects.first.id) - post_service = PostService.new(id: message.id, user: alice) - expect(alice).to receive(:retract).with(message) - post_service.retract_post + expect(alice).to receive(:retract).with(post) + PostService.new(alice).destroy(post.id) end it "will not let you destroy posts visible to you but that you do not own" do - message = bob.post(:status_message, text: "hey", to: bob.aspects.first.id) - post_service = PostService.new(id: message.id, user: alice) - expect { post_service.retract_post }.to raise_error(Diaspora::NotMine) - expect(StatusMessage.exists?(message.id)).to be true + expect { + PostService.new(bob).destroy(post.id) + }.to raise_error Diaspora::NotMine + expect(StatusMessage.find_by_id(post.id)).not_to be_nil end it "will not let you destroy posts that are not visible to you" do - message = eve.post(:status_message, text: "hey", to: eve.aspects.first.id) - expect { PostService.new(id: message.id, user: alice) }.to raise_error(ActiveRecord::RecordNotFound) - expect(StatusMessage.exists?(message.id)).to be true + expect { + PostService.new(eve).destroy(post.id) + }.to raise_error(ActiveRecord::RecordNotFound) + expect(StatusMessage.find_by_id(post.id)).not_to be_nil end end end diff --git a/spec/services/status_message_creation_service_spec.rb b/spec/services/status_message_creation_service_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..617034e09d4b0b08ef7cabb276d6e1ef2b477dcd --- /dev/null +++ b/spec/services/status_message_creation_service_spec.rb @@ -0,0 +1,208 @@ +require "spec_helper" + +describe StatusMessageCreationService do + describe "#create" do + let(:aspect) { alice.aspects.first } + let(:text) { "I'm writing tests" } + let(:params) { + { + status_message: {text: text}, + aspect_ids: [aspect.id.to_s] + } + } + + it "returns the created StatusMessage" do + status_message = StatusMessageCreationService.new(alice).create(params) + expect(status_message).to_not be_nil + expect(status_message.text).to eq(text) + end + + context "with aspect_ids" do + it "creates aspect_visibilities for the StatusMessages" do + alice.aspects.create(name: "another aspect") + + status_message = StatusMessageCreationService.new(alice).create(params) + expect(status_message.aspect_visibilities.map(&:aspect)).to eq([aspect]) + end + + it "does not create aspect_visibilities if the post is public" do + status_message = StatusMessageCreationService.new(alice).create(params.merge(public: true)) + expect(status_message.aspect_visibilities).to be_empty + end + end + + context "with public" do + it "it creates a private StatusMessage by default" do + status_message = StatusMessageCreationService.new(alice).create(params) + expect(status_message.public).to be_falsey + end + + it "it creates a private StatusMessage" do + status_message = StatusMessageCreationService.new(alice).create(params.merge(public: false)) + expect(status_message.public).to be_falsey + end + + it "it creates a public StatusMessage" do + status_message = StatusMessageCreationService.new(alice).create(params.merge(public: true)) + expect(status_message.public).to be_truthy + end + end + + context "with location" do + it "it creates a location" do + location_params = {location_address: "somewhere", location_coords: "1,2"} + status_message = StatusMessageCreationService.new(alice).create(params.merge(location_params)) + location = status_message.location + expect(location.address).to eq("somewhere") + expect(location.lat).to eq("1") + expect(location.lng).to eq("2") + end + + it "does not add a location without location params" do + status_message = StatusMessageCreationService.new(alice).create(params) + expect(status_message.location).to be_nil + end + end + + context "with poll" do + it "it creates a poll" do + poll_params = {poll_question: "something?", poll_answers: %w(yes no maybe)} + status_message = StatusMessageCreationService.new(alice).create(params.merge(poll_params)) + poll = status_message.poll + expect(poll.question).to eq("something?") + expect(poll.poll_answers.size).to eq(3) + poll_answers = poll.poll_answers.map(&:answer) + expect(poll_answers).to include("yes") + expect(poll_answers).to include("no") + expect(poll_answers).to include("maybe") + end + + it "does not add a poll without poll params" do + status_message = StatusMessageCreationService.new(alice).create(params) + expect(status_message.poll).to be_nil + end + end + + context "with photos" do + let(:photo1) { + alice.build_post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: aspect.id).tap(&:save!) + } + let(:photo2) { + alice.build_post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: aspect.id).tap(&:save!) + } + let(:photo_ids) { [photo1.id.to_s, photo2.id.to_s] } + + it "it attaches all photos" do + status_message = StatusMessageCreationService.new(alice).create(params.merge(photos: photo_ids)) + photos = status_message.photos + expect(photos.size).to eq(2) + expect(photos.map(&:id).map(&:to_s)).to match_array(photo_ids) + end + + it "does not attach photos without photos param" do + status_message = StatusMessageCreationService.new(alice).create(params) + expect(status_message.photos).to be_empty + end + + context "with aspect_ids" do + it "it marks the photos as non-public if the post is non-public" do + status_message = StatusMessageCreationService.new(alice).create(params.merge(photos: photo_ids)) + status_message.photos.each do |photo| + expect(photo.public).to be_falsey + end + end + + it "creates aspect_visibilities for the Photo" do + alice.aspects.create(name: "another aspect") + + status_message = StatusMessageCreationService.new(alice).create(params.merge(photos: photo_ids)) + status_message.photos.each do |photo| + expect(photo.aspect_visibilities.map(&:aspect)).to eq([aspect]) + end + end + + it "does not create aspect_visibilities if the post is public" do + status_message = StatusMessageCreationService.new(alice).create(params.merge(photos: photo_ids, public: true)) + status_message.photos.each do |photo| + expect(photo.aspect_visibilities).to be_empty + end + end + + it "sets pending to false on any attached photos" do + status_message = StatusMessageCreationService.new(alice).create(params.merge(photos: photo_ids)) + status_message.photos.each do |photo| + expect(photo.reload.pending).to be_falsey + end + end + end + + context "with public" do + it "it marks the photos as public if the post is public" do + status_message = StatusMessageCreationService.new(alice).create(params.merge(photos: photo_ids, public: true)) + status_message.photos.each do |photo| + expect(photo.public).to be_truthy + end + end + + it "sets pending to false on any attached photos" do + status_message = StatusMessageCreationService.new(alice).create(params.merge(photos: photo_ids, public: true)) + status_message.photos.each do |photo| + expect(photo.reload.pending).to be_falsey + end + end + end + end + + context "with mentions" do + let(:mentioned_user) { FactoryGirl.create(:user) } + let(:text) { + "Hey @{#{bob.name}; #{bob.diaspora_handle}} and @{#{mentioned_user.name}; #{mentioned_user.diaspora_handle}}!" + } + + it "calls Diaspora::Mentionable#filter_for_aspects for private posts" do + expect(Diaspora::Mentionable).to receive(:filter_for_aspects).with(text, alice, aspect.id.to_s) + .and_call_original + StatusMessageCreationService.new(alice).create(params) + end + + it "keeps mentions for users in one of the aspects" do + status_message = StatusMessageCreationService.new(alice).create(params) + expect(status_message.text).to include bob.name + expect(status_message.text).to include bob.diaspora_handle + end + + it "removes mentions for users in other aspects" do + status_message = StatusMessageCreationService.new(alice).create(params) + expect(status_message.text).to include mentioned_user.name + expect(status_message.text).not_to include mentioned_user.diaspora_handle + end + + it "doesn't call Diaspora::Mentionable#filter_for_aspects for public posts" do + expect(Diaspora::Mentionable).not_to receive(:filter_for_aspects) + StatusMessageCreationService.new(alice).create(params.merge(public: true)) + end + + it "keeps all mentions in public posts" do + status_message = StatusMessageCreationService.new(alice).create(params.merge(public: true)) + expect(status_message.text).to include bob.name + expect(status_message.text).to include bob.diaspora_handle + expect(status_message.text).to include mentioned_user.name + expect(status_message.text).to include mentioned_user.diaspora_handle + end + end + + context "dispatch" do + it "dispatches the StatusMessage" do + expect(alice).to receive(:dispatch_post).with(instance_of(StatusMessage), hash_including(service_types: [])) + StatusMessageCreationService.new(alice).create(params) + end + + it "dispatches the StatusMessage to services" do + expect(alice).to receive(:dispatch_post) + .with(instance_of(StatusMessage), + hash_including(service_types: array_including(%w(Services::Facebook Services::Twitter)))) + StatusMessageCreationService.new(alice).create(params.merge(services: %w(twitter facebook))) + end + end + end +end diff --git a/spec/shared_behaviors/account_deletion.rb b/spec/shared_behaviors/account_deletion.rb index 027442b14099e44dfb0fe00ea0c9ccebe7262b76..1f4b655c11353e2d9e43215d39d40e5105fd0e92 100644 --- a/spec/shared_behaviors/account_deletion.rb +++ b/spec/shared_behaviors/account_deletion.rb @@ -32,8 +32,4 @@ shared_examples_for 'it removes the person associations' do expect(ConversationVisibility.where(:person_id => alice.person.id)).not_to be_empty expect(ConversationVisibility.where(:person_id => @person.id)).to be_empty end - - it "deletes the share visibilities on the person's posts" do - expect(ShareVisibility.for_contacts_of_a_person(@person)).to be_empty - end end diff --git a/spec/shared_behaviors/dispatcher.rb b/spec/shared_behaviors/dispatcher.rb new file mode 100644 index 0000000000000000000000000000000000000000..1d87d8c24daeb7caf609d596cd1bfdbf21307ae4 --- /dev/null +++ b/spec/shared_behaviors/dispatcher.rb @@ -0,0 +1,85 @@ +shared_examples "a dispatcher" do + describe "#dispatch" do + context "deliver to user services" do + let(:twitter) { Services::Twitter.new(access_token: "twitter") } + + before do + alice.services << twitter + end + + it "delivers a StatusMessage to specified services" do + opts = {service_types: "Services::Twitter", url: "https://example.org/p/123"} + expect(Workers::PostToService).to receive(:perform_async).with(twitter.id, post.id, "https://example.org/p/123") + Diaspora::Federation::Dispatcher.build(alice, post, opts).dispatch + end + + it "delivers a Retraction of a Post to specified services" do + opts = {service_types: "Services::Twitter", tweet_id: "123"} + expect(Workers::DeletePostFromService).to receive(:perform_async).with(twitter.id, opts) + + retraction = Retraction.for(post, alice) + Diaspora::Federation::Dispatcher.build(alice, retraction, opts).dispatch + end + + it "does not queue service jobs when no services specified" do + opts = {url: "https://example.org/p/123"} + expect(Workers::PostToService).not_to receive(:perform_async) + Diaspora::Federation::Dispatcher.build(alice, post, opts).dispatch + end + + it "does not deliver a Comment to services" do + expect(Workers::PostToService).not_to receive(:perform_async) + Diaspora::Federation::Dispatcher.build(alice, comment).dispatch + end + + it "does not deliver a Retraction of a Comment to services" do + expect(Workers::DeletePostFromService).not_to receive(:perform_async) + + retraction = Retraction.for(comment, alice) + Diaspora::Federation::Dispatcher.build(alice, retraction).dispatch + end + end + + context "deliver to local user" do + it "queues receive local job for all local receivers" do + local_subscriber_ids = post.subscribers.select(&:local?).map(&:owner_id) + expect(Workers::ReceiveLocal).to receive(:perform_async).with("StatusMessage", post.id, local_subscriber_ids) + Diaspora::Federation::Dispatcher.build(alice, post).dispatch + end + + it "gets the object for the receiving user" do + expect(Workers::ReceiveLocal).to receive(:perform_async).with("RSpec::Mocks::Double", 42, [bob.id]) + + object = double + object_to_receive = double + expect(object).to receive(:subscribers).and_return([bob.person]) + expect(object).to receive(:object_to_receive).and_return(object_to_receive) + expect(object).to receive(:public?).and_return(post.public?) + expect(object_to_receive).to receive(:id).and_return(42) + + Diaspora::Federation::Dispatcher.build(alice, object).dispatch + end + + it "does not queue a job if the object to receive is nil" do + expect(Workers::ReceiveLocal).not_to receive(:perform_async) + + object = double + expect(object).to receive(:subscribers).and_return([bob.person]) + expect(object).to receive(:object_to_receive).and_return(nil) + expect(object).to receive(:public?).and_return(post.public?) + + Diaspora::Federation::Dispatcher.build(alice, object).dispatch + end + + it "queues receive local job for a specific subscriber" do + expect(Workers::ReceiveLocal).to receive(:perform_async).with("StatusMessage", post.id, [eve.id]) + Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [eve.person]).dispatch + end + + it "queues receive local job for a specific subscriber id" do + expect(Workers::ReceiveLocal).to receive(:perform_async).with("StatusMessage", post.id, [eve.id]) + Diaspora::Federation::Dispatcher.build(alice, post, subscriber_ids: [eve.person.id]).dispatch + end + end + end +end diff --git a/spec/shared_behaviors/receiving.rb b/spec/shared_behaviors/receiving.rb new file mode 100644 index 0000000000000000000000000000000000000000..78898dc8c78c916b5f00df425db6b305c13395fc --- /dev/null +++ b/spec/shared_behaviors/receiving.rb @@ -0,0 +1,75 @@ +require "spec_helper" + +shared_examples_for "it ignores existing object received twice" do |klass| + it "return nil if the #{klass} already exists" do + expect(Diaspora::Federation::Receive.perform(entity)).not_to be_nil + expect(Diaspora::Federation::Receive.perform(entity)).to be_nil + end + + it "does not change anything if the #{klass} already exists" do + Diaspora::Federation::Receive.perform(entity) + + expect_any_instance_of(klass).not_to receive(:create_or_update) + + Diaspora::Federation::Receive.perform(entity) + end +end + +shared_examples_for "it rejects if the parent author ignores the author" do |klass| + it "saves the relayable if the author is not ignored" do + Diaspora::Federation::Receive.perform(entity) + + expect(klass.find_by!(guid: entity.guid)).to be_instance_of(klass) + end + + context "if the author is ignored" do + before do + alice.blocks.create(person: sender) + end + + it "raises an error and does not save the relayable" do + expect { + Diaspora::Federation::Receive.perform(entity) + }.to raise_error Diaspora::Federation::AuthorIgnored + + expect(klass.find_by(guid: entity.guid)).to be_nil + end + + it "it sends a retraction back to the author" do + dispatcher = double + expect(Diaspora::Federation::Dispatcher).to receive(:build) do |retraction_sender, retraction, opts| + expect(retraction_sender).to eq(alice) + expect(retraction.data[:target_guid]).to eq(entity.guid) + expect(retraction.data[:target_type]).to eq(klass.to_s) + expect(opts).to eq(subscribers: [sender]) + dispatcher + end + expect(dispatcher).to receive(:dispatch) + + expect { + Diaspora::Federation::Receive.perform(entity) + }.to raise_error Diaspora::Federation::AuthorIgnored + end + end +end + +shared_examples_for "it relays relayables" do |klass| + it "dispatches the received relayable" do + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch) do |parent_author, relayable| + expect(parent_author).to eq(alice) + expect(relayable).to be_instance_of(klass) + expect(relayable.guid).to eq(entity.guid) + end + + Diaspora::Federation::Receive.perform(entity) + end + + it "does not dispatch the received relayable if there was an error saving it and it exists already" do + allow_any_instance_of(klass).to receive(:save!).and_raise(RuntimeError, "something went wrong") + allow(Diaspora::Federation::Receive).to receive(:load_from_database).and_return(true) + + expect(Diaspora::Federation::Dispatcher).to_not receive(:defer_dispatch) + + Diaspora::Federation::Receive.perform(entity) + end +end diff --git a/spec/shared_behaviors/relayable.rb b/spec/shared_behaviors/relayable.rb index 6973f6e1f6d3bd49ba693fbd3619d18ea95d63a5..2fd48d904db74e7f0c6df18f0416a838c2e2bc0c 100644 --- a/spec/shared_behaviors/relayable.rb +++ b/spec/shared_behaviors/relayable.rb @@ -2,14 +2,12 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' +require "spec_helper" shared_examples_for "it is relayable" do - - describe 'interacted_at' do - it 'sets the interacted at of the parent to the created at of the relayable post' do + describe "interacted_at" do + it "sets the interacted at of the parent to the created at of the relayable post" do Timecop.freeze Time.now do - relayable = build_object relayable.save if relayable.parent.respond_to?(:interacted_at) #I'm sorry. expect(relayable.parent.interacted_at.to_i).to eq(relayable.created_at.to_i) @@ -18,113 +16,84 @@ shared_examples_for "it is relayable" do end end - describe 'validations' do - describe 'on :author_id' do + describe "validations" do + context "author ignored by parent author" do context "the author is on the parent object author's ignore list when object is created" do before do - bob.blocks.create(:person => alice.person) - @relayable = build_object + bob.blocks.create(person: alice.person) end it "is invalid" do - expect(@relayable).not_to be_valid - expect(@relayable.errors[:author_id].size).to eq(1) - end - - it "sends a retraction for the object" do - skip 'need to figure out how to test this' - expect(RelayableRetraction).to receive(:build) - expect(Postzord::Dispatcher).to receive(:build) - @relayable.valid? + expect(relayable).not_to be_valid + expect(relayable.errors[:author_id].size).to eq(1) end it "works if the object has no parent" do # This can happen if we get a comment for a post that's been deleted - @relayable.parent = nil - expect { @relayable.valid? }.to_not raise_exception + relayable.parent = nil + expect { relayable.valid? }.to_not raise_exception end end context "the author is added to the parent object author's ignore list later" do it "is valid" do - relayable = build_object relayable.save! - bob.blocks.create(:person => alice.person) + bob.blocks.create(person: alice.person) expect(relayable).to be_valid end end end end - context 'encryption' do - describe '#parent_author_signature' do - it 'should sign the object if the user is the post author' do - expect(@object_by_parent_author.verify_parent_author_signature).to be true + describe "#subscribers" do + context "parent is local" do + it "returns the parents original audience, if author is local" do + expect(object_on_local_parent.subscribers.map(&:id)) + .to match_array([local_leia.person, remote_raphael].map(&:id)) end - it 'does not sign as the parent author is not parent' do - @object_by_recipient.author_signature = @object_by_recipient.send(:sign_with_key, @local_leia.encryption_key) - expect(@object_by_recipient.verify_parent_author_signature).to be false - end + it "returns remote persons of the parents original audience not on same pod as the author, if author is remote" do + person1 = FactoryGirl.create(:person, pod: remote_raphael.pod) + person2 = FactoryGirl.create(:person, pod: FactoryGirl.create(:pod)) + local_luke.share_with(person1, local_luke.aspects.first) + local_luke.share_with(person2, local_luke.aspects.first) - it 'should verify a object made on a remote post by a different contact' do - @object_by_recipient.author_signature = @object_by_recipient.send(:sign_with_key, @local_leia.encryption_key) - @object_by_recipient.parent_author_signature = @object_by_recipient.send(:sign_with_key, @local_luke.encryption_key) - expect(@object_by_recipient.verify_parent_author_signature).to be true + expect(remote_object_on_local_parent.subscribers.map(&:id)).to match_array([person2].map(&:id)) end end - describe '#author_signature' do - it 'should sign as the object author' do - expect(@object_on_remote_parent.signature_valid?).to be true - expect(@object_by_parent_author.signature_valid?).to be true - expect(@object_by_recipient.signature_valid?).to be true + context "parent is remote" do + it "returns the author of parent and author of relayable (for local delivery)" do + expect(object_on_remote_parent.subscribers.map(&:id)) + .to match_array([remote_raphael, local_luke.person].map(&:id)) end end end - context 'propagation' do - describe '#receive' do - it 'does not overwrite a object that is already in the db' do - expect { - @dup_object_by_parent_author.receive(@local_leia, @local_luke.person) - }.to_not change { @dup_object_by_parent_author.class.count } - end - - it 'does not process if post_creator_signature is invalid' do - @object_by_parent_author.delete # remove object from db so we set a creator sig - @dup_object_by_parent_author.parent_author_signature = "dsfadsfdsa" - expect(@dup_object_by_parent_author.receive(@local_leia, @local_luke.person)).to eq(nil) - end + describe "#signature" do + let(:signature_class) { described_class.reflect_on_association(:signature).klass } - it 'signs when the person receiving is the parent author' do - @object_by_recipient.save - @object_by_recipient.receive(@local_luke, @local_leia.person) - expect(@object_by_recipient.reload.parent_author_signature).not_to be_blank - end - - it 'dispatches when the person receiving is the parent author' do - p = Postzord::Dispatcher.build(@local_luke, @object_by_recipient) - expect(p).to receive(:post) - allow(p.class).to receive(:new).and_return(p) - @object_by_recipient.receive(@local_luke, @local_leia.person) - end + before do + remote_object_on_local_parent.signature = signature_class.new( + author_signature: "signature", + additional_data: {"new_property" => "some text"}, + signature_order: FactoryGirl.create(:signature_order) + ) + end - it 'calls after_receive callback' do - expect(@object_by_recipient).to receive(:after_receive) - allow(@object_by_recipient.class).to receive(:where).and_return([@object_by_recipient]) - @object_by_recipient.receive(@local_luke, @local_leia.person) - end + it "returns the signature data" do + signature = described_class.find(remote_object_on_local_parent.id).signature + expect(signature).not_to be_nil + expect(signature.author_signature).to eq("signature") + expect(signature.additional_data).to eq("new_property" => "some text") + expect(signature.order).to eq(%w(guid parent_guid text author)) end - describe '#subscribers' do - it 'returns the posts original audience, if the post is owned by the user' do - expect(@object_by_parent_author.subscribers(@local_luke).map(&:id)).to match_array([@local_leia.person, @remote_raphael].map(&:id)) - end + it "deletes the signature when destroying the relayable" do + id = remote_object_on_local_parent.id + remote_object_on_local_parent.destroy! - it 'returns the owner of the original post, if the user owns the object' do - expect(@object_by_recipient.subscribers(@local_leia).map(&:id)).to match_array([@local_luke.person].map(&:id)) - end + signature = signature_class.find_by(signature_class.primary_key => id) + expect(signature).to be_nil end end end - diff --git a/spec/shared_behaviors/signature.rb b/spec/shared_behaviors/signature.rb new file mode 100644 index 0000000000000000000000000000000000000000..3b40d751ef613e37ea6890a0d2aa69803fb380fb --- /dev/null +++ b/spec/shared_behaviors/signature.rb @@ -0,0 +1,57 @@ +require "spec_helper" + +shared_examples_for "signature data" do + let(:relayable) { FactoryGirl.create(relayable_type) } + let(:signature) { + described_class.new( + relayable_type => relayable, + :author_signature => "signature", + :additional_data => {"additional_data" => "some data"}, + :signature_order => SignatureOrder.new(order: "author guid parent_guid") + ) + } + + describe "#order" do + it "it returns the order as array" do + expect(signature.order).to eq(%w(author guid parent_guid)) + end + end + + describe "#additional_data" do + it "is stored as hash" do + signature.save + + entity = described_class.reflect_on_association(relayable_type).klass.find(relayable.id) + expect(entity.signature.additional_data).to eq("additional_data" => "some data") + end + + it "can be missing" do + signature.additional_data = nil + signature.save + + entity = described_class.reflect_on_association(relayable_type).klass.find(relayable.id) + expect(entity.signature.additional_data).to eq({}) + end + end + + context "validation" do + it "is valid" do + expect(signature).to be_valid + end + + it "requires a linked relayable" do + signature.public_send("#{relayable_type}=", nil) + expect(signature).not_to be_valid + end + + it "requires a signature_order" do + signature.signature_order = nil + expect(signature).not_to be_valid + end + + it "requires a author_signature" do + signature.author_signature = nil + expect(signature).not_to be_valid + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 586ec28241b4e267bf2a4957964e8d9233112e4c..9033d284285c3e42bd8cfdf45a0cfb17766ba66a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,10 @@ # the COPYRIGHT file. ENV["RAILS_ENV"] ||= "test" + +require 'coveralls' +Coveralls.wear!('rails') + require File.join(File.dirname(__FILE__), "..", "config", "environment") require Rails.root.join("spec", "helper_methods") require Rails.root.join("spec", "spec-doc") @@ -23,10 +27,6 @@ UnprocessedImage.enable_processing = false Rails.application.routes.default_url_options[:host] = AppConfig.pod_uri.host Rails.application.routes.default_url_options[:port] = AppConfig.pod_uri.port -def set_up_friends - [local_luke, local_leia, remote_raphael] -end - def alice @alice ||= User.find_by(username: "alice") end @@ -59,6 +59,29 @@ def photo_fixture_name @photo_fixture_name = File.join(File.dirname(__FILE__), "fixtures", "button.png") end +def jwks_file_path + @jwks_file = File.join(File.dirname(__FILE__), "fixtures", "jwks.json") +end + +def valid_client_assertion_path + @valid_client_assertion = File.join(File.dirname(__FILE__), "fixtures", "valid_client_assertion.txt") +end + +def client_assertion_with_tampered_sig_path + @client_assertion_with_tampered_sig = File.join(File.dirname(__FILE__), "fixtures", + "client_assertion_with_tampered_sig.txt") +end + +def client_assertion_with_nonexistent_kid_path + @client_assertion_with_nonexistent_kid = File.join(File.dirname(__FILE__), "fixtures", + "client_assertion_with_nonexistent_kid.txt") +end + +def client_assertion_with_nonexistent_client_id_path + @client_assertion_with_nonexistent_client_id = File.join(File.dirname(__FILE__), "fixtures", + "client_assertion_with_nonexistent_client_id.txt") +end + # Force fixture rebuild FileUtils.rm_f(Rails.root.join("tmp", "fixture_builder.yml")) @@ -70,7 +93,8 @@ support_files.each {|f| require f } require fixture_builder_file RSpec.configure do |config| - config.include Devise::TestHelpers, :type => :controller + config.include Devise::Test::ControllerHelpers, type: :controller + config.include Devise::Test::IntegrationHelpers, type: :request config.mock_with :rspec config.example_status_persistence_file_path = "tmp/rspec-persistance.txt" @@ -82,10 +106,9 @@ RSpec.configure do |config| config.before(:each) do I18n.locale = :en stub_request(:post, "https://pubsubhubbub.appspot.com/") - disable_typhoeus $process_queue = false - allow_any_instance_of(Postzord::Dispatcher::Public).to receive(:deliver_to_remote) - allow_any_instance_of(Postzord::Dispatcher::Private).to receive(:deliver_to_remote) + allow(Workers::SendPublic).to receive(:perform_async) + allow(Workers::SendPrivate).to receive(:perform_async) end config.expect_with :rspec do |expect_config| @@ -106,6 +129,11 @@ RSpec.configure do |config| ActionMailer::Base.deliveries.clear end + # Reset gon + config.after(:each) do + RequestStore.store[:gon].gon.clear unless RequestStore.store[:gon].nil? + end + config.include FactoryGirl::Syntax::Methods end diff --git a/spec/support/fake_typhoeus.rb b/spec/support/fake_typhoeus.rb deleted file mode 100644 index fdbacaba42a69a5a41f5a0eb633c82d94ae7de94..0000000000000000000000000000000000000000 --- a/spec/support/fake_typhoeus.rb +++ /dev/null @@ -1,22 +0,0 @@ -class FakeHydra - def queue(*args); end - def run; end -end - -class FakeHydraRequest - def initialize(*args); end - def on_complete; end -end - -def disable_typhoeus - silence_warnings do - Workers::HttpMulti.const_set('Hydra', FakeHydra) - Workers::HttpMulti.const_set('Request', FakeHydraRequest) - end -end -def enable_typhoeus - silence_warnings do - Workers::HttpMulti.const_set('Hydra', Typhoeus::Hydra) - Workers::HttpMulti.const_set('Request', Typhoeus::Request) - end -end diff --git a/spec/support/fixture_generation.rb b/spec/support/fixture_generation.rb index b952f145b8165b6ddd66b5cbcf24d907d676bb9c..3f3496c421606194fa64f28dc30703ca11aff641 100644 --- a/spec/support/fixture_generation.rb +++ b/spec/support/fixture_generation.rb @@ -44,3 +44,6 @@ RSpec::Rails::ControllerExampleGroup.class_eval do include JasmineFixtureGeneration end +RSpec::Rails::HelperExampleGroup.class_eval do + include JasmineFixtureGeneration +end diff --git a/spec/support/gon.rb b/spec/support/gon.rb new file mode 100644 index 0000000000000000000000000000000000000000..418c755b6de136b9958b543cbcb560de95202d05 --- /dev/null +++ b/spec/support/gon.rb @@ -0,0 +1,30 @@ +shared_context :gon do + let(:gon) { RequestStore.store[:gon].gon } +end + +module HelperMethods + def expect_aspects + expect(gon["user"].aspects).not_to be_nil + expect(gon["user"].aspects.length).not_to be_nil + end + + def expect_memberships(memberships) + expect(memberships).not_to be_nil + expect(memberships.length).not_to be_nil + end + + def expect_contact(preload_key) + expect(gon["preloads"][preload_key][:contact]).not_to be_falsy + expect_memberships(gon["preloads"][preload_key][:contact][:aspect_memberships]) + end + + def expect_gon_preloads_for_aspect_membership_dropdown(preload_key, sharing) + expect(gon["preloads"][preload_key]).not_to be_nil + if sharing + expect_contact(preload_key) + else + expect(gon["preloads"][preload_key][:contact]).to be_falsy + end + expect_aspects + end +end diff --git a/spec/support/user_methods.rb b/spec/support/user_methods.rb index 3909c1645a275bc4a8fd0a519a232eb27db95027..9b5860809dbdb073b1dbc3919ba93b5dbed62f40 100644 --- a/spec/support/user_methods.rb +++ b/spec/support/user_methods.rb @@ -7,6 +7,11 @@ class User end end + def add_contact_to_aspect(contact, aspect) + return if AspectMembership.exists?(contact_id: contact.id, aspect_id: aspect.id) + contact.aspect_memberships.create!(aspect: aspect) + end + def post(class_name, opts = {}) inlined_jobs do aspects = self.aspects_from_ids(opts[:to]) @@ -16,14 +21,12 @@ class User if p.save! self.aspects.reload - add_to_streams(p, aspects) dispatch_opts = { url: Rails.application.routes.url_helpers.post_url( p, host: AppConfig.pod_uri.to_s ), to: opts[:to]} - dispatch_opts.merge!(:additional_subscribers => p.root.author) if class_name == :reshare dispatch_post(p, dispatch_opts) end unless opts[:created_at] @@ -33,4 +36,8 @@ class User p end end + + def build_comment(options={}) + Comment::Generator.new(self, options.delete(:post), options.delete(:text)).build(options) + end end diff --git a/spec/workers/deferred_dispatch_spec.rb b/spec/workers/deferred_dispatch_spec.rb index f0a20d768e8fdf5152a7e69418f8e13f1d02e823..214106d8d07e4acd1b88cd2a0eced8ebdff7bda3 100644 --- a/spec/workers/deferred_dispatch_spec.rb +++ b/spec/workers/deferred_dispatch_spec.rb @@ -1,9 +1,9 @@ -require 'spec_helper' +require "spec_helper" describe Workers::DeferredDispatch do it "handles non existing records gracefully" do expect { - described_class.new.perform(alice.id, 'Comment', 0, {}) + described_class.new.perform(alice.id, "Comment", 0, {}) }.to_not raise_error end end diff --git a/spec/workers/delete_post_from_service_spec.rb b/spec/workers/delete_post_from_service_spec.rb index 75e902034428094be3235a4333d9999d804cd222..2830ca7cddd9602fef42342e1ecc4007da8e7fee 100644 --- a/spec/workers/delete_post_from_service_spec.rb +++ b/spec/workers/delete_post_from_service_spec.rb @@ -1,16 +1,13 @@ -require 'spec_helper' +require "spec_helper" describe Workers::DeletePostFromService do - before do - @user = alice - @post = @user.post(:status_message, :text => "hello", :to =>@user.aspects.first.id, :public =>true, :facebook_id => "23456" ) - end + it "calls service#delete_from_service with given opts" do + service = double + opts = {facebook_id: "23456"} + + expect(service).to receive(:delete_from_service).with(opts) + allow(Service).to receive(:find_by_id).with("123").and_return(service) - it 'calls service#delete_post with given service' do - m = double() - url = "foobar" - expect(m).to receive(:delete_post) - allow(Service).to receive(:find_by_id).and_return(m) - Workers::DeletePostFromService.new.perform("123", @post.id.to_s) + Workers::DeletePostFromService.new.perform("123", opts) end end diff --git a/spec/workers/http_multi_spec.rb b/spec/workers/http_multi_spec.rb deleted file mode 100644 index a4831614b2255e4674507596caa349f164dc6dd1..0000000000000000000000000000000000000000 --- a/spec/workers/http_multi_spec.rb +++ /dev/null @@ -1,141 +0,0 @@ -require 'spec_helper' - -describe Workers::HttpMulti do - before :all do - WebMock.disable_net_connect! allow_localhost: true - WebMock::HttpLibAdapters::TyphoeusAdapter.disable! - enable_typhoeus - end - after :all do - disable_typhoeus - WebMock.disable_net_connect! - end - - before do - @people = [FactoryGirl.create(:person), FactoryGirl.create(:person)] - @post_xml = Base64.encode64 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH" - - @hydra = Typhoeus::Hydra.new - allow(Typhoeus::Hydra).to receive(:new).and_return(@hydra) - @salmon = Salmon::EncryptedSlap.create_by_user_and_activity bob, Base64.decode64(@post_xml) - allow(Salmon::EncryptedSlap).to receive(:create_by_user_and_activity).and_return @salmon - @body = "encrypted things" - allow(@salmon).to receive(:xml_for).and_return @body - - @response = Typhoeus::Response.new( - code: 200, - body: "", - time: 0.2, - effective_url: 'http://foobar.com', - return_code: :ok - ) - @failed_response = Typhoeus::Response.new( - code: 504, - body: "", - time: 0.2, - effective_url: 'http://foobar.com', - return_code: :ok - ) - @ssl_error_response = Typhoeus::Response.new( - code: 0, - body: "", - time: 0.2, - effective_url: 'http://foobar.com', - return_code: :ssl_connect_error - ) - @unable_to_resolve_response = Typhoeus::Response.new( - code: 0, - body: "", - time: 0.2, - effective_url: 'http://foobar.com', - return_code: :couldnt_resolve_host - ) - end - - it 'POSTs to more than one person' do - @people.each do |person| - Typhoeus.stub(person.receive_url).and_return @response - end - - expect(@hydra).to receive(:queue).twice - expect(@hydra).to receive(:run).once - - Workers::HttpMulti.new.perform bob.id, @post_xml, @people.map(&:id), "Postzord::Dispatcher::Private" - end - - it 'retries' do - person = @people.first - - Typhoeus.stub(person.receive_url).and_return @failed_response - - expect(Workers::HttpMulti).to receive(:perform_in).with(1.hour, bob.id, @post_xml, [person.id], anything, 1).once - Workers::HttpMulti.new.perform bob.id, @post_xml, [person.id], "Postzord::Dispatcher::Private" - end - - it 'retries if it could not resolve the server' do - person = @people.first - - Typhoeus.stub(person.receive_url).and_return @unable_to_resolve_response - - expect(Workers::HttpMulti).to receive(:perform_in).with(1.hour, bob.id, @post_xml, [person.id], anything, 1).once - Workers::HttpMulti.new.perform bob.id, @post_xml, [person.id], "Postzord::Dispatcher::Private" - end - - it 'does not retry on an SSL error' do - person = @people.first - - Typhoeus.stub(person.receive_url).and_return @ssl_error_response - - expect(Workers::HttpMulti).not_to receive(:perform_in) - Workers::HttpMulti.new.perform bob.id, @post_xml, [person.id], "Postzord::Dispatcher::Private" - end - - it 'max retries' do - person = @people.first - - Typhoeus.stub(person.receive_url).and_return @failed_response - - expect(Workers::HttpMulti).not_to receive :perform_in - Workers::HttpMulti.new.perform bob.id, @post_xml, [person.id], "Postzord::Dispatcher::Private", 3 - end - - it 'generates encrypted xml for people' do - person = @people.first - - Typhoeus.stub(person.receive_url).and_return @response - expect(@salmon).to receive(:xml_for).and_return @body - - Workers::HttpMulti.new.perform bob.id, @post_xml, [person.id], "Postzord::Dispatcher::Private" - end - - it 'updates http users who have moved to https' do - person = @people.first - person.update_url("http://remote.net/") - - response = Typhoeus::Response.new( - code: 301, - effective_url: 'https://foobar.com', - response_headers: "Location: #{person.receive_url.sub('http://', 'https://')}", - body: "", - time: 0.2 - ) - Typhoeus.stub(person.receive_url).and_return response - - Workers::HttpMulti.new.perform bob.id, @post_xml, [person.id], "Postzord::Dispatcher::Private" - expect(Person.find(person.id).url).to eq("https://remote.net/") - end - - it 'only sends to users with valid RSA keys' do - person = @people.first - person.serialized_public_key = "-----BEGIN RSA PUBLIC KEY-----\nPsych!\n-----END RSA PUBLIC KEY-----" - person.save - - allow(@salmon).to receive(:xml_for).and_call_original - - Typhoeus.stub(person.receive_url).and_return @response - Typhoeus.stub(@people[1].receive_url).and_return @response - - expect(@hydra).to receive(:queue).once - Workers::HttpMulti.new.perform bob.id, @post_xml, @people.map(&:id), "Postzord::Dispatcher::Private" - end -end diff --git a/spec/workers/notify_local_users_spec.rb b/spec/workers/notify_local_users_spec.rb deleted file mode 100644 index f49383e4645c9b33fd8f7d84742d0b42929a9b04..0000000000000000000000000000000000000000 --- a/spec/workers/notify_local_users_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Workers::NotifyLocalUsers do - describe '#perfom' do - it 'should call Notification.notify for each participant user' do - post = double(id: 1234, author: double(diaspora_handle: "foo@bar")) - klass_name = double(constantize: double(find_by_id: post)) - person = double(id: 4321) - allow(Person).to receive(:find_by_id).and_return(person) - expect(Notification).to receive(:notify).with(instance_of(User), post, person).twice - - Workers::NotifyLocalUsers.new.perform([alice.id, eve.id], klass_name, post.id, person.id) - end - end -end diff --git a/spec/workers/receive_local_batch_spec.rb b/spec/workers/receive_local_batch_spec.rb deleted file mode 100644 index acd841cf3101e303401e9a0fb185fbca3f62fe59..0000000000000000000000000000000000000000 --- a/spec/workers/receive_local_batch_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -require "spec_helper" - -describe Workers::ReceiveLocalBatch do - it "calls the postzord" do - post = double - allow(Post).to receive(:find).with(1).and_return(post) - - zord = double - expect(Postzord::Receiver::LocalBatch).to receive(:new).with(post, [2]).and_return(zord) - expect(zord).to receive(:perform!) - - Workers::ReceiveLocalBatch.new.perform("Post", 1, [2]) - end -end diff --git a/spec/workers/receive_private_spec.rb b/spec/workers/receive_private_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..86d09ed19423a363d599cd98e03b228a3ba5200e --- /dev/null +++ b/spec/workers/receive_private_spec.rb @@ -0,0 +1,40 @@ +require "spec_helper" + +describe Workers::ReceivePrivate do + let(:data) { "<xml></xml>" } + + it "calls receive_private of federation gem" do + rsa_key = double + + expect(OpenSSL::PKey::RSA).to receive(:new).with(alice.serialized_private_key).and_return(rsa_key) + expect(DiasporaFederation::Federation::Receiver).to receive(:receive_private).with(data, rsa_key, alice.id, true) + + Workers::ReceivePrivate.new.perform(alice.id, data, true) + end + + it "filters errors that would also fail on second try" do + rsa_key = double + + expect(OpenSSL::PKey::RSA).to receive(:new).with(alice.serialized_private_key).and_return(rsa_key) + expect(DiasporaFederation::Federation::Receiver).to receive(:receive_private).with( + data, rsa_key, alice.id, false + ).and_raise(DiasporaFederation::Salmon::InvalidSignature) + + expect { + Workers::ReceivePrivate.new.perform(alice.id, data, false) + }.not_to raise_error + end + + it "does not filter errors that would succeed on second try" do + rsa_key = double + + expect(OpenSSL::PKey::RSA).to receive(:new).with(alice.serialized_private_key).and_return(rsa_key) + expect(DiasporaFederation::Federation::Receiver).to receive(:receive_private).with( + data, rsa_key, alice.id, false + ).and_raise(DiasporaFederation::Federation::Fetcher::NotFetchable) + + expect { + Workers::ReceivePrivate.new.perform(alice.id, data, false) + }.to raise_error DiasporaFederation::Federation::Fetcher::NotFetchable + end +end diff --git a/spec/workers/receive_public_spec.rb b/spec/workers/receive_public_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..0f2c3aa7c86fb732366b98daf1f6a1e072acd4f3 --- /dev/null +++ b/spec/workers/receive_public_spec.rb @@ -0,0 +1,31 @@ +require "spec_helper" + +describe Workers::ReceivePublic do + let(:data) { "<xml></xml>" } + + it "calls receive_public of federation gem" do + expect(DiasporaFederation::Federation::Receiver).to receive(:receive_public).with(data, true) + + Workers::ReceivePublic.new.perform(data, true) + end + + it "filters errors that would also fail on second try" do + expect(DiasporaFederation::Federation::Receiver).to receive(:receive_public).with( + data, false + ).and_raise(DiasporaFederation::Salmon::InvalidSignature) + + expect { + Workers::ReceivePublic.new.perform(data, false) + }.not_to raise_error + end + + it "does not filter errors that would succeed on second try" do + expect(DiasporaFederation::Federation::Receiver).to receive(:receive_public).with( + data, false + ).and_raise(DiasporaFederation::Federation::Fetcher::NotFetchable) + + expect { + Workers::ReceivePublic.new.perform(data, false) + }.to raise_error DiasporaFederation::Federation::Fetcher::NotFetchable + end +end diff --git a/spec/workers/receive_salmon_spec.rb b/spec/workers/receive_salmon_spec.rb deleted file mode 100644 index a57bc6fbcdd51d01fd8e96dda49f57762016685a..0000000000000000000000000000000000000000 --- a/spec/workers/receive_salmon_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'spec_helper' - -describe Workers::ReceiveEncryptedSalmon do - before do - @user = alice - @xml = '<xml></xml>' - allow(User).to receive(:find){ |id| - if id == @user.id - @user - else - nil - end - } - end - it 'calls receive_salmon' do - zord = double - - expect(zord).to receive(:perform!) - expect(Postzord::Receiver::Private).to receive(:new).with(@user, hash_including(:salmon_xml => @xml)).and_return(zord) - - Workers::ReceiveEncryptedSalmon.new.perform(@user.id, @xml) - end -end diff --git a/spec/workers/receive_spec.rb b/spec/workers/receive_spec.rb deleted file mode 100644 index 0ee0b0a5341bc6346afa1eacf3144ed40218d537..0000000000000000000000000000000000000000 --- a/spec/workers/receive_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'spec_helper' - -describe Workers::Receive do - before do - @user = alice - @person = FactoryGirl.create(:person) - @xml = '<xml></xml>' - allow(User).to receive(:find){ |id| - if id == @user.id - @user - else - nil - end - } - end - - it 'calls receive' do - zord_double = double() - expect(zord_double).to receive(:parse_and_receive).with(@xml) - expect(Postzord::Receiver::Private).to receive(:new).with(@user, anything).and_return(zord_double) - Workers::Receive.new.perform(@user.id, @xml, @person.id) - end -end diff --git a/spec/workers/recurring_pod_check_spec.rb b/spec/workers/recurring_pod_check_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..fec3b7f24a4dd3c49679c14bdb3529d6981517e1 --- /dev/null +++ b/spec/workers/recurring_pod_check_spec.rb @@ -0,0 +1,17 @@ + +require "spec_helper" + +describe Workers::RecurringPodCheck do + before do + @pods = (0..4).map do + FactoryGirl.build(:pod).tap { |pod| + expect(pod).to receive(:test_connection!) + } + end + allow(Pod).to receive(:find_in_batches).and_yield(@pods) + end + + it "performs a connection test on all existing pods" do + Workers::RecurringPodCheck.new.perform + end +end diff --git a/spec/workers/resend_invitation_spec.rb b/spec/workers/resend_invitation_spec.rb deleted file mode 100644 index 002cf78a570468f79f9828f7d384135ece386908..0000000000000000000000000000000000000000 --- a/spec/workers/resend_invitation_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe Workers::ResendInvitation do - describe '#perfom' do - it 'should call .resend on the object' do - invite = FactoryGirl.build(:invitation, :service => 'email', :identifier => 'foo@bar.com') - - allow(Invitation).to receive(:find).and_return(invite) - expect(invite).to receive(:resend) - Workers::ResendInvitation.new.perform(invite.id) - end - end -end diff --git a/spec/workers/send_base_spec.rb b/spec/workers/send_base_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..6515faf9069d6796ad105d9616119a163475b88f --- /dev/null +++ b/spec/workers/send_base_spec.rb @@ -0,0 +1,20 @@ +require "spec_helper" + +describe Workers::SendBase do + it "retries first time after at least 256 seconds" do + retry_delay = Workers::SendBase.new.send(:seconds_to_delay, 1) + expect(retry_delay).to be >= 256 + expect(retry_delay).to be < 316 + end + + it "increases the interval for each retry" do + expect(Workers::SendBase.new.send(:seconds_to_delay, 2)).to be >= 625 + expect(Workers::SendBase.new.send(:seconds_to_delay, 3)).to be >= 1_296 + expect(Workers::SendBase.new.send(:seconds_to_delay, 4)).to be >= 2_401 + expect(Workers::SendBase.new.send(:seconds_to_delay, 5)).to be >= 4_096 + expect(Workers::SendBase.new.send(:seconds_to_delay, 6)).to be >= 6_561 + expect(Workers::SendBase.new.send(:seconds_to_delay, 7)).to be >= 10_000 + expect(Workers::SendBase.new.send(:seconds_to_delay, 8)).to be >= 14_641 + expect(Workers::SendBase.new.send(:seconds_to_delay, 9)).to be >= 20_736 + end +end diff --git a/spec/workers/send_private_spec.rb b/spec/workers/send_private_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..947b6c8ee701b9b2fffebce87cc1d6c0d7d84538 --- /dev/null +++ b/spec/workers/send_private_spec.rb @@ -0,0 +1,44 @@ +require "spec_helper" + +describe Workers::SendPrivate do + let(:sender_id) { "any_user@example.org" } + let(:obj_str) { "status_message@guid" } + let(:targets) { + { + "https://example.org/receive/user/guid" => "<xml>post</xml>", + "https://example.com/receive/user/guid" => "<xml>post2</xml>" + } + } + let(:failing_targets) { {"https://example.org/receive/user/guid" => "<xml>post</xml>"} } + + it "succeeds if all urls were successful" do + expect(DiasporaFederation::Federation::Sender).to receive(:private).with( + sender_id, obj_str, targets + ).and_return({}) + expect(Workers::SendPrivate).not_to receive(:perform_in) + + Workers::SendPrivate.new.perform(sender_id, obj_str, targets) + end + + it "retries failing urls" do + expect(DiasporaFederation::Federation::Sender).to receive(:private).with( + sender_id, obj_str, targets + ).and_return(failing_targets) + expect(Workers::SendPrivate).to receive(:perform_in).with( + kind_of(Fixnum), sender_id, obj_str, failing_targets, 1 + ) + + Workers::SendPrivate.new.perform(sender_id, obj_str, targets) + end + + it "does not retry failing urls if max retries is reached" do + expect(DiasporaFederation::Federation::Sender).to receive(:private).with( + sender_id, obj_str, targets + ).and_return(failing_targets) + expect(Workers::SendPrivate).not_to receive(:perform_in) + + expect { + Workers::SendPrivate.new.perform(sender_id, obj_str, targets, 9) + }.to raise_error Workers::SendBase::MaxRetriesReached + end +end diff --git a/spec/workers/send_public_spec.rb b/spec/workers/send_public_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..2bb7eb9c47df5594b59b8b8ffb51492e0ae6f5a6 --- /dev/null +++ b/spec/workers/send_public_spec.rb @@ -0,0 +1,41 @@ +require "spec_helper" + +describe Workers::SendPublic do + let(:sender_id) { "any_user@example.org" } + let(:obj_str) { "status_message@guid" } + let(:urls) { ["https://example.org/receive/public", "https://example.com/receive/public"] } + let(:xml) { "<xml>post</xml>" } + + it "succeeds if all urls were successful" do + expect(DiasporaFederation::Federation::Sender).to receive(:public).with( + sender_id, obj_str, urls, xml + ).and_return([]) + expect(Workers::SendPublic).not_to receive(:perform_in) + + Workers::SendPublic.new.perform(sender_id, obj_str, urls, xml) + end + + it "retries failing urls" do + failing_urls = [urls.at(0)] + expect(DiasporaFederation::Federation::Sender).to receive(:public).with( + sender_id, obj_str, urls, xml + ).and_return(failing_urls) + expect(Workers::SendPublic).to receive(:perform_in).with( + kind_of(Fixnum), sender_id, obj_str, failing_urls, xml, 1 + ) + + Workers::SendPublic.new.perform(sender_id, obj_str, urls, xml) + end + + it "does not retry failing urls if max retries is reached" do + failing_urls = [urls.at(0)] + expect(DiasporaFederation::Federation::Sender).to receive(:public).with( + sender_id, obj_str, urls, xml + ).and_return(failing_urls) + expect(Workers::SendPublic).not_to receive(:perform_in) + + expect { + Workers::SendPublic.new.perform(sender_id, obj_str, urls, xml, 9) + }.to raise_error Workers::SendBase::MaxRetriesReached + end +end diff --git a/vendor/assets/javascripts/jquery.autocomplete-custom.js b/vendor/assets/javascripts/jquery.autocomplete-custom.js deleted file mode 100644 index e10b9de6d49a4275a4b75c6ec6042c7bf15719d3..0000000000000000000000000000000000000000 --- a/vendor/assets/javascripts/jquery.autocomplete-custom.js +++ /dev/null @@ -1,763 +0,0 @@ -/* - * Autocomplete - jQuery plugin 1.1pre - * - * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * Revision: $Id: jquery.autocomplete.js 5785 2008-07-12 10:37:33Z joern.zaefferer $ - * Modified by Diaspora - */ - -;(function($) { - -$.fn.extend({ - autocomplete: function(urlOrData, options) { - var isUrl = typeof urlOrData == "string"; - options = $.extend({}, $.Autocompleter.defaults, { - url: isUrl ? urlOrData : null, - data: isUrl ? null : urlOrData, - delay: isUrl ? $.Autocompleter.defaults.delay : 10, - max: options && !options.scroll ? 10 : 150 - }, options); - - // if highlight is set to false, replace it with a do-nothing function - options.highlight = options.highlight || function(value) { return value; }; - - // if the formatMatch option is not specified, then use formatItem for backwards compatibility - options.formatMatch = options.formatMatch || options.formatItem; - - return this.each(function() { - new $.Autocompleter(this, options); - }); - }, - result: function(handler) { - return this.bind("result", handler); - }, - search: function(handler) { - return this.trigger("search", [handler]); - }, - flushCache: function() { - return this.trigger("flushCache"); - }, - setOptions: function(options){ - return this.trigger("setOptions", [options]); - }, - unautocomplete: function() { - return this.trigger("unautocomplete"); - } -}); - -$.Autocompleter = function(input, options) { - - var KEY = KEYCODES; - - // Create $ object for input element - var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass); - - var timeout; - var previousValue = ""; - var cache = $.Autocompleter.Cache(options); - var hasFocus = 0; - var lastKeyPressCode; - var config = { - mouseDownOnSelect: false - }; - var select = $.Autocompleter.Select(options, input, selectCurrent, config); - - var blockSubmit; - - // prevent form submit in opera when selecting with return key - $.browser.opera && $(input.form).bind("submit.autocomplete", function() { - if (blockSubmit) { - blockSubmit = false; - return false; - } - }); - - // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all - $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) { - // track last key pressed - lastKeyPressCode = event.keyCode; - switch(event.keyCode) { - - case KEY.LEFT: - case KEY.RIGHT: - if( options.disableRightAndLeft && select.visible()){ - event.preventDefault(); - } - break; - case KEY.UP: - if ( select.visible() ) { - event.preventDefault(); - select.prev(); - } else { - onChange(0, true); - } - break; - - case KEY.DOWN: - if ( select.visible() ) { - event.preventDefault(); - select.next(); - } else { - onChange(0, true); - } - break; - - case KEY.PAGEUP: - if ( select.visible() ) { - event.preventDefault(); - select.pageUp(); - } else { - onChange(0, true); - } - break; - - case KEY.PAGEDOWN: - if ( select.visible() ) { - event.preventDefault(); - select.pageDown(); - } else { - onChange(0, true); - } - break; - - // matches also semicolon - case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA: - case KEY.TAB: - case KEY.RETURN: - if( selectCurrent() ) { - // stop default to prevent a form submit, Opera needs special handling - event.preventDefault(); - blockSubmit = true; - return false; - } - break; - - case KEY.ESC: - select.hide(); - break; - - default: - options.onLetterTyped(event, $input); - clearTimeout(timeout); - timeout = setTimeout(onChange, options.delay); - break; - } - }).focus(function(){ - // track whether the field has focus, we shouldn't process any - // results if the field no longer has focus - hasFocus++; - }).blur(function() { - hasFocus = 0; - if (!config.mouseDownOnSelect) { - hideResults(); - } - }).click(function() { - // show select when clicking in a focused field - if ( hasFocus++ > 1 && !select.visible() ) { - onChange(0, true); - } - }).bind("search", function() { - // TODO why not just specifying both arguments? - var fn = (arguments.length > 1) ? arguments[1] : null; - function findValueCallback(q, data) { - var result; - if( data && data.length ) { - for (var i=0; i < data.length; i++) { - if( data[i].result.toLowerCase() == q.toLowerCase() ) { - result = data[i]; - break; - } - } - } - if( typeof fn == "function" ) fn(result); - else $input.trigger("result", result && [result.data, result.value]); - } - $.each(trimWords($input.val()), function(i, value) { - request(value, findValueCallback, findValueCallback); - }); - }).bind("flushCache", function() { - cache.flush(); - }).bind("setOptions", function() { - $.extend(options, arguments[1]); - // if we've updated the data, repopulate - if ( "data" in arguments[1] ) - cache.populate(); - }).bind("unautocomplete", function() { - select.unbind(); - $input.unbind(); - $(input.form).unbind(".autocomplete"); - }); - - - function selectCurrent() { - var selected = select.selected(); - if( !selected ) - return false; - - var v = selected.result; - previousValue = v; - - if ( options.multiple ) { - var words = trimWords($input.val()); - if ( words.length > 1 ) { - v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v; - } - v += options.multipleSeparator; - } - - hideResultsNow(); - options.onSelect($input, selected.data, selected.value); - return true; - } - - function onChange(crap, skipPrevCheck) { - if( lastKeyPressCode == KEY.DEL ) { - select.hide(); - return; - } - - var currentValue = $input.val(); - - if ( !skipPrevCheck && currentValue == previousValue ) - return; - - previousValue = currentValue; - - currentValue = options.searchTermFromValue(currentValue, $input[0].selectionStart); - if ( currentValue.length >= options.minChars) { - $input.addClass(options.loadingClass); - if (!options.matchCase) - currentValue = currentValue.toLowerCase(); - request(currentValue, receiveData, hideResultsNow); - } else { - stopLoading(); - select.hide(); - } - }; - - function trimWords(value) { - if ( !value ) { - return [""]; - } - var words = value.split( options.multipleSeparator ); - var result = []; - $.each(words, function(i, value) { - if ( $.trim(value) ) - result[i] = $.trim(value); - }); - return result; - } - - // fills in the input box w/the first match (assumed to be the best match) - // q: the term entered - // sValue: the first matching result - function autoFill(q, sValue){ - // autofill in the complete box w/the first match as long as the user hasn't entered in more data - // if the last user key pressed was backspace, don't autofill - if( options.autoFill && (options.lastWord($input.val(), null, options.multiple).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) { - // fill in the value (keep the case the user has typed) - $input.val($input.val() + sValue.substring(options.lastWord(previousValue, null, options.multiple).length)); - // select the portion of the value not typed by the user (so the next character will erase) - $.Autocompleter.Selection(input, previousValue.length, previousValue.length + sValue.length); - } - }; - - function hideResults() { - clearTimeout(timeout); - timeout = setTimeout(hideResultsNow, 200); - }; - - function hideResultsNow() { - select.hide(); - clearTimeout(timeout); - stopLoading(); - if (options.mustMatch) { - // call search and run callback - $input.search( - function (result){ - // if no value found, clear the input box - if( !result ) { - if (options.multiple) { - var words = trimWords($input.val()).slice(0, -1); - $input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") ); - } - else - $input.val( "" ); - } - } - ); - } - }; - - function receiveData(q, data) { - if ( data && data.length && hasFocus ) { - stopLoading(); - select.display(data, q); - autoFill(q, data[0].value); - select.show(); - } else { - hideResultsNow(); - } - }; - - function request(term, success, failure) { - if (!options.matchCase) - term = term.toLowerCase(); - var data = cache.load(term); - // recieve the cached data - if (data && data.length) { - success(term, data); - // if an AJAX url has been supplied, try loading the data now - } else if( (typeof options.url == "string") && (options.url.length > 0) ){ - - var extraParams = { - timestamp: +new Date() - }; - $.each(options.extraParams, function(key, param) { - extraParams[key] = typeof param == "function" ? param() : param; - }); - - $.ajax({ - // try to leverage ajaxQueue plugin to abort previous requests - mode: "abort", - // limit abortion to this input - port: "autocomplete" + input.name, - dataType: options.dataType, - url: options.url, - data: $.extend({ - q: options.lastWord(term, null, options.multiple), - limit: options.max - }, extraParams), - success: function(data) { - var parsed = options.parse && options.parse(data) || parse(data); - cache.add(term, parsed); - success(term, parsed); - } - }); - } else { - // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match - select.emptyList(); - failure(term); - } - }; - - function parse(data) { - var parsed = []; - var rows = data.split("\n"); - for (var i=0; i < rows.length; i++) { - var row = $.trim(rows[i]); - if (row) { - row = row.split("|"); - parsed[parsed.length] = { - data: row, - value: row[0], - result: options.formatResult && options.formatResult(row, row[0]) || row[0] - }; - } - } - return parsed; - }; - - function stopLoading() { - $input.removeClass(options.loadingClass); - }; - -}; - -$.Autocompleter.defaults = { - onLetterTyped : function(event){}, - lastWord : function(value, crap, multiple) { - if ( !multiple ) - return value; - var words = trimWords(value); - return words[words.length - 1]; - }, - inputClass: "ac_input", - resultsClass: "ac_results", - loadingClass: "ac_loading", - onSelect: function(input, data, formatted){ - if (select.visible()) - // position cursor at end of input field - $.Autocompleter.Selection(input, input.value.length, input.value.length); - input.val(formatted); - }, - minChars: 1, - delay: 400, - matchCase: false, - matchSubset: true, - matchContains: false, - cacheLength: 10, - max: 100, - mustMatch: false, - extraParams: {}, - selectFirst: true, - formatItem: function(row) { return row[0]; }, - selectionChanged : function(newItem) {}, - formatMatch: null, - autoFill: false, - width: 0, - multiple: false, - multipleSeparator: ", ", - disableRightAndLeft: false, - highlight: function(value, term) { - return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>"); - }, - scroll: true, - scrollHeight: 180 -}; -$.Autocompleter.defaults.searchTermFromValue = $.Autocompleter.defaults.lastWord; - -$.Autocompleter.Cache = function(options) { - - var data = {}; - var length = 0; - - function matchSubset(s, sub) { - if (!options.matchCase) - s = s.toLowerCase(); - var i = s.indexOf(sub); - if (options.matchContains == "word"){ - i = s.toLowerCase().search("\\b" + sub.toLowerCase()); - } - if (i == -1) return false; - return i == 0 || options.matchContains; - }; - - function add(q, value) { - if (length > options.cacheLength){ - flush(); - } - if (!data[q]){ - length++; - } - data[q] = value; - } - - function populate(){ - if( !options.data ) return false; - // track the matches - var stMatchSets = {}, - nullData = 0; - - // no url was specified, we need to adjust the cache length to make sure it fits the local data store - if( !options.url ) options.cacheLength = 1; - - // track all options for minChars = 0 - stMatchSets[""] = []; - - // loop through the array and create a lookup structure - for ( var i = 0, ol = options.data.length; i < ol; i++ ) { - var rawValue = options.data[i]; - // if rawValue is a string, make an array otherwise just reference the array - rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue; - - var value = options.formatMatch(rawValue, i+1, options.data.length); - if ( value === false ) - continue; - - var firstChar = value.charAt(0).toLowerCase(); - // if no lookup array for this character exists, look it up now - if( !stMatchSets[firstChar] ) - stMatchSets[firstChar] = []; - - // if the match is a string - var row = { - value: value, - data: rawValue, - result: options.formatResult && options.formatResult(rawValue) || value - }; - - // push the current match into the set list - stMatchSets[firstChar].push(row); - - // keep track of minChars zero items - if ( nullData++ < options.max ) { - stMatchSets[""].push(row); - } - }; - - // add the data items to the cache - $.each(stMatchSets, function(i, value) { - // increase the cache size - options.cacheLength++; - // add to the cache - add(i, value); - }); - } - - // populate any existing data - setTimeout(populate, 25); - - function flush(){ - data = {}; - length = 0; - } - - return { - flush: flush, - add: add, - populate: populate, - load: function(q) { - if (!options.cacheLength || !length) - return null; - /* - * if dealing w/local data and matchContains than we must make sure - * to loop through all the data collections looking for matches - */ - if( !options.url && options.matchContains ){ - // track all matches - var csub = []; - // loop through all the data grids for matches - for( var k in data ){ - // don't search through the stMatchSets[""] (minChars: 0) cache - // this prevents duplicates - if( k.length > 0 ){ - var c = data[k]; - $.each(c, function(i, x) { - // if we've got a match, add it to the array - if (matchSubset(x.value, q)) { - csub.push(x); - } - }); - } - } - return csub; - } else - // if the exact item exists, use it - if (data[q]){ - return data[q]; - } else - if (options.matchSubset) { - for (var i = q.length - 1; i >= options.minChars; i--) { - var c = data[q.substr(0, i)]; - if (c) { - var csub = []; - $.each(c, function(i, x) { - if (matchSubset(x.value, q)) { - csub[csub.length] = x; - } - }); - return csub; - } - } - } - return null; - } - }; -}; - -$.Autocompleter.Select = function (options, input, select, config) { - var CLASSES = { - ACTIVE: "ac_over" - }; - - var listItems, - active = -1, - data, - term = "", - needsInit = true, - element, - list; - - // Create results - function init() { - if (!needsInit) - return; - element = $("<div/>") - .hide() - .addClass(options.resultsClass) - .css("position", "absolute") - .appendTo(document.body); - - list = $("<ul/>").appendTo(element).mouseover( function(event) { - if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') { - active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event)); - $(target(event)).addClass(CLASSES.ACTIVE); - } - }).click(function(event) { - $(target(event)).addClass(CLASSES.ACTIVE); - select(); - // TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus - input.focus(); - return false; - }).mousedown(function() { - config.mouseDownOnSelect = true; - }).mouseup(function() { - config.mouseDownOnSelect = false; - }); - - if( options.width > 0 ) - element.css("width", options.width); - - needsInit = false; - } - - function target(event) { - var element = event.target; - while(element && element.tagName != "LI") - element = element.parentNode; - // more fun with IE, sometimes event.target is empty, just ignore it then - if(!element) - return []; - return element; - } - - function moveSelect(step) { - listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE); - movePosition(step); - var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE); - if(options.scroll) { - var offset = 0; - listItems.slice(0, active).each(function() { - offset += this.offsetHeight; - }); - if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) { - list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight()); - } else if(offset < list.scrollTop()) { - list.scrollTop(offset); - } - } - options.selectionChanged(activeItem); - }; - - function movePosition(step) { - active += step; - if (active < 0) { - active = listItems.size() - 1; - } else if (active >= listItems.size()) { - active = 0; - } - } - - function limitNumberOfItems(available) { - return options.max && options.max < available - ? options.max - : available; - } - - function fillList() { - list.empty(); - var max = limitNumberOfItems(data.length); - for (var i=0; i < max; i++) { - if (!data[i]) - continue; - var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term); - if ( formatted === false ) - continue; - var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0]; - $.data(li, "ac_data", data[i]); - } - listItems = list.find("li"); - if ( options.selectFirst ) { - listItems.slice(0, 1).addClass(CLASSES.ACTIVE); - active = 0; - } - // apply bgiframe if available - if ( $.fn.bgiframe ) - list.bgiframe(); - } - - return { - display: function(d, q) { - init(); - data = d; - term = q; - fillList(); - }, - next: function() { - moveSelect(1); - }, - prev: function() { - moveSelect(-1); - }, - pageUp: function() { - if (active != 0 && active - 8 < 0) { - moveSelect( -active ); - } else { - moveSelect(-8); - } - }, - pageDown: function() { - if (active != listItems.size() - 1 && active + 8 > listItems.size()) { - moveSelect( listItems.size() - 1 - active ); - } else { - moveSelect(8); - } - }, - hide: function() { - element && element.hide(); - listItems && listItems.removeClass(CLASSES.ACTIVE); - active = -1; - }, - visible : function() { - return element && element.is(":visible"); - }, - current: function() { - return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]); - }, - show: function() { - var offset = $(input).offset(); - element.css({ - width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(), - top: offset.top + input.offsetHeight, - left: offset.left - }).show(); - if(options.scroll) { - list.scrollTop(0); - list.css({ - maxHeight: options.scrollHeight, - overflow: 'auto' - }); - - if($.browser.msie && typeof document.body.style.maxHeight === "undefined") { - var listHeight = 0; - listItems.each(function() { - listHeight += this.offsetHeight; - }); - var scrollbarsVisible = listHeight > options.scrollHeight; - list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight ); - if (!scrollbarsVisible) { - // IE doesn't recalculate width when scrollbar disappears - listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) ); - } - } - - } - }, - selected: function() { - var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE); - return selected && selected.length && $.data(selected[0], "ac_data"); - }, - emptyList: function (){ - list && list.empty(); - }, - unbind: function() { - element && element.remove(); - } - }; -}; - -$.Autocompleter.Selection = function(field, start, end) { - if( field.createTextRange ){ - var selRange = field.createTextRange(); - selRange.collapse(true); - selRange.moveStart("character", start); - selRange.moveEnd("character", end); - selRange.select(); - } else if( field.setSelectionRange ){ - field.setSelectionRange(start, end); - } else { - if( field.selectionStart ){ - field.selectionStart = start; - field.selectionEnd = end; - } - } - field.focus(); -}; - -})(jQuery); diff --git a/vendor/assets/javascripts/jquery.charcount.js b/vendor/assets/javascripts/jquery.charcount.js deleted file mode 100644 index 67d1442d4e3eef1d7f843b52d41bbf80edf1fcb1..0000000000000000000000000000000000000000 --- a/vendor/assets/javascripts/jquery.charcount.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Character Count Plugin - jQuery plugin - * Dynamic character count for text areas and input fields - * written by Alen Grakalic - * http://cssglobe.com/post/7161/jquery-plugin-simplest-twitterlike-dynamic-character-count-for-textareas - * - * Copyright (c) 2009 Alen Grakalic (http://cssglobe.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * Built for jQuery library - * http://jquery.com - * - */ - -(function($) { - - $.fn.charCount = function(options){ - - // default configuration properties - var defaults = { - allowed: 140, - warning: 25, - css: 'counter', - counterElement: 'span', - cssWarning: 'warning', - cssExceeded: 'exceeded', - counterText: '' - }; - - var options = $.extend(defaults, options); - - function calculate(obj){ - var count = $(obj).val().length; - var available = options.allowed - count; - if(available <= options.warning && available >= 0){ - $(obj).next().addClass(options.cssWarning); - } else { - $(obj).next().removeClass(options.cssWarning); - } - if(available < 0){ - $(obj).next().addClass(options.cssExceeded); - } else { - $(obj).next().removeClass(options.cssExceeded); - } - $(obj).next().html(options.counterText + available); - }; - - this.each(function() { - $(this).after('<'+ options.counterElement +' class="' + options.css + '">'+ options.counterText +'</'+ options.counterElement +'>'); - calculate(this); - $(this).keyup(function(){calculate(this)}); - $(this).change(function(){calculate(this)}); - }); - - }; - -})(jQuery); diff --git a/vendor/assets/javascripts/keycodes.js b/vendor/assets/javascripts/keycodes.js deleted file mode 100644 index 10f0817262adb6862274f7410f87fbe62f35640c..0000000000000000000000000000000000000000 --- a/vendor/assets/javascripts/keycodes.js +++ /dev/null @@ -1,117 +0,0 @@ -var KEYCODES = { -BACKSPACE : 8, -TAB : 9, -ENTER : 13, -RETURN : 13, -SHIFT : 16, -CTRL : 17, -ALT : 18, -PAUSE : 19, -BREAK : 19, -CAPSLOCK : 20, -ESCAPE : 27, -ESC : 27, -SPACEBAR : 32, -SPACE: 32, -PAGEUP : 33, -PAGEDOWN : 34, -END : 35, -HOME : 36, -LEFT : 37, -UP : 38, -RIGHT : 39, -DOWN : 40, -INSERT : 45, -DEL : 46, -DELETE : 46, -0 : 48, -1 : 49, -2 : 50, -3 : 51, -4 : 52, -5 : 53, -6 : 54, -7 : 55, -8 : 56, -9 : 57, -A : 65, -B : 66, -C : 67, -D : 68, -E : 69, -F : 70, -G : 71, -H : 72, -I : 73, -J : 74, -K : 75, -L : 76, -M : 77, -N : 78, -O : 79, -P : 80, -Q : 81, -R : 82, -S : 83, -T : 84, -U : 85, -V : 86, -W : 87, -X : 88, -Y : 89, -Z : 90, -LEFTWINDOW : 91, -RIGHTWINDOW : 92, -SELECT : 93, -NUMPAD0 : 96, -NUMPAD1 : 97, -NUMPAD2 : 98, -NUMPAD3 : 99, -NUMPAD4 : 100, -NUMPAD5 : 101, -NUMPAD6 : 102, -NUMPAD7 : 103, -NUMPAD8 : 104, -NUMPAD9 : 105, -MULTIPLY : 106, -ADD : 107, -SUBTRACT : 109, -DECIMALPOINT : 110, -DIVIDE : 111, -F1 : 112, -F2 : 113, -F3 : 114, -F4 : 115, -F5 : 116, -F6 : 117, -F7 : 118, -F8 : 119, -F9 : 120, -F10 : 121, -F11 : 122, -F12 : 123, -NUMLOCK : 144, -SCROLLLOCK : 145, -SEMICOLON : 186, -EQUALSIGN : 187, -COMMA : 188, -DASH : 189, -PERIOD : 190, -FORWARDSLASH : 191, -ACCENTGRAVE : 192, -OPENBRACKET : 219, -BACKSLASH : 220, -CLOSEBRACKET : 221, -SINGLEQUOTE : 222, -isInsertion : function(keyCode){ - if(keyCode <= 46 && keyCode != this.RETURN && keyCode != this.SPACEBAR){ - return false; - }else if(keyCode > 90 && keyCode < 96){ - return false; - }else if(keyCode >= 112 && keyCode <= 145){ - return false; - }else { - return true; - } -} -}; diff --git a/vendor/assets/javascripts/mbp-helper.js b/vendor/assets/javascripts/mbp-helper.js deleted file mode 100644 index 026baea4fbe02c01ed4bc7a9e83a2fedebb63e40..0000000000000000000000000000000000000000 --- a/vendor/assets/javascripts/mbp-helper.js +++ /dev/null @@ -1,171 +0,0 @@ -/* - * MBP - Mobile boilerplate helper functions - */ -(function(document){ - -window.MBP = window.MBP || {}; - -// Fix for iPhone viewport scale bug -// http://www.blog.highub.com/mobile-2/a-fix-for-iphone-viewport-scale-bug/ - -MBP.viewportmeta = document.querySelector && document.querySelector('meta[name="viewport"]'); -MBP.ua = navigator.userAgent; - -MBP.scaleFix = function () { - if (MBP.viewportmeta && /iPhone|iPad/.test(MBP.ua) && !/Opera Mini/.test(MBP.ua)) { - MBP.viewportmeta.content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0"; - document.addEventListener("gesturestart", MBP.gestureStart, false); - } -}; -MBP.gestureStart = function () { - MBP.viewportmeta.content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6"; -}; - - -// Hide URL Bar for iOS and Android by Scott Jehl -// https://gist.github.com/1183357 - -MBP.hideUrlBar = function () { - var win = window, - doc = win.document; - - // If there's a hash, or addEventListener is undefined, stop here - if( !location.hash || !win.addEventListener ){ - - //scroll to 1 - window.scrollTo( 0, 1 ); - var scrollTop = 1, - - //reset to 0 on bodyready, if needed - bodycheck = setInterval(function(){ - if( doc.body ){ - clearInterval( bodycheck ); - scrollTop = "scrollTop" in doc.body ? doc.body.scrollTop : 1; - win.scrollTo( 0, scrollTop === 1 ? 0 : 1 ); - } - }, 15 ); - - win.addEventListener( "load", function(){ - setTimeout(function(){ - //reset to hide addr bar at onload - win.scrollTo( 0, scrollTop === 1 ? 0 : 1 ); - }, 0); - }, false ); - } -}; - - -// Fast Buttons - read wiki below before using -// https://github.com/shichuan/mobile-html5-boilerplate/wiki/JavaScript-Helper - -MBP.fastButton = function (element, handler) { - this.element = element; - this.handler = handler; - if (element.addEventListener) { - element.addEventListener('touchstart', this, false); - element.addEventListener('click', this, false); - } -}; - -MBP.fastButton.prototype.handleEvent = function(event) { - switch (event.type) { - case 'touchstart': this.onTouchStart(event); break; - case 'touchmove': this.onTouchMove(event); break; - case 'touchend': this.onClick(event); break; - case 'click': this.onClick(event); break; - } -}; - -MBP.fastButton.prototype.onTouchStart = function(event) { - event.stopPropagation(); - this.element.addEventListener('touchend', this, false); - document.body.addEventListener('touchmove', this, false); - this.startX = event.touches[0].clientX; - this.startY = event.touches[0].clientY; - this.element.style.backgroundColor = "rgba(0,0,0,.7)"; -}; - -MBP.fastButton.prototype.onTouchMove = function(event) { - if(Math.abs(event.touches[0].clientX - this.startX) > 10 || - Math.abs(event.touches[0].clientY - this.startY) > 10 ) { - this.reset(); - } -}; - -MBP.fastButton.prototype.onClick = function(event) { - event.stopPropagation(); - this.reset(); - this.handler(event); - if(event.type == 'touchend') { - MBP.preventGhostClick(this.startX, this.startY); - } - this.element.style.backgroundColor = ""; -}; - -MBP.fastButton.prototype.reset = function() { - this.element.removeEventListener('touchend', this, false); - document.body.removeEventListener('touchmove', this, false); - this.element.style.backgroundColor = ""; -}; - -MBP.preventGhostClick = function (x, y) { - MBP.coords.push(x, y); - window.setTimeout(function (){ - MBP.coords.splice(0, 2); - }, 2500); -}; - -MBP.ghostClickHandler = function (event) { - for(var i = 0, len = MBP.coords.length; i < len; i += 2) { - var x = MBP.coords[i]; - var y = MBP.coords[i + 1]; - if(Math.abs(event.clientX - x) < 25 && Math.abs(event.clientY - y) < 25) { - event.stopPropagation(); - event.preventDefault(); - } - } -}; - -if (document.addEventListener) { - document.addEventListener('click', MBP.ghostClickHandler, true); -} - -MBP.coords = []; - - -// iOS Startup Image -// https://github.com/shichuan/mobile-html5-boilerplate/issues#issue/2 - -MBP.splash = function () { - var filename = navigator.platform === 'iPad' ? 'h/' : 'l/'; - document.write('<link rel="apple-touch-startup-image" href="/img/' + filename + 'splash.png" />' ); -}; - - -// Autogrow -// http://googlecode.blogspot.com/2009/07/gmail-for-mobile-html5-series.html - -MBP.autogrow = function (element, lh) { - - function handler(e){ - var newHeight = this.scrollHeight, - currentHeight = this.clientHeight; - if (newHeight > currentHeight) { - this.style.height = newHeight + 3 * textLineHeight + "px"; - } - } - - var setLineHeight = (lh) ? lh : 12, - textLineHeight = element.currentStyle ? element.currentStyle.lineHeight : - getComputedStyle(element, null).lineHeight; - - textLineHeight = (textLineHeight.indexOf("px") == -1) ? setLineHeight : - parseInt(textLineHeight, 10); - - element.style.overflow = "hidden"; - element.addEventListener ? element.addEventListener('keyup', handler, false) : - element.attachEvent('onkeyup', handler); -}; - -})(document); - diff --git a/vendor/assets/javascripts/typeahead.bundle.js b/vendor/assets/javascripts/typeahead.bundle.js new file mode 100644 index 0000000000000000000000000000000000000000..bceb0a2bfc93e65e37e46fc8e07c9d7db9529c38 --- /dev/null +++ b/vendor/assets/javascripts/typeahead.bundle.js @@ -0,0 +1,2466 @@ +/*! + * typeahead.js 0.11.1 + * https://github.com/twitter/typeahead.js + * Copyright 2013-2016 Twitter, Inc. and other contributors; Licensed MIT + */ + +(function(root, factory) { + if (typeof define === "function" && define.amd) { + define([ "jquery" ], function(a0) { + return root["Bloodhound"] = factory(a0); + }); + } else if (typeof exports === "object") { + module.exports = factory(require("jquery")); + } else { + root["Bloodhound"] = factory(jQuery); + } +})(this, function($) { + var _ = function() { + "use strict"; + return { + isMsie: function() { + return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; + }, + isBlankString: function(str) { + return !str || /^\s*$/.test(str); + }, + escapeRegExChars: function(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + }, + isString: function(obj) { + return typeof obj === "string"; + }, + isNumber: function(obj) { + return typeof obj === "number"; + }, + isArray: $.isArray, + isFunction: $.isFunction, + isObject: $.isPlainObject, + isUndefined: function(obj) { + return typeof obj === "undefined"; + }, + isElement: function(obj) { + return !!(obj && obj.nodeType === 1); + }, + isJQuery: function(obj) { + return obj instanceof $; + }, + toStr: function toStr(s) { + return _.isUndefined(s) || s === null ? "" : s + ""; + }, + bind: $.proxy, + each: function(collection, cb) { + $.each(collection, reverseArgs); + function reverseArgs(index, value) { + return cb(value, index); + } + }, + map: $.map, + filter: $.grep, + every: function(obj, test) { + var result = true; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (!(result = test.call(null, val, key, obj))) { + return false; + } + }); + return !!result; + }, + some: function(obj, test) { + var result = false; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (result = test.call(null, val, key, obj)) { + return false; + } + }); + return !!result; + }, + mixin: $.extend, + identity: function(x) { + return x; + }, + clone: function(obj) { + return $.extend(true, {}, obj); + }, + getIdGenerator: function() { + var counter = 0; + return function() { + return counter++; + }; + }, + templatify: function templatify(obj) { + return $.isFunction(obj) ? obj : template; + function template() { + return String(obj); + } + }, + defer: function(fn) { + setTimeout(fn, 0); + }, + debounce: function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments, later, callNow; + later = function() { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + } + }; + callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + } + return result; + }; + }, + throttle: function(func, wait) { + var context, args, timeout, result, previous, later; + previous = 0; + later = function() { + previous = new Date(); + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date(), remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }, + stringify: function(val) { + return _.isString(val) ? val : JSON.stringify(val); + }, + noop: function() {} + }; + }(); + var VERSION = "0.11.1"; + var tokenizers = function() { + "use strict"; + return { + nonword: nonword, + whitespace: whitespace, + obj: { + nonword: getObjTokenizer(nonword), + whitespace: getObjTokenizer(whitespace) + } + }; + function whitespace(str) { + str = _.toStr(str); + return str ? str.split(/\s+/) : []; + } + function nonword(str) { + str = _.toStr(str); + return str ? str.split(/\W+/) : []; + } + function getObjTokenizer(tokenizer) { + return function setKey(keys) { + keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0); + return function tokenize(o) { + var tokens = []; + _.each(keys, function(k) { + tokens = tokens.concat(tokenizer(_.toStr(o[k]))); + }); + return tokens; + }; + }; + } + }(); + var LruCache = function() { + "use strict"; + function LruCache(maxSize) { + this.maxSize = _.isNumber(maxSize) ? maxSize : 100; + this.reset(); + if (this.maxSize <= 0) { + this.set = this.get = $.noop; + } + } + _.mixin(LruCache.prototype, { + set: function set(key, val) { + var tailItem = this.list.tail, node; + if (this.size >= this.maxSize) { + this.list.remove(tailItem); + delete this.hash[tailItem.key]; + this.size--; + } + if (node = this.hash[key]) { + node.val = val; + this.list.moveToFront(node); + } else { + node = new Node(key, val); + this.list.add(node); + this.hash[key] = node; + this.size++; + } + }, + get: function get(key) { + var node = this.hash[key]; + if (node) { + this.list.moveToFront(node); + return node.val; + } + }, + reset: function reset() { + this.size = 0; + this.hash = {}; + this.list = new List(); + } + }); + function List() { + this.head = this.tail = null; + } + _.mixin(List.prototype, { + add: function add(node) { + if (this.head) { + node.next = this.head; + this.head.prev = node; + } + this.head = node; + this.tail = this.tail || node; + }, + remove: function remove(node) { + node.prev ? node.prev.next = node.next : this.head = node.next; + node.next ? node.next.prev = node.prev : this.tail = node.prev; + }, + moveToFront: function(node) { + this.remove(node); + this.add(node); + } + }); + function Node(key, val) { + this.key = key; + this.val = val; + this.prev = this.next = null; + } + return LruCache; + }(); + var PersistentStorage = function() { + "use strict"; + var LOCAL_STORAGE; + try { + LOCAL_STORAGE = window.localStorage; + LOCAL_STORAGE.setItem("~~~", "!"); + LOCAL_STORAGE.removeItem("~~~"); + } catch (err) { + LOCAL_STORAGE = null; + } + function PersistentStorage(namespace, override) { + this.prefix = [ "__", namespace, "__" ].join(""); + this.ttlKey = "__ttl__"; + this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix)); + this.ls = override || LOCAL_STORAGE; + !this.ls && this._noop(); + } + _.mixin(PersistentStorage.prototype, { + _prefix: function(key) { + return this.prefix + key; + }, + _ttlKey: function(key) { + return this._prefix(key) + this.ttlKey; + }, + _noop: function() { + this.get = this.set = this.remove = this.clear = this.isExpired = _.noop; + }, + _safeSet: function(key, val) { + try { + this.ls.setItem(key, val); + } catch (err) { + if (err.name === "QuotaExceededError") { + this.clear(); + this._noop(); + } + } + }, + get: function(key) { + if (this.isExpired(key)) { + this.remove(key); + } + return decode(this.ls.getItem(this._prefix(key))); + }, + set: function(key, val, ttl) { + if (_.isNumber(ttl)) { + this._safeSet(this._ttlKey(key), encode(now() + ttl)); + } else { + this.ls.removeItem(this._ttlKey(key)); + } + return this._safeSet(this._prefix(key), encode(val)); + }, + remove: function(key) { + this.ls.removeItem(this._ttlKey(key)); + this.ls.removeItem(this._prefix(key)); + return this; + }, + clear: function() { + var i, keys = gatherMatchingKeys(this.keyMatcher); + for (i = keys.length; i--; ) { + this.remove(keys[i]); + } + return this; + }, + isExpired: function(key) { + var ttl = decode(this.ls.getItem(this._ttlKey(key))); + return _.isNumber(ttl) && now() > ttl ? true : false; + } + }); + return PersistentStorage; + function now() { + return new Date().getTime(); + } + function encode(val) { + return JSON.stringify(_.isUndefined(val) ? null : val); + } + function decode(val) { + return $.parseJSON(val); + } + function gatherMatchingKeys(keyMatcher) { + var i, key, keys = [], len = LOCAL_STORAGE.length; + for (i = 0; i < len; i++) { + if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) { + keys.push(key.replace(keyMatcher, "")); + } + } + return keys; + } + }(); + var Transport = function() { + "use strict"; + var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10); + function Transport(o) { + o = o || {}; + this.cancelled = false; + this.lastReq = null; + this._send = o.transport; + this._get = o.limiter ? o.limiter(this._get) : this._get; + this._cache = o.cache === false ? new LruCache(0) : sharedCache; + } + Transport.setMaxPendingRequests = function setMaxPendingRequests(num) { + maxPendingRequests = num; + }; + Transport.resetCache = function resetCache() { + sharedCache.reset(); + }; + _.mixin(Transport.prototype, { + _fingerprint: function fingerprint(o) { + o = o || {}; + return o.url + o.type + $.param(o.data || {}); + }, + _get: function(o, cb) { + var that = this, fingerprint, jqXhr; + fingerprint = this._fingerprint(o); + if (this.cancelled || fingerprint !== this.lastReq) { + return; + } + if (jqXhr = pendingRequests[fingerprint]) { + jqXhr.done(done).fail(fail); + } else if (pendingRequestsCount < maxPendingRequests) { + pendingRequestsCount++; + pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always); + } else { + this.onDeckRequestArgs = [].slice.call(arguments, 0); + } + function done(resp) { + cb(null, resp); + that._cache.set(fingerprint, resp); + } + function fail() { + cb(true); + } + function always() { + pendingRequestsCount--; + delete pendingRequests[fingerprint]; + if (that.onDeckRequestArgs) { + that._get.apply(that, that.onDeckRequestArgs); + that.onDeckRequestArgs = null; + } + } + }, + get: function(o, cb) { + var resp, fingerprint; + cb = cb || $.noop; + o = _.isString(o) ? { + url: o + } : o || {}; + fingerprint = this._fingerprint(o); + this.cancelled = false; + this.lastReq = fingerprint; + if (resp = this._cache.get(fingerprint)) { + cb(null, resp); + } else { + this._get(o, cb); + } + }, + cancel: function() { + this.cancelled = true; + } + }); + return Transport; + }(); + var SearchIndex = window.SearchIndex = function() { + "use strict"; + var CHILDREN = "c", IDS = "i"; + function SearchIndex(o) { + o = o || {}; + if (!o.datumTokenizer || !o.queryTokenizer) { + $.error("datumTokenizer and queryTokenizer are both required"); + } + this.identify = o.identify || _.stringify; + this.datumTokenizer = o.datumTokenizer; + this.queryTokenizer = o.queryTokenizer; + this.matchAnyQueryToken = o.matchAnyQueryToken; + this.reset(); + } + _.mixin(SearchIndex.prototype, { + bootstrap: function bootstrap(o) { + this.datums = o.datums; + this.trie = o.trie; + }, + add: function(data) { + var that = this; + data = _.isArray(data) ? data : [ data ]; + _.each(data, function(datum) { + var id, tokens; + that.datums[id = that.identify(datum)] = datum; + tokens = normalizeTokens(that.datumTokenizer(datum)); + _.each(tokens, function(token) { + var node, chars, ch; + node = that.trie; + chars = token.split(""); + while (ch = chars.shift()) { + node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode()); + node[IDS].push(id); + } + }); + }); + }, + get: function get(ids) { + var that = this; + return _.map(ids, function(id) { + return that.datums[id]; + }); + }, + search: function search(query) { + var that = this, tokens, matches; + tokens = normalizeTokens(this.queryTokenizer(query)); + _.each(tokens, function(token) { + var node, chars, ch, ids; + if (matches && matches.length === 0 && !that.matchAnyQueryToken) { + return false; + } + node = that.trie; + chars = token.split(""); + while (node && (ch = chars.shift())) { + node = node[CHILDREN][ch]; + } + if (node && chars.length === 0) { + ids = node[IDS].slice(0); + matches = matches ? getIntersection(matches, ids) : ids; + } else { + if (!that.matchAnyQueryToken) { + matches = []; + return false; + } + } + }); + return matches ? _.map(unique(matches), function(id) { + return that.datums[id]; + }) : []; + }, + all: function all() { + var values = []; + for (var key in this.datums) { + values.push(this.datums[key]); + } + return values; + }, + reset: function reset() { + this.datums = {}; + this.trie = newNode(); + }, + serialize: function serialize() { + return { + datums: this.datums, + trie: this.trie + }; + } + }); + return SearchIndex; + function normalizeTokens(tokens) { + tokens = _.filter(tokens, function(token) { + return !!token; + }); + tokens = _.map(tokens, function(token) { + return token.toLowerCase(); + }); + return tokens; + } + function newNode() { + var node = {}; + node[IDS] = []; + node[CHILDREN] = {}; + return node; + } + function unique(array) { + var seen = {}, uniques = []; + for (var i = 0, len = array.length; i < len; i++) { + if (!seen[array[i]]) { + seen[array[i]] = true; + uniques.push(array[i]); + } + } + return uniques; + } + function getIntersection(arrayA, arrayB) { + var ai = 0, bi = 0, intersection = []; + arrayA = arrayA.sort(); + arrayB = arrayB.sort(); + var lenArrayA = arrayA.length, lenArrayB = arrayB.length; + while (ai < lenArrayA && bi < lenArrayB) { + if (arrayA[ai] < arrayB[bi]) { + ai++; + } else if (arrayA[ai] > arrayB[bi]) { + bi++; + } else { + intersection.push(arrayA[ai]); + ai++; + bi++; + } + } + return intersection; + } + }(); + var Prefetch = function() { + "use strict"; + var keys; + keys = { + data: "data", + protocol: "protocol", + thumbprint: "thumbprint" + }; + function Prefetch(o) { + this.url = o.url; + this.ttl = o.ttl; + this.cache = o.cache; + this.prepare = o.prepare; + this.transform = o.transform; + this.transport = o.transport; + this.thumbprint = o.thumbprint; + this.storage = new PersistentStorage(o.cacheKey); + } + _.mixin(Prefetch.prototype, { + _settings: function settings() { + return { + url: this.url, + type: "GET", + dataType: "json" + }; + }, + store: function store(data) { + if (!this.cache) { + return; + } + this.storage.set(keys.data, data, this.ttl); + this.storage.set(keys.protocol, location.protocol, this.ttl); + this.storage.set(keys.thumbprint, this.thumbprint, this.ttl); + }, + fromCache: function fromCache() { + var stored = {}, isExpired; + if (!this.cache) { + return null; + } + stored.data = this.storage.get(keys.data); + stored.protocol = this.storage.get(keys.protocol); + stored.thumbprint = this.storage.get(keys.thumbprint); + isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol; + return stored.data && !isExpired ? stored.data : null; + }, + fromNetwork: function(cb) { + var that = this, settings; + if (!cb) { + return; + } + settings = this.prepare(this._settings()); + this.transport(settings).fail(onError).done(onResponse); + function onError() { + cb(true); + } + function onResponse(resp) { + cb(null, that.transform(resp)); + } + }, + clear: function clear() { + this.storage.clear(); + return this; + } + }); + return Prefetch; + }(); + var Remote = function() { + "use strict"; + function Remote(o) { + this.url = o.url; + this.prepare = o.prepare; + this.transform = o.transform; + this.indexResponse = o.indexResponse; + this.transport = new Transport({ + cache: o.cache, + limiter: o.limiter, + transport: o.transport + }); + } + _.mixin(Remote.prototype, { + _settings: function settings() { + return { + url: this.url, + type: "GET", + dataType: "json" + }; + }, + get: function get(query, cb) { + var that = this, settings; + if (!cb) { + return; + } + query = query || ""; + settings = this.prepare(query, this._settings()); + return this.transport.get(settings, onResponse); + function onResponse(err, resp) { + err ? cb([]) : cb(that.transform(resp)); + } + }, + cancelLastRequest: function cancelLastRequest() { + this.transport.cancel(); + } + }); + return Remote; + }(); + var oParser = function() { + "use strict"; + return function parse(o) { + var defaults, sorter; + defaults = { + initialize: true, + identify: _.stringify, + datumTokenizer: null, + queryTokenizer: null, + matchAnyQueryToken: false, + sufficient: 5, + indexRemote: false, + sorter: null, + local: [], + prefetch: null, + remote: null + }; + o = _.mixin(defaults, o || {}); + !o.datumTokenizer && $.error("datumTokenizer is required"); + !o.queryTokenizer && $.error("queryTokenizer is required"); + sorter = o.sorter; + o.sorter = sorter ? function(x) { + return x.sort(sorter); + } : _.identity; + o.local = _.isFunction(o.local) ? o.local() : o.local; + o.prefetch = parsePrefetch(o.prefetch); + o.remote = parseRemote(o.remote); + return o; + }; + function parsePrefetch(o) { + var defaults; + if (!o) { + return null; + } + defaults = { + url: null, + ttl: 24 * 60 * 60 * 1e3, + cache: true, + cacheKey: null, + thumbprint: "", + prepare: _.identity, + transform: _.identity, + transport: null + }; + o = _.isString(o) ? { + url: o + } : o; + o = _.mixin(defaults, o); + !o.url && $.error("prefetch requires url to be set"); + o.transform = o.filter || o.transform; + o.cacheKey = o.cacheKey || o.url; + o.thumbprint = VERSION + o.thumbprint; + o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax; + return o; + } + function parseRemote(o) { + var defaults; + if (!o) { + return; + } + defaults = { + url: null, + cache: true, + prepare: null, + replace: null, + wildcard: null, + limiter: null, + rateLimitBy: "debounce", + rateLimitWait: 300, + transform: _.identity, + transport: null + }; + o = _.isString(o) ? { + url: o + } : o; + o = _.mixin(defaults, o); + !o.url && $.error("remote requires url to be set"); + o.transform = o.filter || o.transform; + o.prepare = toRemotePrepare(o); + o.limiter = toLimiter(o); + o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax; + delete o.replace; + delete o.wildcard; + delete o.rateLimitBy; + delete o.rateLimitWait; + return o; + } + function toRemotePrepare(o) { + var prepare, replace, wildcard; + prepare = o.prepare; + replace = o.replace; + wildcard = o.wildcard; + if (prepare) { + return prepare; + } + if (replace) { + prepare = prepareByReplace; + } else if (o.wildcard) { + prepare = prepareByWildcard; + } else { + prepare = idenityPrepare; + } + return prepare; + function prepareByReplace(query, settings) { + settings.url = replace(settings.url, query); + return settings; + } + function prepareByWildcard(query, settings) { + settings.url = settings.url.replace(wildcard, encodeURIComponent(query)); + return settings; + } + function idenityPrepare(query, settings) { + return settings; + } + } + function toLimiter(o) { + var limiter, method, wait; + limiter = o.limiter; + method = o.rateLimitBy; + wait = o.rateLimitWait; + if (!limiter) { + limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait); + } + return limiter; + function debounce(wait) { + return function debounce(fn) { + return _.debounce(fn, wait); + }; + } + function throttle(wait) { + return function throttle(fn) { + return _.throttle(fn, wait); + }; + } + } + function callbackToDeferred(fn) { + return function wrapper(o) { + var deferred = $.Deferred(); + fn(o, onSuccess, onError); + return deferred; + function onSuccess(resp) { + _.defer(function() { + deferred.resolve(resp); + }); + } + function onError(err) { + _.defer(function() { + deferred.reject(err); + }); + } + }; + } + }(); + var Bloodhound = function() { + "use strict"; + var old; + old = window && window.Bloodhound; + function Bloodhound(o) { + o = oParser(o); + this.sorter = o.sorter; + this.identify = o.identify; + this.sufficient = o.sufficient; + this.indexRemote = o.indexRemote; + this.local = o.local; + this.remote = o.remote ? new Remote(o.remote) : null; + this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null; + this.index = new SearchIndex({ + identify: this.identify, + datumTokenizer: o.datumTokenizer, + queryTokenizer: o.queryTokenizer + }); + o.initialize !== false && this.initialize(); + } + Bloodhound.noConflict = function noConflict() { + window && (window.Bloodhound = old); + return Bloodhound; + }; + Bloodhound.tokenizers = tokenizers; + _.mixin(Bloodhound.prototype, { + __ttAdapter: function ttAdapter() { + var that = this; + return this.remote ? withAsync : withoutAsync; + function withAsync(query, sync, async) { + return that.search(query, sync, async); + } + function withoutAsync(query, sync) { + return that.search(query, sync); + } + }, + _loadPrefetch: function loadPrefetch() { + var that = this, deferred, serialized; + deferred = $.Deferred(); + if (!this.prefetch) { + deferred.resolve(); + } else if (serialized = this.prefetch.fromCache()) { + this.index.bootstrap(serialized); + deferred.resolve(); + } else { + this.prefetch.fromNetwork(done); + } + return deferred.promise(); + function done(err, data) { + if (err) { + return deferred.reject(); + } + that.add(data); + that.prefetch.store(that.index.serialize()); + deferred.resolve(); + } + }, + _initialize: function initialize() { + var that = this, deferred; + this.clear(); + (this.initPromise = this._loadPrefetch()).done(addLocalToIndex); + return this.initPromise; + function addLocalToIndex() { + that.add(that.local); + } + }, + initialize: function initialize(force) { + return !this.initPromise || force ? this._initialize() : this.initPromise; + }, + add: function add(data) { + this.index.add(data); + return this; + }, + get: function get(ids) { + ids = _.isArray(ids) ? ids : [].slice.call(arguments); + return this.index.get(ids); + }, + search: function search(query, sync, async) { + var that = this, local; + sync = sync || _.noop; + async = async || _.noop; + local = this.sorter(this.index.search(query)); + sync(this.remote ? local.slice() : local); + if (this.remote && local.length < this.sufficient) { + this.remote.get(query, processRemote); + } else if (this.remote) { + this.remote.cancelLastRequest(); + } + return this; + function processRemote(remote) { + var nonDuplicates = []; + _.each(remote, function(r) { + !_.some(local, function(l) { + return that.identify(r) === that.identify(l); + }) && nonDuplicates.push(r); + }); + that.indexRemote && that.add(nonDuplicates); + async(nonDuplicates); + } + }, + all: function all() { + return this.index.all(); + }, + clear: function clear() { + this.index.reset(); + return this; + }, + clearPrefetchCache: function clearPrefetchCache() { + this.prefetch && this.prefetch.clear(); + return this; + }, + clearRemoteCache: function clearRemoteCache() { + Transport.resetCache(); + return this; + }, + ttAdapter: function ttAdapter() { + return this.__ttAdapter(); + } + }); + return Bloodhound; + }(); + return Bloodhound; +}); + +(function(root, factory) { + if (typeof define === "function" && define.amd) { + define([ "jquery" ], function(a0) { + return factory(a0); + }); + } else if (typeof exports === "object") { + module.exports = factory(require("jquery")); + } else { + factory(jQuery); + } +})(this, function($) { + var _ = function() { + "use strict"; + return { + isMsie: function() { + return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; + }, + isBlankString: function(str) { + return !str || /^\s*$/.test(str); + }, + escapeRegExChars: function(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + }, + isString: function(obj) { + return typeof obj === "string"; + }, + isNumber: function(obj) { + return typeof obj === "number"; + }, + isArray: $.isArray, + isFunction: $.isFunction, + isObject: $.isPlainObject, + isUndefined: function(obj) { + return typeof obj === "undefined"; + }, + isElement: function(obj) { + return !!(obj && obj.nodeType === 1); + }, + isJQuery: function(obj) { + return obj instanceof $; + }, + toStr: function toStr(s) { + return _.isUndefined(s) || s === null ? "" : s + ""; + }, + bind: $.proxy, + each: function(collection, cb) { + $.each(collection, reverseArgs); + function reverseArgs(index, value) { + return cb(value, index); + } + }, + map: $.map, + filter: $.grep, + every: function(obj, test) { + var result = true; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (!(result = test.call(null, val, key, obj))) { + return false; + } + }); + return !!result; + }, + some: function(obj, test) { + var result = false; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (result = test.call(null, val, key, obj)) { + return false; + } + }); + return !!result; + }, + mixin: $.extend, + identity: function(x) { + return x; + }, + clone: function(obj) { + return $.extend(true, {}, obj); + }, + getIdGenerator: function() { + var counter = 0; + return function() { + return counter++; + }; + }, + templatify: function templatify(obj) { + return $.isFunction(obj) ? obj : template; + function template() { + return String(obj); + } + }, + defer: function(fn) { + setTimeout(fn, 0); + }, + debounce: function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments, later, callNow; + later = function() { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + } + }; + callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + } + return result; + }; + }, + throttle: function(func, wait) { + var context, args, timeout, result, previous, later; + previous = 0; + later = function() { + previous = new Date(); + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date(), remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }, + stringify: function(val) { + return _.isString(val) ? val : JSON.stringify(val); + }, + noop: function() {} + }; + }(); + var WWW = function() { + "use strict"; + var defaultClassNames = { + wrapper: "twitter-typeahead", + input: "tt-input", + hint: "tt-hint", + menu: "tt-menu", + dataset: "tt-dataset", + suggestion: "tt-suggestion", + selectable: "tt-selectable", + empty: "tt-empty", + open: "tt-open", + cursor: "tt-cursor", + highlight: "tt-highlight" + }; + return build; + function build(o) { + var www, classes; + classes = _.mixin({}, defaultClassNames, o); + www = { + css: buildCss(), + classes: classes, + html: buildHtml(classes), + selectors: buildSelectors(classes) + }; + return { + css: www.css, + html: www.html, + classes: www.classes, + selectors: www.selectors, + mixin: function(o) { + _.mixin(o, www); + } + }; + } + function buildHtml(c) { + return { + wrapper: '<span class="' + c.wrapper + '"></span>', + menu: '<div class="' + c.menu + '"></div>' + }; + } + function buildSelectors(classes) { + var selectors = {}; + _.each(classes, function(v, k) { + selectors[k] = "." + v; + }); + return selectors; + } + function buildCss() { + var css = { + wrapper: { + position: "relative", + display: "inline-block" + }, + hint: { + position: "absolute", + top: "0", + left: "0", + borderColor: "transparent", + boxShadow: "none", + opacity: "1" + }, + input: { + position: "relative", + verticalAlign: "top", + backgroundColor: "transparent" + }, + inputWithNoHint: { + position: "relative", + verticalAlign: "top" + }, + menu: { + position: "absolute", + top: "100%", + left: "0", + zIndex: "100", + display: "none" + }, + ltr: { + left: "0", + right: "auto" + }, + rtl: { + left: "auto", + right: " 0" + } + }; + if (_.isMsie()) { + _.mixin(css.input, { + backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" + }); + } + return css; + } + }(); + var EventBus = function() { + "use strict"; + var namespace, deprecationMap; + namespace = "typeahead:"; + deprecationMap = { + render: "rendered", + cursorchange: "cursorchanged", + select: "selected", + autocomplete: "autocompleted" + }; + function EventBus(o) { + if (!o || !o.el) { + $.error("EventBus initialized without el"); + } + this.$el = $(o.el); + } + _.mixin(EventBus.prototype, { + _trigger: function(type, args) { + var $e; + $e = $.Event(namespace + type); + (args = args || []).unshift($e); + this.$el.trigger.apply(this.$el, args); + return $e; + }, + before: function(type) { + var args, $e; + args = [].slice.call(arguments, 1); + $e = this._trigger("before" + type, args); + return $e.isDefaultPrevented(); + }, + trigger: function(type) { + var deprecatedType; + this._trigger(type, [].slice.call(arguments, 1)); + if (deprecatedType = deprecationMap[type]) { + this._trigger(deprecatedType, [].slice.call(arguments, 1)); + } + } + }); + return EventBus; + }(); + var EventEmitter = function() { + "use strict"; + var splitter = /\s+/, nextTick = getNextTick(); + return { + onSync: onSync, + onAsync: onAsync, + off: off, + trigger: trigger + }; + function on(method, types, cb, context) { + var type; + if (!cb) { + return this; + } + types = types.split(splitter); + cb = context ? bindContext(cb, context) : cb; + this._callbacks = this._callbacks || {}; + while (type = types.shift()) { + this._callbacks[type] = this._callbacks[type] || { + sync: [], + async: [] + }; + this._callbacks[type][method].push(cb); + } + return this; + } + function onAsync(types, cb, context) { + return on.call(this, "async", types, cb, context); + } + function onSync(types, cb, context) { + return on.call(this, "sync", types, cb, context); + } + function off(types) { + var type; + if (!this._callbacks) { + return this; + } + types = types.split(splitter); + while (type = types.shift()) { + delete this._callbacks[type]; + } + return this; + } + function trigger(types) { + var type, callbacks, args, syncFlush, asyncFlush; + if (!this._callbacks) { + return this; + } + types = types.split(splitter); + args = [].slice.call(arguments, 1); + while ((type = types.shift()) && (callbacks = this._callbacks[type])) { + syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); + asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); + syncFlush() && nextTick(asyncFlush); + } + return this; + } + function getFlush(callbacks, context, args) { + return flush; + function flush() { + var cancelled; + for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { + cancelled = callbacks[i].apply(context, args) === false; + } + return !cancelled; + } + } + function getNextTick() { + var nextTickFn; + if (window.setImmediate) { + nextTickFn = function nextTickSetImmediate(fn) { + setImmediate(function() { + fn(); + }); + }; + } else { + nextTickFn = function nextTickSetTimeout(fn) { + setTimeout(function() { + fn(); + }, 0); + }; + } + return nextTickFn; + } + function bindContext(fn, context) { + return fn.bind ? fn.bind(context) : function() { + fn.apply(context, [].slice.call(arguments, 0)); + }; + } + }(); + var highlight = function(doc) { + "use strict"; + var defaults = { + node: null, + pattern: null, + tagName: "strong", + className: null, + wordsOnly: false, + caseSensitive: false + }; + return function hightlight(o) { + var regex; + o = _.mixin({}, defaults, o); + if (!o.node || !o.pattern) { + return; + } + o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ]; + regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly); + traverse(o.node, hightlightTextNode); + function hightlightTextNode(textNode) { + var match, patternNode, wrapperNode; + if (match = regex.exec(textNode.data)) { + wrapperNode = doc.createElement(o.tagName); + o.className && (wrapperNode.className = o.className); + patternNode = textNode.splitText(match.index); + patternNode.splitText(match[0].length); + wrapperNode.appendChild(patternNode.cloneNode(true)); + textNode.parentNode.replaceChild(wrapperNode, patternNode); + } + return !!match; + } + function traverse(el, hightlightTextNode) { + var childNode, TEXT_NODE_TYPE = 3; + for (var i = 0; i < el.childNodes.length; i++) { + childNode = el.childNodes[i]; + if (childNode.nodeType === TEXT_NODE_TYPE) { + i += hightlightTextNode(childNode) ? 1 : 0; + } else { + traverse(childNode, hightlightTextNode); + } + } + } + }; + function getRegex(patterns, caseSensitive, wordsOnly) { + var escapedPatterns = [], regexStr; + for (var i = 0, len = patterns.length; i < len; i++) { + escapedPatterns.push(_.escapeRegExChars(patterns[i])); + } + regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; + return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); + } + }(window.document); + var Input = function() { + "use strict"; + var specialKeyCodeMap; + specialKeyCodeMap = { + 9: "tab", + 27: "esc", + 37: "left", + 39: "right", + 13: "enter", + 38: "up", + 40: "down" + }; + function Input(o, www) { + o = o || {}; + if (!o.input) { + $.error("input is missing"); + } + www.mixin(this); + this.$hint = $(o.hint); + this.$input = $(o.input); + this.query = this.$input.val(); + this.queryWhenFocused = this.hasFocus() ? this.query : null; + this.$overflowHelper = buildOverflowHelper(this.$input); + this._checkLanguageDirection(); + if (this.$hint.length === 0) { + this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; + } + } + Input.normalizeQuery = function(str) { + return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " "); + }; + _.mixin(Input.prototype, EventEmitter, { + _onBlur: function onBlur() { + this.resetInputValue(); + this.trigger("blurred"); + }, + _onFocus: function onFocus() { + this.queryWhenFocused = this.query; + this.trigger("focused"); + }, + _onKeydown: function onKeydown($e) { + var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; + this._managePreventDefault(keyName, $e); + if (keyName && this._shouldTrigger(keyName, $e)) { + this.trigger(keyName + "Keyed", $e); + } + }, + _onInput: function onInput() { + this._setQuery(this.getInputValue()); + this.clearHintIfInvalid(); + this._checkLanguageDirection(); + }, + _managePreventDefault: function managePreventDefault(keyName, $e) { + var preventDefault; + switch (keyName) { + case "up": + case "down": + preventDefault = !withModifier($e); + break; + + default: + preventDefault = false; + } + preventDefault && $e.preventDefault(); + }, + _shouldTrigger: function shouldTrigger(keyName, $e) { + var trigger; + switch (keyName) { + case "tab": + trigger = !withModifier($e); + break; + + default: + trigger = true; + } + return trigger; + }, + _checkLanguageDirection: function checkLanguageDirection() { + var dir = (this.$input.css("direction") || "ltr").toLowerCase(); + if (this.dir !== dir) { + this.dir = dir; + this.$hint.attr("dir", dir); + this.trigger("langDirChanged", dir); + } + }, + _setQuery: function setQuery(val, silent) { + var areEquivalent, hasDifferentWhitespace; + areEquivalent = areQueriesEquivalent(val, this.query); + hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false; + this.query = val; + if (!silent && !areEquivalent) { + this.trigger("queryChanged", this.query); + } else if (!silent && hasDifferentWhitespace) { + this.trigger("whitespaceChanged", this.query); + } + }, + bind: function() { + var that = this, onBlur, onFocus, onKeydown, onInput; + onBlur = _.bind(this._onBlur, this); + onFocus = _.bind(this._onFocus, this); + onKeydown = _.bind(this._onKeydown, this); + onInput = _.bind(this._onInput, this); + this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); + if (!_.isMsie() || _.isMsie() > 9) { + this.$input.on("input.tt", onInput); + } else { + this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { + if (specialKeyCodeMap[$e.which || $e.keyCode]) { + return; + } + _.defer(_.bind(that._onInput, that, $e)); + }); + } + return this; + }, + focus: function focus() { + this.$input.focus(); + }, + blur: function blur() { + this.$input.blur(); + }, + getLangDir: function getLangDir() { + return this.dir; + }, + getQuery: function getQuery() { + return this.query || ""; + }, + setQuery: function setQuery(val, silent) { + this.setInputValue(val); + this._setQuery(val, silent); + }, + hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() { + return this.query !== this.queryWhenFocused; + }, + getInputValue: function getInputValue() { + return this.$input.val(); + }, + setInputValue: function setInputValue(value) { + this.$input.val(value); + this.clearHintIfInvalid(); + this._checkLanguageDirection(); + }, + resetInputValue: function resetInputValue() { + this.setInputValue(this.query); + }, + getHint: function getHint() { + return this.$hint.val(); + }, + setHint: function setHint(value) { + this.$hint.val(value); + }, + clearHint: function clearHint() { + this.setHint(""); + }, + clearHintIfInvalid: function clearHintIfInvalid() { + var val, hint, valIsPrefixOfHint, isValid; + val = this.getInputValue(); + hint = this.getHint(); + valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; + isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); + !isValid && this.clearHint(); + }, + hasFocus: function hasFocus() { + return this.$input.is(":focus"); + }, + hasOverflow: function hasOverflow() { + var constraint = this.$input.width() - 2; + this.$overflowHelper.text(this.getInputValue()); + return this.$overflowHelper.width() >= constraint; + }, + isCursorAtEnd: function() { + var valueLength, selectionStart, range; + valueLength = this.$input.val().length; + selectionStart = this.$input[0].selectionStart; + if (_.isNumber(selectionStart)) { + return selectionStart === valueLength; + } else if (document.selection) { + range = document.selection.createRange(); + range.moveStart("character", -valueLength); + return valueLength === range.text.length; + } + return true; + }, + destroy: function destroy() { + this.$hint.off(".tt"); + this.$input.off(".tt"); + this.$overflowHelper.remove(); + this.$hint = this.$input = this.$overflowHelper = $("<div>"); + } + }); + return Input; + function buildOverflowHelper($input) { + return $('<pre aria-hidden="true"></pre>').css({ + position: "absolute", + visibility: "hidden", + whiteSpace: "pre", + fontFamily: $input.css("font-family"), + fontSize: $input.css("font-size"), + fontStyle: $input.css("font-style"), + fontVariant: $input.css("font-variant"), + fontWeight: $input.css("font-weight"), + wordSpacing: $input.css("word-spacing"), + letterSpacing: $input.css("letter-spacing"), + textIndent: $input.css("text-indent"), + textRendering: $input.css("text-rendering"), + textTransform: $input.css("text-transform") + }).insertAfter($input); + } + function areQueriesEquivalent(a, b) { + return Input.normalizeQuery(a) === Input.normalizeQuery(b); + } + function withModifier($e) { + return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; + } + }(); + var Dataset = function() { + "use strict"; + var keys, nameGenerator; + keys = { + val: "tt-selectable-display", + obj: "tt-selectable-object" + }; + nameGenerator = _.getIdGenerator(); + function Dataset(o, www) { + o = o || {}; + o.templates = o.templates || {}; + o.templates.notFound = o.templates.notFound || o.templates.empty; + if (!o.source) { + $.error("missing source"); + } + if (!o.node) { + $.error("missing node"); + } + if (o.name && !isValidName(o.name)) { + $.error("invalid dataset name: " + o.name); + } + www.mixin(this); + this.highlight = !!o.highlight; + this.name = o.name || nameGenerator(); + this.limit = o.limit || 5; + this.displayFn = getDisplayFn(o.display || o.displayKey); + this.templates = getTemplates(o.templates, this.displayFn); + this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source; + this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async; + this._resetLastSuggestion(); + this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name); + } + Dataset.extractData = function extractData(el) { + var $el = $(el); + if ($el.data(keys.obj)) { + return { + val: $el.data(keys.val) || "", + obj: $el.data(keys.obj) || null + }; + } + return null; + }; + _.mixin(Dataset.prototype, EventEmitter, { + _overwrite: function overwrite(query, suggestions) { + suggestions = suggestions || []; + if (suggestions.length) { + this._renderSuggestions(query, suggestions); + } else if (this.async && this.templates.pending) { + this._renderPending(query); + } else if (!this.async && this.templates.notFound) { + this._renderNotFound(query); + } else { + this._empty(); + } + this.trigger("rendered", this.name, suggestions, false); + }, + _append: function append(query, suggestions) { + suggestions = suggestions || []; + if (suggestions.length && this.$lastSuggestion.length) { + this._appendSuggestions(query, suggestions); + } else if (suggestions.length) { + this._renderSuggestions(query, suggestions); + } else if (!this.$lastSuggestion.length && this.templates.notFound) { + this._renderNotFound(query); + } + this.trigger("rendered", this.name, suggestions, true); + }, + _renderSuggestions: function renderSuggestions(query, suggestions) { + var $fragment; + $fragment = this._getSuggestionsFragment(query, suggestions); + this.$lastSuggestion = $fragment.children().last(); + this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions)); + }, + _appendSuggestions: function appendSuggestions(query, suggestions) { + var $fragment, $lastSuggestion; + $fragment = this._getSuggestionsFragment(query, suggestions); + $lastSuggestion = $fragment.children().last(); + this.$lastSuggestion.after($fragment); + this.$lastSuggestion = $lastSuggestion; + }, + _renderPending: function renderPending(query) { + var template = this.templates.pending; + this._resetLastSuggestion(); + template && this.$el.html(template({ + query: query, + dataset: this.name + })); + }, + _renderNotFound: function renderNotFound(query) { + var template = this.templates.notFound; + this._resetLastSuggestion(); + template && this.$el.html(template({ + query: query, + dataset: this.name + })); + }, + _empty: function empty() { + this.$el.empty(); + this._resetLastSuggestion(); + }, + _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) { + var that = this, fragment; + fragment = document.createDocumentFragment(); + _.each(suggestions, function getSuggestionNode(suggestion) { + var $el, context; + context = that._injectQuery(query, suggestion); + $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable); + fragment.appendChild($el[0]); + }); + this.highlight && highlight({ + className: this.classes.highlight, + node: fragment, + pattern: query + }); + return $(fragment); + }, + _getFooter: function getFooter(query, suggestions) { + return this.templates.footer ? this.templates.footer({ + query: query, + suggestions: suggestions, + dataset: this.name + }) : null; + }, + _getHeader: function getHeader(query, suggestions) { + return this.templates.header ? this.templates.header({ + query: query, + suggestions: suggestions, + dataset: this.name + }) : null; + }, + _resetLastSuggestion: function resetLastSuggestion() { + this.$lastSuggestion = $(); + }, + _injectQuery: function injectQuery(query, obj) { + return _.isObject(obj) ? _.mixin({ + _query: query + }, obj) : obj; + }, + update: function update(query) { + var that = this, canceled = false, syncCalled = false, rendered = 0; + this.cancel(); + this.cancel = function cancel() { + canceled = true; + that.cancel = $.noop; + that.async && that.trigger("asyncCanceled", query); + }; + this.source(query, sync, async); + !syncCalled && sync([]); + function sync(suggestions) { + if (syncCalled) { + return; + } + syncCalled = true; + suggestions = (suggestions || []).slice(0, that.limit); + rendered = suggestions.length; + that._overwrite(query, suggestions); + if (rendered < that.limit && that.async) { + that.trigger("asyncRequested", query); + } + } + function async(suggestions) { + suggestions = suggestions || []; + if (!canceled && rendered < that.limit) { + that.cancel = $.noop; + var idx = Math.abs(rendered - that.limit); + rendered += idx; + that._append(query, suggestions.slice(0, idx)); + that.async && that.trigger("asyncReceived", query); + } + } + }, + cancel: $.noop, + clear: function clear() { + this._empty(); + this.cancel(); + this.trigger("cleared"); + }, + isEmpty: function isEmpty() { + return this.$el.is(":empty"); + }, + destroy: function destroy() { + this.$el = $("<div>"); + } + }); + return Dataset; + function getDisplayFn(display) { + display = display || _.stringify; + return _.isFunction(display) ? display : displayFn; + function displayFn(obj) { + return obj[display]; + } + } + function getTemplates(templates, displayFn) { + return { + notFound: templates.notFound && _.templatify(templates.notFound), + pending: templates.pending && _.templatify(templates.pending), + header: templates.header && _.templatify(templates.header), + footer: templates.footer && _.templatify(templates.footer), + suggestion: templates.suggestion || suggestionTemplate + }; + function suggestionTemplate(context) { + return $("<div>").text(displayFn(context)); + } + } + function isValidName(str) { + return /^[_a-zA-Z0-9-]+$/.test(str); + } + }(); + var Menu = function() { + "use strict"; + function Menu(o, www) { + var that = this; + o = o || {}; + if (!o.node) { + $.error("node is required"); + } + www.mixin(this); + this.$node = $(o.node); + this.query = null; + this.datasets = _.map(o.datasets, initializeDataset); + function initializeDataset(oDataset) { + var node = that.$node.find(oDataset.node).first(); + oDataset.node = node.length ? node : $("<div>").appendTo(that.$node); + return new Dataset(oDataset, www); + } + } + _.mixin(Menu.prototype, EventEmitter, { + _onSelectableClick: function onSelectableClick($e) { + this.trigger("selectableClicked", $($e.currentTarget)); + }, + _onRendered: function onRendered(type, dataset, suggestions, async) { + this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); + this.trigger("datasetRendered", dataset, suggestions, async); + }, + _onCleared: function onCleared() { + this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); + this.trigger("datasetCleared"); + }, + _propagate: function propagate() { + this.trigger.apply(this, arguments); + }, + _allDatasetsEmpty: function allDatasetsEmpty() { + return _.every(this.datasets, isDatasetEmpty); + function isDatasetEmpty(dataset) { + return dataset.isEmpty(); + } + }, + _getSelectables: function getSelectables() { + return this.$node.find(this.selectors.selectable); + }, + _removeCursor: function _removeCursor() { + var $selectable = this.getActiveSelectable(); + $selectable && $selectable.removeClass(this.classes.cursor); + }, + _ensureVisible: function ensureVisible($el) { + var elTop, elBottom, nodeScrollTop, nodeHeight; + elTop = $el.position().top; + elBottom = elTop + $el.outerHeight(true); + nodeScrollTop = this.$node.scrollTop(); + nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10); + if (elTop < 0) { + this.$node.scrollTop(nodeScrollTop + elTop); + } else if (nodeHeight < elBottom) { + this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight)); + } + }, + bind: function() { + var that = this, onSelectableClick; + onSelectableClick = _.bind(this._onSelectableClick, this); + this.$node.on("click.tt", this.selectors.selectable, onSelectableClick); + this.$node.on("mouseover", this.selectors.selectable, function() { + that.setCursor($(this)); + }); + _.each(this.datasets, function(dataset) { + dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that); + }); + return this; + }, + isOpen: function isOpen() { + return this.$node.hasClass(this.classes.open); + }, + open: function open() { + this.$node.scrollTop(0); + this.$node.addClass(this.classes.open); + }, + close: function close() { + this.$node.removeClass(this.classes.open); + this._removeCursor(); + }, + setLanguageDirection: function setLanguageDirection(dir) { + this.$node.attr("dir", dir); + }, + selectableRelativeToCursor: function selectableRelativeToCursor(delta) { + var $selectables, $oldCursor, oldIndex, newIndex; + $oldCursor = this.getActiveSelectable(); + $selectables = this._getSelectables(); + oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1; + newIndex = oldIndex + delta; + newIndex = (newIndex + 1) % ($selectables.length + 1) - 1; + newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex; + return newIndex === -1 ? null : $selectables.eq(newIndex); + }, + setCursor: function setCursor($selectable) { + this._removeCursor(); + if ($selectable = $selectable && $selectable.first()) { + $selectable.addClass(this.classes.cursor); + this._ensureVisible($selectable); + } + }, + getSelectableData: function getSelectableData($el) { + return $el && $el.length ? Dataset.extractData($el) : null; + }, + getActiveSelectable: function getActiveSelectable() { + var $selectable = this._getSelectables().filter(this.selectors.cursor).first(); + return $selectable.length ? $selectable : null; + }, + getTopSelectable: function getTopSelectable() { + var $selectable = this._getSelectables().first(); + return $selectable.length ? $selectable : null; + }, + update: function update(query) { + var isValidUpdate = query !== this.query; + if (isValidUpdate) { + this.query = query; + _.each(this.datasets, updateDataset); + } + return isValidUpdate; + function updateDataset(dataset) { + dataset.update(query); + } + }, + empty: function empty() { + _.each(this.datasets, clearDataset); + this.query = null; + this.$node.addClass(this.classes.empty); + function clearDataset(dataset) { + dataset.clear(); + } + }, + destroy: function destroy() { + this.$node.off(".tt"); + this.$node = $("<div>"); + _.each(this.datasets, destroyDataset); + function destroyDataset(dataset) { + dataset.destroy(); + } + } + }); + return Menu; + }(); + var DefaultMenu = function() { + "use strict"; + var s = Menu.prototype; + function DefaultMenu() { + Menu.apply(this, [].slice.call(arguments, 0)); + } + _.mixin(DefaultMenu.prototype, Menu.prototype, { + open: function open() { + !this._allDatasetsEmpty() && this._show(); + return s.open.apply(this, [].slice.call(arguments, 0)); + }, + close: function close() { + this._hide(); + return s.close.apply(this, [].slice.call(arguments, 0)); + }, + _onRendered: function onRendered() { + if (this._allDatasetsEmpty()) { + this._hide(); + } else { + this.isOpen() && this._show(); + } + return s._onRendered.apply(this, [].slice.call(arguments, 0)); + }, + _onCleared: function onCleared() { + if (this._allDatasetsEmpty()) { + this._hide(); + } else { + this.isOpen() && this._show(); + } + return s._onCleared.apply(this, [].slice.call(arguments, 0)); + }, + setLanguageDirection: function setLanguageDirection(dir) { + this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl); + return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0)); + }, + _hide: function hide() { + this.$node.hide(); + }, + _show: function show() { + this.$node.css("display", "block"); + } + }); + return DefaultMenu; + }(); + var Typeahead = function() { + "use strict"; + function Typeahead(o, www) { + var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged; + o = o || {}; + if (!o.input) { + $.error("missing input"); + } + if (!o.menu) { + $.error("missing menu"); + } + if (!o.eventBus) { + $.error("missing event bus"); + } + www.mixin(this); + this.eventBus = o.eventBus; + this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; + this.input = o.input; + this.menu = o.menu; + this.enabled = true; + this.active = false; + this.input.hasFocus() && this.activate(); + this.dir = this.input.getLangDir(); + this._hacks(); + this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this); + onFocused = c(this, "activate", "open", "_onFocused"); + onBlurred = c(this, "deactivate", "_onBlurred"); + onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed"); + onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed"); + onEscKeyed = c(this, "isActive", "_onEscKeyed"); + onUpKeyed = c(this, "isActive", "open", "_onUpKeyed"); + onDownKeyed = c(this, "isActive", "open", "_onDownKeyed"); + onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed"); + onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed"); + onQueryChanged = c(this, "_openIfActive", "_onQueryChanged"); + onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged"); + this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this); + } + _.mixin(Typeahead.prototype, { + _hacks: function hacks() { + var $input, $menu; + $input = this.input.$input || $("<div>"); + $menu = this.menu.$node || $("<div>"); + $input.on("blur.tt", function($e) { + var active, isActive, hasActive; + active = document.activeElement; + isActive = $menu.is(active); + hasActive = $menu.has(active).length > 0; + if (_.isMsie() && (isActive || hasActive)) { + $e.preventDefault(); + $e.stopImmediatePropagation(); + _.defer(function() { + $input.focus(); + }); + } + }); + $menu.on("mousedown.tt", function($e) { + $e.preventDefault(); + }); + }, + _onSelectableClicked: function onSelectableClicked(type, $el) { + this.select($el); + }, + _onDatasetCleared: function onDatasetCleared() { + this._updateHint(); + }, + _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) { + this._updateHint(); + this.eventBus.trigger("render", suggestions, async, dataset); + }, + _onAsyncRequested: function onAsyncRequested(type, dataset, query) { + this.eventBus.trigger("asyncrequest", query, dataset); + }, + _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) { + this.eventBus.trigger("asynccancel", query, dataset); + }, + _onAsyncReceived: function onAsyncReceived(type, dataset, query) { + this.eventBus.trigger("asyncreceive", query, dataset); + }, + _onFocused: function onFocused() { + this._minLengthMet() && this.menu.update(this.input.getQuery()); + }, + _onBlurred: function onBlurred() { + if (this.input.hasQueryChangedSinceLastFocus()) { + this.eventBus.trigger("change", this.input.getQuery()); + } + }, + _onEnterKeyed: function onEnterKeyed(type, $e) { + var $selectable; + if ($selectable = this.menu.getActiveSelectable()) { + this.select($selectable) && $e.preventDefault(); + } + }, + _onTabKeyed: function onTabKeyed(type, $e) { + var $selectable; + if ($selectable = this.menu.getActiveSelectable()) { + this.select($selectable) && $e.preventDefault(); + } else if ($selectable = this.menu.getTopSelectable()) { + this.autocomplete($selectable) && $e.preventDefault(); + } + }, + _onEscKeyed: function onEscKeyed() { + this.close(); + }, + _onUpKeyed: function onUpKeyed() { + this.moveCursor(-1); + }, + _onDownKeyed: function onDownKeyed() { + this.moveCursor(+1); + }, + _onLeftKeyed: function onLeftKeyed() { + if (this.dir === "rtl" && this.input.isCursorAtEnd()) { + this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable()); + } + }, + _onRightKeyed: function onRightKeyed() { + if (this.dir === "ltr" && this.input.isCursorAtEnd()) { + this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable()); + } + }, + _onQueryChanged: function onQueryChanged(e, query) { + this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty(); + }, + _onWhitespaceChanged: function onWhitespaceChanged() { + this._updateHint(); + }, + _onLangDirChanged: function onLangDirChanged(e, dir) { + if (this.dir !== dir) { + this.dir = dir; + this.menu.setLanguageDirection(dir); + } + }, + _openIfActive: function openIfActive() { + this.isActive() && this.open(); + }, + _minLengthMet: function minLengthMet(query) { + query = _.isString(query) ? query : this.input.getQuery() || ""; + return query.length >= this.minLength; + }, + _updateHint: function updateHint() { + var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match; + $selectable = this.menu.getTopSelectable(); + data = this.menu.getSelectableData($selectable); + val = this.input.getInputValue(); + if (data && !_.isBlankString(val) && !this.input.hasOverflow()) { + query = Input.normalizeQuery(val); + escapedQuery = _.escapeRegExChars(query); + frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); + match = frontMatchRegEx.exec(data.val); + match && this.input.setHint(val + match[1]); + } else { + this.input.clearHint(); + } + }, + isEnabled: function isEnabled() { + return this.enabled; + }, + enable: function enable() { + this.enabled = true; + }, + disable: function disable() { + this.enabled = false; + }, + isActive: function isActive() { + return this.active; + }, + activate: function activate() { + if (this.isActive()) { + return true; + } else if (!this.isEnabled() || this.eventBus.before("active")) { + return false; + } else { + this.active = true; + this.eventBus.trigger("active"); + return true; + } + }, + deactivate: function deactivate() { + if (!this.isActive()) { + return true; + } else if (this.eventBus.before("idle")) { + return false; + } else { + this.active = false; + this.close(); + this.eventBus.trigger("idle"); + return true; + } + }, + isOpen: function isOpen() { + return this.menu.isOpen(); + }, + open: function open() { + if (!this.isOpen() && !this.eventBus.before("open")) { + this.menu.open(); + this._updateHint(); + this.eventBus.trigger("open"); + } + return this.isOpen(); + }, + close: function close() { + if (this.isOpen() && !this.eventBus.before("close")) { + this.menu.close(); + this.input.clearHint(); + this.input.resetInputValue(); + this.eventBus.trigger("close"); + } + return !this.isOpen(); + }, + setVal: function setVal(val) { + this.input.setQuery(_.toStr(val)); + }, + getVal: function getVal() { + return this.input.getQuery(); + }, + select: function select($selectable) { + var data = this.menu.getSelectableData($selectable); + if (data && !this.eventBus.before("select", data.obj)) { + this.input.setQuery(data.val, true); + this.eventBus.trigger("select", data.obj); + this.close(); + return true; + } + return false; + }, + autocomplete: function autocomplete($selectable) { + var query, data, isValid; + query = this.input.getQuery(); + data = this.menu.getSelectableData($selectable); + isValid = data && query !== data.val; + if (isValid && !this.eventBus.before("autocomplete", data.obj)) { + this.input.setQuery(data.val); + this.eventBus.trigger("autocomplete", data.obj); + return true; + } + return false; + }, + moveCursor: function moveCursor(delta) { + var query, $candidate, data, payload, cancelMove; + query = this.input.getQuery(); + $candidate = this.menu.selectableRelativeToCursor(delta); + data = this.menu.getSelectableData($candidate); + payload = data ? data.obj : null; + cancelMove = this._minLengthMet() && this.menu.update(query); + if (!cancelMove && !this.eventBus.before("cursorchange", payload)) { + this.menu.setCursor($candidate); + if (data) { + this.input.setInputValue(data.val); + } else { + this.input.resetInputValue(); + this._updateHint(); + } + this.eventBus.trigger("cursorchange", payload); + return true; + } + return false; + }, + destroy: function destroy() { + this.input.destroy(); + this.menu.destroy(); + } + }); + return Typeahead; + function c(ctx) { + var methods = [].slice.call(arguments, 1); + return function() { + var args = [].slice.call(arguments); + _.each(methods, function(method) { + return ctx[method].apply(ctx, args); + }); + }; + } + }(); + (function() { + "use strict"; + var old, keys, methods; + old = $.fn.typeahead; + keys = { + www: "tt-www", + attrs: "tt-attrs", + typeahead: "tt-typeahead" + }; + methods = { + initialize: function initialize(o, datasets) { + var www; + datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1); + o = o || {}; + www = WWW(o.classNames); + return this.each(attach); + function attach() { + var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor; + _.each(datasets, function(d) { + d.highlight = !!o.highlight; + }); + $input = $(this); + $wrapper = $(www.html.wrapper); + $hint = $elOrNull(o.hint); + $menu = $elOrNull(o.menu); + defaultHint = o.hint !== false && !$hint; + defaultMenu = o.menu !== false && !$menu; + defaultHint && ($hint = buildHintFromInput($input, www)); + defaultMenu && ($menu = $(www.html.menu).css(www.css.menu)); + $hint && $hint.val(""); + $input = prepInput($input, www); + if (defaultHint || defaultMenu) { + $wrapper.css(www.css.wrapper); + $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint); + $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null); + } + MenuConstructor = defaultMenu ? DefaultMenu : Menu; + eventBus = new EventBus({ + el: $input + }); + input = new Input({ + hint: $hint, + input: $input + }, www); + menu = new MenuConstructor({ + node: $menu, + datasets: datasets + }, www); + typeahead = new Typeahead({ + input: input, + menu: menu, + eventBus: eventBus, + minLength: o.minLength + }, www); + $input.data(keys.www, www); + $input.data(keys.typeahead, typeahead); + } + }, + isEnabled: function isEnabled() { + var enabled; + ttEach(this.first(), function(t) { + enabled = t.isEnabled(); + }); + return enabled; + }, + enable: function enable() { + ttEach(this, function(t) { + t.enable(); + }); + return this; + }, + disable: function disable() { + ttEach(this, function(t) { + t.disable(); + }); + return this; + }, + isActive: function isActive() { + var active; + ttEach(this.first(), function(t) { + active = t.isActive(); + }); + return active; + }, + activate: function activate() { + ttEach(this, function(t) { + t.activate(); + }); + return this; + }, + deactivate: function deactivate() { + ttEach(this, function(t) { + t.deactivate(); + }); + return this; + }, + isOpen: function isOpen() { + var open; + ttEach(this.first(), function(t) { + open = t.isOpen(); + }); + return open; + }, + open: function open() { + ttEach(this, function(t) { + t.open(); + }); + return this; + }, + close: function close() { + ttEach(this, function(t) { + t.close(); + }); + return this; + }, + select: function select(el) { + var success = false, $el = $(el); + ttEach(this.first(), function(t) { + success = t.select($el); + }); + return success; + }, + autocomplete: function autocomplete(el) { + var success = false, $el = $(el); + ttEach(this.first(), function(t) { + success = t.autocomplete($el); + }); + return success; + }, + moveCursor: function moveCursoe(delta) { + var success = false; + ttEach(this.first(), function(t) { + success = t.moveCursor(delta); + }); + return success; + }, + val: function val(newVal) { + var query; + if (!arguments.length) { + ttEach(this.first(), function(t) { + query = t.getVal(); + }); + return query; + } else { + ttEach(this, function(t) { + t.setVal(_.toStr(newVal)); + }); + return this; + } + }, + destroy: function destroy() { + ttEach(this, function(typeahead, $input) { + revert($input); + typeahead.destroy(); + }); + return this; + } + }; + $.fn.typeahead = function(method) { + if (methods[method]) { + return methods[method].apply(this, [].slice.call(arguments, 1)); + } else { + return methods.initialize.apply(this, arguments); + } + }; + $.fn.typeahead.noConflict = function noConflict() { + $.fn.typeahead = old; + return this; + }; + function ttEach($els, fn) { + $els.each(function() { + var $input = $(this), typeahead; + (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input); + }); + } + function buildHintFromInput($input, www) { + return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({ + autocomplete: "off", + spellcheck: "false", + tabindex: -1 + }); + } + function prepInput($input, www) { + $input.data(keys.attrs, { + dir: $input.attr("dir"), + autocomplete: $input.attr("autocomplete"), + spellcheck: $input.attr("spellcheck"), + style: $input.attr("style") + }); + $input.addClass(www.classes.input).attr({ + autocomplete: "off", + spellcheck: false + }); + try { + !$input.attr("dir") && $input.attr("dir", "auto"); + } catch (e) {} + return $input; + } + function getBackgroundStyles($el) { + return { + backgroundAttachment: $el.css("background-attachment"), + backgroundClip: $el.css("background-clip"), + backgroundColor: $el.css("background-color"), + backgroundImage: $el.css("background-image"), + backgroundOrigin: $el.css("background-origin"), + backgroundPosition: $el.css("background-position"), + backgroundRepeat: $el.css("background-repeat"), + backgroundSize: $el.css("background-size") + }; + } + function revert($input) { + var www, $wrapper; + www = $input.data(keys.www); + $wrapper = $input.parent().filter(www.selectors.wrapper); + _.each($input.data(keys.attrs), function(val, key) { + _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); + }); + $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input); + if ($wrapper.length) { + $input.detach().insertAfter($wrapper); + $wrapper.remove(); + } + } + function $elOrNull(obj) { + var isValid, $el; + isValid = _.isJQuery(obj) || _.isElement(obj); + $el = isValid ? $(obj).first() : []; + return $el.length ? $el : null; + } + })(); +}); \ No newline at end of file