diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 219793aa..82fb0dca 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,7 +17,7 @@ jobs: uses: errata-ai/vale-action@reviewdog with: reporter: github-check - fail_on_error: true + fail_on_error: false filter_mode: nofilter files: '["cookbook", "guide"]' env: diff --git a/.github/workflows/translation.yml b/.github/workflows/translation.yml new file mode 100644 index 00000000..728bc316 --- /dev/null +++ b/.github/workflows/translation.yml @@ -0,0 +1,34 @@ +name: Update docs translation + +on: + pull_request: + paths: + - 'cookbook/**' + - 'guide/**' + +jobs: + update-docs: + name: Update docs + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.YIISOFT_GITHUB_TOKEN || github.token }} + ref: ${{ github.head_ref }} + repository: ${{ github.event.pull_request.head.repo.full_name }} + + - name: Use po4a + uses: addnab/docker-run-action@v3 + with: + image: arduanovdanil/po4a-fork:v0.73 + options: -v ${{ github.workspace }}:/src + run: | + cd guide + po4a po4a.cfg + + - name: Commit changed files + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: Update translation + file_pattern: 'guide' diff --git a/.gitignore b/.gitignore index a4515a86..4f895a9d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ Thumbs.db # Mac DS_Store Files .DS_Store + +# po4a .mo files +*.mo \ No newline at end of file diff --git a/014-docs.md b/014-docs.md index 53bfd775..5e477700 100644 --- a/014-docs.md +++ b/014-docs.md @@ -23,6 +23,25 @@ focused on a single package but is covering certain use-cases. The guide should follow [Micosoft style guide](https://learn.microsoft.com/en-us/style-guide/welcome/). +### Translation + +The definitive guide uses [po4a](https://github.com/mquinson/po4a) in Github Action for translations. +Translation algorithm: +- Install an application for working with `.po` translation files. For example, [Poedit](https://poedit.net/), [Lokalize](https://apps.kde.org/ru/lokalize/), [Gtranslator](https://wiki.gnome.org/Apps/Gtranslator) or another. +- Find folder with the name of the file you want to translate in `/guide/po`. Note that if the source file is in a subfolder, the subfolder name is appended to the folder and separated by an underscore, for example: for translating `guide/en/concept/aliases.md` file find `guide/po/concept_aliases.md` folder. +- Open the file with the `.po` extension in `Poedit` from the folder with the desired localization, for example `guide/po/intro_what-is-yii.md/ru/intro_what-is-yii.md.ru.po`. If there is no localization yet, create an issue. +- Translate necessary strings and push the changes +- Open pull request to main repository + +> [!CAUTION] +> Do not change the translation in files in `/guide/{lang}` manually. + +If you have changed English documentation: +- Open pull request to main repository +- Pull updated branch after successful completion of workflow `Update docs translation` in Github Action +- Update translation in `.po` files by `Poedit` +- Push changes + ## Blocks Blocks are in the [GitHub Alerts format](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts): diff --git a/guide/po/README.md/README.md.pot b/guide/po/README.md/README.md.pot new file mode 100644 index 00000000..fa90bc02 --- /dev/null +++ b/guide/po/README.md/README.md.pot @@ -0,0 +1,659 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 10:36+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/README.md +#, no-wrap +msgid "The definitive guide to Yii 3.0" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "" +"We release this guide under the [Terms of Yii Documentation](https://www." +"yiiframework.com/license#docs)." +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Introduction +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[About Yii](intro/what-is-yii.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Upgrading from version 2.0](intro/upgrade-from-v2.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Getting started -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[What do you need to know?](start/prerequisites.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Creating a project](start/creating-project.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Running applications](start/workflow.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Saying hello](start/hello.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Working with forms](start/forms.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Working with databases](start/databases.md) !" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Generating code with Gii](start/gii.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Looking ahead](start/looking-ahead.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Application structure +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Application structure overview](structure/overview.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Entry scripts](structure/entry-script.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Application](structure/application.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Service components](structure/service.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Actions](structure/action.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Domain](structure/domain.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Middleware](structure/middleware.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Packages](structure/package.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Key concepts +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Class autoloading](concept/autoloading.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Dependency injection container](concept/di-container.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Configuration](concept/configuration.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Aliases](concept/aliases.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Events](concept/events.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Immutability](concept/immutability.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Handling requests +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Routing and URL generation](runtime/routing.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Request](runtime/request.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Response](runtime/response.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Sessions](runtime/sessions.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Cookies](runtime/cookies.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Handling errors](runtime/handling-errors.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Logging](runtime/logging.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Views -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Views](views/view.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Widgets](views/widget.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Assets](views/asset.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Working with client scripts](views/client-scripts.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Theming](views/theming.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Template engines](views/template-engines.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[View injections](views/view-injections.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Working with databases +-" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "" +"[Database access objects](db-dao.md): Connecting to a database, basic " +"queries, transactions, and schema manipulation" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "" +"[Query builder](db-query-builder.md): Querying the database using a simple " +"abstraction layer" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "" +"[Active record](db-active-record.md): The Active Record ORM, retrieving and " +"manipulating records, and defining relations" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Migrations](databases/db-migrations.md): +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Getting data from users -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Creating forms](input/forms.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "" +"[Validating input](https://github.com/yiisoft/validator/blob/master/docs/" +"guide/en/README.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Uploading files](input/file-upload.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Collecting tabular input](input/tabular-input.md) -" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Displaying data -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Data formatting](output/formatting.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Pagination](output/pagination.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Sorting](output/sorting.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Data providers](output/data-providers.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Data widgets](output/data-widgets.md) -" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Security +-" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Security overview](security/overview.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Authentication](security/authentication.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Authorization](security/authorization.md) +-" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Working with passwords](security/passwords.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Cryptography](security/cryptography.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Best practices](security/best-practices.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Caching +-" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Caching overview](caching/overview.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Data caching](caching/data.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Fragment caching](caching/fragment.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Page caching](caching/page.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[HTTP caching](caching/http.md) -" +msgstr "" + +#. type: Title - +#: en/README.md +#, no-wrap +msgid "REST APIs -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Quick start](rest/quick-start.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Resources](rest/resources.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Controllers](rest/controllers.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Routing](rest/routing.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Authentication](rest/authentication.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Rate limiting](rest/rate-limiting.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Versioning](rest/versioning.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Error handling](rest/error-handling.md)" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Development tools -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "Debug toolbar and debugger" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "Generating code using Gii" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "Generating API documentation" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Testing -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Testing overview](testing/overview.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Testing environment setup](testing/environment-setup.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Unit tests](testing/unit.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Functional tests](testing/functional.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Acceptance tests](testing/acceptance.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Fixtures](testing/fixtures.md)" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Special topics -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Building application from scratch](tutorial/start-from-scratch.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Console applications](tutorial/console-applications.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Docker](tutorial/docker.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Internationalization](tutorial/i18n.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Mailing](tutorial/mailing.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Performance tuning](tutorial/performance-tuning.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Using Yii with event loop](tutorial/using-with-event-loop.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Using Yii with RoadRunner](tutorial/using-yii-with-roadrunner.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Using Yii with Swoole](tutorial/using-yii-with-swoole.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Widgets -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[GridView](https://www.yiiframework.com/doc-2.0/yii-grid-gridview.html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "" +"[ListView](https://www.yiiframework.com/doc-2.0/yii-widgets-listview.html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "" +"[DetailView](https://www.yiiframework.com/doc-2.0/yii-widgets-detailview." +"html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "" +"[ActiveForm](https://www.yiiframework.com/doc-2.0/guide-input-forms." +"html#activerecord-based-forms-activeform)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Menu](https://www.yiiframework.com/doc-2.0/yii-widgets-menu.html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "" +"[LinkPager](https://www.yiiframework.com/doc-2.0/yii-widgets-linkpager.html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "" +"[LinkSorter](https://www.yiiframework.com/doc-2.0/yii-widgets-linksorter." +"html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "" +"[Bootstrap widgets](https://www.yiiframework.com/extension/yiisoft/yii2-" +"bootstrap/doc/guide)" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Helpers +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Arrays](https://github.com/yiisoft/arrays/)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Files](https://github.com/yiisoft/files/)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Html](https://github.com/yiisoft/html/)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Json](https://github.com/yiisoft/json)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Network utilities](https://github.com/yiisoft/network-utilities/)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[VarDumper](https://github.com/yiisoft/var-dumper)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Strings](https://github.com/yiisoft/strings)" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Extras +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Glossary](glossary.md)" +msgstr "" diff --git a/guide/po/README.md/ru/README.md.ru.po b/guide/po/README.md/ru/README.md.ru.po new file mode 100644 index 00000000..8f44d3be --- /dev/null +++ b/guide/po/README.md/ru/README.md.ru.po @@ -0,0 +1,639 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 10:36+0500\n" +"PO-Revision-Date: 2025-09-03 17:50+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/README.md +#, no-wrap +msgid "The definitive guide to Yii 3.0" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "We release this guide under the [Terms of Yii Documentation](https://www.yiiframework.com/license#docs)." +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Introduction +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[About Yii](intro/what-is-yii.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Upgrading from version 2.0](intro/upgrade-from-v2.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Getting started -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[What do you need to know?](start/prerequisites.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Creating a project](start/creating-project.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Running applications](start/workflow.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Saying hello](start/hello.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Working with forms](start/forms.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Working with databases](start/databases.md) !" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Generating code with Gii](start/gii.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Looking ahead](start/looking-ahead.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Application structure +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Application structure overview](structure/overview.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Entry scripts](structure/entry-script.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Application](structure/application.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Service components](structure/service.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Actions](structure/action.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Domain](structure/domain.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Middleware](structure/middleware.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Packages](structure/package.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Key concepts +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Class autoloading](concept/autoloading.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Dependency injection container](concept/di-container.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Configuration](concept/configuration.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Aliases](concept/aliases.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Events](concept/events.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Immutability](concept/immutability.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Handling requests +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Routing and URL generation](runtime/routing.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Request](runtime/request.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Response](runtime/response.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Sessions](runtime/sessions.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Cookies](runtime/cookies.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Handling errors](runtime/handling-errors.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Logging](runtime/logging.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Views -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Views](views/view.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Widgets](views/widget.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Assets](views/asset.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Working with client scripts](views/client-scripts.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Theming](views/theming.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Template engines](views/template-engines.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[View injections](views/view-injections.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Working with databases +-" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Database access objects](db-dao.md): Connecting to a database, basic queries, transactions, and schema manipulation" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Query builder](db-query-builder.md): Querying the database using a simple abstraction layer" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Active record](db-active-record.md): The Active Record ORM, retrieving and manipulating records, and defining relations" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Migrations](databases/db-migrations.md): +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Getting data from users -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Creating forms](input/forms.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Validating input](https://github.com/yiisoft/validator/blob/master/docs/guide/en/README.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Uploading files](input/file-upload.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Collecting tabular input](input/tabular-input.md) -" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Displaying data -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Data formatting](output/formatting.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Pagination](output/pagination.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Sorting](output/sorting.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Data providers](output/data-providers.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Data widgets](output/data-widgets.md) -" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Security +-" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Security overview](security/overview.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Authentication](security/authentication.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Authorization](security/authorization.md) +-" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Working with passwords](security/passwords.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Cryptography](security/cryptography.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Best practices](security/best-practices.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Caching +-" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Caching overview](caching/overview.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Data caching](caching/data.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Fragment caching](caching/fragment.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Page caching](caching/page.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[HTTP caching](caching/http.md) -" +msgstr "" + +#. type: Title - +#: en/README.md +#, no-wrap +msgid "REST APIs -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Quick start](rest/quick-start.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Resources](rest/resources.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Controllers](rest/controllers.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Routing](rest/routing.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Authentication](rest/authentication.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Rate limiting](rest/rate-limiting.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Versioning](rest/versioning.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Error handling](rest/error-handling.md)" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Development tools -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "Debug toolbar and debugger" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "Generating code using Gii" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "Generating API documentation" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Testing -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Testing overview](testing/overview.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Testing environment setup](testing/environment-setup.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Unit tests](testing/unit.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Functional tests](testing/functional.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Acceptance tests](testing/acceptance.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Fixtures](testing/fixtures.md)" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Special topics -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Building application from scratch](tutorial/start-from-scratch.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Console applications](tutorial/console-applications.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Docker](tutorial/docker.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Internationalization](tutorial/i18n.md) -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Mailing](tutorial/mailing.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Performance tuning](tutorial/performance-tuning.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Using Yii with event loop](tutorial/using-with-event-loop.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Using Yii with RoadRunner](tutorial/using-yii-with-roadrunner.md) +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Using Yii with Swoole](tutorial/using-yii-with-swoole.md) +" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Widgets -" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[GridView](https://www.yiiframework.com/doc-2.0/yii-grid-gridview.html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[ListView](https://www.yiiframework.com/doc-2.0/yii-widgets-listview.html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[DetailView](https://www.yiiframework.com/doc-2.0/yii-widgets-detailview.html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[ActiveForm](https://www.yiiframework.com/doc-2.0/guide-input-forms.html#activerecord-based-forms-activeform)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Menu](https://www.yiiframework.com/doc-2.0/yii-widgets-menu.html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[LinkPager](https://www.yiiframework.com/doc-2.0/yii-widgets-linkpager.html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[LinkSorter](https://www.yiiframework.com/doc-2.0/yii-widgets-linksorter.html)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Bootstrap widgets](https://www.yiiframework.com/extension/yiisoft/yii2-bootstrap/doc/guide)" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Helpers +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Arrays](https://github.com/yiisoft/arrays/)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Files](https://github.com/yiisoft/files/)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Html](https://github.com/yiisoft/html/)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Json](https://github.com/yiisoft/json)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Network utilities](https://github.com/yiisoft/network-utilities/)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[VarDumper](https://github.com/yiisoft/var-dumper)" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Strings](https://github.com/yiisoft/strings)" +msgstr "" + +#. type: Plain text +#: en/README.md +msgid "Extras +" +msgstr "" + +#. type: Bullet: '* ' +#: en/README.md +msgid "[Glossary](glossary.md)" +msgstr "" diff --git a/guide/po/caching_data.md/caching_data.md.pot b/guide/po/caching_data.md/caching_data.md.pot new file mode 100644 index 00000000..e835e327 --- /dev/null +++ b/guide/po/caching_data.md/caching_data.md.pot @@ -0,0 +1,431 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/caching/data.md +#, no-wrap +msgid "Data caching" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"Data caching is about storing some PHP variables in a cache and retrieving " +"them later from the cache. It's also the foundation for more advanced " +"caching features, such as [page caching](page.md)." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"To use cache, install [yiisoft/cache](https://github.com/yiisoft/cache) " +"package:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/caching/data.md +#, no-wrap +msgid "composer require yiisoft/cache\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"The following code is a typical usage pattern of data caching, where " +"`$cache` refers to a `Cache` instance from the package:" +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "" +"public function getTopProducts(\\Yiisoft\\Cache\\CacheInterface $cache): array\n" +"{\n" +" $key = ['top-products', $count = 10];\n" +" \n" +" // Try retrieving $data from cache.\n" +" $data = $cache->getOrSet($key, function (\\Psr\\SimpleCache\\CacheInterface $cache) use ($count) {\n" +" // Can't find $data in cache, calculate it from scratch.\n" +" return getTopProductsFromDatabase($count);\n" +" }, 3600);\n" +" \n" +" return $data;\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"When cache has data associated with the `$key`, it returns the cached " +"value. Otherwise, it executes the passed anonymous function to calculate " +"the value to cache and return." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"If the anonymous function requires some data from the outer scope, you can " +"pass it with the `use` statement." +msgstr "" + +#. type: Title ## +#: en/caching/data.md +#, no-wrap +msgid "Cache handlers" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"The cache service uses [PSR-16](https://www.php-fig.org/psr/psr-16/) " +"compatible cache handlers which represent various cache storages, such as " +"memory, files, and databases." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Yii provides the following handlers:" +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"`NullCache` — a cache placeholder which does no real caching. The purpose of " +"this handler is to simplify the code that needs to check the availability of " +"cache. For example, during development or if the server doesn't have actual " +"cache support, you may configure a cache service to use this handler. When " +"you enable actual cache support, you can switch to using the corresponding " +"cache handler. In both cases, you may use the same code without extra " +"checks." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"`ArrayCache` — provides caching for the current request only by storing the " +"values in an array." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"[APCu](https://github.com/yiisoft/cache-apcu) - uses a PHP [APC](https://" +"secure.php.net/manual/en/book.apc.php) extension. You can consider this " +"option as the fastest one when dealing with cache for a centralized thick " +"application (e.g., one server, no dedicated load balancers, etc.)." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"[Database](https://github.com/yiisoft/cache-db) — uses a database table to " +"store cached data." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"[File](https://github.com/yiisoft/cache-file) — uses standard files to store " +"cached data. This is particularly suitable to cache large chunks of data, " +"such as page content." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"[Memcached](https://github.com/yiisoft/cache-memcached) — uses a PHP " +"[memcached](https://secure.php.net/manual/en/book.memcached.php) extension. " +"You can consider this option as the fastest one when dealing with cache in " +"distributed application (e.g., with several servers, load balancers, etc.)" +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"[Wincache](https://github.com/yiisoft/cache-wincache) — uses PHP [WinCache]" +"(https://iis.net/downloads/microsoft/wincache-extension) ([see also]" +"(https://secure.php.net/manual/en/book.wincache.php)) extension." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"[You could find more handlers at packagist.org](https://packagist.org/" +"providers/psr/simple-cache-implementation)." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +#, no-wrap +msgid "" +"> [!TIP]\n" +"> You may use different cache storage in the same application. A common strategy is:\n" +"> - To use memory-based cache storage to store small but constantly used data (e.g., statistics)\n" +"> - To use file-based or database-based cache storage to store big and less often used data (e.g., page content)\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"Cache handlers are usually set up in a [dependency injection container](../" +"concept/di-container.md) so that they can be globally configurable and " +"accessible." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"Because all cache handlers support the same set of APIs, you can swap the " +"underlying cache handler with a different one. You can do it by " +"reconfiguring the application without modifying the code that uses the cache." +msgstr "" + +#. type: Title ### +#: en/caching/data.md +#, no-wrap +msgid "Cache keys" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"A key uniquely identifies each data item stored in the cache. When you store " +"a data item, you have to specify a key for it. Later, when you retrieve the " +"data item, you should give the corresponding key." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"You may use a string or an arbitrary value as a cache key. When a key isn't " +"a string, it will be automatically serialized into a string." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"A common strategy of defining a cache key is to include all determining " +"factors in terms of an array." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"When different applications use the same cache storage, you should specify a " +"unique cache key prefix for each application to avoid conflicts of cache " +"keys. You can do this by using `\\Yiisoft\\Cache\\PrefixedCache` decorator:" +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "" +"$arrayCacheWithPrefix = new \\Yiisoft\\Cache\\PrefixedCache(new \\Yiisoft\\Cache\\ArrayCache(), 'myapp_');\n" +"$cache = new \\Yiisoft\\Cache\\Cache($arrayCacheWithPrefix);\n" +msgstr "" + +#. type: Title ### +#: en/caching/data.md +#, no-wrap +msgid "Cache expiration" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"A data item stored in a cache will remain there forever unless it's removed " +"because of some caching policy enforcement. For example, caching space is " +"full and cache storage removes the oldest data. To change this behavior, " +"you can set a TTL parameter when calling a method to store a data item:" +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "" +"$ttl = 3600;\n" +"$data = $cache->getOrSet($key, function (\\Psr\\SimpleCache\\CacheInterface $cache) use ($count) {\n" +"return getTopProductsFromDatabase($count);\n" +"}, $ttl);\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"The `$ttl` parameter indicates for how many seconds the data item can remain " +"valid in the cache. When you retrieve the data item, if it has passed the " +"expiration time, the method will execute the function and set the resulting " +"value into cache." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "You may set default TTL for the cache:" +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "$cache = new \\Yiisoft\\Cache\\Cache($arrayCache, 60 * 60); // 1 hour\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Additionally, you can invalidate a cache key explicitly:" +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "$cache->remove($key);\n" +msgstr "" + +#. type: Title ### +#: en/caching/data.md +#, no-wrap +msgid "Invalidation dependencies" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"Besides the expiration setting, changes of the so-called **invalidation " +"dependencies** may also invalidate cached data item. For example, " +"`\\Yiisoft\\Cache\\Dependency\\FileDependency` represents the dependency of " +"a file's modification time. When this dependency changes, it means " +"something modifying the corresponding file. As a result, any outdated file " +"content found in the cache should invalidate." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"Cache dependencies are objects of `\\Yiisoft\\Cache\\Dependency\\Dependency` " +"descendant classes. When you store a data item in the cache, you can pass " +"along an associated cache dependency object. For example," +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "" +"/**\n" +" * @var callable $callable\n" +" * @var \\Yiisoft\\Cache\\CacheInterface $cache\n" +" */\n" +"\n" +"use Yiisoft\\Cache\\Dependency\\TagDependency;\n" +"\n" +"// Set many cache values marking both with a tag.\n" +"$cache->getOrSet('item_42_price', $callable, null, new TagDependency('item_42'));\n" +"$cache->getOrSet('item_42_total', $callable, 3600, new TagDependency('item_42'));\n" +"\n" +"// Trigger invalidation by tag.\n" +"TagDependency::invalidate($cache, 'item_42');\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Below is a summary of the available cache dependencies:" +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"`\\Yiisoft\\Cache\\Dependency\\ValueDependency`: invalidates the cache when " +"specified value changes." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"`\\Yiisoft\\Cache\\Dependency\\CallbackDependency`: invalidates the cache " +"when the result of the specified PHP callback is different." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"`\\Yiisoft\\Cache\\Dependency\\FileDependency`: invalidates the cache when " +"the file's last modification time is different." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "" +"`\\Yiisoft\\Cache\\Dependency\\TagDependency`: associates a cached data item " +"with one or many tags. You may invalidate the cached data items with the " +"specified tag(s) by calling `TagDependency::invalidate()`." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"You may combine many dependencies using " +"`\\Yiisoft\\Cache\\Dependency\\AnyDependency` or " +"`\\Yiisoft\\Cache\\Dependency\\AllDependencies`." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"To implement your own dependency, extend from " +"`\\Yiisoft\\Cache\\Dependency\\Dependency`." +msgstr "" + +#. type: Title ### +#: en/caching/data.md +#, no-wrap +msgid "Cache stampede prevention" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"[A cache stampede](https://en.wikipedia.org/wiki/Cache_stampede) is a type " +"of cascading failure that can occur when massively parallel computing " +"systems with caching mechanisms come under a high load. This behavior is " +"sometimes also called dog-piling." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "" +"The `\\Yiisoft\\Cache\\Cache` uses a built-in \"Probably early expiration\" " +"algorithm that prevents cache stampede. This algorithm randomly fakes a " +"cache miss for one user while others are still served the cached value. You " +"can control its behavior with the fifth optional parameter of `getOrSet()`, " +"which is a float value called `$beta`. By default, beta is `1.0`, which is " +"usually enough. The higher the value the earlier cache will be re-created." +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "" +"/**\n" +" * @var mixed $key\n" +" * @var callable $callable\n" +" * @var \\DateInterval $ttl\n" +" * @var \\Yiisoft\\Cache\\CacheInterface $cache\n" +" * @var \\Yiisoft\\Cache\\Dependency\\Dependency $dependency\n" +" */\n" +"\n" +"$beta = 2.0;\n" +"$cache->getOrSet($key, $callable, $ttl, $dependency, $beta);\n" +msgstr "" diff --git a/guide/po/caching_data.md/ru/caching_data.md.ru.po b/guide/po/caching_data.md/ru/caching_data.md.ru.po new file mode 100644 index 00000000..4b0147e8 --- /dev/null +++ b/guide/po/caching_data.md/ru/caching_data.md.ru.po @@ -0,0 +1,333 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/caching/data.md +#, no-wrap +msgid "Data caching" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Data caching is about storing some PHP variables in a cache and retrieving them later from the cache. It's also the foundation for more advanced caching features, such as [page caching](page.md)." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "To use cache, install [yiisoft/cache](https://github.com/yiisoft/cache) package:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/caching/data.md +#, fuzzy, no-wrap +#| msgid "composer install yiisoft/security\n" +msgid "composer require yiisoft/cache\n" +msgstr "composer install yiisoft/security\n" + +#. type: Plain text +#: en/caching/data.md +msgid "The following code is a typical usage pattern of data caching, where `$cache` refers to a `Cache` instance from the package:" +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "" +"public function getTopProducts(\\Yiisoft\\Cache\\CacheInterface $cache): array\n" +"{\n" +" $key = ['top-products', $count = 10];\n" +" \n" +" // Try retrieving $data from cache.\n" +" $data = $cache->getOrSet($key, function (\\Psr\\SimpleCache\\CacheInterface $cache) use ($count) {\n" +" // Can't find $data in cache, calculate it from scratch.\n" +" return getTopProductsFromDatabase($count);\n" +" }, 3600);\n" +" \n" +" return $data;\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "When cache has data associated with the `$key`, it returns the cached value. Otherwise, it executes the passed anonymous function to calculate the value to cache and return." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "If the anonymous function requires some data from the outer scope, you can pass it with the `use` statement." +msgstr "" + +#. type: Title ## +#: en/caching/data.md +#, no-wrap +msgid "Cache handlers" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "The cache service uses [PSR-16](https://www.php-fig.org/psr/psr-16/) compatible cache handlers which represent various cache storages, such as memory, files, and databases." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Yii provides the following handlers:" +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "`NullCache` — a cache placeholder which does no real caching. The purpose of this handler is to simplify the code that needs to check the availability of cache. For example, during development or if the server doesn't have actual cache support, you may configure a cache service to use this handler. When you enable actual cache support, you can switch to using the corresponding cache handler. In both cases, you may use the same code without extra checks." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "`ArrayCache` — provides caching for the current request only by storing the values in an array." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "[APCu](https://github.com/yiisoft/cache-apcu) - uses a PHP [APC](https://secure.php.net/manual/en/book.apc.php) extension. You can consider this option as the fastest one when dealing with cache for a centralized thick application (e.g., one server, no dedicated load balancers, etc.)." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "[Database](https://github.com/yiisoft/cache-db) — uses a database table to store cached data." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "[File](https://github.com/yiisoft/cache-file) — uses standard files to store cached data. This is particularly suitable to cache large chunks of data, such as page content." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "[Memcached](https://github.com/yiisoft/cache-memcached) — uses a PHP [memcached](https://secure.php.net/manual/en/book.memcached.php) extension. You can consider this option as the fastest one when dealing with cache in distributed application (e.g., with several servers, load balancers, etc.)" +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "[Wincache](https://github.com/yiisoft/cache-wincache) — uses PHP [WinCache](https://iis.net/downloads/microsoft/wincache-extension) ([see also](https://secure.php.net/manual/en/book.wincache.php)) extension." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "[You could find more handlers at packagist.org](https://packagist.org/providers/psr/simple-cache-implementation)." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +#, no-wrap +msgid "" +"> [!TIP]\n" +"> You may use different cache storage in the same application. A common strategy is:\n" +"> - To use memory-based cache storage to store small but constantly used data (e.g., statistics)\n" +"> - To use file-based or database-based cache storage to store big and less often used data (e.g., page content)\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Cache handlers are usually set up in a [dependency injection container](../concept/di-container.md) so that they can be globally configurable and accessible." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Because all cache handlers support the same set of APIs, you can swap the underlying cache handler with a different one. You can do it by reconfiguring the application without modifying the code that uses the cache." +msgstr "" + +#. type: Title ### +#: en/caching/data.md +#, no-wrap +msgid "Cache keys" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "A key uniquely identifies each data item stored in the cache. When you store a data item, you have to specify a key for it. Later, when you retrieve the data item, you should give the corresponding key." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "You may use a string or an arbitrary value as a cache key. When a key isn't a string, it will be automatically serialized into a string." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "A common strategy of defining a cache key is to include all determining factors in terms of an array." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "When different applications use the same cache storage, you should specify a unique cache key prefix for each application to avoid conflicts of cache keys. You can do this by using `\\Yiisoft\\Cache\\PrefixedCache` decorator:" +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "" +"$arrayCacheWithPrefix = new \\Yiisoft\\Cache\\PrefixedCache(new \\Yiisoft\\Cache\\ArrayCache(), 'myapp_');\n" +"$cache = new \\Yiisoft\\Cache\\Cache($arrayCacheWithPrefix);\n" +msgstr "" + +#. type: Title ### +#: en/caching/data.md +#, no-wrap +msgid "Cache expiration" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "A data item stored in a cache will remain there forever unless it's removed because of some caching policy enforcement. For example, caching space is full and cache storage removes the oldest data. To change this behavior, you can set a TTL parameter when calling a method to store a data item:" +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "" +"$ttl = 3600;\n" +"$data = $cache->getOrSet($key, function (\\Psr\\SimpleCache\\CacheInterface $cache) use ($count) {\n" +"return getTopProductsFromDatabase($count);\n" +"}, $ttl);\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "The `$ttl` parameter indicates for how many seconds the data item can remain valid in the cache. When you retrieve the data item, if it has passed the expiration time, the method will execute the function and set the resulting value into cache." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "You may set default TTL for the cache:" +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "$cache = new \\Yiisoft\\Cache\\Cache($arrayCache, 60 * 60); // 1 hour\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Additionally, you can invalidate a cache key explicitly:" +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "$cache->remove($key);\n" +msgstr "" + +#. type: Title ### +#: en/caching/data.md +#, no-wrap +msgid "Invalidation dependencies" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Besides the expiration setting, changes of the so-called **invalidation dependencies** may also invalidate cached data item. For example, `\\Yiisoft\\Cache\\Dependency\\FileDependency` represents the dependency of a file's modification time. When this dependency changes, it means something modifying the corresponding file. As a result, any outdated file content found in the cache should invalidate." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Cache dependencies are objects of `\\Yiisoft\\Cache\\Dependency\\Dependency` descendant classes. When you store a data item in the cache, you can pass along an associated cache dependency object. For example," +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "" +"/**\n" +" * @var callable $callable\n" +" * @var \\Yiisoft\\Cache\\CacheInterface $cache\n" +" */\n" +"\n" +"use Yiisoft\\Cache\\Dependency\\TagDependency;\n" +"\n" +"// Set many cache values marking both with a tag.\n" +"$cache->getOrSet('item_42_price', $callable, null, new TagDependency('item_42'));\n" +"$cache->getOrSet('item_42_total', $callable, 3600, new TagDependency('item_42'));\n" +"\n" +"// Trigger invalidation by tag.\n" +"TagDependency::invalidate($cache, 'item_42');\n" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "Below is a summary of the available cache dependencies:" +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "`\\Yiisoft\\Cache\\Dependency\\ValueDependency`: invalidates the cache when specified value changes." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "`\\Yiisoft\\Cache\\Dependency\\CallbackDependency`: invalidates the cache when the result of the specified PHP callback is different." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "`\\Yiisoft\\Cache\\Dependency\\FileDependency`: invalidates the cache when the file's last modification time is different." +msgstr "" + +#. type: Bullet: '- ' +#: en/caching/data.md +msgid "`\\Yiisoft\\Cache\\Dependency\\TagDependency`: associates a cached data item with one or many tags. You may invalidate the cached data items with the specified tag(s) by calling `TagDependency::invalidate()`." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "You may combine many dependencies using `\\Yiisoft\\Cache\\Dependency\\AnyDependency` or `\\Yiisoft\\Cache\\Dependency\\AllDependencies`." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "To implement your own dependency, extend from `\\Yiisoft\\Cache\\Dependency\\Dependency`." +msgstr "" + +#. type: Title ### +#: en/caching/data.md +#, no-wrap +msgid "Cache stampede prevention" +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "[A cache stampede](https://en.wikipedia.org/wiki/Cache_stampede) is a type of cascading failure that can occur when massively parallel computing systems with caching mechanisms come under a high load. This behavior is sometimes also called dog-piling." +msgstr "" + +#. type: Plain text +#: en/caching/data.md +msgid "The `\\Yiisoft\\Cache\\Cache` uses a built-in \"Probably early expiration\" algorithm that prevents cache stampede. This algorithm randomly fakes a cache miss for one user while others are still served the cached value. You can control its behavior with the fifth optional parameter of `getOrSet()`, which is a float value called `$beta`. By default, beta is `1.0`, which is usually enough. The higher the value the earlier cache will be re-created." +msgstr "" + +#. type: Fenced code block (php) +#: en/caching/data.md +#, no-wrap +msgid "" +"/**\n" +" * @var mixed $key\n" +" * @var callable $callable\n" +" * @var \\DateInterval $ttl\n" +" * @var \\Yiisoft\\Cache\\CacheInterface $cache\n" +" * @var \\Yiisoft\\Cache\\Dependency\\Dependency $dependency\n" +" */\n" +"\n" +"$beta = 2.0;\n" +"$cache->getOrSet($key, $callable, $ttl, $dependency, $beta);\n" +msgstr "" diff --git a/guide/po/caching_overview.md/caching_overview.md.pot b/guide/po/caching_overview.md/caching_overview.md.pot new file mode 100644 index 00000000..dd9d7c50 --- /dev/null +++ b/guide/po/caching_overview.md/caching_overview.md.pot @@ -0,0 +1,69 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/caching/overview.md +#, no-wrap +msgid "Caching" +msgstr "" + +#. type: Plain text +#: en/caching/overview.md +msgid "" +"Caching is an inexpensive and effective way to improve the performance of an " +"application. By storing relatively static data in cache and serving it from " +"cache when requested, the application saves the time that it otherwise would " +"require to generate the data from scratch every time." +msgstr "" + +#. type: Plain text +#: en/caching/overview.md +msgid "" +"Caching can occur at different levels and places in an application. On the " +"server-side, at the lower level, cache may be used to store basic data, such " +"as a list of most recent article information fetched from the database; and " +"at the higher level, cache may be used to store fragments or whole of Web " +"pages, such as the rendering result of the most recent articles. On the " +"client-side, you may use HTTP caching to keep most recently visited page " +"content in the browser cache." +msgstr "" + +#. type: Plain text +#: en/caching/overview.md +msgid "Yii supports all these caching mechanisms:" +msgstr "" + +#. type: Bullet: '* ' +#: en/caching/overview.md +msgid "[Data caching](data.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/caching/overview.md +msgid "[Fragment caching](fragment.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/caching/overview.md +msgid "[Page caching](page.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/caching/overview.md +msgid "[HTTP caching](http.md)" +msgstr "" diff --git a/guide/po/caching_overview.md/ru/caching_overview.md.ru.po b/guide/po/caching_overview.md/ru/caching_overview.md.ru.po new file mode 100644 index 00000000..e753183e --- /dev/null +++ b/guide/po/caching_overview.md/ru/caching_overview.md.ru.po @@ -0,0 +1,58 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/caching/overview.md +#, no-wrap +msgid "Caching" +msgstr "" + +#. type: Plain text +#: en/caching/overview.md +msgid "Caching is an inexpensive and effective way to improve the performance of an application. By storing relatively static data in cache and serving it from cache when requested, the application saves the time that it otherwise would require to generate the data from scratch every time." +msgstr "" + +#. type: Plain text +#: en/caching/overview.md +msgid "Caching can occur at different levels and places in an application. On the server-side, at the lower level, cache may be used to store basic data, such as a list of most recent article information fetched from the database; and at the higher level, cache may be used to store fragments or whole of Web pages, such as the rendering result of the most recent articles. On the client-side, you may use HTTP caching to keep most recently visited page content in the browser cache." +msgstr "" + +#. type: Plain text +#: en/caching/overview.md +msgid "Yii supports all these caching mechanisms:" +msgstr "" + +#. type: Bullet: '* ' +#: en/caching/overview.md +msgid "[Data caching](data.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/caching/overview.md +msgid "[Fragment caching](fragment.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/caching/overview.md +msgid "[Page caching](page.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/caching/overview.md +msgid "[HTTP caching](http.md)" +msgstr "" diff --git a/guide/po/concept_aliases.md/concept_aliases.md.pot b/guide/po/concept_aliases.md/concept_aliases.md.pot new file mode 100644 index 00000000..370bc2f8 --- /dev/null +++ b/guide/po/concept_aliases.md/concept_aliases.md.pot @@ -0,0 +1,307 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-03 17:50+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/concept/aliases.md +#, no-wrap +msgid "Aliases" +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "" +"You can use aliases to represent file paths or URLs so that you don't have " +"to hard-code absolute paths or URLs in your project. An alias must start " +"with the `@` character to be differentiated from normal file paths and URLs. " +"Alias defined without leading `@` will be prefixed with `@` character." +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "" +"Default Yii application has some aliases pre-defined in `config/params.php`. " +"For example, the alias `@public` represents the web root path; `@baseUrl` " +"represents the base URL for the currently running Web application." +msgstr "" + +#. type: Title ## +#: en/concept/aliases.md +#, no-wrap +msgid "Defining aliases " +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "You can define an alias via application's `config/params.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "" +"return [\n" +" // ...\n" +" \n" +" 'yiisoft/aliases' => [\n" +" 'aliases' => [\n" +" // ...\n" +" \n" +" // an alias of a file path\n" +" '@foo' => '/path/to/foo',\n" +" \n" +" // an alias of a URL\n" +" '@bar' => 'https://www.example.com',\n" +" \n" +" // an alias of a concrete file that contains a \\foo\\Bar class \n" +" '@foo/Bar.php' => '/definitely/not/foo/Bar.php',\n" +" ],\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> The file path or URL being aliased may *not* necessarily refer to an existing file or resource.\n" +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "" +"Given a defined alias, you may derive a new alias by appending a slash `/` " +"followed with one or more path segments. For example, `@foo` is a root " +"alias, while `@foo/bar/file.php` is a derived alias." +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "You can define an alias using another alias (either root or derived):" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "'@foobar' => '@foo/bar', \n" +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "" +"The `yiisoft/aliases` parameter initializes `Aliases` service from [`yiisoft/" +"aliases` package](https://github.com/yiisoft/aliases). You can set extra " +"aliases in runtime by using the service:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "" +"use \\Yiisoft\\Aliases\\Aliases;\n" +"\n" +"public function actionIndex(Aliases $aliases)\n" +"{\n" +" $aliases->set('@uploads', '@root/uploads');\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/concept/aliases.md +#, no-wrap +msgid "Using aliases in configuration " +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "" +"It's preferred to resolve aliases at the configuration level, so services " +"get URLs and paths as ready to use strings:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "" +" static fn (Aliases $aliases) => new FileCache(\n" +" $aliases->get($params['yiisoft/cache-file']['fileCache']['path'])\n" +" ),\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/concept/aliases.md +#, no-wrap +msgid "Resolving aliases " +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "" +"You can use `Aliases` service to resolve an alias or derived alias into the " +"file path or URL it represents:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "" +"use \\Yiisoft\\Aliases\\Aliases;\n" +"\n" +"public function actionIndex(Aliases $aliases)\n" +"{\n" +" $foo = $aliases->get('@foo'); // /path/to/foo\n" +" $bar = $aliases->get('@bar'); // https://www.example.com\n" +" $file = $aliases->get('@foo/bar/file.php'); // /path/to/foo/bar/file.php\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "" +"The path/URL represented by a derived alias is determined by replacing the " +"root alias part with its corresponding path/URL in the derived alias." +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> The `get()` method doesn't check whether the resulting path/URL refers to an existing file or resource.\n" +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "" +"A root alias may also contain slash `/` characters. The `get()` method is " +"intelligent enough to tell, which part of an alias is a root alias and thus " +"correctly determines the corresponding file path or URL:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "" +"use \\Yiisoft\\Aliases\\Aliases;\n" +"\n" +"public function actionIndex(Aliases $aliases)\n" +"{\n" +" $aliases->set('@foo', '/path/to/foo');\n" +" $aliases->set('@foo/bar', '/path2/bar');\n" +"\n" +" $aliases->get('@foo/test/file.php'); // /path/to/foo/test/file.php\n" +" $aliases->get('@foo/bar/file.php'); // /path2/bar/file.php\n" +"} \n" +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "" +"If `@foo/bar` isn't defined as a root alias, the last statement would " +"display `/path/to/foo/bar/file.php`." +msgstr "" + +#. type: Title ## +#: en/concept/aliases.md +#, no-wrap +msgid "Predefined aliases " +msgstr "" + +#. type: Plain text +#: en/concept/aliases.md +msgid "" +"[Yii application](https://github.com/yiisoft/app) predefines a set of " +"aliases to reference commonly used file paths and URLs:" +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@root` - the base directory of the currently running application." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@assets` - application's public directory where it publishes assets." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@assetsUrl` - URL of base directory with published assets." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "" +"`@baseUrl` - the base URL of the currently running Web application. Defaults " +"to `/`." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@npm` - node packages directory." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@bower` - bower packages directory." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@vendor` - Composer's `vendor` directory." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "" +"`@public` - application's publicly accessible directory that with `index." +"php`." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "" +"`@runtime` - the runtime path of the currently running application. Defaults " +"to `@root/runtime`." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@layout` - the directory with layouts." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@resources` - directory with views, asset sources and other resources." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@views` - application view templates base directory." +msgstr "" diff --git a/guide/po/concept_aliases.md/ru/concept_aliases.md.ru.po b/guide/po/concept_aliases.md/ru/concept_aliases.md.ru.po new file mode 100644 index 00000000..5b72afeb --- /dev/null +++ b/guide/po/concept_aliases.md/ru/concept_aliases.md.ru.po @@ -0,0 +1,351 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2025-09-03 17:50+0500\n" +"PO-Revision-Date: 2025-09-03 20:24+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 3.7\n" + +#. type: Title # +#: en/concept/aliases.md +#, no-wrap +msgid "Aliases" +msgstr "Псевдонимы (алиасы)" + +#. type: Plain text +#: en/concept/aliases.md +msgid "You can use aliases to represent file paths or URLs so that you don't have to hard-code absolute paths or URLs in your project. An alias must start with the `@` character to be differentiated from normal file paths and URLs. Alias defined without leading `@` will be prefixed with `@` character." +msgstr "Вы можете использовать псевдонимы для представления путей к файлам или URL-адресов, чтобы вам не приходилось жестко указывать абсолютные пути или URL-адреса в вашем проекте. Каждый псевдоним должен начинаться с символа `@`, чтобы отличаться от обычных файловых путей или URL. Алиас, определенный без предшествующего `@` будет префиксироваться с помощью символа `@`." + +#. type: Plain text +#: en/concept/aliases.md +msgid "Default Yii application has some aliases pre-defined in `config/params.php`. For example, the alias `@public` represents the web root path; `@baseUrl` represents the base URL for the currently running Web application." +msgstr "По умолчанию Yii-приложение имеет несколько алисов, предопределенных в `config/params.php`. Например, алиас `@public` представляет корневой путь для web; `@baseUrl` представляет базовый URL для запущенного в текущий момент Web-приложения." + +#. type: Title ## +#: en/concept/aliases.md +#, no-wrap +msgid "Defining aliases " +msgstr "Определение псевдонимов " + +#. type: Plain text +#: en/concept/aliases.md +msgid "You can define an alias via application's `config/params.php`:" +msgstr "Вы можете определить какой-либо псевдоним через `config/params.php` приложения:" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "" +"return [\n" +" // ...\n" +" \n" +" 'yiisoft/aliases' => [\n" +" 'aliases' => [\n" +" // ...\n" +" \n" +" // an alias of a file path\n" +" '@foo' => '/path/to/foo',\n" +" \n" +" // an alias of a URL\n" +" '@bar' => 'https://www.example.com',\n" +" \n" +" // an alias of a concrete file that contains a \\foo\\Bar class \n" +" '@foo/Bar.php' => '/definitely/not/foo/Bar.php',\n" +" ],\n" +" ],\n" +"];\n" +msgstr "" +"return [\n" +" // ...\n" +" \n" +" 'yiisoft/aliases' => [\n" +" 'aliases' => [\n" +" // ...\n" +" \n" +" // an alias of a file path\n" +" '@foo' => '/path/to/foo',\n" +" \n" +" // an alias of a URL\n" +" '@bar' => 'http://www.example.com',\n" +" \n" +" // an alias of a concrete file that contains a \\foo\\Bar class \n" +" '@foo/Bar.php' => '/definitely/not/foo/Bar.php',\n" +" ],\n" +" ],\n" +"];\n" + +#. type: Plain text +#: en/concept/aliases.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> The file path or URL being aliased may *not* necessarily refer to an existing file or resource.\n" +msgstr "" +"> Примечание: Псевдонимизированный файловый путь или URL *не обязательно* может ссылаться на существующий файл или \n" +"> ресурс.\n" + +#. type: Plain text +#: en/concept/aliases.md +msgid "Given a defined alias, you may derive a new alias by appending a slash `/` followed with one or more path segments. For example, `@foo` is a root alias, while `@foo/bar/file.php` is a derived alias." +msgstr "" +"Учитывая определенный псевдоним, вы можете создать новый, добавив слэш `/`, за которым следует один или несколько \n" +"сегментов пути. Например, `@foo` - это корневой псевдоним, а `@foo/bar/file.php` - производный псевдоним." + +#. type: Plain text +#: en/concept/aliases.md +msgid "You can define an alias using another alias (either root or derived):" +msgstr "Вы можете определить псевдоним, используя другой псевдоним (корневой или производный):" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "'@foobar' => '@foo/bar', \n" +msgstr "'@foobar' => '@foo/bar', \n" + +#. type: Plain text +#: en/concept/aliases.md +msgid "The `yiisoft/aliases` parameter initializes `Aliases` service from [`yiisoft/aliases` package](https://github.com/yiisoft/aliases). You can set extra aliases in runtime by using the service:" +msgstr "" +"Параметр `yiisoft/aliases` инициализирует сервис `Aliases` из [пакета](https://github.com/yiisoft/aliases) \n" +"`yiisoft/aliases`. Используя этот сервис, вы можете установить дополнительные псевдонимы времени выполнения:" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "" +"use \\Yiisoft\\Aliases\\Aliases;\n" +"\n" +"public function actionIndex(Aliases $aliases)\n" +"{\n" +" $aliases->set('@uploads', '@root/uploads');\n" +"}\n" +msgstr "" +"use \\Yiisoft\\Aliases\\Aliases;\n" +"\n" +"public function actionIndex(Aliases $aliases)\n" +"{\n" +" $aliases->set('@uploads', '@root/uploads');\n" +"}\n" + +#. type: Title ## +#: en/concept/aliases.md +#, no-wrap +msgid "Using aliases in configuration " +msgstr "Использование псевдонимов в конфигурации " + +#. type: Plain text +#: en/concept/aliases.md +msgid "It's preferred to resolve aliases at the configuration level, so services get URLs and paths as ready to use strings:" +msgstr "" +"Предпочтительно разрешать псевдонимы на уровне конфигурации, чтобы сервисы получали URL-адреса и пути как готовые к \n" +"использованию строки:" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "" +" static fn (Aliases $aliases) => new FileCache(\n" +" $aliases->get($params['yiisoft/cache-file']['fileCache']['path'])\n" +" ),\n" +"];\n" +msgstr "" +" static fn (Aliases $aliases) => new FileCache(\n" +" $aliases->get($params['yiisoft/cache-file']['fileCache']['path'])\n" +" ),\n" +"];\n" + +#. type: Title ## +#: en/concept/aliases.md +#, no-wrap +msgid "Resolving aliases " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/concept/aliases.md +msgid "You can use `Aliases` service to resolve an alias or derived alias into the file path or URL it represents:" +msgstr "" +"Вы можете использовать сервис `Aliases`, чтобы преобразовать псевдоним или производный псевдоним в путь к файлу или URL,\n" +"который он представляет:" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "" +"use \\Yiisoft\\Aliases\\Aliases;\n" +"\n" +"public function actionIndex(Aliases $aliases)\n" +"{\n" +" $foo = $aliases->get('@foo'); // /path/to/foo\n" +" $bar = $aliases->get('@bar'); // https://www.example.com\n" +" $file = $aliases->get('@foo/bar/file.php'); // /path/to/foo/bar/file.php\n" +"}\n" +msgstr "" +"use \\Yiisoft\\Aliases\\Aliases;\n" +"\n" +"public function actionIndex(Aliases $aliases)\n" +"{\n" +" $foo = $aliases->get('@foo'); // /path/to/foo\n" +" $bar = $aliases->get('@bar'); // http://www.example.com\n" +" $file = $aliases->get('@foo/bar/file.php'); // /path/to/foo/bar/file.php\n" +"}\n" + +#. type: Plain text +#: en/concept/aliases.md +msgid "The path/URL represented by a derived alias is determined by replacing the root alias part with its corresponding path/URL in the derived alias." +msgstr "" +"Путь/URL, представленный производным псевдонимом, определяется путем замены части корневого псевдонима на \n" +"соответствующий путь/URL в производном псевдониме." + +#. type: Plain text +#: en/concept/aliases.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> The `get()` method doesn't check whether the resulting path/URL refers to an existing file or resource.\n" +msgstr "> Примечание: Метод `get()` не проверяет, относится ли результирующий путь/URL-адрес к существующему файлу или ресурсу.\n" + +#. type: Plain text +#: en/concept/aliases.md +msgid "A root alias may also contain slash `/` characters. The `get()` method is intelligent enough to tell, which part of an alias is a root alias and thus correctly determines the corresponding file path or URL:" +msgstr "" +"Псевдоним root также может содержать символы косой черты `/`. Метод `get()` достаточно интеллектуален, чтобы определить, \n" +"какая часть псевдонима является корневым псевдонимом, и, таким образом, правильно определить путь к соответствующему \n" +"файлу или URL-адрес:" + +#. type: Fenced code block (php) +#: en/concept/aliases.md +#, no-wrap +msgid "" +"use \\Yiisoft\\Aliases\\Aliases;\n" +"\n" +"public function actionIndex(Aliases $aliases)\n" +"{\n" +" $aliases->set('@foo', '/path/to/foo');\n" +" $aliases->set('@foo/bar', '/path2/bar');\n" +"\n" +" $aliases->get('@foo/test/file.php'); // /path/to/foo/test/file.php\n" +" $aliases->get('@foo/bar/file.php'); // /path2/bar/file.php\n" +"} \n" +msgstr "" +"use \\Yiisoft\\Aliases\\Aliases;\n" +"\n" +"public function actionIndex(Aliases $aliases)\n" +"{\n" +" $aliases->set('@foo', '/path/to/foo');\n" +" $aliases->set('@foo/bar', '/path2/bar');\n" +"\n" +" $aliases->get('@foo/test/file.php'); // /path/to/foo/test/file.php\n" +" $aliases->get('@foo/bar/file.php'); // /path2/bar/file.php\n" +"} \n" + +#. type: Plain text +#: en/concept/aliases.md +msgid "If `@foo/bar` isn't defined as a root alias, the last statement would display `/path/to/foo/bar/file.php`." +msgstr "" +"Если бы `@foo/bar` не был бы определен как корневой псевдоним, то последний оператор отобразил бы \n" +"`/path/to/foo/bar/file.php`." + +#. type: Title ## +#: en/concept/aliases.md +#, no-wrap +msgid "Predefined aliases " +msgstr "Предопределенные псевдонимы " + +#. type: Plain text +#: en/concept/aliases.md +msgid "[Yii application](https://github.com/yiisoft/app) predefines a set of aliases to reference commonly used file paths and URLs:" +msgstr "" +"[Yii приложение](https://github.com/yiisoft/app) предопределяет набор псевдонимов, чтобы ссылаться на часто используемые\n" +"файловые пути и URL-адреса:" + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@root` - the base directory of the currently running application." +msgstr "`@root` - базовая директория для приложения запущенного в текущий момент." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@assets` - application's public directory where it publishes assets." +msgstr "`@assets` - публичная директория приложения, где оно публикует ресурсы (assets)." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@assetsUrl` - URL of base directory with published assets." +msgstr "`@assetsUrl` - URL базовой директории с опубликованными ресурсами." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@baseUrl` - the base URL of the currently running Web application. Defaults to `/`." +msgstr "`@baseUrl` - базовый URL запущенного в текущий момент Web приложения. По умолчанию - `/`." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@npm` - node packages directory." +msgstr "`@npm` - директория пакетов Node JS." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@bower` - bower packages directory." +msgstr "`@bower` - директория пакетов Bower." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@vendor` - Composer's `vendor` directory." +msgstr "`@vendor` - директория `vendor` Composer'а ." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@public` - application's publicly accessible directory that with `index.php`." +msgstr "`@public` - публично доступная директория приложения, которая содержит `index.php`." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@runtime` - the runtime path of the currently running application. Defaults to `@root/runtime`." +msgstr "`@runtime` - путь времени выполнения текущего запущенного приложения. По умолчанию - `@root/runtime`." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@layout` - the directory with layouts." +msgstr "`@layout` - директория с макетами." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@resources` - directory with views, asset sources and other resources." +msgstr "`@resources` - директория с представлениями, исходниками ресурсов (asset) и другими ресурсами." + +#. type: Bullet: '- ' +#: en/concept/aliases.md +msgid "`@views` - application view templates base directory." +msgstr "`@views` - базовая директория шаблонов представлений приложения." diff --git a/guide/po/concept_autoloading.md/concept_autoloading.md.pot b/guide/po/concept_autoloading.md/concept_autoloading.md.pot new file mode 100644 index 00000000..4adfa1e7 --- /dev/null +++ b/guide/po/concept_autoloading.md/concept_autoloading.md.pot @@ -0,0 +1,90 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 07:25+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/concept/autoloading.md +#, no-wrap +msgid "Class autoloading" +msgstr "" + +#. type: Plain text +#: en/concept/autoloading.md +msgid "" +"Since Yii uses [Composer](https://getcomposer.org) to manage packages, it " +"automatically loads classes from these packages without the need to " +"`require` their file explicitly. When it installs packages, it generates a " +"[PSR-4 compatible autoloader](https://www.php-fig.org/psr/psr-4/). To use " +"it, `require_once` autoloader `/vendor/autoload.php` in your `index.php` " +"entry point file." +msgstr "" + +#. type: Plain text +#: en/concept/autoloading.md +msgid "" +"You can use autoloader not only for the packages installed, but for your " +"application as well since it's also a package. To load classes of a certain " +"namespace, add the following to `composer.json`:" +msgstr "" + +#. type: Fenced code block (json) +#: en/concept/autoloading.md +#, no-wrap +msgid "" +"{\n" +" \"autoload\": {\n" +" \"psr-4\": {\n" +" \"App\\\\\": \"src/\"\n" +" }\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/autoloading.md +msgid "" +"Where `App\\\\` is a root namespace and `src/` is a directory where you have " +"your classes. You can add more source roots if needed. When done, execute " +"`composer dump-autoload` or simply `composer du` and classes from the " +"corresponding namespaces will start loading automatically." +msgstr "" + +#. type: Plain text +#: en/concept/autoloading.md +msgid "" +"If you need development-environment-specific autoloading that isn't used " +"when executing Composer with `--no-dev` flag, add it to `autoload-dev` " +"section instead of `autoload`." +msgstr "" + +#. type: Title ## +#: en/concept/autoloading.md +#, no-wrap +msgid "References" +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/autoloading.md +msgid "[PSR-4: Autoloader](https://www.php-fig.org/psr/psr-4/)." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/autoloading.md +msgid "" +"[Composer guide on autoloading](https://getcomposer.org/doc/01-basic-usage." +"md#autoloading)." +msgstr "" diff --git a/guide/po/concept_autoloading.md/ru/concept_autoloading.md.ru.po b/guide/po/concept_autoloading.md/ru/concept_autoloading.md.ru.po new file mode 100644 index 00000000..0042cede --- /dev/null +++ b/guide/po/concept_autoloading.md/ru/concept_autoloading.md.ru.po @@ -0,0 +1,83 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2025-09-04 07:25+0500\n" +"PO-Revision-Date: 2025-09-04 07:29+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 3.7\n" + +#. type: Title # +#: en/concept/autoloading.md +#, no-wrap +msgid "Class autoloading" +msgstr "Автозагрузка класоов" + +#. type: Plain text +#: en/concept/autoloading.md +msgid "Since Yii uses [Composer](https://getcomposer.org) to manage packages, it automatically loads classes from these packages without the need to `require` their file explicitly. When it installs packages, it generates a [PSR-4 compatible autoloader](https://www.php-fig.org/psr/psr-4/). To use it, `require_once` autoloader `/vendor/autoload.php` in your `index.php` entry point file." +msgstr "" +"Поскольку Yii использует [Composer](https://getcomposer.org) для управления пакетами, он автоматически загружает классы из пакетов без необходимости явно подключать их через `require`.\n" +"При установке пакетов он создает [автозагрузчик, совместимый с PSR-4](https://www.php-fig.org/psr/psr-4/).\n" +"Чтобы использовать его, подключите `/vendor/autoload.php` через `require_once` в ваш входной скрипт `index.php`." + +#. type: Plain text +#: en/concept/autoloading.md +msgid "You can use autoloader not only for the packages installed, but for your application as well since it's also a package. To load classes of a certain namespace, add the following to `composer.json`:" +msgstr "Вы можете использовать автозагрузчик не только для установленных пакетов, но и для всего вашего приложения, поскольку оно тоже является пакетом. Чтобы загрузить классы определенного пространства имен, добавьте в `composer.json`:" + +#. type: Fenced code block (json) +#: en/concept/autoloading.md +#, no-wrap +msgid "" +"{\n" +" \"autoload\": {\n" +" \"psr-4\": {\n" +" \"App\\\\\": \"src/\"\n" +" }\n" +" }\n" +"}\n" +msgstr "" +"{\n" +" \"autoload\": {\n" +" \"psr-4\": {\n" +" \"App\\\\\": \"src/\"\n" +" }\n" +" }\n" +"}\n" + +#. type: Plain text +#: en/concept/autoloading.md +msgid "Where `App\\\\` is a root namespace and `src/` is a directory where you have your classes. You can add more source roots if needed. When done, execute `composer dump-autoload` or simply `composer du` and classes from the corresponding namespaces will start loading automatically." +msgstr "Здесь `App\\\\` это корневое пространство имен, а `src/` - директория, где вы храните ваши классы. При необходимости, вы можете добавить несколько корневых директорий. После изменения `composer.json` выполните `composer dump-autoload` или `composer du` и классы из соответствующих пространств имен начнут загружаться автоматически." + +#. type: Plain text +#: en/concept/autoloading.md +msgid "If you need development-environment-specific autoloading that isn't used when executing Composer with `--no-dev` flag, add it to `autoload-dev` section instead of `autoload`." +msgstr "Если вам нужна специфичная для разработки автозагрузка, которая не используется при запуске Composer с флагом `--no-dev`, добавьте ее в секцию `autoload-dev` вместо `autoload`." + +#. type: Title ## +#: en/concept/autoloading.md +#, no-wrap +msgid "References" +msgstr "Ссылки" + +#. type: Bullet: '- ' +#: en/concept/autoloading.md +msgid "[PSR-4: Autoloader](https://www.php-fig.org/psr/psr-4/)." +msgstr "[PSR-4: Autoloader](https://www.php-fig.org/psr/psr-4/)." + +#. type: Bullet: '- ' +#: en/concept/autoloading.md +msgid "[Composer guide on autoloading](https://getcomposer.org/doc/01-basic-usage.md#autoloading)." +msgstr "[Composer guide on autoloading](https://getcomposer.org/doc/01-basic-usage.md#autoloading)." diff --git a/guide/po/concept_configuration.md/concept_configuration.md.pot b/guide/po/concept_configuration.md/concept_configuration.md.pot new file mode 100644 index 00000000..6ef34e59 --- /dev/null +++ b/guide/po/concept_configuration.md/concept_configuration.md.pot @@ -0,0 +1,594 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title ## +#: en/concept/configuration.md en/tutorial/using-yii-with-roadrunner.md +#: en/views/view-injections.md +#, no-wrap +msgid "Configuration" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"There are many ways to configure your application. We will focus on concepts " +"used in the [default project template](https://github.com/yiisoft/app)." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"Yii3 configs are part of the application. You can change many aspects of how " +"the application works by editing configuration under `config/`." +msgstr "" + +#. type: Title ## +#: en/concept/configuration.md +#, no-wrap +msgid "Config plugin" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"In the application template [yiisoft/config](https://github.com/yiisoft/" +"config) is used. Since writing all application configurations from scratch " +"is a tedious process, many packages offer default configs, and the plugin " +"helps with copying these into the application." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"To offer default configs, `composer.json` of the package has to have `config-" +"plugin` section. When installing or updating packages with Composer, the " +"plugin reads `config-plugin` sections for each dependency, copies files " +"themselves to application `config/packages/` if they don't yet exist and " +"writes a merge plan to `config/packages/merge_plan.php`. The merge plan " +"defines how to merge the configs into a single big array ready to be passed " +"to [DI container](di-container.md)." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"Take a look at what's in the \"yiisoft/app\" `composer.json` by default:" +msgstr "" + +#. type: Fenced code block (json) +#: en/concept/configuration.md +#, no-wrap +msgid "" +"\"config-plugin-options\": {\n" +" \"output-directory\": \"config/packages\"\n" +"},\n" +"\"config-plugin\": {\n" +" \"common\": \"config/common/*.php\",\n" +" \"params\": [\n" +" \"config/params.php\",\n" +" \"?config/params-local.php\"\n" +" ],\n" +" \"web\": [\n" +" \"$common\",\n" +" \"config/web/*.php\"\n" +" ],\n" +" \"console\": [\n" +" \"$common\",\n" +" \"config/console/*.php\"\n" +" ],\n" +" \"events\": \"config/events.php\",\n" +" \"events-web\": [\n" +" \"$events\",\n" +" \"config/events-web.php\"\n" +" ],\n" +" \"events-console\": [\n" +" \"$events\",\n" +" \"config/events-console.php\"\n" +" ],\n" +" \"providers\": \"config/providers.php\",\n" +" \"providers-web\": [\n" +" \"$providers\",\n" +" \"config/providers-web.php\"\n" +" ],\n" +" \"providers-console\": [\n" +" \"$providers\",\n" +" \"config/providers-console.php\"\n" +" ],\n" +" \"routes\": \"config/routes.php\"\n" +"},\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"There are many named configs defined. For each name, there is a " +"configuration." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"A string means that the plugin takes config as is and merges it with same-" +"named configs from packages you require. That happens if these packages " +"have `config-plugin` in their `composer.json`." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"The array means that the plugin will merge many files in the order they're " +"specified." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"`?` at the beginning of the file path indicated that the file may be absent. " +"In this case, it's skipped." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"`$` at the beginning of the name means a reference to another named config." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"`params` is a bit special because it's reserved for application parameters. " +"These are automatically available as `$params` in all other configuration " +"files." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"You can learn more about config plugin features [from its documentation]" +"(https://github.com/yiisoft/config/blob/master/README.md)." +msgstr "" + +#. type: Title ## +#: en/concept/configuration.md +#, no-wrap +msgid "Config files" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"Now, as you know how the plugin assembles configs, look at `config` " +"directory:" +msgstr "" + +#. type: Fenced code block +#: en/concept/configuration.md +#, no-wrap +msgid "" +"common/\n" +" application-parameters.php\n" +" i18n.php\n" +" router.php\n" +"console/\n" +"packages/\n" +" yiisoft/\n" +" dist.lock\n" +" merge_plan.php\n" +"web/\n" +" application.php\n" +" psr17.php\n" +"events.php\n" +"events-console.php\n" +"events-web.php\n" +"params.php\n" +"providers.php\n" +"providers-console.php\n" +"providers-web.php\n" +"routes.php\n" +msgstr "" + +#. type: Title ### +#: en/concept/configuration.md +#, no-wrap +msgid "Container configuration" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"The application consists of a set of services registered in a [dependency " +"container](di-container.md). The config files that responsible for direct " +"dependency container configuration are under `common/`, `console/` and `web/" +"` directories. We use `web/` for config specific to web application and " +"`console/` for config specific to console commands. Both web and console are " +"sharing configuration under `common/`." +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +" [\n" +" 'class' => ApplicationParameters::class,\n" +" 'charset()' => [$params['app']['charset']],\n" +" 'name()' => [$params['app']['name']],\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"Config plugin passes special `$params` variable to all config files. The " +"code passes its values to the service." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"The guide on [\"Dependency injection and container\"](di-container.md) " +"describes the configuration format and the idea of dependency injection in " +"detail." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "For convenience, there is a naming convention for custom string keys:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/concept/configuration.md +msgid "Prefix package name such as `yiisoft/cache-file/custom-definition`." +msgstr "" + +#. type: Bullet: '2. ' +#: en/concept/configuration.md +msgid "" +"In case configuration are for the application itself, skip package prefix, " +"such as `custom-definition`." +msgstr "" + +#. type: Title ### +#: en/concept/configuration.md +#, no-wrap +msgid "Service providers" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"As an alternative to registering dependencies directly, you can use service " +"providers. Basically, these are classes that given parameters are " +"configuring and registering services within the container. Similar to three " +"dependency configuration files described, there are three configs for " +"specifying service providers: `providers-console.php` for console commands, " +"`providers-web.php` for web application and `providers.php` for both:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +"/* @var array $params */\n" +"\n" +"// ...\n" +"use App\\Provider\\CacheProvider;\n" +"use App\\Provider\\MiddlewareProvider;\n" +"// ...\n" +"\n" +"return [\n" +" // ...\n" +" 'yiisoft/yii-web/middleware' => MiddlewareProvider::class,\n" +" 'yiisoft/cache/cache' => [\n" +" 'class' => CacheProvider::class,\n" +" '__construct()' => [\n" +" $params['yiisoft/cache-file']['file-cache']['path'],\n" +" ],\n" +" ],\n" +" // ...\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"In this config keys are provider names. By convention these are `vendor/" +"package-name/provider-name`. Values are provider class names. These classes " +"could be either created in the project itself or provided by a package." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"If you need to configure some options for a service, similar to direct " +"container configuration, take values from `$params` and pass them to " +"providers." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"Provider should implement a single method, `public function " +"register(Container $container): void`. In this method you need to add a " +"service to container using `set()` method. Below is a provider for a cache " +"service:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +"use Psr\\Container\\ContainerInterface;\n" +"use Psr\\SimpleCache\\CacheInterface;\n" +"use Yiisoft\\Aliases\\Aliases;\n" +"use Yiisoft\\Cache\\Cache;\n" +"use Yiisoft\\Cache\\CacheInterface as YiiCacheInterface;\n" +"use Yiisoft\\Cache\\File\\FileCache;\n" +"use Yiisoft\\Di\\Container;\n" +"use Yiisoft\\Di\\Support\\ServiceProvider;\n" +"\n" +"final readonly class CacheProvider extends ServiceProvider\n" +"{\n" +" public function __construct(\n" +" private string $cachePath = '@runtime/cache'\n" +" )\n" +" {\n" +" $this->cachePath = $cachePath;\n" +" }\n" +"\n" +" public function register(Container $container): void\n" +" {\n" +" $container->set(CacheInterface::class, function (ContainerInterface $container) {\n" +" $aliases = $container->get(Aliases::class);\n" +"\n" +" return new FileCache($aliases->get($this->cachePath));\n" +" });\n" +"\n" +" $container->set(YiiCacheInterface::class, Cache::class);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ### +#: en/concept/configuration.md +#, no-wrap +msgid "Routes" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"You can configure how web application responds to certain URLs in `config/" +"routes.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +"use App\\Controller\\SiteController;\n" +"use Yiisoft\\Router\\Route;\n" +"\n" +"return [\n" +" Route::get('/')->action([SiteController::class, 'index'])->name('site/index')\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Read more about it in [\"Routes\"](../runtime/routing.md)." +msgstr "" + +#. type: Title # +#: en/concept/configuration.md en/concept/events.md +#, no-wrap +msgid "Events" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"Many services emit certain events that you can attach to. You could do that " +"via three config files: `events-web.php` for web application events, `events-" +"console.php` for console events and `events.php` for both. The " +"configuration is an array where keys are event names and values are an array " +"of handlers:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +"return [\n" +" EventName::class => [\n" +" // Just a regular closure, it will be called from the Dispatcher \"as is\".\n" +" static fn (EventName $event) => someStuff($event),\n" +" \n" +" // A regular closure with an extra dependency. All the parameters after the first one (the event itself)\n" +" // will be resolved from your DI container within `yiisoft/injector`.\n" +" static fn (EventName $event, DependencyClass $dependency) => someStuff($event),\n" +" \n" +" // An example with a regular callable. If the `staticMethodName` method has some dependencies,\n" +" // they will be resolved the same way as in the earlier example.\n" +" [SomeClass::class, 'staticMethodName'],\n" +" \n" +" // Non-static methods are allowed too. In this case, `SomeClass` will be instantiated by your DI container.\n" +" [SomeClass::class, 'methodName'],\n" +" \n" +" // An object of a class with the `__invoke` method implemented\n" +" new InvokableClass(),\n" +" \n" +" // In this case, the `InvokableClass` with the `__invoke` method will be instantiated by your DI container\n" +" InvokableClass::class,\n" +" \n" +" // Any definition of an invokable class may be here while your `$container->has('the definition)` \n" +" 'di-alias'\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Read more about it in [\"Events\"](events.md)." +msgstr "" + +#. type: Title ### +#: en/concept/configuration.md +#, no-wrap +msgid "Parameters" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"Parameters, `config/params.php` store configuration values that are used in " +"other config files to configuring services and service providers." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +#, no-wrap +msgid "" +"> [!TIP]\n" +"> Don't use parameters, constants or environment variables directly in your application, configure\n" +"> services instead.\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Default application `params.php` looks like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +" [\n" +" 'charset' => 'UTF-8',\n" +" 'locale' => 'en',\n" +" 'name' => 'My Project',\n" +" ],\n" +"\n" +" 'yiisoft/aliases' => [\n" +" 'aliases' => [\n" +" '@root' => dirname(__DIR__),\n" +" '@assets' => '@root/public/assets',\n" +" '@assetsUrl' => '/assets',\n" +" '@baseUrl' => '/',\n" +" '@message' => '@root/resources/message',\n" +" '@npm' => '@root/node_modules',\n" +" '@public' => '@root/public',\n" +" '@resources' => '@root/resources',\n" +" '@runtime' => '@root/runtime',\n" +" '@vendor' => '@root/vendor',\n" +" '@layout' => '@resources/views/layout',\n" +" '@views' => '@resources/views',\n" +" ],\n" +" ],\n" +"\n" +" 'yiisoft/yii-view' => [\n" +" 'injections' => [\n" +" Reference::to(ContentViewInjection::class),\n" +" Reference::to(CsrfViewInjection::class),\n" +" Reference::to(LayoutViewInjection::class),\n" +" ],\n" +" ],\n" +"\n" +" 'yiisoft/yii-console' => [\n" +" 'commands' => [\n" +" 'hello' => Hello::class,\n" +" ],\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "For convenience, there is a naming convention about parameters:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/concept/configuration.md +msgid "Group parameters package name such as `yiisoft/cache-file`." +msgstr "" + +#. type: Bullet: '2. ' +#: en/concept/configuration.md +msgid "" +"In case parameters are for the application itself, as in `app`, skip package " +"prefix." +msgstr "" + +#. type: Bullet: '3. ' +#: en/concept/configuration.md +msgid "" +"In case there are many services in the package, such as `file-target` and " +"`file-rotator` in `yiisoft/log-target-file` package, group parameters by " +"service name." +msgstr "" + +#. type: Bullet: '4. ' +#: en/concept/configuration.md +msgid "" +"Use `enabled` as parameter name to be able to disable or enable a service, " +"such as `yiisoft/yii-debug`." +msgstr "" + +#. type: Title ### +#: en/concept/configuration.md +#, no-wrap +msgid "Package configs" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"Config plugin described copy default package configurations to `packages/` " +"directory. Once copied you own the configs, so you can adjust these as you " +"like. `yiisoft/` in the default template stands for package vendor. Since " +"only `yiisoft` packages are in template, there's a single directory. " +"`merge_plan.php` is used in runtime to get the order on how configs are " +"merged. Note that for config keys there should be a single source of " +"truth. One config can't override values of another config." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "" +"`dist.lock` is used by the plugin to keep track of changes and display diff " +"between current config and example one." +msgstr "" diff --git a/guide/po/concept_configuration.md/ru/concept_configuration.md.ru.po b/guide/po/concept_configuration.md/ru/concept_configuration.md.ru.po new file mode 100644 index 00000000..66298e24 --- /dev/null +++ b/guide/po/concept_configuration.md/ru/concept_configuration.md.ru.po @@ -0,0 +1,508 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title ## +#: en/concept/configuration.md en/tutorial/using-yii-with-roadrunner.md +#: en/views/view-injections.md +#, fuzzy, no-wrap +msgid "Configuration" +msgstr "конфигурация может быть:" + +#. type: Plain text +#: en/concept/configuration.md +msgid "There are many ways to configure your application. We will focus on concepts used in the [default project template](https://github.com/yiisoft/app)." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Yii3 configs are part of the application. You can change many aspects of how the application works by editing configuration under `config/`." +msgstr "" + +#. type: Title ## +#: en/concept/configuration.md +#, no-wrap +msgid "Config plugin" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "In the application template [yiisoft/config](https://github.com/yiisoft/config) is used. Since writing all application configurations from scratch is a tedious process, many packages offer default configs, and the plugin helps with copying these into the application." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "To offer default configs, `composer.json` of the package has to have `config-plugin` section. When installing or updating packages with Composer, the plugin reads `config-plugin` sections for each dependency, copies files themselves to application `config/packages/` if they don't yet exist and writes a merge plan to `config/packages/merge_plan.php`. The merge plan defines how to merge the configs into a single big array ready to be passed to [DI container](di-container.md)." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Take a look at what's in the \"yiisoft/app\" `composer.json` by default:" +msgstr "" + +#. type: Fenced code block (json) +#: en/concept/configuration.md +#, no-wrap +msgid "" +"\"config-plugin-options\": {\n" +" \"output-directory\": \"config/packages\"\n" +"},\n" +"\"config-plugin\": {\n" +" \"common\": \"config/common/*.php\",\n" +" \"params\": [\n" +" \"config/params.php\",\n" +" \"?config/params-local.php\"\n" +" ],\n" +" \"web\": [\n" +" \"$common\",\n" +" \"config/web/*.php\"\n" +" ],\n" +" \"console\": [\n" +" \"$common\",\n" +" \"config/console/*.php\"\n" +" ],\n" +" \"events\": \"config/events.php\",\n" +" \"events-web\": [\n" +" \"$events\",\n" +" \"config/events-web.php\"\n" +" ],\n" +" \"events-console\": [\n" +" \"$events\",\n" +" \"config/events-console.php\"\n" +" ],\n" +" \"providers\": \"config/providers.php\",\n" +" \"providers-web\": [\n" +" \"$providers\",\n" +" \"config/providers-web.php\"\n" +" ],\n" +" \"providers-console\": [\n" +" \"$providers\",\n" +" \"config/providers-console.php\"\n" +" ],\n" +" \"routes\": \"config/routes.php\"\n" +"},\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "There are many named configs defined. For each name, there is a configuration." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "A string means that the plugin takes config as is and merges it with same-named configs from packages you require. That happens if these packages have `config-plugin` in their `composer.json`." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "The array means that the plugin will merge many files in the order they're specified." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "`?` at the beginning of the file path indicated that the file may be absent. In this case, it's skipped." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "`$` at the beginning of the name means a reference to another named config." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "`params` is a bit special because it's reserved for application parameters. These are automatically available as `$params` in all other configuration files." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "You can learn more about config plugin features [from its documentation](https://github.com/yiisoft/config/blob/master/README.md)." +msgstr "" + +#. type: Title ## +#: en/concept/configuration.md +#, no-wrap +msgid "Config files" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Now, as you know how the plugin assembles configs, look at `config` directory:" +msgstr "" + +#. type: Fenced code block +#: en/concept/configuration.md +#, no-wrap +msgid "" +"common/\n" +" application-parameters.php\n" +" i18n.php\n" +" router.php\n" +"console/\n" +"packages/\n" +" yiisoft/\n" +" dist.lock\n" +" merge_plan.php\n" +"web/\n" +" application.php\n" +" psr17.php\n" +"events.php\n" +"events-console.php\n" +"events-web.php\n" +"params.php\n" +"providers.php\n" +"providers-console.php\n" +"providers-web.php\n" +"routes.php\n" +msgstr "" + +#. type: Title ### +#: en/concept/configuration.md +#, fuzzy, no-wrap +#| msgid "Secure server configuration" +msgid "Container configuration" +msgstr "Безопасная конфигурация сервера" + +#. type: Plain text +#: en/concept/configuration.md +msgid "The application consists of a set of services registered in a [dependency container](di-container.md). The config files that responsible for direct dependency container configuration are under `common/`, `console/` and `web/` directories. We use `web/` for config specific to web application and `console/` for config specific to console commands. Both web and console are sharing configuration under `common/`." +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +" [\n" +" 'class' => ApplicationParameters::class,\n" +" 'charset()' => [$params['app']['charset']],\n" +" 'name()' => [$params['app']['name']],\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Config plugin passes special `$params` variable to all config files. The code passes its values to the service." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "The guide on [\"Dependency injection and container\"](di-container.md) describes the configuration format and the idea of dependency injection in detail." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "For convenience, there is a naming convention for custom string keys:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/concept/configuration.md +msgid "Prefix package name such as `yiisoft/cache-file/custom-definition`." +msgstr "" + +#. type: Bullet: '2. ' +#: en/concept/configuration.md +msgid "In case configuration are for the application itself, skip package prefix, such as `custom-definition`." +msgstr "" + +#. type: Title ### +#: en/concept/configuration.md +#, no-wrap +msgid "Service providers" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "As an alternative to registering dependencies directly, you can use service providers. Basically, these are classes that given parameters are configuring and registering services within the container. Similar to three dependency configuration files described, there are three configs for specifying service providers: `providers-console.php` for console commands, `providers-web.php` for web application and `providers.php` for both:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +"/* @var array $params */\n" +"\n" +"// ...\n" +"use App\\Provider\\CacheProvider;\n" +"use App\\Provider\\MiddlewareProvider;\n" +"// ...\n" +"\n" +"return [\n" +" // ...\n" +" 'yiisoft/yii-web/middleware' => MiddlewareProvider::class,\n" +" 'yiisoft/cache/cache' => [\n" +" 'class' => CacheProvider::class,\n" +" '__construct()' => [\n" +" $params['yiisoft/cache-file']['file-cache']['path'],\n" +" ],\n" +" ],\n" +" // ...\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "In this config keys are provider names. By convention these are `vendor/package-name/provider-name`. Values are provider class names. These classes could be either created in the project itself or provided by a package." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "If you need to configure some options for a service, similar to direct container configuration, take values from `$params` and pass them to providers." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Provider should implement a single method, `public function register(Container $container): void`. In this method you need to add a service to container using `set()` method. Below is a provider for a cache service:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +"use Psr\\Container\\ContainerInterface;\n" +"use Psr\\SimpleCache\\CacheInterface;\n" +"use Yiisoft\\Aliases\\Aliases;\n" +"use Yiisoft\\Cache\\Cache;\n" +"use Yiisoft\\Cache\\CacheInterface as YiiCacheInterface;\n" +"use Yiisoft\\Cache\\File\\FileCache;\n" +"use Yiisoft\\Di\\Container;\n" +"use Yiisoft\\Di\\Support\\ServiceProvider;\n" +"\n" +"final readonly class CacheProvider extends ServiceProvider\n" +"{\n" +" public function __construct(\n" +" private string $cachePath = '@runtime/cache'\n" +" )\n" +" {\n" +" $this->cachePath = $cachePath;\n" +" }\n" +"\n" +" public function register(Container $container): void\n" +" {\n" +" $container->set(CacheInterface::class, function (ContainerInterface $container) {\n" +" $aliases = $container->get(Aliases::class);\n" +"\n" +" return new FileCache($aliases->get($this->cachePath));\n" +" });\n" +"\n" +" $container->set(YiiCacheInterface::class, Cache::class);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ### +#: en/concept/configuration.md +#, no-wrap +msgid "Routes" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "You can configure how web application responds to certain URLs in `config/routes.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +"use App\\Controller\\SiteController;\n" +"use Yiisoft\\Router\\Route;\n" +"\n" +"return [\n" +" Route::get('/')->action([SiteController::class, 'index'])->name('site/index')\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Read more about it in [\"Routes\"](../runtime/routing.md)." +msgstr "" + +#. type: Title # +#: en/concept/configuration.md en/concept/events.md +#, no-wrap +msgid "Events" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Many services emit certain events that you can attach to. You could do that via three config files: `events-web.php` for web application events, `events-console.php` for console events and `events.php` for both. The configuration is an array where keys are event names and values are an array of handlers:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +"return [\n" +" EventName::class => [\n" +" // Just a regular closure, it will be called from the Dispatcher \"as is\".\n" +" static fn (EventName $event) => someStuff($event),\n" +" \n" +" // A regular closure with an extra dependency. All the parameters after the first one (the event itself)\n" +" // will be resolved from your DI container within `yiisoft/injector`.\n" +" static fn (EventName $event, DependencyClass $dependency) => someStuff($event),\n" +" \n" +" // An example with a regular callable. If the `staticMethodName` method has some dependencies,\n" +" // they will be resolved the same way as in the earlier example.\n" +" [SomeClass::class, 'staticMethodName'],\n" +" \n" +" // Non-static methods are allowed too. In this case, `SomeClass` will be instantiated by your DI container.\n" +" [SomeClass::class, 'methodName'],\n" +" \n" +" // An object of a class with the `__invoke` method implemented\n" +" new InvokableClass(),\n" +" \n" +" // In this case, the `InvokableClass` with the `__invoke` method will be instantiated by your DI container\n" +" InvokableClass::class,\n" +" \n" +" // Any definition of an invokable class may be here while your `$container->has('the definition)` \n" +" 'di-alias'\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Read more about it in [\"Events\"](events.md)." +msgstr "" + +#. type: Title ### +#: en/concept/configuration.md +#, no-wrap +msgid "Parameters" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Parameters, `config/params.php` store configuration values that are used in other config files to configuring services and service providers." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +#, no-wrap +msgid "" +"> [!TIP]\n" +"> Don't use parameters, constants or environment variables directly in your application, configure\n" +"> services instead.\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Default application `params.php` looks like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/configuration.md +#, no-wrap +msgid "" +" [\n" +" 'charset' => 'UTF-8',\n" +" 'locale' => 'en',\n" +" 'name' => 'My Project',\n" +" ],\n" +"\n" +" 'yiisoft/aliases' => [\n" +" 'aliases' => [\n" +" '@root' => dirname(__DIR__),\n" +" '@assets' => '@root/public/assets',\n" +" '@assetsUrl' => '/assets',\n" +" '@baseUrl' => '/',\n" +" '@message' => '@root/resources/message',\n" +" '@npm' => '@root/node_modules',\n" +" '@public' => '@root/public',\n" +" '@resources' => '@root/resources',\n" +" '@runtime' => '@root/runtime',\n" +" '@vendor' => '@root/vendor',\n" +" '@layout' => '@resources/views/layout',\n" +" '@views' => '@resources/views',\n" +" ],\n" +" ],\n" +"\n" +" 'yiisoft/yii-view' => [\n" +" 'injections' => [\n" +" Reference::to(ContentViewInjection::class),\n" +" Reference::to(CsrfViewInjection::class),\n" +" Reference::to(LayoutViewInjection::class),\n" +" ],\n" +" ],\n" +"\n" +" 'yiisoft/yii-console' => [\n" +" 'commands' => [\n" +" 'hello' => Hello::class,\n" +" ],\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "For convenience, there is a naming convention about parameters:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/concept/configuration.md +msgid "Group parameters package name such as `yiisoft/cache-file`." +msgstr "" + +#. type: Bullet: '2. ' +#: en/concept/configuration.md +msgid "In case parameters are for the application itself, as in `app`, skip package prefix." +msgstr "" + +#. type: Bullet: '3. ' +#: en/concept/configuration.md +msgid "In case there are many services in the package, such as `file-target` and `file-rotator` in `yiisoft/log-target-file` package, group parameters by service name." +msgstr "" + +#. type: Bullet: '4. ' +#: en/concept/configuration.md +msgid "Use `enabled` as parameter name to be able to disable or enable a service, such as `yiisoft/yii-debug`." +msgstr "" + +#. type: Title ### +#: en/concept/configuration.md +#, no-wrap +msgid "Package configs" +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "Config plugin described copy default package configurations to `packages/` directory. Once copied you own the configs, so you can adjust these as you like. `yiisoft/` in the default template stands for package vendor. Since only `yiisoft` packages are in template, there's a single directory. `merge_plan.php` is used in runtime to get the order on how configs are merged. Note that for config keys there should be a single source of truth. One config can't override values of another config." +msgstr "" + +#. type: Plain text +#: en/concept/configuration.md +msgid "`dist.lock` is used by the plugin to keep track of changes and display diff between current config and example one." +msgstr "" diff --git a/guide/po/concept_di-container.md/concept_di-container.md.pot b/guide/po/concept_di-container.md/concept_di-container.md.pot new file mode 100644 index 00000000..6f5fd9a4 --- /dev/null +++ b/guide/po/concept_di-container.md/concept_di-container.md.pot @@ -0,0 +1,383 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 07:37+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/concept/di-container.md +#, no-wrap +msgid "Dependency injection and container" +msgstr "" + +#. type: Title ## +#: en/concept/di-container.md +#, no-wrap +msgid "Dependency injection " +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"There are two ways of re-using things in OOP: inheritance and composition." +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "Inheritance is simple:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"class Cache\n" +"{\n" +" public function getCachedValue($key)\n" +" {\n" +" // ..\n" +" }\n" +"}\n" +"\n" +"final readonly class CachedWidget extends Cache\n" +"{\n" +" public function render(): string\n" +" {\n" +" $output = $this->getCachedValue('cachedWidget');\n" +" if ($output !== null) {\n" +" return $output;\n" +" }\n" +" // ... \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"The issue here is that these two are becoming unnecessarily coupled or inter-" +"dependent making them more fragile." +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "Another way to handle this is composition:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"interface CacheInterface\n" +"{\n" +" public function getCachedValue($key);\n" +"}\n" +"\n" +"final readonly class Cache implements CacheInterface\n" +"{\n" +" public function getCachedValue($key)\n" +" {\n" +" // ..\n" +" }\n" +"}\n" +"\n" +"final readonly class CachedWidget\n" +"{\n" +" public function __construct(\n" +" private CacheInterface $cache\n" +" )\n" +" {\n" +" }\n" +" \n" +" public function render(): string\n" +" {\n" +" $output = $this->cache->getCachedValue('cachedWidget');\n" +" if ($output !== null) {\n" +" return $output;\n" +" }\n" +" // ... \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"We've avoided unnecessary inheritance and used interface to reduce coupling. " +"You can replace cache implementation without changing `CachedWidget` so it's " +"becoming more stable." +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"The `CacheInterface` here is a dependency: an object another object depends " +"on. The process of putting an instance of dependency into an object " +"(`CachedWidget`) is called dependency injection. There are many ways to " +"perform it:" +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "Constructor injection. Best for mandatory dependencies." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "Method injection. Best for optional dependencies." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "" +"Property injection. Better to be avoided in PHP except maybe data transfer " +"objects." +msgstr "" + +#. type: Title ## +#: en/concept/di-container.md +#, no-wrap +msgid "DI container " +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"Injecting basic dependencies is simple and easy. You're choosing a place " +"where you don't care about dependencies, which is usually an action handler, " +"which you aren't going to unit-test ever, create instances of dependencies " +"needed and pass these to dependent classes." +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"It works well when there aren't many dependencies overall and when there are " +"no nested dependencies. When there are many and each dependency has " +"dependencies itself, instantiating the whole hierarchy becomes a tedious " +"process, which requires lots of code and may lead to hard to debug mistakes." +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"Additionally, lots of dependencies, such as certain third party API wrapper, " +"are the same for any class using it. So it makes sense to:" +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "Define how to instantiate such API wrapper once." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "Instantiate it when required and only once per request." +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "That's what dependency containers are for." +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"A dependency injection (DI) container is an object that knows how to " +"instantiate and configure objects and all their dependent objects. [Martin " +"Fowler's article](https://martinfowler.com/articles/injection.html) has well " +"explained why DI container is useful. Here we will mainly explain the usage " +"of the DI container provided by Yii." +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"Yii provides the DI container feature through the [yiisoft/di](https://" +"github.com/yiisoft/di) package and [yiisoft/injector](https://github.com/" +"yiisoft/injector) package." +msgstr "" + +#. type: Title ### +#: en/concept/di-container.md +#, no-wrap +msgid "Configuring container " +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"Because to create a new object you need its dependencies, you should " +"register them as early as possible. You can do it in the application " +"configuration, `config/web.php`. For the following service:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"final class MyService implements MyServiceInterface\n" +"{\n" +" public function __construct(int $amount)\n" +" {\n" +" }\n" +"\n" +" public function setDiscount(int $discount): void\n" +" {\n" +" \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "configuration could be:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"return [\n" +" MyServiceInterface::class => [\n" +" 'class' => MyService::class,\n" +" '__construct()' => [42],\n" +" 'setDiscount()' => [10],\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "That's equal to the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"$myService = new MyService(42);\n" +"$myService->setDiscount(10);\n" +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "There are extra methods of declaring dependencies:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"return [\n" +" // declare a class for an interface, resolve dependencies automatically\n" +" EngineInterface::class => EngineMarkOne::class,\n" +"\n" +" // array definition (same as above)\n" +" 'full_definition' => [\n" +" 'class' => EngineMarkOne::class,\n" +" '__construct()' => [42], \n" +" '$propertyName' => 'value',\n" +" 'setX()' => [42],\n" +" ],\n" +"\n" +" // closure\n" +" 'closure' => static function(ContainerInterface $container) {\n" +" return new MyClass($container->get('db'));\n" +" },\n" +"\n" +" // static call\n" +" 'static_call' => [MyFactory::class, 'create'],\n" +"\n" +" // instance of an object\n" +" 'object' => new MyClass(),\n" +"];\n" +msgstr "" + +#. type: Title ### +#: en/concept/di-container.md +#, no-wrap +msgid "Injecting dependencies " +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"Directly referencing container in a class is a bad idea since the code " +"becomes non-generic, coupled to container interface and, what's worse, " +"dependencies are becoming hidden. Because of that, Yii inverts the control " +"by automatically injecting objects from a container in some constructors and " +"methods based on method argument types." +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"This is primarily done in constructor and handing method of action handlers:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"use \\Yiisoft\\Cache\\CacheInterface;\n" +"\n" +"final readonly class MyController\n" +"{\n" +" public function __construct(\n" +" private CacheInterface $cache\n" +" )\n" +" {\n" +" $this->cache = $cache; \n" +" }\n" +"\n" +" public function actionDashboard(RevenueReport $report)\n" +" {\n" +" $reportData = $this->cache->getOrSet('revenue_report', function() use ($report) {\n" +" return $report->getData(); \n" +" });\n" +"\n" +" return $this->render('dashboard', [\n" +" 'reportData' => $reportData,\n" +" ]);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/di-container.md +msgid "" +"Since it's [yiisoft/injector](https://github.com/yiisoft/injector) that " +"instantiates and calls action handler, it checks the constructor and method " +"argument types, get dependencies of these types from a container and pass " +"them as arguments. That's usually called auto-wiring. It happens for sub-" +"dependencies as well, that's if you don't give dependency explicitly, " +"container would check if it has such a dependency first. It's enough to " +"declare a dependency you need, and it would be got from a container " +"automatically." +msgstr "" + +#. type: Title ## +#: en/concept/di-container.md +#, no-wrap +msgid "References " +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "" +"[Inversion of Control Containers and the Dependency Injection pattern by " +"Martin Fowler](https://martinfowler.com/articles/injection.html)" +msgstr "" diff --git a/guide/po/concept_di-container.md/ru/concept_di-container.md.ru.po b/guide/po/concept_di-container.md/ru/concept_di-container.md.ru.po new file mode 100644 index 00000000..5054b01b --- /dev/null +++ b/guide/po/concept_di-container.md/ru/concept_di-container.md.ru.po @@ -0,0 +1,468 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2025-09-04 07:37+0500\n" +"PO-Revision-Date: 2025-09-04 07:50+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 3.7\n" + +#. type: Title # +#: en/concept/di-container.md +#, no-wrap +msgid "Dependency injection and container" +msgstr "Внедрение зависимостей и контейнер внедрения зависимостей" + +#. type: Title ## +#: en/concept/di-container.md +#, no-wrap +msgid "Dependency injection " +msgstr "Внедрение зависимостей " + +#. type: Plain text +#: en/concept/di-container.md +msgid "There are two ways of re-using things in OOP: inheritance and composition." +msgstr "В ООП существует два способа повторного использования кода: наследование и композиция." + +#. type: Plain text +#: en/concept/di-container.md +msgid "Inheritance is simple:" +msgstr "Наследование — это просто:" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"class Cache\n" +"{\n" +" public function getCachedValue($key)\n" +" {\n" +" // ..\n" +" }\n" +"}\n" +"\n" +"final readonly class CachedWidget extends Cache\n" +"{\n" +" public function render(): string\n" +" {\n" +" $output = $this->getCachedValue('cachedWidget');\n" +" if ($output !== null) {\n" +" return $output;\n" +" }\n" +" // ... \n" +" }\n" +"}\n" +msgstr "" +"class Cache\n" +"{\n" +" public function getCachedValue($key)\n" +" {\n" +" // ..\n" +" }\n" +"}\n" +"\n" +"class CachedWidget extends Cache\n" +"{\n" +" public function render(): string\n" +" {\n" +" $output = $this->getCachedValue('cachedWidget');\n" +" if ($output !== null) {\n" +" return $output;\n" +" }\n" +" // ... \n" +" }\n" +"}\n" + +#. type: Plain text +#: en/concept/di-container.md +msgid "The issue here is that these two are becoming unnecessarily coupled or inter-dependent making them more fragile." +msgstr "Проблема здесь в том, что эти два класса становятся излишне сопряженными или взаимозависимыми, что делает их более хрупкими." + +#. type: Plain text +#: en/concept/di-container.md +msgid "Another way to handle this is composition:" +msgstr "Есть способ справиться с этой проблемой — композиция:" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"interface CacheInterface\n" +"{\n" +" public function getCachedValue($key);\n" +"}\n" +"\n" +"final readonly class Cache implements CacheInterface\n" +"{\n" +" public function getCachedValue($key)\n" +" {\n" +" // ..\n" +" }\n" +"}\n" +"\n" +"final readonly class CachedWidget\n" +"{\n" +" public function __construct(\n" +" private CacheInterface $cache\n" +" )\n" +" {\n" +" }\n" +" \n" +" public function render(): string\n" +" {\n" +" $output = $this->cache->getCachedValue('cachedWidget');\n" +" if ($output !== null) {\n" +" return $output;\n" +" }\n" +" // ... \n" +" }\n" +"}\n" +msgstr "" +"interface CacheInterface\n" +"{\n" +" public function getCachedValue($key);\n" +"}\n" +"\n" +"final class Cache implements CacheInterface\n" +"{\n" +" public function getCachedValue($key)\n" +" {\n" +" // ..\n" +" }\n" +"}\n" +"\n" +"final class CachedWidget\n" +"{\n" +" private CacheInterface $cache;\n" +"\n" +" public function __construct(CacheInterface $cache)\n" +" {\n" +" $this->cache = $cache;\n" +" }\n" +" \n" +" public function render(): string\n" +" {\n" +" $output = $this->cache->getCachedValue('cachedWidget');\n" +" if ($output !== null) {\n" +" return $output;\n" +" }\n" +" // ... \n" +" }\n" +"}\n" + +#. type: Plain text +#: en/concept/di-container.md +msgid "We've avoided unnecessary inheritance and used interface to reduce coupling. You can replace cache implementation without changing `CachedWidget` so it's becoming more stable." +msgstr "" +"Мы избежали ненужного наследования и использовали интерфейс, чтобы уменьшить сопряженность.\n" +"Вы можете заменить реализацию кэша без изменения класса `CachedWidget`, поэтому он становится более стабильным." + +#. type: Plain text +#: en/concept/di-container.md +msgid "The `CacheInterface` here is a dependency: an object another object depends on. The process of putting an instance of dependency into an object (`CachedWidget`) is called dependency injection. There are many ways to perform it:" +msgstr "" +"Здесь `CacheInterface` это зависимость — объект, от которого зависит другой объект. \n" +"Процесс помещения экземпляра объекта зависимости в объект (`CachedWidget`) называется внедрением зависимости. Существует множество способов его реализации:" + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "Constructor injection. Best for mandatory dependencies." +msgstr "Внедрение через конструктор. Лучше всего подходит для обязательных зависимостей." + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "Method injection. Best for optional dependencies." +msgstr "Через метод. Лучше использовать для необязательных зависимостей." + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "Property injection. Better to be avoided in PHP except maybe data transfer objects." +msgstr "Через свойство. Лучше избегать использования в PHP, за исключением, может быть, объектов передачи данных (DTO)" + +#. type: Title ## +#: en/concept/di-container.md +#, no-wrap +msgid "DI container " +msgstr "Контейнер внедрения зависимостей " + +#. type: Plain text +#: en/concept/di-container.md +msgid "Injecting basic dependencies is simple and easy. You're choosing a place where you don't care about dependencies, which is usually an action handler, which you aren't going to unit-test ever, create instances of dependencies needed and pass these to dependent classes." +msgstr "" +"Внедрять базовые зависимости просто и легко.\n" +"Вы выбираете место, где вас не волнуют зависимости, которые обычно являются обработчиками действий и которые вы не собираетесь тестировать, создаете экземпляры необходимых зависимостей и передаете их в зависимые классы." + +#. type: Plain text +#: en/concept/di-container.md +msgid "It works well when there aren't many dependencies overall and when there are no nested dependencies. When there are many and each dependency has dependencies itself, instantiating the whole hierarchy becomes a tedious process, which requires lots of code and may lead to hard to debug mistakes." +msgstr "" +"Это хорошо работает, когда в целом зависимостей немного и нет вложенных зависимостей.\n" +"Когда их много, и каждая зависимость сама имеет зависимости, создание всей иерархии становится утомительным процессом, который требует большого количества кода и может привести к трудно отлаживаемым ошибкам." + +#. type: Plain text +#: en/concept/di-container.md +msgid "Additionally, lots of dependencies, such as certain third party API wrapper, are the same for any class using it. So it makes sense to:" +msgstr "" +"Кроме того, многие зависимости, такие как некоторые сторонние обертки API, одинаковы для любого класса, использующего его.\n" +"Поэтому имеет смысл:" + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "Define how to instantiate such API wrapper once." +msgstr "Определить, как создать экземпляр такой обертки API один раз." + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "Instantiate it when required and only once per request." +msgstr "Создавать его экземпляр при необходимости и только один раз за запрос." + +#. type: Plain text +#: en/concept/di-container.md +msgid "That's what dependency containers are for." +msgstr "Именно для этого нужны контейнеры зависимостей." + +#. type: Plain text +#: en/concept/di-container.md +msgid "A dependency injection (DI) container is an object that knows how to instantiate and configure objects and all their dependent objects. [Martin Fowler's article](https://martinfowler.com/articles/injection.html) has well explained why DI container is useful. Here we will mainly explain the usage of the DI container provided by Yii." +msgstr "" +"Контейнер внедрения зависимостей (DI-контейнер) — это объект, который знает, как создавать и настраивать объекты и все зависимые от них объекты.\n" +"[Статья Мартина Фаулера](https://martinfowler.com/articles/injection.html) хорошо объясняет почему DI-контейнер полезен.\n" +"Здесь мы в основном поясним использование DI-контейнера, предоставляемого Yii." + +#. type: Plain text +#: en/concept/di-container.md +msgid "Yii provides the DI container feature through the [yiisoft/di](https://github.com/yiisoft/di) package and [yiisoft/injector](https://github.com/yiisoft/injector) package." +msgstr "Yii реализует DI-контейнер через пакет [yiisoft/di](https://github.com/yiisoft/di) и [yiisoft/injector](https://github.com/yiisoft/injector)." + +#. type: Title ### +#: en/concept/di-container.md +#, no-wrap +msgid "Configuring container " +msgstr "Конфигурирование контейнера " + +#. type: Plain text +#: en/concept/di-container.md +msgid "Because to create a new object you need its dependencies, you should register them as early as possible. You can do it in the application configuration, `config/web.php`. For the following service:" +msgstr "" +"Поскольку для создания нового объекта вам нужны его зависимости, вам следует зарегестрировать их как можно раньше.\n" +"Вы можете сделать это в конфигурации приложения, `config/web.php`.\n" +"Например, для следующего сервиса:" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"final class MyService implements MyServiceInterface\n" +"{\n" +" public function __construct(int $amount)\n" +" {\n" +" }\n" +"\n" +" public function setDiscount(int $discount): void\n" +" {\n" +" \n" +" }\n" +"}\n" +msgstr "" +"class MyService implements MyServiceInterface\n" +"{\n" +" public function __construct(int $amount)\n" +" {\n" +" }\n" +"\n" +" public function setDiscount(int $discount): void\n" +" {\n" +" \n" +" }\n" + +#. type: Plain text +#: en/concept/di-container.md +msgid "configuration could be:" +msgstr "конфигурация может быть:" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"return [\n" +" MyServiceInterface::class => [\n" +" 'class' => MyService::class,\n" +" '__construct()' => [42],\n" +" 'setDiscount()' => [10],\n" +" ],\n" +"];\n" +msgstr "" +"return [\n" +" MyServiceInterface::class => [\n" +" 'class' => MyService::class,\n" +" '__construct()' => [42],\n" +" 'setDiscount()' => [10],\n" +" ],\n" +"];\n" + +#. type: Plain text +#: en/concept/di-container.md +msgid "That's equal to the following:" +msgstr "Это соответствует:" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"$myService = new MyService(42);\n" +"$myService->setDiscount(10);\n" +msgstr "" +"$myService = new MyService(42);\n" +"$myService->setDiscount(10);\n" + +#. type: Plain text +#: en/concept/di-container.md +msgid "There are extra methods of declaring dependencies:" +msgstr "Существуют дополнительные методы объявления зависимостей:" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"return [\n" +" // declare a class for an interface, resolve dependencies automatically\n" +" EngineInterface::class => EngineMarkOne::class,\n" +"\n" +" // array definition (same as above)\n" +" 'full_definition' => [\n" +" 'class' => EngineMarkOne::class,\n" +" '__construct()' => [42], \n" +" '$propertyName' => 'value',\n" +" 'setX()' => [42],\n" +" ],\n" +"\n" +" // closure\n" +" 'closure' => static function(ContainerInterface $container) {\n" +" return new MyClass($container->get('db'));\n" +" },\n" +"\n" +" // static call\n" +" 'static_call' => [MyFactory::class, 'create'],\n" +"\n" +" // instance of an object\n" +" 'object' => new MyClass(),\n" +"];\n" +msgstr "" +"return [\n" +" // объявить класс для интерфейса, автоматически разрешить зависимости\n" +" EngineInterface::class => EngineMarkOne::class,\n" +"\n" +" // определение в массиве (то же, что и выше)\n" +" 'full_definition' => [\n" +" 'class' => EngineMarkOne::class,\n" +" '__construct()' => [42], \n" +" '$propertyName' => 'value',\n" +" 'setX()' => [42],\n" +" ],\n" +"\n" +" // замыкание\n" +" 'closure' => static function(ContainerInterface $container) {\n" +" return new MyClass($container->get('db'));\n" +" },\n" +"\n" +" // статический вызов\n" +" 'static_call' => [MyFactory::class, 'create'],\n" +"\n" +" // экземпляр объекта\n" +" 'object' => new MyClass(),\n" +"];\n" + +#. type: Title ### +#: en/concept/di-container.md +#, no-wrap +msgid "Injecting dependencies " +msgstr "Внедрение зависимостей " + +#. type: Plain text +#: en/concept/di-container.md +msgid "Directly referencing container in a class is a bad idea since the code becomes non-generic, coupled to container interface and, what's worse, dependencies are becoming hidden. Because of that, Yii inverts the control by automatically injecting objects from a container in some constructors and methods based on method argument types." +msgstr "Непосредственное обращение к контейнеру в классе — плохая идея, так как код становится не универсальным, сопряжен с интерфейсом контейнера и, что еще хуже, зависимости становятся скрытыми. Поэтому Yii инвертирует управление, автоматически вводя объекты из контейнера в конструкторы и методы, основываясь на типах аргументов." + +#. type: Plain text +#: en/concept/di-container.md +msgid "This is primarily done in constructor and handing method of action handlers:" +msgstr "В основном это делается в конструкторе и методе, обрабатывающем действие:" + +#. type: Fenced code block (php) +#: en/concept/di-container.md +#, no-wrap +msgid "" +"use \\Yiisoft\\Cache\\CacheInterface;\n" +"\n" +"final readonly class MyController\n" +"{\n" +" public function __construct(\n" +" private CacheInterface $cache\n" +" )\n" +" {\n" +" $this->cache = $cache; \n" +" }\n" +"\n" +" public function actionDashboard(RevenueReport $report)\n" +" {\n" +" $reportData = $this->cache->getOrSet('revenue_report', function() use ($report) {\n" +" return $report->getData(); \n" +" });\n" +"\n" +" return $this->render('dashboard', [\n" +" 'reportData' => $reportData,\n" +" ]);\n" +" }\n" +"}\n" +msgstr "" +"use \\Yiisoft\\Cache\\CacheInterface;\n" +"\n" +"class MyController\n" +"{\n" +" private CacheInterface $cache;\n" +"\n" +" public function __construct(CacheInterface $cache) {\n" +" $this->cache = $cache; \n" +" }\n" +"\n" +" public function actionDashboard(RevenueReport $report)\n" +" {\n" +" $reportData = $this->cache->getOrSet('revenue_report', function() use ($report) {\n" +" return $report->getData(); \n" +" });\n" +"\n" +" return $this->render('dashboard', [\n" +" 'reportData' => $reportData,\n" +" ]);\n" +" }\n" +"}\n" + +#. type: Plain text +#: en/concept/di-container.md +msgid "Since it's [yiisoft/injector](https://github.com/yiisoft/injector) that instantiates and calls action handler, it checks the constructor and method argument types, get dependencies of these types from a container and pass them as arguments. That's usually called auto-wiring. It happens for sub-dependencies as well, that's if you don't give dependency explicitly, container would check if it has such a dependency first. It's enough to declare a dependency you need, and it would be got from a container automatically." +msgstr "" +"Поскольку именно [yiisoft/injector](https://github.com/yiisoft/injector) создает экземпляр и вызывает обработчик действий - он проверяет типы аргументов конструктора и метода, получает зависимости этих типов из контейнера и передает их как аргументы.\n" +"Обычно это называется автоматическим разрешением зависимостей.\n" +"Это происходит и с дополнительными зависимостями - если вы явно не указываете зависимость, контейнер сначала проверит, есть ли у него такая зависимость.\n" +"Достаточно объявить нужную вам зависимость, и она будет получена из контейнера автоматически." + +#. type: Title ## +#: en/concept/di-container.md +#, no-wrap +msgid "References " +msgstr "Полезные ссылки " + +#. type: Bullet: '- ' +#: en/concept/di-container.md +msgid "[Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler](https://martinfowler.com/articles/injection.html)" +msgstr "[Inversion of Control Containers and the Dependency Injection pattern Мартина Фаулера](https://martinfowler.com/articles/injection.html)" diff --git a/guide/po/concept_events.md/concept_events.md.pot b/guide/po/concept_events.md/concept_events.md.pot new file mode 100644 index 00000000..e06793b7 --- /dev/null +++ b/guide/po/concept_events.md/concept_events.md.pot @@ -0,0 +1,284 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/concept/configuration.md en/concept/events.md +#, no-wrap +msgid "Events" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "" +"Events allow you to make custom code executed at certain execution points " +"without modifying existing code. You can attach a custom code called " +"\"handler\" to an event so that when the event is triggered, the handler " +"gets executed automatically." +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "" +"For example, when a user is signed up, you need to send a welcome email. You " +"can do it right in the `SignupService` but then, when you additionally need " +"to resize user's avatar image, you'll have to change `SignupService` code " +"again. In other words, `SignupService` will be coupled to both code sending " +"welcome email and code resizing avatar image." +msgstr "" + +#. type: Plain text +#: en/concept/events.md +#, no-wrap +msgid "" +"To avoid it, instead of telling what do after signup explicitly you can, instead, raise `UserSignedUp` event\n" +"and then finish a signup process. The code sending an email and the code resizing avatar image will attach to the event\n" +" and, therefore, will be executed. If you'll ever need to do more on signup, you'll be able to attach extra event\n" +"handlers without modifying `SignupService`. \n" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "" +"For raising events and attaching handlers to these events, Yii has a special " +"service called event dispatcher. It's available from [yiisoft/event-" +"dispatcher package](https://github.com/yiisoft/event-dispatcher)." +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, no-wrap +msgid "Event Handlers " +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "" +"An event handler is [PHP callable](https://www.php.net/manual/en/language." +"types.callable.php) that gets executed when the event it's attached to is " +"triggered." +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "The signature of an event handler is:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"function (EventClass $event) {\n" +" // handle it\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, no-wrap +msgid "Attaching event handlers " +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "You can attach a handler to an event like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"use Yiisoft\\EventDispatcher\\Provider\\Provider;\n" +"\n" +"final readonly class WelcomeEmailSender\n" +"{\n" +" public function __construct(Provider $provider)\n" +" {\n" +" $provider->attach([$this, 'handleUserSignup']);\n" +" }\n" +"\n" +" public function handleUserSignup(UserSignedUp $event)\n" +" {\n" +" // handle it \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "" +"The `attach()` method is accepting a callback. Based on the type of this " +"callback argument, the event type is determined." +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, no-wrap +msgid "Event handlers order" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "" +"You may attach one or more handlers to a single event. When an event is " +"triggered, the attached handlers will be called in the order that they were " +"attached to the event. In case an event implements " +"`Psr\\EventDispatcher\\StoppableEventInterface`, event handler can stop " +"executing the rest of the handlers that follow it if " +"`isPropagationStopped()` returns `true`." +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "In general, it's better not to rely on the order of event handlers." +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, no-wrap +msgid "Raising events " +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "Events are raised like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"use Psr\\EventDispatcher\\EventDispatcherInterface;\n" +"\n" +"final readonly class SignupService\n" +"{\n" +" public function __construct(\n" +" private EventDispatcherInterface $eventDispatcher\n" +" )\n" +" {\n" +" }\n" +"\n" +" public function signup(SignupForm $form)\n" +" {\n" +" // handle signup\n" +"\n" +" $event = new UserSignedUp($form);\n" +" $this->eventDispatcher->dispatch($event);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "" +"First, you create an event supplying it with data that may be useful for " +"handlers. Then you dispatch the event." +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "The event class itself may look like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"final readonly class UserSignedUp\n" +"{\n" +" public function __construct(\n" +" public SignupForm $form\n" +" )\n" +" {\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, no-wrap +msgid "Events hierarchy" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "" +"Events don't have any name or wildcard matching on purpose. Event class " +"names and class/interface hierarchy and composition could be used to achieve " +"great flexibility:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"interface DocumentEvent\n" +"{\n" +"}\n" +"\n" +"final readonly class BeforeDocumentProcessed implements DocumentEvent\n" +"{\n" +"}\n" +"\n" +"final readonly class AfterDocumentProcessed implements DocumentEvent\n" +"{\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "With the interface, you can listen to all document-related events:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"$provider->attach(function (DocumentEvent $event) {\n" +" // log events here\n" +"});\n" +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, no-wrap +msgid "Detaching event handlers " +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "To detach a handler from an event you can call `detach()` method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "$provider->detach(DocmentEvent::class);\n" +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, no-wrap +msgid "Configuring application events" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "" +"You usually assign event handlers via application config. See " +"[\"Configuration\"](configuration.md) for details." +msgstr "" diff --git a/guide/po/concept_events.md/ru/concept_events.md.ru.po b/guide/po/concept_events.md/ru/concept_events.md.ru.po new file mode 100644 index 00000000..b42e5134 --- /dev/null +++ b/guide/po/concept_events.md/ru/concept_events.md.ru.po @@ -0,0 +1,283 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/concept/configuration.md en/concept/events.md +#, no-wrap +msgid "Events" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "Events allow you to make custom code executed at certain execution points without modifying existing code. You can attach a custom code called \"handler\" to an event so that when the event is triggered, the handler gets executed automatically." +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "For example, when a user is signed up, you need to send a welcome email. You can do it right in the `SignupService` but then, when you additionally need to resize user's avatar image, you'll have to change `SignupService` code again. In other words, `SignupService` will be coupled to both code sending welcome email and code resizing avatar image." +msgstr "" + +#. type: Plain text +#: en/concept/events.md +#, no-wrap +msgid "" +"To avoid it, instead of telling what do after signup explicitly you can, instead, raise `UserSignedUp` event\n" +"and then finish a signup process. The code sending an email and the code resizing avatar image will attach to the event\n" +" and, therefore, will be executed. If you'll ever need to do more on signup, you'll be able to attach extra event\n" +"handlers without modifying `SignupService`. \n" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "For raising events and attaching handlers to these events, Yii has a special service called event dispatcher. It's available from [yiisoft/event-dispatcher package](https://github.com/yiisoft/event-dispatcher)." +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, fuzzy, no-wrap +#| msgid "DI container " +msgid "Event Handlers " +msgstr "Контейнер внедрения зависимостей " + +#. type: Plain text +#: en/concept/events.md +msgid "An event handler is [PHP callable](https://www.php.net/manual/en/language.types.callable.php) that gets executed when the event it's attached to is triggered." +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "The signature of an event handler is:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"function (EventClass $event) {\n" +" // handle it\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, fuzzy, no-wrap +#| msgid "Injecting dependencies " +msgid "Attaching event handlers " +msgstr "Внедрение зависимостей " + +#. type: Plain text +#: en/concept/events.md +msgid "You can attach a handler to an event like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"use Yiisoft\\EventDispatcher\\Provider\\Provider;\n" +"\n" +"final readonly class WelcomeEmailSender\n" +"{\n" +" public function __construct(Provider $provider)\n" +" {\n" +" $provider->attach([$this, 'handleUserSignup']);\n" +" }\n" +"\n" +" public function handleUserSignup(UserSignedUp $event)\n" +" {\n" +" // handle it \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "The `attach()` method is accepting a callback. Based on the type of this callback argument, the event type is determined." +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, no-wrap +msgid "Event handlers order" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "You may attach one or more handlers to a single event. When an event is triggered, the attached handlers will be called in the order that they were attached to the event. In case an event implements `Psr\\EventDispatcher\\StoppableEventInterface`, event handler can stop executing the rest of the handlers that follow it if `isPropagationStopped()` returns `true`." +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "In general, it's better not to rely on the order of event handlers." +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Raising events " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/concept/events.md +#, fuzzy +#| msgid "That's equal to the following:" +msgid "Events are raised like the following:" +msgstr "Это соответствует:" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"use Psr\\EventDispatcher\\EventDispatcherInterface;\n" +"\n" +"final readonly class SignupService\n" +"{\n" +" public function __construct(\n" +" private EventDispatcherInterface $eventDispatcher\n" +" )\n" +" {\n" +" }\n" +"\n" +" public function signup(SignupForm $form)\n" +" {\n" +" // handle signup\n" +"\n" +" $event = new UserSignedUp($form);\n" +" $this->eventDispatcher->dispatch($event);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "First, you create an event supplying it with data that may be useful for handlers. Then you dispatch the event." +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "The event class itself may look like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, fuzzy, no-wrap +#| msgid "" +#| "final class MyService implements MyServiceInterface\n" +#| "{\n" +#| " public function __construct(int $amount)\n" +#| " {\n" +#| " }\n" +#| "\n" +#| " public function setDiscount(int $discount): void\n" +#| " {\n" +#| " \n" +#| " }\n" +#| "}\n" +msgid "" +"final readonly class UserSignedUp\n" +"{\n" +" public function __construct(\n" +" public SignupForm $form\n" +" )\n" +" {\n" +" }\n" +"}\n" +msgstr "" +"class MyService implements MyServiceInterface\n" +"{\n" +" public function __construct(int $amount)\n" +" {\n" +" }\n" +"\n" +" public function setDiscount(int $discount): void\n" +" {\n" +" \n" +" }\n" + +#. type: Title ## +#: en/concept/events.md +#, no-wrap +msgid "Events hierarchy" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "Events don't have any name or wildcard matching on purpose. Event class names and class/interface hierarchy and composition could be used to achieve great flexibility:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"interface DocumentEvent\n" +"{\n" +"}\n" +"\n" +"final readonly class BeforeDocumentProcessed implements DocumentEvent\n" +"{\n" +"}\n" +"\n" +"final readonly class AfterDocumentProcessed implements DocumentEvent\n" +"{\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/concept/events.md +msgid "With the interface, you can listen to all document-related events:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "" +"$provider->attach(function (DocumentEvent $event) {\n" +" // log events here\n" +"});\n" +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, fuzzy, no-wrap +#| msgid "Defining aliases " +msgid "Detaching event handlers " +msgstr "Определение псевдонимов " + +#. type: Plain text +#: en/concept/events.md +msgid "To detach a handler from an event you can call `detach()` method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/events.md +#, no-wrap +msgid "$provider->detach(DocmentEvent::class);\n" +msgstr "" + +#. type: Title ## +#: en/concept/events.md +#, fuzzy, no-wrap +#| msgid "Configuring SSL peer validation" +msgid "Configuring application events" +msgstr "Настройка проверки SSL-сертификата" + +#. type: Plain text +#: en/concept/events.md +msgid "You usually assign event handlers via application config. See [\"Configuration\"](configuration.md) for details." +msgstr "" diff --git a/guide/po/concept_immutability.md/concept_immutability.md.pot b/guide/po/concept_immutability.md/concept_immutability.md.pot new file mode 100644 index 00000000..5c38218f --- /dev/null +++ b/guide/po/concept_immutability.md/concept_immutability.md.pot @@ -0,0 +1,248 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/concept/immutability.md +#, no-wrap +msgid "Immutability" +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +msgid "" +"Immutability means an object's state cannot change after it has been " +"created. Instead of modifying an instance, you create a new instance with " +"the desired changes. This approach is common for value objects such as " +"Money, IDs, and DTOs. It helps to avoid accidental side effects: methods " +"cannot silently change shared state, which makes code easier to reason about." +msgstr "" + +#. type: Title ## +#: en/concept/immutability.md +#, no-wrap +msgid "Mutable pitfalls (what we avoid)" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/immutability.md +#, no-wrap +msgid "" +"// A shared base query built once and reused:\n" +"$base = Post::find()->where(['status' => Post::STATUS_PUBLISHED]);\n" +"\n" +"// Somewhere deep in the code we only need one post:\n" +"$one = $base->limit(1)->one(); // mutates the underlying builder (sticky limit!)\n" +"\n" +"// Later we reuse the same $base expecting a full list:\n" +"$list = $base->orderBy(['created_at' => SORT_DESC])->all();\n" +"// Oops: still limited to 1 because the previous limit(1) modified $base.\n" +msgstr "" + +#. type: Title ## +#: en/concept/immutability.md +#, no-wrap +msgid "Creating an immutable object in PHP" +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +msgid "" +"There is no direct way to modify an instance, but you can use clone to " +"create a new instance with the desired changes. That is what `with*` " +"methods do." +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/immutability.md +#, no-wrap +msgid "" +"final class Money\n" +"{\n" +" public function __construct(\n" +" private int $amount,\n" +" private string $currency,\n" +" ) {\n" +" $this->validateAmount($amount);\n" +" $this->validateCurrency($currency);\n" +" }\n" +" \n" +" private function validateAmount(string $amount) \n" +" {\n" +" if ($amount < 0) {\n" +" throw new InvalidArgumentException('Amount must be positive.');\n" +" }\n" +" }\n" +" \n" +" private function validateCurrency(string $currency)\n" +" {\n" +" if (!in_array($currency, ['USD', 'EUR'])) {\n" +" throw new InvalidArgumentException('Invalid currency. Only USD and EUR are supported.');\n" +" }\n" +" } \n" +"\n" +" public function withAmount(int $amount): self\n" +" {\n" +" $this->validateAmount($amount);\n" +" \n" +" if ($amount === $this->amount) {\n" +" return $this;\n" +" }\n" +" \n" +" $clone = clone $this;\n" +" $clone->amount = $amount;\n" +" return $clone;\n" +" }\n" +" \n" +" public function withCurrency(string $currency): self\n" +" {\n" +" $this->validateCurrency($currency);\n" +" \n" +" if ($currency === $this->currency) {\n" +" return $this;\n" +" }\n" +" \n" +" $clone = clone $this;\n" +" $clone->currency = $currency;\n" +" return $clone;\n" +" }\n" +" \n" +" public function amount(): int \n" +" {\n" +" return $this->amount;\n" +" }\n" +" \n" +" public function currency(): string \n" +" {\n" +" return $this->currency;\n" +" }\n" +"\n" +" public function add(self $money): self\n" +" {\n" +" if ($money->currency !== $this->currency) {\n" +" throw new InvalidArgumentException('Currency mismatch. Cannot add money of different currency.');\n" +" }\n" +" return $this->withAmount($this->amount + $money->amount);\n" +" }\n" +"}\n" +"\n" +"$price = new Money(1000, 'USD');\n" +"$discounted = $price->withAmount(800);\n" +"// $price is still 1000 USD, $discounted is 800 USD\n" +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/immutability.md +msgid "" +"We mark the class `final` to prevent subclass mutations; alternatively, " +"design for extension carefully." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/immutability.md +msgid "" +"Validate in the constructor and `with*` methods so every instance is always " +"valid." +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +#, no-wrap +msgid "" +"> [!TIP]\n" +"> If you define a simple DTO, you can use modern PHP `readonly` and leave properties `public`. The `readonly` keyword\n" +"> would ensure that the properties cannot be modified after the object is created.\n" +msgstr "" + +#. type: Title ## +#: en/concept/immutability.md +#, no-wrap +msgid "Using clone (and why it is cheap)" +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +msgid "" +"PHP's clone performs a shallow copy of the object. For immutable value " +"objects that contain only scalars or other immutable objects, shallow " +"cloning is enough and fast. In modern PHP, cloning small value objects is " +"inexpensive in both time and memory." +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +msgid "" +"If your object holds mutable sub-objects that must also be copied, implement " +"`__clone` to deep-clone them:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/immutability.md +#, no-wrap +msgid "" +"final class Order\n" +"{\n" +" public function __construct(\n" +" private Money $total\n" +" ) {}\n" +" \n" +" public function total(): Money \n" +" {\n" +" return $this->total;\n" +" }\n" +"\n" +" public function __clone(): void\n" +" {\n" +" // Money is immutable in our example, so a deep clone is not required.\n" +" // If it were mutable, you could do: $this->total = clone $this->total;\n" +" }\n" +"\n" +" public function withTotal(Money $total): self\n" +" {\n" +" $clone = clone $this;\n" +" $clone->total = $total;\n" +" return $clone;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/concept/immutability.md +#, no-wrap +msgid "Usage style" +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/immutability.md +msgid "" +"Build a value object once and pass it around. If you need a change, use a " +"`with*` method that returns a new instance." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/immutability.md +msgid "" +"Prefer scalar/immutable fields inside immutable objects; if a field can " +"mutate, isolate it and deep-clone in `__clone` when needed." +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +msgid "" +"Immutability aligns well with Yii's preference for predictable, side-effect-" +"free code and makes services, caching, and configuration more robust." +msgstr "" diff --git a/guide/po/concept_immutability.md/ru/concept_immutability.md.ru.po b/guide/po/concept_immutability.md/ru/concept_immutability.md.ru.po new file mode 100644 index 00000000..a6ba0b22 --- /dev/null +++ b/guide/po/concept_immutability.md/ru/concept_immutability.md.ru.po @@ -0,0 +1,224 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/concept/immutability.md +#, no-wrap +msgid "Immutability" +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +msgid "Immutability means an object's state cannot change after it has been created. Instead of modifying an instance, you create a new instance with the desired changes. This approach is common for value objects such as Money, IDs, and DTOs. It helps to avoid accidental side effects: methods cannot silently change shared state, which makes code easier to reason about." +msgstr "" + +#. type: Title ## +#: en/concept/immutability.md +#, no-wrap +msgid "Mutable pitfalls (what we avoid)" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/immutability.md +#, no-wrap +msgid "" +"// A shared base query built once and reused:\n" +"$base = Post::find()->where(['status' => Post::STATUS_PUBLISHED]);\n" +"\n" +"// Somewhere deep in the code we only need one post:\n" +"$one = $base->limit(1)->one(); // mutates the underlying builder (sticky limit!)\n" +"\n" +"// Later we reuse the same $base expecting a full list:\n" +"$list = $base->orderBy(['created_at' => SORT_DESC])->all();\n" +"// Oops: still limited to 1 because the previous limit(1) modified $base.\n" +msgstr "" + +#. type: Title ## +#: en/concept/immutability.md +#, no-wrap +msgid "Creating an immutable object in PHP" +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +msgid "There is no direct way to modify an instance, but you can use clone to create a new instance with the desired changes. That is what `with*` methods do." +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/immutability.md +#, no-wrap +msgid "" +"final class Money\n" +"{\n" +" public function __construct(\n" +" private int $amount,\n" +" private string $currency,\n" +" ) {\n" +" $this->validateAmount($amount);\n" +" $this->validateCurrency($currency);\n" +" }\n" +" \n" +" private function validateAmount(string $amount) \n" +" {\n" +" if ($amount < 0) {\n" +" throw new InvalidArgumentException('Amount must be positive.');\n" +" }\n" +" }\n" +" \n" +" private function validateCurrency(string $currency)\n" +" {\n" +" if (!in_array($currency, ['USD', 'EUR'])) {\n" +" throw new InvalidArgumentException('Invalid currency. Only USD and EUR are supported.');\n" +" }\n" +" } \n" +"\n" +" public function withAmount(int $amount): self\n" +" {\n" +" $this->validateAmount($amount);\n" +" \n" +" if ($amount === $this->amount) {\n" +" return $this;\n" +" }\n" +" \n" +" $clone = clone $this;\n" +" $clone->amount = $amount;\n" +" return $clone;\n" +" }\n" +" \n" +" public function withCurrency(string $currency): self\n" +" {\n" +" $this->validateCurrency($currency);\n" +" \n" +" if ($currency === $this->currency) {\n" +" return $this;\n" +" }\n" +" \n" +" $clone = clone $this;\n" +" $clone->currency = $currency;\n" +" return $clone;\n" +" }\n" +" \n" +" public function amount(): int \n" +" {\n" +" return $this->amount;\n" +" }\n" +" \n" +" public function currency(): string \n" +" {\n" +" return $this->currency;\n" +" }\n" +"\n" +" public function add(self $money): self\n" +" {\n" +" if ($money->currency !== $this->currency) {\n" +" throw new InvalidArgumentException('Currency mismatch. Cannot add money of different currency.');\n" +" }\n" +" return $this->withAmount($this->amount + $money->amount);\n" +" }\n" +"}\n" +"\n" +"$price = new Money(1000, 'USD');\n" +"$discounted = $price->withAmount(800);\n" +"// $price is still 1000 USD, $discounted is 800 USD\n" +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/immutability.md +msgid "We mark the class `final` to prevent subclass mutations; alternatively, design for extension carefully." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/immutability.md +msgid "Validate in the constructor and `with*` methods so every instance is always valid." +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +#, no-wrap +msgid "" +"> [!TIP]\n" +"> If you define a simple DTO, you can use modern PHP `readonly` and leave properties `public`. The `readonly` keyword\n" +"> would ensure that the properties cannot be modified after the object is created.\n" +msgstr "" + +#. type: Title ## +#: en/concept/immutability.md +#, no-wrap +msgid "Using clone (and why it is cheap)" +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +msgid "PHP's clone performs a shallow copy of the object. For immutable value objects that contain only scalars or other immutable objects, shallow cloning is enough and fast. In modern PHP, cloning small value objects is inexpensive in both time and memory." +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +msgid "If your object holds mutable sub-objects that must also be copied, implement `__clone` to deep-clone them:" +msgstr "" + +#. type: Fenced code block (php) +#: en/concept/immutability.md +#, no-wrap +msgid "" +"final class Order\n" +"{\n" +" public function __construct(\n" +" private Money $total\n" +" ) {}\n" +" \n" +" public function total(): Money \n" +" {\n" +" return $this->total;\n" +" }\n" +"\n" +" public function __clone(): void\n" +" {\n" +" // Money is immutable in our example, so a deep clone is not required.\n" +" // If it were mutable, you could do: $this->total = clone $this->total;\n" +" }\n" +"\n" +" public function withTotal(Money $total): self\n" +" {\n" +" $clone = clone $this;\n" +" $clone->total = $total;\n" +" return $clone;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/concept/immutability.md +#, no-wrap +msgid "Usage style" +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/immutability.md +msgid "Build a value object once and pass it around. If you need a change, use a `with*` method that returns a new instance." +msgstr "" + +#. type: Bullet: '- ' +#: en/concept/immutability.md +msgid "Prefer scalar/immutable fields inside immutable objects; if a field can mutate, isolate it and deep-clone in `__clone` when needed." +msgstr "" + +#. type: Plain text +#: en/concept/immutability.md +msgid "Immutability aligns well with Yii's preference for predictable, side-effect-free code and makes services, caching, and configuration more robust." +msgstr "" diff --git a/guide/po/databases_db-migrations.md/databases_db-migrations.md.pot b/guide/po/databases_db-migrations.md/databases_db-migrations.md.pot new file mode 100644 index 00000000..1a0ab593 --- /dev/null +++ b/guide/po/databases_db-migrations.md/databases_db-migrations.md.pot @@ -0,0 +1,184 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/databases/db-migrations.md +#, no-wrap +msgid "Migrations" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "" +"To use migrations, install [yiisoft/db-migration](https://github.com/yiisoft/" +"db-migration/) package:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/databases/db-migrations.md +#, no-wrap +msgid "composer require yiisoft/db-migration\n" +msgstr "" + +#. type: Title ### +#: en/databases/db-migrations.md +#, no-wrap +msgid "Example usage" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "" +"First, configure DI container. Create `config/common/db.php` with the " +"following content:" +msgstr "" + +#. type: Fenced code block (php) +#: en/databases/db-migrations.md +#, no-wrap +msgid "" +" [\n" +" 'class' => SqliteConnection::class,\n" +" '__construct()' => [\n" +" 'dsn' => 'sqlite:' . __DIR__ . '/Data/yiitest.sq3'\n" +" ]\n" +" ]\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "Add the following to `config/params.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/databases/db-migrations.md +#, no-wrap +msgid "" +"...\n" +"'yiisoft/db-migration' => [\n" +" 'newMigrationNamespace' => 'App\\\\Migration',\n" +" 'sourceNamespaces' => ['App\\\\Migration'],\n" +"],\n" +"...\n" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "Now test if it works:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/databases/db-migrations.md +#, no-wrap +msgid "./yii list migrate\n" +msgstr "" + +#. type: Title ### +#: en/databases/db-migrations.md +#, no-wrap +msgid "Creating a migration" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "" +"To work with migrations, you can use the provided [view](https://github.com/" +"yiisoft/db-migration/tree/master/resources/views)." +msgstr "" + +#. type: Fenced code block (shell) +#: en/databases/db-migrations.md +#, no-wrap +msgid "./yii migrate:create my_first_table --command=table --fields=name,example --table-comment=my_first_table\n" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "That would generate the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/databases/db-migrations.md +#, no-wrap +msgid "" +"createTable('my_first_table', [\n" +" 'id' => $b->primaryKey(),\n" +" 'name',\n" +" 'example',\n" +" ]);\n" +" \n" +" $b->addCommentOnTable('my_first_table', 'dest');\n" +" }\n" +"\n" +" public function down(MigrationBuilder $b): void\n" +" {\n" +" $b->dropTable('my_first_table');\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "" +"For more information [see](https://github.com/yiisoft/db-migration/tree/" +"master/docs/guide/en)" +msgstr "" + +#. type: Title ### +#: en/databases/db-migrations.md +#, no-wrap +msgid "Upgrading from Yii2" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "" +"Migrations in Yii2 and the [yiisoft/db-migration](https://github.com/yiisoft/" +"db-migration/) package are not compatible, and the `migration` table is also " +"not compatible. A probable solution is to use structure dumps and rename " +"the old `migration` table. Upon the initial execution of migrations, a new " +"`migration` table with new fields will be created. All subsequent changes in " +"the database schema are applied using the new `migration` component and " +"recorded in the new migration table." +msgstr "" diff --git a/guide/po/databases_db-migrations.md/ru/databases_db-migrations.md.ru.po b/guide/po/databases_db-migrations.md/ru/databases_db-migrations.md.ru.po new file mode 100644 index 00000000..04de7706 --- /dev/null +++ b/guide/po/databases_db-migrations.md/ru/databases_db-migrations.md.ru.po @@ -0,0 +1,174 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/databases/db-migrations.md +#, no-wrap +msgid "Migrations" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "To use migrations, install [yiisoft/db-migration](https://github.com/yiisoft/db-migration/) package:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/databases/db-migrations.md +#, fuzzy, no-wrap +#| msgid "composer install yiisoft/security\n" +msgid "composer require yiisoft/db-migration\n" +msgstr "composer install yiisoft/security\n" + +#. type: Title ### +#: en/databases/db-migrations.md +#, no-wrap +msgid "Example usage" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "First, configure DI container. Create `config/common/db.php` with the following content:" +msgstr "" + +#. type: Fenced code block (php) +#: en/databases/db-migrations.md +#, no-wrap +msgid "" +" [\n" +" 'class' => SqliteConnection::class,\n" +" '__construct()' => [\n" +" 'dsn' => 'sqlite:' . __DIR__ . '/Data/yiitest.sq3'\n" +" ]\n" +" ]\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +#, fuzzy +#| msgid "Add the following to your php.ini:" +msgid "Add the following to `config/params.php`:" +msgstr "Добавьте в свой php.ini следующее:" + +#. type: Fenced code block (php) +#: en/databases/db-migrations.md +#, no-wrap +msgid "" +"...\n" +"'yiisoft/db-migration' => [\n" +" 'newMigrationNamespace' => 'App\\\\Migration',\n" +" 'sourceNamespaces' => ['App\\\\Migration'],\n" +"],\n" +"...\n" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "Now test if it works:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/databases/db-migrations.md +#, no-wrap +msgid "./yii list migrate\n" +msgstr "" + +#. type: Title ### +#: en/databases/db-migrations.md +#, no-wrap +msgid "Creating a migration" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "To work with migrations, you can use the provided [view](https://github.com/yiisoft/db-migration/tree/master/resources/views)." +msgstr "" + +#. type: Fenced code block (shell) +#: en/databases/db-migrations.md +#, no-wrap +msgid "./yii migrate:create my_first_table --command=table --fields=name,example --table-comment=my_first_table\n" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +#, fuzzy +#| msgid "That's equal to the following:" +msgid "That would generate the following:" +msgstr "Это соответствует:" + +#. type: Fenced code block (php) +#: en/databases/db-migrations.md +#, no-wrap +msgid "" +"createTable('my_first_table', [\n" +" 'id' => $b->primaryKey(),\n" +" 'name',\n" +" 'example',\n" +" ]);\n" +" \n" +" $b->addCommentOnTable('my_first_table', 'dest');\n" +" }\n" +"\n" +" public function down(MigrationBuilder $b): void\n" +" {\n" +" $b->dropTable('my_first_table');\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "For more information [see](https://github.com/yiisoft/db-migration/tree/master/docs/guide/en)" +msgstr "" + +#. type: Title ### +#: en/databases/db-migrations.md +#, no-wrap +msgid "Upgrading from Yii2" +msgstr "" + +#. type: Plain text +#: en/databases/db-migrations.md +msgid "Migrations in Yii2 and the [yiisoft/db-migration](https://github.com/yiisoft/db-migration/) package are not compatible, and the `migration` table is also not compatible. A probable solution is to use structure dumps and rename the old `migration` table. Upon the initial execution of migrations, a new `migration` table with new fields will be created. All subsequent changes in the database schema are applied using the new `migration` component and recorded in the new migration table." +msgstr "" diff --git a/guide/po/intro_upgrade-from-v2.md/intro_upgrade-from-v2.md.pot b/guide/po/intro_upgrade-from-v2.md/intro_upgrade-from-v2.md.pot new file mode 100644 index 00000000..3ed471a9 --- /dev/null +++ b/guide/po/intro_upgrade-from-v2.md/intro_upgrade-from-v2.md.pot @@ -0,0 +1,321 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Upgrading from Version 2.0" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "" +"> If you haven't used Yii2, you can skip this section and get directly to \"[getting started](../start/installation.md)\"\n" +"> section.\n" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"While sharing some common ideas and values, Yii 3 is conceptually different " +"from Yii 2. There is no easy upgrade path, so first [check maintenance " +"policy and end-of-life dates for Yii 2](https://www.yiiframework.com/release-" +"cycle) and consider starting new projects on Yii 3 while keeping existing " +"ones on Yii 2." +msgstr "" + +#. type: Title ## +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "PHP requirements" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"Yii3 requires PHP 8.2 or above. As a result, there are language features " +"used that weren't used in Yii 2:" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "" +"[Type declarations](https://www.php.net/manual/en/functions.arguments." +"php#functions.arguments.type-declaration)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "" +"[Return type declarations](https://www.php.net/manual/en/functions.returning-" +"values.php#functions.returning-values.type-declaration)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "" +"[Class constant visibility](https://www.php.net/manual/en/language.oop5." +"constants.php)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "" +"[Named arguments](https://www.php.net/manual/en/functions.arguments." +"php#functions.named-arguments)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "" +"[Anonymous classes](https://www.php.net/manual/en/language.oop5.anonymous." +"php)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "" +"[::class](https://www.php.net/manual/en/language.oop5.basic.php#language." +"oop5.basic.class.class)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "[Generators](https://www.php.net/manual/en/language.generators.php)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "" +"[Variadic functions](https://www.php.net/manual/en/functions.arguments." +"php#functions.variable-arg-list)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "" +"[Readonly properties](https://www.php.net/manual/en/language.oop5.properties." +"php#language.oop5.properties.readonly-properties)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "" +"[Readonly classes](https://www.php.net/manual/en/language.oop5.basic." +"php#language.oop5.basic.class.readonly)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "" +"[Constructor property promotion](https://www.php.net/manual/en/language.oop5." +"decon.php#language.oop5.decon.constructor.promotion)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "[Attributes](https://www.php.net/manual/en/language.attributes.php)" +msgstr "" + +#. type: Title ## +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Preliminary refactoring" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"It's a good idea to refactor your Yii 2 project before porting it to Yii 3. " +"That would both make porting easier and benefit the project in question " +"while it's not moved to Yii 3 yet." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Use DI instead of the service locator" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "" +"Since Yii 3 is forcing you to inject dependencies, it's a good idea to prepare and switch from using\n" +"service locator (`Yii::$app->`) to [DI container](https://www.yiiframework.com/doc/guide/2.0/en/concept-di-container).\n" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "" +"If usage of DI container is problematic for whatever reason, consider moving all calls to `Yii::$app->` to controller\n" +"actions and widgets and passing dependencies manually from a controller to what needs them.\n" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"See [Dependency injection and container](../concept/di-container.md) for an " +"explanation of the idea." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Introduce repositories for getting data" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"Since Active Record isn't the only way to work with a database in Yii 3, " +"consider introducing repositories that would hide details of getting data " +"and gather them in a single place. You can later redo it:" +msgstr "" + +#. type: Fenced code block (php) +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "" +"final readonly class PostRepository\n" +"{\n" +" public function getArchive()\n" +" {\n" +" // ...\n" +" }\n" +" \n" +" public function getTop10ForFrontPage()\n" +" {\n" +" // ...\n" +" }\n" +"\n" +"}\n" +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Separate domain layer from infrastructure" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"In case you have a rich complicated domain, it's a good idea to separate it " +"from infrastructure provided by a framework that's all the business logic " +"has to go to framework-independent classes." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Move more into components" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"Yii 3 services are conceptually similar to Yii 2 components, so it's a good " +"idea to move reusable parts of your application into components." +msgstr "" + +#. type: Title ## +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Things to learn" +msgstr "" + +#. type: Title ## +#: en/intro/upgrade-from-v2.md en/start/prerequisites.md +#, no-wrap +msgid "Docker" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"Default application templates are using [Docker](https://www.docker.com/get-" +"started/) to run application. It's a good idea to learn how to use it and " +"use it for your own projects since it provides a lot of benefits:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/intro/upgrade-from-v2.md +msgid "Exactly the same environment as in production." +msgstr "" + +#. type: Bullet: '2. ' +#: en/intro/upgrade-from-v2.md +msgid "No need to install anything except Docker itself." +msgstr "" + +#. type: Bullet: '3. ' +#: en/intro/upgrade-from-v2.md +msgid "Environment is per application, not per server." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Environment variables" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"Yii3 application templates are using [environment variables](https://en." +"wikipedia.org/wiki/Environment_variable) to configure pars of the " +"application. The concept is [very handy for Dockerized applications]" +"(https://12factor.net/) but might be alien to users of Yii 1.1 and Yii 2." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Handlers" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"Unlike Yii2, Yii3 doesn't have controllers per se. Instead, it uses " +"[handlers](../structure/handler.md) which are similar to controllers but " +"different." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Application structure" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"Suggested Yii3 application structure is different from Yii 2. It's " +"described in [application structure](../structure/overview.md)." +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "" +"Despite that, Yii3 is flexible, so it's still possible to use a structure " +"similar to Yii 2 with Yii 3." +msgstr "" diff --git a/guide/po/intro_upgrade-from-v2.md/ru/intro_upgrade-from-v2.md.ru.po b/guide/po/intro_upgrade-from-v2.md/ru/intro_upgrade-from-v2.md.ru.po new file mode 100644 index 00000000..042c0108 --- /dev/null +++ b/guide/po/intro_upgrade-from-v2.md/ru/intro_upgrade-from-v2.md.ru.po @@ -0,0 +1,275 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Upgrading from Version 2.0" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "" +"> If you haven't used Yii2, you can skip this section and get directly to \"[getting started](../start/installation.md)\"\n" +"> section.\n" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "While sharing some common ideas and values, Yii 3 is conceptually different from Yii 2. There is no easy upgrade path, so first [check maintenance policy and end-of-life dates for Yii 2](https://www.yiiframework.com/release-cycle) and consider starting new projects on Yii 3 while keeping existing ones on Yii 2." +msgstr "" + +#. type: Title ## +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "PHP requirements" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "Yii3 requires PHP 8.2 or above. As a result, there are language features used that weren't used in Yii 2:" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "[Type declarations](https://www.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "[Return type declarations](https://www.php.net/manual/en/functions.returning-values.php#functions.returning-values.type-declaration)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +#, fuzzy +#| msgid "[PHP manual: security](https://www.php.net/manual/en/security.php)" +msgid "[Class constant visibility](https://www.php.net/manual/en/language.oop5.constants.php)" +msgstr "[Руководство по PHP: безопасность](https://www.php.net/manual/en/security.php)" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "[Named arguments](https://www.php.net/manual/en/functions.arguments.php#functions.named-arguments)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +#, fuzzy +#| msgid "[PHP manual: security](https://www.php.net/manual/en/security.php)" +msgid "[Anonymous classes](https://www.php.net/manual/en/language.oop5.anonymous.php)" +msgstr "[Руководство по PHP: безопасность](https://www.php.net/manual/en/security.php)" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "[::class](https://www.php.net/manual/en/language.oop5.basic.php#language.oop5.basic.class.class)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +#, fuzzy +#| msgid "[PHP manual: security](https://www.php.net/manual/en/security.php)" +msgid "[Generators](https://www.php.net/manual/en/language.generators.php)" +msgstr "[Руководство по PHP: безопасность](https://www.php.net/manual/en/security.php)" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "[Variadic functions](https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "[Readonly properties](https://www.php.net/manual/en/language.oop5.properties.php#language.oop5.properties.readonly-properties)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "[Readonly classes](https://www.php.net/manual/en/language.oop5.basic.php#language.oop5.basic.class.readonly)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +msgid "[Constructor property promotion](https://www.php.net/manual/en/language.oop5.decon.php#language.oop5.decon.constructor.promotion)" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/upgrade-from-v2.md +#, fuzzy +#| msgid "[PHP manual: security](https://www.php.net/manual/en/security.php)" +msgid "[Attributes](https://www.php.net/manual/en/language.attributes.php)" +msgstr "[Руководство по PHP: безопасность](https://www.php.net/manual/en/security.php)" + +#. type: Title ## +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Preliminary refactoring" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "It's a good idea to refactor your Yii 2 project before porting it to Yii 3. That would both make porting easier and benefit the project in question while it's not moved to Yii 3 yet." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Use DI instead of the service locator" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "" +"Since Yii 3 is forcing you to inject dependencies, it's a good idea to prepare and switch from using\n" +"service locator (`Yii::$app->`) to [DI container](https://www.yiiframework.com/doc/guide/2.0/en/concept-di-container).\n" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "" +"If usage of DI container is problematic for whatever reason, consider moving all calls to `Yii::$app->` to controller\n" +"actions and widgets and passing dependencies manually from a controller to what needs them.\n" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "See [Dependency injection and container](../concept/di-container.md) for an explanation of the idea." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Introduce repositories for getting data" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "Since Active Record isn't the only way to work with a database in Yii 3, consider introducing repositories that would hide details of getting data and gather them in a single place. You can later redo it:" +msgstr "" + +#. type: Fenced code block (php) +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "" +"final readonly class PostRepository\n" +"{\n" +" public function getArchive()\n" +" {\n" +" // ...\n" +" }\n" +" \n" +" public function getTop10ForFrontPage()\n" +" {\n" +" // ...\n" +" }\n" +"\n" +"}\n" +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Separate domain layer from infrastructure" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "In case you have a rich complicated domain, it's a good idea to separate it from infrastructure provided by a framework that's all the business logic has to go to framework-independent classes." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Move more into components" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "Yii 3 services are conceptually similar to Yii 2 components, so it's a good idea to move reusable parts of your application into components." +msgstr "" + +#. type: Title ## +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Things to learn" +msgstr "" + +#. type: Title ## +#: en/intro/upgrade-from-v2.md en/start/prerequisites.md +#, no-wrap +msgid "Docker" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "Default application templates are using [Docker](https://www.docker.com/get-started/) to run application. It's a good idea to learn how to use it and use it for your own projects since it provides a lot of benefits:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/intro/upgrade-from-v2.md +msgid "Exactly the same environment as in production." +msgstr "" + +#. type: Bullet: '2. ' +#: en/intro/upgrade-from-v2.md +msgid "No need to install anything except Docker itself." +msgstr "" + +#. type: Bullet: '3. ' +#: en/intro/upgrade-from-v2.md +msgid "Environment is per application, not per server." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Environment variables" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "Yii3 application templates are using [environment variables](https://en.wikipedia.org/wiki/Environment_variable) to configure pars of the application. The concept is [very handy for Dockerized applications](https://12factor.net/) but might be alien to users of Yii 1.1 and Yii 2." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Handlers" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "Unlike Yii2, Yii3 doesn't have controllers per se. Instead, it uses [handlers](../structure/handler.md) which are similar to controllers but different." +msgstr "" + +#. type: Title ### +#: en/intro/upgrade-from-v2.md +#, no-wrap +msgid "Application structure" +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "Suggested Yii3 application structure is different from Yii 2. It's described in [application structure](../structure/overview.md)." +msgstr "" + +#. type: Plain text +#: en/intro/upgrade-from-v2.md +msgid "Despite that, Yii3 is flexible, so it's still possible to use a structure similar to Yii 2 with Yii 3." +msgstr "" diff --git a/guide/po/intro_what-is-yii.md/intro_what-is-yii.md.pot b/guide/po/intro_what-is-yii.md/intro_what-is-yii.md.pot new file mode 100644 index 00000000..8e5d0560 --- /dev/null +++ b/guide/po/intro_what-is-yii.md/intro_what-is-yii.md.pot @@ -0,0 +1,178 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 07:51+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/intro/what-is-yii.md +#, no-wrap +msgid "What is Yii" +msgstr "" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "" +"Yii is a high-performance, package-based PHP framework for developing modern " +"applications. The name Yii (pronounced `Yee` or `[ji:]`) means \"simple and " +"evolutionary\" in Chinese. You can also think about it as an acronym for " +"**Yes It Is**!" +msgstr "" + +#. type: Title ## +#: en/intro/what-is-yii.md +#, no-wrap +msgid "What's Yii best for" +msgstr "" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "" +"Yii is a generic Web programming framework. You can use it for developing " +"all kinds of Web applications using PHP. Because of its architecture and " +"sophisticated caching support, it's especially suitable for developing large-" +"scale applications such as portals, content management systems, e-commerce, " +"REST APIs, etc." +msgstr "" + +#. type: Title ## +#: en/intro/what-is-yii.md +#, no-wrap +msgid "How does Yii compare with other frameworks?" +msgstr "" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "" +"If you're already familiar with another framework, you may appreciate " +"knowing how Yii compares:" +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/what-is-yii.md +msgid "" +"Yii takes the [philosophy of being practical and helpful](https://github.com/" +"yiisoft/docs/blob/master/001-yii-values.md) achieving:" +msgstr "" + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Performance in both development and execution." +msgstr "" + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Convenient customizable defaults." +msgstr "" + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Practice-orientation." +msgstr "" + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Simplicity." +msgstr "" + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Explicitness." +msgstr "" + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Consistency." +msgstr "" + +#. type: Plain text +#: en/intro/what-is-yii.md +#, no-wrap +msgid "" +" Yii will never try to over-design things mainly to follow some design patterns.\n" +"- Yii extensively uses PSR interfaces with the ability to reuse what PHP community created and even\n" +" replace core implementations if needed.\n" +"- Yii is both a set of libraries and a full-stack framework providing many proven and ready-to-use features:\n" +" caching, logging, template engine, data abstraction, development tools, code generation, and more.\n" +"- Yii is extensible. You can customize or replace every piece of the core's code. You can also\n" +" take advantage of Yii's solid architecture to use or develop redistributable packages.\n" +"- High performance is always a primary goal of Yii.\n" +msgstr "" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "" +"Yii is backed up by a [strong core developer team](https://www.yiiframework." +"com/team/) financially backed from an [OpenCollective foundation](https://" +"opencollective.com/yiisoft), as well as a large community of professionals " +"constantly contributing to Yii's development. The Yii developer team keeps a " +"close eye on the latest Web development trends and on the best practices and " +"features found in other frameworks and projects. The most relevant best " +"practices and features found elsewhere are incorporated into the core " +"framework and exposed via simple and elegant interfaces." +msgstr "" + +#. type: Title ## +#: en/intro/what-is-yii.md +#, no-wrap +msgid "Yii versions" +msgstr "" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "Yii currently has three major versions available: 1.1, 2.0, and 3.0." +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/what-is-yii.md +msgid "" +"Version 1.1 is the old generation and is now in the feature freeze bugfix " +"mode." +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/what-is-yii.md +msgid "" +"Version 2.0 is a current stable version in the feature freeze bugfix mode." +msgstr "" + +#. type: Bullet: '- ' +#: en/intro/what-is-yii.md +msgid "" +"Version 3.0 is the current version in development. This guide is mainly " +"about version 3." +msgstr "" + +#. type: Title ## +#: en/intro/what-is-yii.md +#, no-wrap +msgid "Requirements and prerequisites" +msgstr "" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "" +"Yii3 requires PHP 8.2 or above, but some packages also older PHP such as PHP " +"7.4." +msgstr "" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "" +"Using Yii requires basic knowledge of object-oriented programming (OOP), as " +"Yii is a pure OOP-based framework. Yii3 also makes use of the latest PHP " +"features, such as type declarations and generators. Understanding these " +"concepts will help you pick up Yii3 faster." +msgstr "" diff --git a/guide/po/intro_what-is-yii.md/ru/intro_what-is-yii.md.ru.po b/guide/po/intro_what-is-yii.md/ru/intro_what-is-yii.md.ru.po new file mode 100644 index 00000000..3d25b3a9 --- /dev/null +++ b/guide/po/intro_what-is-yii.md/ru/intro_what-is-yii.md.ru.po @@ -0,0 +1,162 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2025-09-04 07:51+0500\n" +"PO-Revision-Date: 2025-09-04 07:58+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 3.7\n" + +#. type: Title # +#: en/intro/what-is-yii.md +#, no-wrap +msgid "What is Yii" +msgstr "Что такое Yii?" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "Yii is a high-performance, package-based PHP framework for developing modern applications. The name Yii (pronounced `Yee` or `[ji:]`) means \"simple and evolutionary\" in Chinese. You can also think about it as an acronym for **Yes It Is**!" +msgstr "" +"Yii – это высокопроизводительный пакетный PHP фреймворк, предназначенный для разработки современных веб-приложений. \n" +"Слово Yii (произносится как `Йии` или `[ji:]`) в китайском языке означает «простой и эволюционирующий». \n" +"Также Yii может расшифровываться как акроним **Yes It Is**!" + +#. type: Title ## +#: en/intro/what-is-yii.md +#, no-wrap +msgid "What's Yii best for" +msgstr "Для каких задач больше всего подходит Yii?" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "Yii is a generic Web programming framework. You can use it for developing all kinds of Web applications using PHP. Because of its architecture and sophisticated caching support, it's especially suitable for developing large-scale applications such as portals, content management systems, e-commerce, REST APIs, etc." +msgstr "" +"Yii – это универсальный веб-фреймворк.\n" +"Вы можете использовать его для разработки всех типов веб-приложений.\n" +"Благодаря его архитектуре и отличной поддержке кеширования, фреймворк особенно подходит для разработки таких крупных проектов, как порталы, CMS, магазины или RESTful-приложения." + +#. type: Title ## +#: en/intro/what-is-yii.md +#, no-wrap +msgid "How does Yii compare with other frameworks?" +msgstr "Сравнение Yii с другими фреймворками" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "If you're already familiar with another framework, you may appreciate knowing how Yii compares:" +msgstr "Если вы уже знакомы с другими фреймворками, вам наверняка будет интересно сравнить их с Yii:" + +#. type: Bullet: '- ' +#: en/intro/what-is-yii.md +msgid "Yii takes the [philosophy of being practical and helpful](https://github.com/yiisoft/docs/blob/master/001-yii-values.md) achieving:" +msgstr "Yii придерживается [философии практичности и полезности] (https://github.com/yiisoft/docs/blob/master/001-yii-values.md), достигая следующего:" + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Performance in both development and execution." +msgstr "Производительность как в разработке, так и во время выполнения." + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Convenient customizable defaults." +msgstr "Удобные изменяемые настройки по-умолчанию." + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Practice-orientation." +msgstr "Практикоориентированность." + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Simplicity." +msgstr "Простота." + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Explicitness." +msgstr "Ясность." + +#. type: Bullet: ' - ' +#: en/intro/what-is-yii.md +msgid "Consistency." +msgstr "Согласованность." + +#. type: Plain text +#: en/intro/what-is-yii.md +#, no-wrap +msgid "" +" Yii will never try to over-design things mainly to follow some design patterns.\n" +"- Yii extensively uses PSR interfaces with the ability to reuse what PHP community created and even\n" +" replace core implementations if needed.\n" +"- Yii is both a set of libraries and a full-stack framework providing many proven and ready-to-use features:\n" +" caching, logging, template engine, data abstraction, development tools, code generation, and more.\n" +"- Yii is extensible. You can customize or replace every piece of the core's code. You can also\n" +" take advantage of Yii's solid architecture to use or develop redistributable packages.\n" +"- High performance is always a primary goal of Yii.\n" +msgstr "" +" Yii не усложняет дизайн только ради следования каким-либо шаблонам проектирования.\n" +"- Yii широко использует PSR интерфейсы с возможностью не только повторно использовать то, что создано PHP-сообществм, но и заменять, при необходимости, реализованный в ядре функционал.\n" +"- Yii это одновременно набор библиотек и full-stack фреймворк, предоставляющий множество проверенных и готовых к использованию компонентов:\n" +" кеширование, логирование, шаблонизатор, абстракция данных, инструменты разработчика, кодогенератор и др.\n" +"- Yii расширяем. Вы можете настроить или заменить практически любую часть основного кода. Используя пакетную архитектуру, легко делиться кодом или использовать код сообщества.\n" +"- Одна из главных целей Yii – производительность.\n" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "Yii is backed up by a [strong core developer team](https://www.yiiframework.com/team/) financially backed from an [OpenCollective foundation](https://opencollective.com/yiisoft), as well as a large community of professionals constantly contributing to Yii's development. The Yii developer team keeps a close eye on the latest Web development trends and on the best practices and features found in other frameworks and projects. The most relevant best practices and features found elsewhere are incorporated into the core framework and exposed via simple and elegant interfaces." +msgstr "Yii разрабатывается [сильной командой разработчиков](https://www.yiiframework.com/team/), финансируемой [фондом OpenCollective](https://opencollective.com/yiisoft), и большим сообществом, которое ей помогает. Авторы фреймворка следят за тенденциями веб-разработки и развитием других проектов. Наиболее подходящие возможности и лучшие практики регулярно внедряются во фреймворк в виде простых и элегантных интерфейсов." + +#. type: Title ## +#: en/intro/what-is-yii.md +#, no-wrap +msgid "Yii versions" +msgstr "Версии Yii" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "Yii currently has three major versions available: 1.1, 2.0, and 3.0." +msgstr "В настоящее время доступны три основные ветки: 1.1, 2.0 и 3.0." + +#. type: Bullet: '- ' +#: en/intro/what-is-yii.md +msgid "Version 1.1 is the old generation and is now in the feature freeze bugfix mode." +msgstr "Ветка 1.1 является предыдущим поколением и находится в состоянии исправления ошибок и заморозки добавления новой функциональности." + +#. type: Bullet: '- ' +#: en/intro/what-is-yii.md +msgid "Version 2.0 is a current stable version in the feature freeze bugfix mode." +msgstr "Ветка 2.0 — текущая стабильная версия. Находится в состоянии исправления ошибок и заморозки добавления новой функциональности." + +#. type: Bullet: '- ' +#: en/intro/what-is-yii.md +msgid "Version 3.0 is the current version in development. This guide is mainly about version 3." +msgstr "Ветка 3.0 — текущая разрабатываемая версия. Данное руководство именно о версии 3.0." + +#. type: Title ## +#: en/intro/what-is-yii.md +#, no-wrap +msgid "Requirements and prerequisites" +msgstr "Требования к ПО и знаниям" + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "Yii3 requires PHP 8.2 or above, but some packages also older PHP such as PHP 7.4." +msgstr "Yii3 требует PHP 8.2 или выше, но некоторые пакеты также поддерживают PHP 7.4." + +#. type: Plain text +#: en/intro/what-is-yii.md +msgid "Using Yii requires basic knowledge of object-oriented programming (OOP), as Yii is a pure OOP-based framework. Yii3 also makes use of the latest PHP features, such as type declarations and generators. Understanding these concepts will help you pick up Yii3 faster." +msgstr "" +"Для разработки на Yii потребуется общее понимание объектно-ориентированного программирования (ООП), так как фреймворк\n" +"полностью следует этой парадигме. Yii3 также использует новейшие возможности PHP, такие, как декларация типов и генераторы.\n" +"Понимание этих концепций поможет вам быстрее разобраться с Yii3." diff --git a/guide/po/runtime_cookies.md/ru/runtime_cookies.md.ru.po b/guide/po/runtime_cookies.md/ru/runtime_cookies.md.ru.po new file mode 100644 index 00000000..0bfefc9e --- /dev/null +++ b/guide/po/runtime_cookies.md/ru/runtime_cookies.md.ru.po @@ -0,0 +1,314 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/runtime/cookies.md +#, no-wrap +msgid "Cookies" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "Cookies are for persisting data between requests by sending it to the client browser using HTTP headers. The client sends data back to the server in request headers. Thus, cookies are handy to store small amounts of data, such as tokens or flags." +msgstr "" + +#. type: Title ## +#: en/runtime/cookies.md +#, no-wrap +msgid "Reading cookies" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "You could obtain Cookie values from server request that's available as route handler (such as controller action) argument:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"private function actionProfile(\\Psr\\Http\\Message\\ServerRequestInterface $request)\n" +"{\n" +" $cookieValues = $request->getCookieParams();\n" +" $cookieValue = $cookieValues['cookieName'] ?? null;\n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "In addition to getting cookie values directly from the server request, you can also use the [yiisoft/request-provider](https://github.com/yiisoft/request-provider) package, which provides a more structured way to handle cookies through the `\\Yiisoft\\RequestProvider\\RequestCookieProvider`. This approach can simplify your code and improve readability." +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "Here’s an example of how to work with cookies using the `\\Yiisoft\\RequestProvider\\RequestCookieProvider`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"final readonly class MyService\n" +"{\n" +" public function __construct(\n" +" private \\Yiisoft\\RequestProvider\\RequestCookieProvider $cookies\n" +" ) {}\n" +"\n" +" public function go(): void\n" +" {\n" +" // Check if a specific cookie exists\n" +" if ($this->cookies->has('foo')) {\n" +" // Retrieve the value of the cookie\n" +" $fooValue = $this->cookies->get('foo');\n" +" // Do something with the cookie value\n" +" }\n" +"\n" +" // Retrieve another cookie value\n" +" $barValue = $this->cookies->get('bar');\n" +" // Do something with the bar cookie value\n" +" }\n" +"}\n" +"\n" +"## Sending cookies\n" +"\n" +"Since sending cookies is, in fact, sending a header but since forming the header isn't trivial, there is\n" +"`\\Yiisoft\\Cookies\\Cookie` class to help with it:\n" +"\n" +"```php\n" +"$cookie = (new \\Yiisoft\\Cookies\\Cookie('cookieName', 'value'))\n" +" ->withPath('/')\n" +" ->withDomain('yiiframework.com')\n" +" ->withHttpOnly(true)\n" +" ->withSecure(true)\n" +" ->withSameSite(\\Yiisoft\\Cookies\\Cookie::SAME_SITE_STRICT)\n" +" ->withMaxAge(new \\DateInterval('P7D'));\n" +"\n" +"return $cookie->addToResponse($response);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "After forming a cookie call `addToResponse()` passing an instance of `\\Psr\\Http\\Message\\ResponseInterface` to add corresponding HTTP headers to it." +msgstr "" + +#. type: Title ## +#: en/runtime/cookies.md +#, no-wrap +msgid "Signing and encrypting cookies" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "To prevent the substitution of the cookie value, the package provides two implementations:" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "`Yiisoft\\Cookies\\CookieSigner` - signs each cookie with a unique prefix hash based on the value of the cookie and a secret key. `Yiisoft\\Cookies\\CookieEncryptor` - encrypts each cookie with a secret key." +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "Encryption is more secure than signing but has lower performance." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"$cookie = new \\Yiisoft\\Cookies\\Cookie('identity', 'identityValue');\n" +"\n" +"// The secret key used to sign and validate cookies.\n" +"$key = '0my1xVkjCJnD_q1yr6lUxcAdpDlTMwiU';\n" +"\n" +"$signer = new \\Yiisoft\\Cookies\\CookieSigner($key);\n" +"$encryptor = new \\Yiisoft\\Cookies\\CookieEncryptor($key);\n" +"\n" +"$signedCookie = $signer->sign($cookie);\n" +"$encryptedCookie = $encryptor->encrypt($cookie);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "To validate and get back the pure value, use the `validate()` and `decrypt()` method." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"$cookie = $signer->validate($signedCookie);\n" +"$cookie = $encryptor->decrypt($encryptedCookie);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "If the cookie value is tampered with or hasn't been signed/encrypted before, a `\\RuntimeException` will be thrown. Therefore, if you aren't sure that the cookie value was signed/encrypted earlier, first use the `isSigned()` and `isEncrypted()` methods, respectively." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"if ($signer->isSigned($cookie)) {\n" +" $cookie = $signer->validate($cookie);\n" +"}\n" +"\n" +"if ($encryptor->isEncrypted($cookie)) {\n" +" $cookie = $encryptor->decrypt($cookie);\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "It makes sense to sign or encrypt the value of a cookie if you store important data that a user shouldn't change." +msgstr "" + +#. type: Title ### +#: en/runtime/cookies.md +#, no-wrap +msgid "Automating encryption and signing" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "To automate the encryption/signing and decryption/validation of cookie values, use an instance of `Yiisoft\\Cookies\\CookieMiddleware`, which is [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware." +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +#, fuzzy +#| msgid "In this section, we'll review the following security aspects:" +msgid "This middleware provides the following features:" +msgstr "В этом разделе мы рассмотрим следующие аспекты безопасности:" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "Validates and decrypts the cookie parameter values from the request." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "Excludes the cookie parameter from the request if it was tampered with and logs information about it." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "Encrypts/signs cookie values and replaces their clean values in the `Set-Cookie` headers in the response." +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "In order for the middleware to know which values of which cookies need to be encrypted/signed, an array of settings must be passed to its constructor. The array keys are cookie name patterns and values are constant values of `CookieMiddleware::ENCRYPT` or `CookieMiddleware::SIGN`." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"use Yiisoft\\Cookies\\CookieMiddleware;\n" +"\n" +"$cookiesSettings = [\n" +" // Exact match with the name `identity`.\n" +" 'identity' => CookieMiddleware::ENCRYPT,\n" +" // Matches any number from 1 to 9 after the underscore.\n" +" 'name_[1-9]' => CookieMiddleware::SIGN,\n" +" // Matches any string after the prefix, including an\n" +" // empty string, except for the delimiters \"/\" and \"\\\".\n" +" 'prefix*' => CookieMiddleware::SIGN,\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "For more information on using the wildcard pattern, see the [yiisoft/strings](https://github.com/yiisoft/strings#wildcardpattern-usage) package." +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "Creating and using middleware:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"/**\n" +" * @var \\Psr\\Http\\Message\\ServerRequestInterface $request\n" +" * @var \\Psr\\Http\\Server\\RequestHandlerInterface $handler\n" +" * @var \\Psr\\Log\\LoggerInterface $logger\n" +" */\n" +"\n" +"// The secret key used to sign and validate cookies.\n" +"$key = '0my1xVkjCJnD_q1yr6lUxcAdpDlTMwiU';\n" +"$signer = new \\Yiisoft\\Cookies\\CookieSigner($key);\n" +"$encryptor = new \\Yiisoft\\Cookies\\CookieEncryptor($key);\n" +"\n" +"$cookiesSettings = [\n" +" 'identity' => \\Yiisoft\\Cookies\\CookieMiddleware::ENCRYPT,\n" +" 'session' => \\Yiisoft\\Cookies\\CookieMiddleware::SIGN,\n" +"];\n" +"\n" +"$middleware = new \\Yiisoft\\Cookies\\CookieMiddleware(\n" +" $logger\n" +" $encryptor,\n" +" $signer,\n" +" $cookiesSettings,\n" +");\n" +"\n" +"// The cookie parameter values from the request are decrypted/validated.\n" +"// The cookie values are encrypted/signed and appended to the response.\n" +"$response = $middleware->process($request, $handler);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "If the `$cookiesSettings` array is empty, no cookies will be encrypted and signed." +msgstr "" + +#. type: Title ## +#: en/runtime/cookies.md +#, no-wrap +msgid "Cookies security" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "You should configure each cookie to be secure. Important security settings are:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "`httpOnly`. Setting it to `true` would prevent JavaScript to access cookie value." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "`secure`. Setting it to `true` would prevent sending cookie via `HTTP`. It will be sent via `HTTPS` only." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "`sameSite`, if set to either `SAME_SITE_LAX` or `SAME_SITE_STRICT` would prevent sending a cookie in cross-site browsing context. `SAME_SITE_LAX` would prevent cookie sending during CSRF-prone request methods (e.g., POST, PUT, PATCH, etc.). `SAME_SITE_STRICT` would prevent cookies sending for all methods." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "Sign or encrypt the value of the cookie to prevent spoofing of values if the data in the value shouldn't be tampered with." +msgstr "" diff --git a/guide/po/runtime_cookies.md/runtime_cookies.md.pot b/guide/po/runtime_cookies.md/runtime_cookies.md.pot new file mode 100644 index 00000000..1d04030a --- /dev/null +++ b/guide/po/runtime_cookies.md/runtime_cookies.md.pot @@ -0,0 +1,369 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/runtime/cookies.md +#, no-wrap +msgid "Cookies" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"Cookies are for persisting data between requests by sending it to the client " +"browser using HTTP headers. The client sends data back to the server in " +"request headers. Thus, cookies are handy to store small amounts of data, " +"such as tokens or flags." +msgstr "" + +#. type: Title ## +#: en/runtime/cookies.md +#, no-wrap +msgid "Reading cookies" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"You could obtain Cookie values from server request that's available as route " +"handler (such as controller action) argument:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"private function actionProfile(\\Psr\\Http\\Message\\ServerRequestInterface $request)\n" +"{\n" +" $cookieValues = $request->getCookieParams();\n" +" $cookieValue = $cookieValues['cookieName'] ?? null;\n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"In addition to getting cookie values directly from the server request, you " +"can also use the [yiisoft/request-provider](https://github.com/yiisoft/" +"request-provider) package, which provides a more structured way to handle " +"cookies through the `\\Yiisoft\\RequestProvider\\RequestCookieProvider`. " +"This approach can simplify your code and improve readability." +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"Here’s an example of how to work with cookies using the " +"`\\Yiisoft\\RequestProvider\\RequestCookieProvider`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"final readonly class MyService\n" +"{\n" +" public function __construct(\n" +" private \\Yiisoft\\RequestProvider\\RequestCookieProvider $cookies\n" +" ) {}\n" +"\n" +" public function go(): void\n" +" {\n" +" // Check if a specific cookie exists\n" +" if ($this->cookies->has('foo')) {\n" +" // Retrieve the value of the cookie\n" +" $fooValue = $this->cookies->get('foo');\n" +" // Do something with the cookie value\n" +" }\n" +"\n" +" // Retrieve another cookie value\n" +" $barValue = $this->cookies->get('bar');\n" +" // Do something with the bar cookie value\n" +" }\n" +"}\n" +"\n" +"## Sending cookies\n" +"\n" +"Since sending cookies is, in fact, sending a header but since forming the header isn't trivial, there is\n" +"`\\Yiisoft\\Cookies\\Cookie` class to help with it:\n" +"\n" +"```php\n" +"$cookie = (new \\Yiisoft\\Cookies\\Cookie('cookieName', 'value'))\n" +" ->withPath('/')\n" +" ->withDomain('yiiframework.com')\n" +" ->withHttpOnly(true)\n" +" ->withSecure(true)\n" +" ->withSameSite(\\Yiisoft\\Cookies\\Cookie::SAME_SITE_STRICT)\n" +" ->withMaxAge(new \\DateInterval('P7D'));\n" +"\n" +"return $cookie->addToResponse($response);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"After forming a cookie call `addToResponse()` passing an instance of " +"`\\Psr\\Http\\Message\\ResponseInterface` to add corresponding HTTP headers " +"to it." +msgstr "" + +#. type: Title ## +#: en/runtime/cookies.md +#, no-wrap +msgid "Signing and encrypting cookies" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"To prevent the substitution of the cookie value, the package provides two " +"implementations:" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"`Yiisoft\\Cookies\\CookieSigner` - signs each cookie with a unique prefix " +"hash based on the value of the cookie and a secret key. " +"`Yiisoft\\Cookies\\CookieEncryptor` - encrypts each cookie with a secret key." +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "Encryption is more secure than signing but has lower performance." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"$cookie = new \\Yiisoft\\Cookies\\Cookie('identity', 'identityValue');\n" +"\n" +"// The secret key used to sign and validate cookies.\n" +"$key = '0my1xVkjCJnD_q1yr6lUxcAdpDlTMwiU';\n" +"\n" +"$signer = new \\Yiisoft\\Cookies\\CookieSigner($key);\n" +"$encryptor = new \\Yiisoft\\Cookies\\CookieEncryptor($key);\n" +"\n" +"$signedCookie = $signer->sign($cookie);\n" +"$encryptedCookie = $encryptor->encrypt($cookie);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"To validate and get back the pure value, use the `validate()` and " +"`decrypt()` method." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"$cookie = $signer->validate($signedCookie);\n" +"$cookie = $encryptor->decrypt($encryptedCookie);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"If the cookie value is tampered with or hasn't been signed/encrypted before, " +"a `\\RuntimeException` will be thrown. Therefore, if you aren't sure that " +"the cookie value was signed/encrypted earlier, first use the `isSigned()` " +"and `isEncrypted()` methods, respectively." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"if ($signer->isSigned($cookie)) {\n" +" $cookie = $signer->validate($cookie);\n" +"}\n" +"\n" +"if ($encryptor->isEncrypted($cookie)) {\n" +" $cookie = $encryptor->decrypt($cookie);\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"It makes sense to sign or encrypt the value of a cookie if you store " +"important data that a user shouldn't change." +msgstr "" + +#. type: Title ### +#: en/runtime/cookies.md +#, no-wrap +msgid "Automating encryption and signing" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"To automate the encryption/signing and decryption/validation of cookie " +"values, use an instance of `Yiisoft\\Cookies\\CookieMiddleware`, which is " +"[PSR-15](https://www.php-fig.org/psr/psr-15/) middleware." +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "This middleware provides the following features:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "Validates and decrypts the cookie parameter values from the request." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "" +"Excludes the cookie parameter from the request if it was tampered with and " +"logs information about it." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "" +"Encrypts/signs cookie values and replaces their clean values in the `Set-" +"Cookie` headers in the response." +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"In order for the middleware to know which values of which cookies need to be " +"encrypted/signed, an array of settings must be passed to its constructor. " +"The array keys are cookie name patterns and values are constant values of " +"`CookieMiddleware::ENCRYPT` or `CookieMiddleware::SIGN`." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"use Yiisoft\\Cookies\\CookieMiddleware;\n" +"\n" +"$cookiesSettings = [\n" +" // Exact match with the name `identity`.\n" +" 'identity' => CookieMiddleware::ENCRYPT,\n" +" // Matches any number from 1 to 9 after the underscore.\n" +" 'name_[1-9]' => CookieMiddleware::SIGN,\n" +" // Matches any string after the prefix, including an\n" +" // empty string, except for the delimiters \"/\" and \"\\\".\n" +" 'prefix*' => CookieMiddleware::SIGN,\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"For more information on using the wildcard pattern, see the [yiisoft/strings]" +"(https://github.com/yiisoft/strings#wildcardpattern-usage) package." +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "Creating and using middleware:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/cookies.md +#, no-wrap +msgid "" +"/**\n" +" * @var \\Psr\\Http\\Message\\ServerRequestInterface $request\n" +" * @var \\Psr\\Http\\Server\\RequestHandlerInterface $handler\n" +" * @var \\Psr\\Log\\LoggerInterface $logger\n" +" */\n" +"\n" +"// The secret key used to sign and validate cookies.\n" +"$key = '0my1xVkjCJnD_q1yr6lUxcAdpDlTMwiU';\n" +"$signer = new \\Yiisoft\\Cookies\\CookieSigner($key);\n" +"$encryptor = new \\Yiisoft\\Cookies\\CookieEncryptor($key);\n" +"\n" +"$cookiesSettings = [\n" +" 'identity' => \\Yiisoft\\Cookies\\CookieMiddleware::ENCRYPT,\n" +" 'session' => \\Yiisoft\\Cookies\\CookieMiddleware::SIGN,\n" +"];\n" +"\n" +"$middleware = new \\Yiisoft\\Cookies\\CookieMiddleware(\n" +" $logger\n" +" $encryptor,\n" +" $signer,\n" +" $cookiesSettings,\n" +");\n" +"\n" +"// The cookie parameter values from the request are decrypted/validated.\n" +"// The cookie values are encrypted/signed and appended to the response.\n" +"$response = $middleware->process($request, $handler);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"If the `$cookiesSettings` array is empty, no cookies will be encrypted and " +"signed." +msgstr "" + +#. type: Title ## +#: en/runtime/cookies.md +#, no-wrap +msgid "Cookies security" +msgstr "" + +#. type: Plain text +#: en/runtime/cookies.md +msgid "" +"You should configure each cookie to be secure. Important security settings " +"are:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "" +"`httpOnly`. Setting it to `true` would prevent JavaScript to access cookie " +"value." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "" +"`secure`. Setting it to `true` would prevent sending cookie via `HTTP`. It " +"will be sent via `HTTPS` only." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "" +"`sameSite`, if set to either `SAME_SITE_LAX` or `SAME_SITE_STRICT` would " +"prevent sending a cookie in cross-site browsing context. `SAME_SITE_LAX` " +"would prevent cookie sending during CSRF-prone request methods (e.g., POST, " +"PUT, PATCH, etc.). `SAME_SITE_STRICT` would prevent cookies sending for all " +"methods." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/cookies.md +msgid "" +"Sign or encrypt the value of the cookie to prevent spoofing of values if the " +"data in the value shouldn't be tampered with." +msgstr "" diff --git a/guide/po/runtime_handling-errors.md/ru/runtime_handling-errors.md.ru.po b/guide/po/runtime_handling-errors.md/ru/runtime_handling-errors.md.ru.po new file mode 100644 index 00000000..b6b7d095 --- /dev/null +++ b/guide/po/runtime_handling-errors.md/ru/runtime_handling-errors.md.ru.po @@ -0,0 +1,444 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/runtime/handling-errors.md +#, no-wrap +msgid "Handling errors" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Yii has a [yiisoft/error-handler](https://github.com/yiisoft/error-handler) package that makes error handling a much more pleasant experience than before. In particular, the Yii error handler provides the following:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "[PSR-15](https://www.php-fig.org/psr/psr-15/) middleware for catching unhandled errors." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "PSR-15 middleware for mapping certain exceptions to custom responses." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "Production and debug modes." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "Debug mode displays details, stacktrace, has dark and light themes and handy buttons to search for error without typing." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "Takes PHP settings into account." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "Handles out of memory errors, fatal errors, warnings, notices, and exceptions." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "Can use any [PSR-3](https://www.php-fig.org/psr/psr-3/) compatible logger for error logging." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "Detects a response format based on a mime type of the request." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "Supports responding with HTML, plain text, JSON, XML, and headers out of the box." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "You can implement your own error rendering for extra types." +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "This guide describes how to use the error handler in the [Yii framework](https://www.yiiframework.com/), for information about using it separate from Yii, see the [package description](https://github.com/yiisoft/error-handler)." +msgstr "" + +#. type: Title ## +#: en/runtime/handling-errors.md +#, no-wrap +msgid "Using error handler" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "The error handler consists of two parts. One part is `Yiisoft\\ErrorHandler\\Middleware\\ErrorCatcher` middleware that, when registered, catches exceptions that may appear during middleware stack execution and passes them to the handler. Another part is the error handler itself, `Yiisoft\\ErrorHandler\\ErrorHandler`, that's catching exceptions occurring outside the middleware stack and fatal errors. The handler also converts warnings and notices to exceptions and does more handy things." +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Error handler is registered in the application itself. Usually it happens in `ApplicationRunner`. By default, the handler configuration comes from the container. You may configure it in the application configuration, `config/web.php` like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"use Psr\\Log\\LoggerInterface;\n" +"use Yiisoft\\ErrorHandler\\ErrorHandler;\n" +"use Yiisoft\\ErrorHandler\\Renderer\\HtmlRenderer;\n" +"use Yiisoft\\ErrorHandler\\ThrowableRendererInterface;\n" +"\n" +"return [\n" +" // ...\n" +" ErrorHandler::class => static function (LoggerInterface $logger, ThrowableRendererInterface $renderer) {\n" +" $errorHandler = new ErrorHandler($logger, $renderer);\n" +" // Set the size of the reserved memory to 512 KB. Defaults to 256KB.\n" +" $errorHandler->memoryReserveSize(524_288);\n" +" return $errorHandler;\n" +" },\n" +" \n" +" ThrowableRendererInterface::class => static fn () => new HtmlRenderer([\n" +" // Defaults to the package file \"templates/production.php\".\n" +" 'template' => '/full/path/to/production/template/file',\n" +" // Defaults to package file \"templates/development.php\".\n" +" 'verboseTemplate' => '/full/path/to/development/template/file',\n" +" // Maximum number of source code lines to be displayed. Defaults to 19.\n" +" 'maxSourceLines' => 20,\n" +" // Maximum number of trace source code lines to be displayed. Defaults to 13.\n" +" 'maxTraceLines' => 5,\n" +" // Trace the header line with placeholders (file, line, icon) to be substituted. Defaults to `null`.\n" +" 'traceHeaderLine' => '{icon}',\n" +" ]),\n" +" // ...\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "As aforementioned, the error handler turns all non-fatal PHP errors into catchable exceptions (`Yiisoft\\ErrorHandler\\Exception\\ErrorException`). This means you can use the following code to deal with PHP errors:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"try {\n" +" 10 / 0;\n" +"} catch (\\Yiisoft\\ErrorHandler\\Exception\\ErrorException $e) {\n" +" // Write a log or something else.\n" +"}\n" +"// execution continues...\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "The package has another middleware, `Yiisoft\\ErrorHandler\\Middleware\\ExceptionResponder`. This middleware maps certain exceptions to custom responses. Configure it in the application configuration as follows:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"use Psr\\Http\\Message\\ResponseFactoryInterface;\n" +"use Yiisoft\\ErrorHandler\\Middleware\\ExceptionResponder;\n" +"use Yiisoft\\Injector\\Injector;\n" +"\n" +"return [\n" +" // ...\n" +" ErrorHandler::class => static function (ResponseFactoryInterface $responseFactory, Injector $injector) {\n" +" $exceptionMap = [\n" +" // Status code with which the factory creates the response.\n" +" MyNotFoundException::class => 404,\n" +" // PHP callable that must return a `Psr\\Http\\Message\\ResponseInterface`.\n" +" MyHttpException::class => static fn (MyHttpException $exception) => new MyResponse($exception),\n" +" // ...\n" +" ],\n" +" \n" +" return new ExceptionResponder($exceptionMap, $responseFactory, $injector);\n" +" },\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Note that when configuring application middleware stack, you must place `Yiisoft\\ErrorHandler\\Middleware\\ExceptionResponder` before `Yiisoft\\ErrorHandler\\Middleware\\ErrorCatcher`." +msgstr "" + +#. type: Title ## +#: en/runtime/handling-errors.md +#, fuzzy, no-wrap +#| msgid "Generating random data" +msgid "Rendering error data" +msgstr "Генерация случайных данных" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "One of the renderers could render error data into a certain format. The following renderers are available out of the box:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "`Yiisoft\\ErrorHandler\\Renderer\\HeaderRenderer` - Renders error into HTTP headers. It's used for `HEAD` request." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "`Yiisoft\\ErrorHandler\\Renderer\\HtmlRenderer` - Renders error into HTML." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "`Yiisoft\\ErrorHandler\\Renderer\\JsonRenderer` - Renders error into JSON." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "`Yiisoft\\ErrorHandler\\Renderer\\PlainTextRenderer` - Renders error into plain text." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "`Yiisoft\\ErrorHandler\\Renderer\\XmlRenderer` - Renders error into XML." +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "The renderer produces detailed error data depending on whether debug mode is enabled or disabled." +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "An Example of header rendering with a debugging mode turned off:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"...\n" +"X-Error-Message: An internal server error occurred.\n" +"...\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "An Example of header rendering with a debugging mode turned on:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"...\n" +"X-Error-Type: Error\n" +"X-Error-Message: Call to undefined function App\\Controller\\myFunc()\n" +"X-Error-Code: 0\n" +"X-Error-File: /var/www/yii/app/src/Controller/SiteController.php\n" +"X-Error-Line: 21\n" +"...\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Example of JSON rendering output with a debugging mode turned off:" +msgstr "" + +#. type: Fenced code block (json) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "{\"message\":\"An internal server error occurred.\"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "An Example of JSON rendering output with debugging mode turned on:" +msgstr "" + +#. type: Fenced code block (json) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"{\n" +" \"type\": \"Error\",\n" +" \"message\": \"Call to undefined function App\\\\Controller\\\\myFunc()\",\n" +" \"code\": 0,\n" +" \"file\": \"/var/www/yii/app/src/Controller/SiteController.php\",\n" +" \"line\": 21,\n" +" \"trace\": [\n" +" {\n" +" \"function\": \"index\",\n" +" \"class\": \"App\\\\Controller\\\\SiteController\",\n" +" \"type\": \"->\"\n" +" },\n" +" {\n" +" \"file\": \"/var/www/yii/app/vendor/yiisoft/injector/src/Injector.php\",\n" +" \"line\": 63,\n" +" \"function\": \"invokeArgs\",\n" +" \"class\": \"ReflectionFunction\",\n" +" \"type\": \"->\"\n" +" },\n" +" ...\n" +" ]\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Example of HTML rendering with debugging mode turned off:" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "![View production](img/view-production.png)" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Example of HTML rendering with debugging mode on and a light theme:" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "![View development with light theme](img/view-development-light.png)" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Example of HTML rendering with debugging mode on and a dark theme:" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "![View development with dark theme](img/view-development-dark.png)" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "The error catcher chooses how to render an exception based on `accept` HTTP header. If it's `text/html` or any unknown content type, it will use the error or exception HTML template to display errors. For other mime types, the error handler will choose different renderers that you register within the error catcher. By default, it supports JSON, XML, and plain text." +msgstr "" + +#. type: Title ### +#: en/runtime/handling-errors.md +#, no-wrap +msgid "Implementing your own renderer" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "You may customize the error response format by providing your own instance of `Yiisoft\\ErrorHandler\\ThrowableRendererInterface` when registering error catcher middleware." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"use Psr\\Http\\Message\\ServerRequestInterface;\n" +"use Yiisoft\\ErrorHandler\\ErrorData;\n" +"use Yiisoft\\ErrorHandler\\ThrowableRendererInterface;\n" +"\n" +"final readonly class MyRenderer implements ThrowableRendererInterface\n" +"{\n" +" public function render(Throwable $t, ServerRequestInterface $request = null): ErrorData\n" +" {\n" +" return new ErrorData($t->getMessage());\n" +" }\n" +"\n" +" public function renderVerbose(Throwable $t, ServerRequestInterface $request = null): ErrorData\n" +" {\n" +" return new ErrorData(\n" +" $t->getMessage(),\n" +" ['X-Custom-Header' => 'value-header'], // Headers to be added to the response.\n" +" );\n" +" }\n" +"};\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +#, fuzzy +#| msgid "You can define an alias via application's `config/params.php`:" +msgid "You may configure it in the application configuration `config/web.php`:" +msgstr "Вы можете определить какой-либо псевдоним через `config/params.php` приложения:" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"use Psr\\Container\\ContainerInterface;\n" +"use Psr\\Http\\Message\\ResponseFactoryInterface;\n" +"use Yiisoft\\ErrorHandler\\ErrorHandler;\n" +"use Yiisoft\\ErrorHandler\\Middleware\\ErrorCatcher;\n" +"\n" +"return [\n" +" // ...\n" +" ErrorCatcher::class => static function (ContainerInterface $container): ErrorCatcher {\n" +" $errorCatcher = new ErrorCatcher(\n" +" $container->get(ResponseFactoryInterface::class),\n" +" $container->get(ErrorHandler::class),\n" +" $container,\n" +" );\n" +" // Returns a new instance without renderers by the specified content types.\n" +" $errorCatcher = $errorCatcher->withoutRenderers('application/xml', 'text/xml');\n" +" // Returns a new instance with the specified content type and renderer class.\n" +" return $errorCatcher->withRenderer('my/format', new MyRenderer());\n" +" },\n" +" // ...\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/runtime/handling-errors.md +#, no-wrap +msgid "Friendly exceptions" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Yii error renderer supports [friendly exceptions](https://github.com/yiisoft/friendly-exception) that make error handling an even more pleasant experience for your team. The idea is to offer a readable name and possible solutions to the problem:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"use Yiisoft\\FriendlyException\\FriendlyExceptionInterface;\n" +"\n" +"final readonly class RequestTimeoutException extends \\RuntimeException implements FriendlyExceptionInterface\n" +"{\n" +" public function getName(): string\n" +" {\n" +" return 'Request timed out';\n" +" }\n" +" \n" +" public function getSolution(): ?string\n" +" {\n" +" return <<<'SOLUTION'\n" +"Likely it is a result of resource request is not responding in a timely fashion. Try increasing timeout.\n" +"SOLUTION;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "When the application throws such an exception, the error renderer would display the name and the solution if the debug mode is on." +msgstr "" diff --git a/guide/po/runtime_handling-errors.md/runtime_handling-errors.md.pot b/guide/po/runtime_handling-errors.md/runtime_handling-errors.md.pot new file mode 100644 index 00000000..1bcb9cdb --- /dev/null +++ b/guide/po/runtime_handling-errors.md/runtime_handling-errors.md.pot @@ -0,0 +1,504 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/runtime/handling-errors.md +#, no-wrap +msgid "Handling errors" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"Yii has a [yiisoft/error-handler](https://github.com/yiisoft/error-handler) " +"package that makes error handling a much more pleasant experience than " +"before. In particular, the Yii error handler provides the following:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "" +"[PSR-15](https://www.php-fig.org/psr/psr-15/) middleware for catching " +"unhandled errors." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "PSR-15 middleware for mapping certain exceptions to custom responses." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "Production and debug modes." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "" +"Debug mode displays details, stacktrace, has dark and light themes and handy " +"buttons to search for error without typing." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "Takes PHP settings into account." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "" +"Handles out of memory errors, fatal errors, warnings, notices, and " +"exceptions." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "" +"Can use any [PSR-3](https://www.php-fig.org/psr/psr-3/) compatible logger " +"for error logging." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "Detects a response format based on a mime type of the request." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "" +"Supports responding with HTML, plain text, JSON, XML, and headers out of the " +"box." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "You can implement your own error rendering for extra types." +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"This guide describes how to use the error handler in the [Yii framework]" +"(https://www.yiiframework.com/), for information about using it separate " +"from Yii, see the [package description](https://github.com/yiisoft/error-" +"handler)." +msgstr "" + +#. type: Title ## +#: en/runtime/handling-errors.md +#, no-wrap +msgid "Using error handler" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"The error handler consists of two parts. One part is " +"`Yiisoft\\ErrorHandler\\Middleware\\ErrorCatcher` middleware that, when " +"registered, catches exceptions that may appear during middleware stack " +"execution and passes them to the handler. Another part is the error handler " +"itself, `Yiisoft\\ErrorHandler\\ErrorHandler`, that's catching exceptions " +"occurring outside the middleware stack and fatal errors. The handler also " +"converts warnings and notices to exceptions and does more handy things." +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"Error handler is registered in the application itself. Usually it happens in " +"`ApplicationRunner`. By default, the handler configuration comes from the " +"container. You may configure it in the application configuration, `config/" +"web.php` like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"use Psr\\Log\\LoggerInterface;\n" +"use Yiisoft\\ErrorHandler\\ErrorHandler;\n" +"use Yiisoft\\ErrorHandler\\Renderer\\HtmlRenderer;\n" +"use Yiisoft\\ErrorHandler\\ThrowableRendererInterface;\n" +"\n" +"return [\n" +" // ...\n" +" ErrorHandler::class => static function (LoggerInterface $logger, ThrowableRendererInterface $renderer) {\n" +" $errorHandler = new ErrorHandler($logger, $renderer);\n" +" // Set the size of the reserved memory to 512 KB. Defaults to 256KB.\n" +" $errorHandler->memoryReserveSize(524_288);\n" +" return $errorHandler;\n" +" },\n" +" \n" +" ThrowableRendererInterface::class => static fn () => new HtmlRenderer([\n" +" // Defaults to the package file \"templates/production.php\".\n" +" 'template' => '/full/path/to/production/template/file',\n" +" // Defaults to package file \"templates/development.php\".\n" +" 'verboseTemplate' => '/full/path/to/development/template/file',\n" +" // Maximum number of source code lines to be displayed. Defaults to 19.\n" +" 'maxSourceLines' => 20,\n" +" // Maximum number of trace source code lines to be displayed. Defaults to 13.\n" +" 'maxTraceLines' => 5,\n" +" // Trace the header line with placeholders (file, line, icon) to be substituted. Defaults to `null`.\n" +" 'traceHeaderLine' => '{icon}',\n" +" ]),\n" +" // ...\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"As aforementioned, the error handler turns all non-fatal PHP errors into " +"catchable exceptions (`Yiisoft\\ErrorHandler\\Exception\\ErrorException`). " +"This means you can use the following code to deal with PHP errors:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"try {\n" +" 10 / 0;\n" +"} catch (\\Yiisoft\\ErrorHandler\\Exception\\ErrorException $e) {\n" +" // Write a log or something else.\n" +"}\n" +"// execution continues...\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"The package has another middleware, " +"`Yiisoft\\ErrorHandler\\Middleware\\ExceptionResponder`. This middleware " +"maps certain exceptions to custom responses. Configure it in the application " +"configuration as follows:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"use Psr\\Http\\Message\\ResponseFactoryInterface;\n" +"use Yiisoft\\ErrorHandler\\Middleware\\ExceptionResponder;\n" +"use Yiisoft\\Injector\\Injector;\n" +"\n" +"return [\n" +" // ...\n" +" ErrorHandler::class => static function (ResponseFactoryInterface $responseFactory, Injector $injector) {\n" +" $exceptionMap = [\n" +" // Status code with which the factory creates the response.\n" +" MyNotFoundException::class => 404,\n" +" // PHP callable that must return a `Psr\\Http\\Message\\ResponseInterface`.\n" +" MyHttpException::class => static fn (MyHttpException $exception) => new MyResponse($exception),\n" +" // ...\n" +" ],\n" +" \n" +" return new ExceptionResponder($exceptionMap, $responseFactory, $injector);\n" +" },\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"Note that when configuring application middleware stack, you must place " +"`Yiisoft\\ErrorHandler\\Middleware\\ExceptionResponder` before " +"`Yiisoft\\ErrorHandler\\Middleware\\ErrorCatcher`." +msgstr "" + +#. type: Title ## +#: en/runtime/handling-errors.md +#, no-wrap +msgid "Rendering error data" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"One of the renderers could render error data into a certain format. The " +"following renderers are available out of the box:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "" +"`Yiisoft\\ErrorHandler\\Renderer\\HeaderRenderer` - Renders error into HTTP " +"headers. It's used for `HEAD` request." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "" +"`Yiisoft\\ErrorHandler\\Renderer\\HtmlRenderer` - Renders error into HTML." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "" +"`Yiisoft\\ErrorHandler\\Renderer\\JsonRenderer` - Renders error into JSON." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "" +"`Yiisoft\\ErrorHandler\\Renderer\\PlainTextRenderer` - Renders error into " +"plain text." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/handling-errors.md +msgid "" +"`Yiisoft\\ErrorHandler\\Renderer\\XmlRenderer` - Renders error into XML." +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"The renderer produces detailed error data depending on whether debug mode is " +"enabled or disabled." +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "An Example of header rendering with a debugging mode turned off:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"...\n" +"X-Error-Message: An internal server error occurred.\n" +"...\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "An Example of header rendering with a debugging mode turned on:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"...\n" +"X-Error-Type: Error\n" +"X-Error-Message: Call to undefined function App\\Controller\\myFunc()\n" +"X-Error-Code: 0\n" +"X-Error-File: /var/www/yii/app/src/Controller/SiteController.php\n" +"X-Error-Line: 21\n" +"...\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Example of JSON rendering output with a debugging mode turned off:" +msgstr "" + +#. type: Fenced code block (json) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "{\"message\":\"An internal server error occurred.\"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "An Example of JSON rendering output with debugging mode turned on:" +msgstr "" + +#. type: Fenced code block (json) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"{\n" +" \"type\": \"Error\",\n" +" \"message\": \"Call to undefined function App\\\\Controller\\\\myFunc()\",\n" +" \"code\": 0,\n" +" \"file\": \"/var/www/yii/app/src/Controller/SiteController.php\",\n" +" \"line\": 21,\n" +" \"trace\": [\n" +" {\n" +" \"function\": \"index\",\n" +" \"class\": \"App\\\\Controller\\\\SiteController\",\n" +" \"type\": \"->\"\n" +" },\n" +" {\n" +" \"file\": \"/var/www/yii/app/vendor/yiisoft/injector/src/Injector.php\",\n" +" \"line\": 63,\n" +" \"function\": \"invokeArgs\",\n" +" \"class\": \"ReflectionFunction\",\n" +" \"type\": \"->\"\n" +" },\n" +" ...\n" +" ]\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Example of HTML rendering with debugging mode turned off:" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "![View production](img/view-production.png)" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Example of HTML rendering with debugging mode on and a light theme:" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "![View development with light theme](img/view-development-light.png)" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "Example of HTML rendering with debugging mode on and a dark theme:" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "![View development with dark theme](img/view-development-dark.png)" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"The error catcher chooses how to render an exception based on `accept` HTTP " +"header. If it's `text/html` or any unknown content type, it will use the " +"error or exception HTML template to display errors. For other mime types, " +"the error handler will choose different renderers that you register within " +"the error catcher. By default, it supports JSON, XML, and plain text." +msgstr "" + +#. type: Title ### +#: en/runtime/handling-errors.md +#, no-wrap +msgid "Implementing your own renderer" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"You may customize the error response format by providing your own instance " +"of `Yiisoft\\ErrorHandler\\ThrowableRendererInterface` when registering " +"error catcher middleware." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"use Psr\\Http\\Message\\ServerRequestInterface;\n" +"use Yiisoft\\ErrorHandler\\ErrorData;\n" +"use Yiisoft\\ErrorHandler\\ThrowableRendererInterface;\n" +"\n" +"final readonly class MyRenderer implements ThrowableRendererInterface\n" +"{\n" +" public function render(Throwable $t, ServerRequestInterface $request = null): ErrorData\n" +" {\n" +" return new ErrorData($t->getMessage());\n" +" }\n" +"\n" +" public function renderVerbose(Throwable $t, ServerRequestInterface $request = null): ErrorData\n" +" {\n" +" return new ErrorData(\n" +" $t->getMessage(),\n" +" ['X-Custom-Header' => 'value-header'], // Headers to be added to the response.\n" +" );\n" +" }\n" +"};\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "You may configure it in the application configuration `config/web.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"use Psr\\Container\\ContainerInterface;\n" +"use Psr\\Http\\Message\\ResponseFactoryInterface;\n" +"use Yiisoft\\ErrorHandler\\ErrorHandler;\n" +"use Yiisoft\\ErrorHandler\\Middleware\\ErrorCatcher;\n" +"\n" +"return [\n" +" // ...\n" +" ErrorCatcher::class => static function (ContainerInterface $container): ErrorCatcher {\n" +" $errorCatcher = new ErrorCatcher(\n" +" $container->get(ResponseFactoryInterface::class),\n" +" $container->get(ErrorHandler::class),\n" +" $container,\n" +" );\n" +" // Returns a new instance without renderers by the specified content types.\n" +" $errorCatcher = $errorCatcher->withoutRenderers('application/xml', 'text/xml');\n" +" // Returns a new instance with the specified content type and renderer class.\n" +" return $errorCatcher->withRenderer('my/format', new MyRenderer());\n" +" },\n" +" // ...\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/runtime/handling-errors.md +#, no-wrap +msgid "Friendly exceptions" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"Yii error renderer supports [friendly exceptions](https://github.com/yiisoft/" +"friendly-exception) that make error handling an even more pleasant " +"experience for your team. The idea is to offer a readable name and possible " +"solutions to the problem:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/handling-errors.md +#, no-wrap +msgid "" +"use Yiisoft\\FriendlyException\\FriendlyExceptionInterface;\n" +"\n" +"final readonly class RequestTimeoutException extends \\RuntimeException implements FriendlyExceptionInterface\n" +"{\n" +" public function getName(): string\n" +" {\n" +" return 'Request timed out';\n" +" }\n" +" \n" +" public function getSolution(): ?string\n" +" {\n" +" return <<<'SOLUTION'\n" +"Likely it is a result of resource request is not responding in a timely fashion. Try increasing timeout.\n" +"SOLUTION;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/handling-errors.md +msgid "" +"When the application throws such an exception, the error renderer would " +"display the name and the solution if the debug mode is on." +msgstr "" diff --git a/guide/po/runtime_logging.md/ru/runtime_logging.md.ru.po b/guide/po/runtime_logging.md/ru/runtime_logging.md.ru.po new file mode 100644 index 00000000..0a8f7c0b --- /dev/null +++ b/guide/po/runtime_logging.md/ru/runtime_logging.md.ru.po @@ -0,0 +1,650 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/runtime/logging.md +#, no-wrap +msgid "Logging" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "Yii relies on [PSR-3 interfaces](https://www.php-fig.org/psr/psr-3/) for logging, so you could configure any PSR-3 compatible logging library to do the actual job." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "Yii provides its own logger that's highly customizable and extensible. Using it, you can log various types of messages, filter them, and gather them at different targets, such as files or emails." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "Using the Yii logging framework involves the following steps:" +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "Record [log messages](#log-messages) at various places in your code;" +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "Configure [log targets](#log-targets) in the application configuration to filter and export log messages;" +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "Examine the filtered logged messages exported by different targets (e.g. the [Yii debugger](../tool/debugger.md))." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "In this section, the focus in on the first two steps." +msgstr "" + +#. type: Title ## +#: en/runtime/logging.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Log Messages " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/runtime/logging.md +msgid "To record log messages, you need an instance of PSR-3 logger. A class that writes log messages should receive it as a dependency:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"class MyService\n" +"{\n" +" private $logger;\n" +" \n" +" public function __construct(\\Psr\\Log\\LoggerInterface $logger)\n" +" {\n" +" $this->logger = $logger; \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "Recording a log message is as simple as calling one of the following logging methods that correspond to log levels:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`emergency` - System is unusable." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`alert` - Action must be taken immediately. Example: Entire website down, database unavailable, etc. This should trigger the SMS alerts and wake you up." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`critical` - Critical conditions. Example: Application component unavailable, unexpected exception." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`error` - Runtime errors that don't require immediate action but should typically be logged and monitored." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`warning` - Exceptional occurrences that aren't errors. Example: Use of deprecated APIs, poor use of an API, undesirable things that aren't necessarily wrong." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`notice` - Normal but significant events." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`info` - Interesting events. Example: User logs in, SQL logs." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`debug` - Detailed debug information." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "Each method has two arguments. The first is a message. The Second is a context array that typically has structured data that doesn't fit a message well but still does offer important information. In case you provide an exception as context, you should pass the \"exception\" key. Another special key is \"category.\" Categories are handy to better organize and filter log messages." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"use \\Psr\\Log\\LoggerInterface;\n" +"\n" +"final readonly class MyService\n" +"{\n" +" public function __construct(\n" +" private LoggerInterface $logger\n" +" )\n" +" { \n" +" }\n" +"\n" +" public function serve(): void\n" +" {\n" +" $this->logger->info('MyService is serving', ['context' => __METHOD__]); \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "When deciding on a category for a message, you may choose a hierarchical naming scheme, which will make it easier for [log targets](#log-targets) to filter messages based on their categories. A simple yet effective naming scheme is to use the PHP magic constant `__METHOD__` for the category names. This is also the approach used in the core Yii framework code." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "The `__METHOD__` constant evaluates as the name of the method (prefixed with the fully qualified class name) where the constant appears. For example, it's equal to the string `'App\\\\Service\\\\MyService::serve'` if the above line of code is called within this method." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"> [!IMPORTANT]\n" +"> The logging methods described above are actually shortcuts to the [[\\Psr\\Log\\LoggerInterface::log()]].\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "Note that PSR-3 package provides `\\Psr\\Log\\NullLogger` class that provides the same set of methods but doesn't log anything. That means that you don't have to check if logger is configured with `if ($logger !== null)` and, instead, can assume that logger is always present." +msgstr "" + +#. type: Title ## +#: en/runtime/logging.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Log targets " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/runtime/logging.md +msgid "A log target is an instance of a class that extends the [[\\Yiisoft\\Log\\Target]]. It filters the log messages by their severity levels and categories and then exports them to some medium. For example, a [[\\Yiisoft\\Log\\Target\\File\\FileTarget|file target]]exports the filtered log messages to a file, while a [[Yiisoft\\Log\\Target\\Email\\EmailTarget|email target]] exports the log messages to specified email addresses." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "You can register many log targets in an application by configuring them through the `\\Yiisoft\\Log\\Logger` constructor:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"use \\Psr\\Log\\LogLevel;\n" +"\n" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$fileTarget->setLevels([LogLevel::ERROR, LogLevel::WARNING]);\n" +"\n" +"$emailTarget = new \\Yiisoft\\Log\\Target\\Email\\EmailTarget($mailer, ['to' => 'log@example.com']);\n" +"$emailTarget->setLevels([LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL]);\n" +"$emailTarget->setCategories(['Yiisoft\\Cache\\*']); \n" +"\n" +"$logger = new \\Yiisoft\\Log\\Logger([\n" +" $fileTarget,\n" +" $emailTarget\n" +"]);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "In the above code, two log targets are registered:" +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "the first target selects error and warning messages and writes them to `/path/to/app.log` file;" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"* the second target selects emergency, alert, and critical messages under the categories whose names start with\n" +"`Yiisoft\\Cache\\`, and sends them in an email to both `admin@example.com` and `developer@example.com`.\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "Yii comes with the following built-in log targets. Please refer to the API documentation about these classes to learn how to configure and use them." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "[[\\Yiisoft\\Log\\PsrTarget]]: passes log messages to another PSR-3 compatible logger." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "[[\\Yiisoft\\Log\\StreamTarget]]: writes log messages into a specified output stream." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "[[\\Yiisoft\\Log\\Target\\Db\\DbTarget]]: saves log messages in database." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "[[\\Yiisoft\\Log\\Target\\Email\\EmailTarget]]: sends log messages to pre-specified email addresses." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "[[\\Yiisoft\\Log\\Target\\File\\FileTarget]]: saves log messages in files." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "[[\\Yiisoft\\Log\\Target\\Syslog\\SyslogTarget]]: saves log messages to syslog by calling the PHP function `syslog()`." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "In the following, we will describe the features common to all log targets." +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, fuzzy, no-wrap +#| msgid "References " +msgid "Message Filtering " +msgstr "Полезные ссылки " + +#. type: Plain text +#: en/runtime/logging.md +msgid "For each log target, you can configure its levels and categories to specify which severity levels and categories of the messages the target should process." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "The target `setLevels()` method takes an array consisting of one or several of `\\Psr\\Log\\LogLevel` constants." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "By default, the target will process messages of *any* severity level." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "The target `setCategories()` method takes an array consisting of message category names or patterns. A target will only process messages whose category can be found or match one of the patterns in this array. A category pattern is a category name prefix with an asterisk `*` at its end. A category name matches a category pattern if it starts with the same prefix of the pattern. For example, `Yiisoft\\Cache\\Cache::set` and `Yiisoft\\Cache\\Cache::get` both match the pattern `Yiisoft\\Cache\\*`." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "By default, the target will process messages of *any* category." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "Besides allowing the categories by the `setCategories()` method, you may also deny certain categories by the `setExcept()` method. If the category of a message is found or matches one of the patterns in this property, the target will NOT process it." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "The following target configuration specifies that the target should only process error and warning messages under the categories whose names match either `Yiisoft\\Cache\\*` or `App\\Exceptions\\HttpException:*`, but not `App\\Exceptions\\HttpException:404`." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$fileTarget->setLevels([LogLevel::ERROR, LogLevel::WARNING]);\n" +"$fileTarget->setCategories(['Yiisoft\\Cache\\*', 'App\\Exceptions\\HttpException:*']);\n" +"$fileTarget->setExcept(['App\\Exceptions\\HttpException:404']);\n" +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, fuzzy, no-wrap +#| msgid "DI container " +msgid "Message Formatting " +msgstr "Контейнер внедрения зависимостей " + +#. type: Plain text +#: en/runtime/logging.md +msgid "Log targets export the filtered log messages in a certain format. For example, if you install a log target of the class [[\\Yiisoft\\Log\\Target\\File\\FileTarget]], you may find a log message similar to the following in the log file:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/logging.md +#, no-wrap +msgid "" +"2020-12-05 09:27:52.223800 [info][application] Some message\n" +"\n" +"Message context:\n" +"\n" +"time: 1607160472.2238\n" +"memory: 4398536\n" +"category: 'application'\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "By default, log messages have the following format:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/logging.md +#, no-wrap +msgid "Timestamp Prefix[Level][Category] Message Context\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "You may customize this format by calling [[\\Yiisoft\\Log\\Target::setFormat()|setFormat()]] method, which takes a PHP callable returning a custom-formatted message." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"\n" +"$fileTarget->setFormat(static function (\\Yiisoft\\Log\\Message $message) {\n" +" $category = strtoupper($message->context('category'));\n" +" return \"({$category}) [{$message->level()}] {$message->message()}\";\n" +"});\n" +"\n" +"$logger = new \\Yiisoft\\Log\\Logger([$fileTarget]);\n" +"$logger->info('Text message', ['category' => 'app']);\n" +"\n" +"// Result:\n" +"// (APP) [info] Text message\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "In addition, if you're comfortable with the default message format but need to change the timestamp format or add custom data to the message, you can call the [[\\Yiisoft\\Log\\Target::setTimestampFormat()|setTimestampFormat()]] and [[\\Yiisoft\\Log\\Target::setPrefix()|setPrefix()]] methods. For example, the following code changes the timestamp format and configures a log target to prefix each log message with the current user ID (IP address and Session ID are removed for privacy reasons)." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$userId = '123e4567-e89b-12d3-a456-426655440000';\n" +"\n" +"// Default: 'Y-m-d H: i: s.u'\n" +"$fileTarget->setTimestampFormat('D d F Y');\n" +"// Default: ''\n" +"$fileTarget->setPrefix(static fn () => \"[{$userId}]\");\n" +"\n" +"$logger = new \\Yiisoft\\Log\\Logger([$fileTarget]);\n" +"$logger->info('Text', ['category' => 'user']);\n" +"\n" +"// Result:\n" +"// Fri 04 December 2020 [123e4567-e89b-12d3-a456-426655440000][info][user] Text\n" +"// Message context: ...\n" +"// Common context: ...\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "The PHP callable that's passed to the [[\\Yiisoft\\Log\\Target::setFormat()|setFormat()]] and [[\\Yiisoft\\Log\\Target::setPrefix()|setPrefix()]] methods has the following signature:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "function (\\Yiisoft\\Log\\Message $message, array $commonContext): string;\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"Besides message prefixes, log targets also append some common context information to each of the log messages.\n" +"You may adjust this behavior by calling target [[\\Yiisoft\\Log\\Target::setCommonContext()|setCommonContext()]]\n" +"method, passing an array of data in the `key => value` format that you want to include.\n" +"For example, the following log target configuration specifies that only the\n" +"value of the `$_SERVER` variable will be appended to the log messages.\n" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$fileTarget->setCommonContext(['server' => $_SERVER]);\n" +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, fuzzy, no-wrap +#| msgid "References " +msgid "Message Trace Level " +msgstr "Полезные ссылки " + +#. type: Plain text +#: en/runtime/logging.md +msgid "During development, it's often desirable to see where each log message is coming from. You can achieve this by calling the [[\\Yiisoft\\Log\\Logger::setTraceLevel()|setTraceLevel()]] method like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$logger = new \\Yiisoft\\Log\\Logger($targets);\n" +"$logger->setTraceLevel(3);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "This application configuration sets the trace level to be 3, so each log message will be appended with at most three levels of the call stack at which the log message is recorded. You can also set a list of paths to exclude from the trace by calling the [[\\Yiisoft\\Log\\Logger::setExcludedTracePaths()|setExcludedTracePaths()]] method." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$logger = new \\Yiisoft\\Log\\Logger($targets);\n" +"$logger->setExcludedTracePaths(['/path/to/file', '/path/to/folder']);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"> [!IMPORTANT]\n" +"> Getting call stack information isn't trivial. Therefore, you should only use this feature during development\n" +"or when debugging an application.\n" +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, fuzzy, no-wrap +#| msgid "Configuring container " +msgid "Message flushing and exporting " +msgstr "Конфигурирование контейнера " + +#. type: Plain text +#: en/runtime/logging.md +msgid "As aforementioned, log messages are maintained in an array by [[\\Yiisoft\\Log\\Logger|logger object]]. To limit the memory consumption by this array, the logger will flush the recorded messages to the [log targets](#log-targets) each time the array accumulates a certain number of log messages. You can customize this number by calling the [[\\Yiisoft\\Log\\Logger::setFlushInterval()]] method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$logger = new \\Yiisoft\\Log\\Logger($targets);\n" +"$logger->setFlushInterval(100); // default is 1000\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"> [!IMPORTANT]\n" +"> Message flushing also occurs when the application ends,\n" +"which ensures log targets can receive complete log messages.\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"When the [[\\Yiisoft\\Log\\Logger|logger object]] flushes log messages to [log targets](#log-targets),\n" +"they don't get exported immediately. Instead, the message exporting only occurs when a log target\n" +" accumulates a certain number of the filtered messages. You can customize this number by calling the\n" +"[[\\Yiisoft\\Log\\Target::setExportInterval()|setExportInterval()]] method of individual\n" +"[log targets](#log-targets), like the following:\n" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$fileTarget->setExportInterval(100); // default is 1000\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "Because of the flushing and exporting level setting, by default when you call any logging method, you will NOT see the log message immediately in the log targets. This could be a problem for some long-running console applications. To make each log message appear immediately in the log targets, you should set both flush interval and export interval to be 1, as shown below:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$fileTarget->setExportInterval(1);\n" +"\n" +"$logger = new \\Yiisoft\\Log\\Logger([$fileTarget]);\n" +"$logger->setFlushInterval(1);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> Frequent message flushing and exporting will degrade the performance of your application.\n" +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Toggling log targets " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/runtime/logging.md +msgid "You can enable or disable a log target by calling its [[\\Yiisoft\\Log\\Target::enable()|enable()] ] and [[\\Yiisoft\\Log\\Target::disable()|disable()]] methods. You may do so via the log target configuration or by the following PHP statement in your code:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$logger = new \\Yiisoft\\Log\\Logger([$fileTarget, /*Other targets*/]);\n" +"\n" +"foreach ($logger->getTargets() as $target) {\n" +" if ($target instanceof \\Yiisoft\\Log\\Target\\File\\FileTarget) {\n" +" $target->disable();\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "To check whether the log target is enabled, call the `isEnabled()` method. You also may pass callable to [[\\Yiisoft\\Log\\Target::setEnabled()|setEnabled()]] to define a dynamic condition for whether the log target should be enabled or not." +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, fuzzy, no-wrap +#| msgid "Predefined aliases " +msgid "Creating new targets " +msgstr "Предопределенные псевдонимы " + +#. type: Plain text +#: en/runtime/logging.md +msgid "Creating a new log target class is straightforward. You mainly need to implement the [[\\Yii\\Log\\Target::export()]] abstract method that sends all accumulated log messages to a designated medium." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "The following protected methods will also be available for child targets:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`getMessages` - Get a list of log messages ([[\\Yii\\Log\\Message]] instances)." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`getFormattedMessages` - Get a list of log messages formatted as strings." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`formatMessages` - Get all log messages formatted as a string." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`getCommonContext` - Get an array with common context data in the `key => value` format." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "For more details, you may refer to any of the log target classes included in the package." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"> [!TIP]\n" +"> Instead of creating your own loggers, you may try any PSR-3 compatible logger such\n" +"as [Monolog](https://github.com/Seldaek/monolog) by using [[\\Yii\\Log\\PsrTarget]].\n" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"/**\n" +" * @var \\Psr\\Log\\LoggerInterface $psrLogger\n" +" */\n" +"\n" +"$psrTarget = new \\Yiisoft\\Log\\PsrTarget($psrLogger);\n" +"$logger = new \\Yiisoft\\Log\\Logger([$psrTarget]);\n" +"\n" +"$logger->info('Text message');\n" +msgstr "" diff --git a/guide/po/runtime_logging.md/runtime_logging.md.pot b/guide/po/runtime_logging.md/runtime_logging.md.pot new file mode 100644 index 00000000..bc5aa29b --- /dev/null +++ b/guide/po/runtime_logging.md/runtime_logging.md.pot @@ -0,0 +1,784 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/runtime/logging.md +#, no-wrap +msgid "Logging" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"Yii relies on [PSR-3 interfaces](https://www.php-fig.org/psr/psr-3/) for " +"logging, so you could configure any PSR-3 compatible logging library to do " +"the actual job." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"Yii provides its own logger that's highly customizable and extensible. " +"Using it, you can log various types of messages, filter them, and gather " +"them at different targets, such as files or emails." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "Using the Yii logging framework involves the following steps:" +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "Record [log messages](#log-messages) at various places in your code;" +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "" +"Configure [log targets](#log-targets) in the application configuration to " +"filter and export log messages;" +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "" +"Examine the filtered logged messages exported by different targets (e.g. the " +"[Yii debugger](../tool/debugger.md))." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "In this section, the focus in on the first two steps." +msgstr "" + +#. type: Title ## +#: en/runtime/logging.md +#, no-wrap +msgid "Log Messages " +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"To record log messages, you need an instance of PSR-3 logger. A class that " +"writes log messages should receive it as a dependency:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"class MyService\n" +"{\n" +" private $logger;\n" +" \n" +" public function __construct(\\Psr\\Log\\LoggerInterface $logger)\n" +" {\n" +" $this->logger = $logger; \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"Recording a log message is as simple as calling one of the following logging " +"methods that correspond to log levels:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`emergency` - System is unusable." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "" +"`alert` - Action must be taken immediately. Example: Entire website down, " +"database unavailable, etc. This should trigger the SMS alerts and wake you " +"up." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "" +"`critical` - Critical conditions. Example: Application component " +"unavailable, unexpected exception." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "" +"`error` - Runtime errors that don't require immediate action but should " +"typically be logged and monitored." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "" +"`warning` - Exceptional occurrences that aren't errors. Example: Use of " +"deprecated APIs, poor use of an API, undesirable things that aren't " +"necessarily wrong." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`notice` - Normal but significant events." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`info` - Interesting events. Example: User logs in, SQL logs." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`debug` - Detailed debug information." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"Each method has two arguments. The first is a message. The Second is a " +"context array that typically has structured data that doesn't fit a message " +"well but still does offer important information. In case you provide an " +"exception as context, you should pass the \"exception\" key. Another " +"special key is \"category.\" Categories are handy to better organize and " +"filter log messages." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"use \\Psr\\Log\\LoggerInterface;\n" +"\n" +"final readonly class MyService\n" +"{\n" +" public function __construct(\n" +" private LoggerInterface $logger\n" +" )\n" +" { \n" +" }\n" +"\n" +" public function serve(): void\n" +" {\n" +" $this->logger->info('MyService is serving', ['context' => __METHOD__]); \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"When deciding on a category for a message, you may choose a hierarchical " +"naming scheme, which will make it easier for [log targets](#log-targets) to " +"filter messages based on their categories. A simple yet effective naming " +"scheme is to use the PHP magic constant `__METHOD__` for the category names. " +"This is also the approach used in the core Yii framework code." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"The `__METHOD__` constant evaluates as the name of the method (prefixed with " +"the fully qualified class name) where the constant appears. For example, " +"it's equal to the string `'App\\\\Service\\\\MyService::serve'` if the above " +"line of code is called within this method." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"> [!IMPORTANT]\n" +"> The logging methods described above are actually shortcuts to the [[\\Psr\\Log\\LoggerInterface::log()]].\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"Note that PSR-3 package provides `\\Psr\\Log\\NullLogger` class that " +"provides the same set of methods but doesn't log anything. That means that " +"you don't have to check if logger is configured with `if ($logger !== null)` " +"and, instead, can assume that logger is always present." +msgstr "" + +#. type: Title ## +#: en/runtime/logging.md +#, no-wrap +msgid "Log targets " +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"A log target is an instance of a class that extends the " +"[[\\Yiisoft\\Log\\Target]]. It filters the log messages by their severity " +"levels and categories and then exports them to some medium. For example, a " +"[[\\Yiisoft\\Log\\Target\\File\\FileTarget|file target]]exports the filtered " +"log messages to a file, while a [[Yiisoft\\Log\\Target\\Email\\EmailTarget|" +"email target]] exports the log messages to specified email addresses." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"You can register many log targets in an application by configuring them " +"through the `\\Yiisoft\\Log\\Logger` constructor:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"use \\Psr\\Log\\LogLevel;\n" +"\n" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$fileTarget->setLevels([LogLevel::ERROR, LogLevel::WARNING]);\n" +"\n" +"$emailTarget = new \\Yiisoft\\Log\\Target\\Email\\EmailTarget($mailer, ['to' => 'log@example.com']);\n" +"$emailTarget->setLevels([LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL]);\n" +"$emailTarget->setCategories(['Yiisoft\\Cache\\*']); \n" +"\n" +"$logger = new \\Yiisoft\\Log\\Logger([\n" +" $fileTarget,\n" +" $emailTarget\n" +"]);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "In the above code, two log targets are registered:" +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "" +"the first target selects error and warning messages and writes them to `/" +"path/to/app.log` file;" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"* the second target selects emergency, alert, and critical messages under the categories whose names start with\n" +"`Yiisoft\\Cache\\`, and sends them in an email to both `admin@example.com` and `developer@example.com`.\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"Yii comes with the following built-in log targets. Please refer to the API " +"documentation about these classes to learn how to configure and use them." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "" +"[[\\Yiisoft\\Log\\PsrTarget]]: passes log messages to another PSR-3 " +"compatible logger." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "" +"[[\\Yiisoft\\Log\\StreamTarget]]: writes log messages into a specified " +"output stream." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "" +"[[\\Yiisoft\\Log\\Target\\Db\\DbTarget]]: saves log messages in database." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "" +"[[\\Yiisoft\\Log\\Target\\Email\\EmailTarget]]: sends log messages to pre-" +"specified email addresses." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "" +"[[\\Yiisoft\\Log\\Target\\File\\FileTarget]]: saves log messages in files." +msgstr "" + +#. type: Bullet: '* ' +#: en/runtime/logging.md +msgid "" +"[[\\Yiisoft\\Log\\Target\\Syslog\\SyslogTarget]]: saves log messages to " +"syslog by calling the PHP function `syslog()`." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"In the following, we will describe the features common to all log targets." +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, no-wrap +msgid "Message Filtering " +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"For each log target, you can configure its levels and categories to specify " +"which severity levels and categories of the messages the target should " +"process." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"The target `setLevels()` method takes an array consisting of one or several " +"of `\\Psr\\Log\\LogLevel` constants." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "By default, the target will process messages of *any* severity level." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"The target `setCategories()` method takes an array consisting of message " +"category names or patterns. A target will only process messages whose " +"category can be found or match one of the patterns in this array. A " +"category pattern is a category name prefix with an asterisk `*` at its end. " +"A category name matches a category pattern if it starts with the same prefix " +"of the pattern. For example, `Yiisoft\\Cache\\Cache::set` and " +"`Yiisoft\\Cache\\Cache::get` both match the pattern `Yiisoft\\Cache\\*`." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "By default, the target will process messages of *any* category." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"Besides allowing the categories by the `setCategories()` method, you may " +"also deny certain categories by the `setExcept()` method. If the category " +"of a message is found or matches one of the patterns in this property, the " +"target will NOT process it." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"The following target configuration specifies that the target should only " +"process error and warning messages under the categories whose names match " +"either `Yiisoft\\Cache\\*` or `App\\Exceptions\\HttpException:*`, but not " +"`App\\Exceptions\\HttpException:404`." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$fileTarget->setLevels([LogLevel::ERROR, LogLevel::WARNING]);\n" +"$fileTarget->setCategories(['Yiisoft\\Cache\\*', 'App\\Exceptions\\HttpException:*']);\n" +"$fileTarget->setExcept(['App\\Exceptions\\HttpException:404']);\n" +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, no-wrap +msgid "Message Formatting " +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"Log targets export the filtered log messages in a certain format. For " +"example, if you install a log target of the class " +"[[\\Yiisoft\\Log\\Target\\File\\FileTarget]], you may find a log message " +"similar to the following in the log file:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/logging.md +#, no-wrap +msgid "" +"2020-12-05 09:27:52.223800 [info][application] Some message\n" +"\n" +"Message context:\n" +"\n" +"time: 1607160472.2238\n" +"memory: 4398536\n" +"category: 'application'\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "By default, log messages have the following format:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/logging.md +#, no-wrap +msgid "Timestamp Prefix[Level][Category] Message Context\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"You may customize this format by calling [[\\Yiisoft\\Log\\Target::" +"setFormat()|setFormat()]] method, which takes a PHP callable returning a " +"custom-formatted message." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"\n" +"$fileTarget->setFormat(static function (\\Yiisoft\\Log\\Message $message) {\n" +" $category = strtoupper($message->context('category'));\n" +" return \"({$category}) [{$message->level()}] {$message->message()}\";\n" +"});\n" +"\n" +"$logger = new \\Yiisoft\\Log\\Logger([$fileTarget]);\n" +"$logger->info('Text message', ['category' => 'app']);\n" +"\n" +"// Result:\n" +"// (APP) [info] Text message\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"In addition, if you're comfortable with the default message format but need " +"to change the timestamp format or add custom data to the message, you can " +"call the [[\\Yiisoft\\Log\\Target::setTimestampFormat()|" +"setTimestampFormat()]] and [[\\Yiisoft\\Log\\Target::setPrefix()|" +"setPrefix()]] methods. For example, the following code changes the timestamp " +"format and configures a log target to prefix each log message with the " +"current user ID (IP address and Session ID are removed for privacy reasons)." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$userId = '123e4567-e89b-12d3-a456-426655440000';\n" +"\n" +"// Default: 'Y-m-d H: i: s.u'\n" +"$fileTarget->setTimestampFormat('D d F Y');\n" +"// Default: ''\n" +"$fileTarget->setPrefix(static fn () => \"[{$userId}]\");\n" +"\n" +"$logger = new \\Yiisoft\\Log\\Logger([$fileTarget]);\n" +"$logger->info('Text', ['category' => 'user']);\n" +"\n" +"// Result:\n" +"// Fri 04 December 2020 [123e4567-e89b-12d3-a456-426655440000][info][user] Text\n" +"// Message context: ...\n" +"// Common context: ...\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"The PHP callable that's passed to the [[\\Yiisoft\\Log\\Target::setFormat()|" +"setFormat()]] and [[\\Yiisoft\\Log\\Target::setPrefix()|setPrefix()]] " +"methods has the following signature:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "function (\\Yiisoft\\Log\\Message $message, array $commonContext): string;\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"Besides message prefixes, log targets also append some common context information to each of the log messages.\n" +"You may adjust this behavior by calling target [[\\Yiisoft\\Log\\Target::setCommonContext()|setCommonContext()]]\n" +"method, passing an array of data in the `key => value` format that you want to include.\n" +"For example, the following log target configuration specifies that only the\n" +"value of the `$_SERVER` variable will be appended to the log messages.\n" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$fileTarget->setCommonContext(['server' => $_SERVER]);\n" +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, no-wrap +msgid "Message Trace Level " +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"During development, it's often desirable to see where each log message is " +"coming from. You can achieve this by calling the [[\\Yiisoft\\Log\\Logger::" +"setTraceLevel()|setTraceLevel()]] method like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$logger = new \\Yiisoft\\Log\\Logger($targets);\n" +"$logger->setTraceLevel(3);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"This application configuration sets the trace level to be 3, so each log " +"message will be appended with at most three levels of the call stack at " +"which the log message is recorded. You can also set a list of paths to " +"exclude from the trace by calling the [[\\Yiisoft\\Log\\Logger::" +"setExcludedTracePaths()|setExcludedTracePaths()]] method." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$logger = new \\Yiisoft\\Log\\Logger($targets);\n" +"$logger->setExcludedTracePaths(['/path/to/file', '/path/to/folder']);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"> [!IMPORTANT]\n" +"> Getting call stack information isn't trivial. Therefore, you should only use this feature during development\n" +"or when debugging an application.\n" +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, no-wrap +msgid "Message flushing and exporting " +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"As aforementioned, log messages are maintained in an array by " +"[[\\Yiisoft\\Log\\Logger|logger object]]. To limit the memory consumption by " +"this array, the logger will flush the recorded messages to the [log targets]" +"(#log-targets) each time the array accumulates a certain number of log " +"messages. You can customize this number by calling the " +"[[\\Yiisoft\\Log\\Logger::setFlushInterval()]] method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$logger = new \\Yiisoft\\Log\\Logger($targets);\n" +"$logger->setFlushInterval(100); // default is 1000\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"> [!IMPORTANT]\n" +"> Message flushing also occurs when the application ends,\n" +"which ensures log targets can receive complete log messages.\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"When the [[\\Yiisoft\\Log\\Logger|logger object]] flushes log messages to [log targets](#log-targets),\n" +"they don't get exported immediately. Instead, the message exporting only occurs when a log target\n" +" accumulates a certain number of the filtered messages. You can customize this number by calling the\n" +"[[\\Yiisoft\\Log\\Target::setExportInterval()|setExportInterval()]] method of individual\n" +"[log targets](#log-targets), like the following:\n" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$fileTarget->setExportInterval(100); // default is 1000\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"Because of the flushing and exporting level setting, by default when you " +"call any logging method, you will NOT see the log message immediately in the " +"log targets. This could be a problem for some long-running console " +"applications. To make each log message appear immediately in the log " +"targets, you should set both flush interval and export interval to be 1, as " +"shown below:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$fileTarget->setExportInterval(1);\n" +"\n" +"$logger = new \\Yiisoft\\Log\\Logger([$fileTarget]);\n" +"$logger->setFlushInterval(1);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> Frequent message flushing and exporting will degrade the performance of your application.\n" +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, no-wrap +msgid "Toggling log targets " +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"You can enable or disable a log target by calling its " +"[[\\Yiisoft\\Log\\Target::enable()|enable()] ] and [[\\Yiisoft\\Log\\Target::" +"disable()|disable()]] methods. You may do so via the log target " +"configuration or by the following PHP statement in your code:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"$fileTarget = new \\Yiisoft\\Log\\Target\\File\\FileTarget('/path/to/app.log');\n" +"$logger = new \\Yiisoft\\Log\\Logger([$fileTarget, /*Other targets*/]);\n" +"\n" +"foreach ($logger->getTargets() as $target) {\n" +" if ($target instanceof \\Yiisoft\\Log\\Target\\File\\FileTarget) {\n" +" $target->disable();\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"To check whether the log target is enabled, call the `isEnabled()` method. " +"You also may pass callable to [[\\Yiisoft\\Log\\Target::setEnabled()|" +"setEnabled()]] to define a dynamic condition for whether the log target " +"should be enabled or not." +msgstr "" + +#. type: Title ### +#: en/runtime/logging.md +#, no-wrap +msgid "Creating new targets " +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"Creating a new log target class is straightforward. You mainly need to " +"implement the [[\\Yii\\Log\\Target::export()]] abstract method that sends " +"all accumulated log messages to a designated medium." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"The following protected methods will also be available for child targets:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "" +"`getMessages` - Get a list of log messages ([[\\Yii\\Log\\Message]] " +"instances)." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "" +"`getFormattedMessages` - Get a list of log messages formatted as strings." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "`formatMessages` - Get all log messages formatted as a string." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/logging.md +msgid "" +"`getCommonContext` - Get an array with common context data in the `key => " +"value` format." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +msgid "" +"For more details, you may refer to any of the log target classes included in " +"the package." +msgstr "" + +#. type: Plain text +#: en/runtime/logging.md +#, no-wrap +msgid "" +"> [!TIP]\n" +"> Instead of creating your own loggers, you may try any PSR-3 compatible logger such\n" +"as [Monolog](https://github.com/Seldaek/monolog) by using [[\\Yii\\Log\\PsrTarget]].\n" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/logging.md +#, no-wrap +msgid "" +"/**\n" +" * @var \\Psr\\Log\\LoggerInterface $psrLogger\n" +" */\n" +"\n" +"$psrTarget = new \\Yiisoft\\Log\\PsrTarget($psrLogger);\n" +"$logger = new \\Yiisoft\\Log\\Logger([$psrTarget]);\n" +"\n" +"$logger->info('Text message');\n" +msgstr "" diff --git a/guide/po/runtime_request.md/ru/runtime_request.md.ru.po b/guide/po/runtime_request.md/ru/runtime_request.md.ru.po new file mode 100644 index 00000000..173d594e --- /dev/null +++ b/guide/po/runtime_request.md/ru/runtime_request.md.ru.po @@ -0,0 +1,394 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/runtime/request.md +#, no-wrap +msgid "Request" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "HTTP request has a method, URI, a set of headers and a body:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/request.md +#, no-wrap +msgid "" +"POST /contact HTTP/1.1\n" +"Host: example.org\n" +"Accept-Language: en-us\n" +"Accept-Encoding: gzip, deflate\n" +"\n" +"{\n" +" \"subject\": \"Hello\",\n" +" \"body\": \"Hello there, we need to build Yii application together!\"\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "The method is `POST`, URI is `/contact`. Extra headers are specifying host, preferred language and encoding. The body could be anything. In this case, it's a JSON payload." +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Yii uses [PSR-7 `ServerRequest`](https://www.php-fig.org/psr/psr-7/) as request representation. The object is available in controller actions and other types of middleware:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"public function view(ServerRequestInterface $request): ResponseInterface\n" +"{\n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md +#, no-wrap +msgid "Method" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "The method could be obtained from a request object:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "$method = $request->getMethod();\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Usually it's one of the:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "GET" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "POST" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "PUT" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "DELETE" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "HEAD" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "PATCH" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "OPTIONS" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "In case you want to make sure the request method is of a certain type, there is a special class with method names:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"use Yiisoft\\Http\\Method;\n" +"\n" +"if ($request->getMethod() === Method::POST) {\n" +" // method is POST\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md +#, no-wrap +msgid "URI" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "A URI has:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Scheme (`http`, `https`)" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Host (`yiiframework.com`)" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Port (`80`, `443`)" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Path (`/posts/1`)" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Query string (`page=1&sort=+id`)" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Fragment (`#anchor`)" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "You can obtain `UriInterface` from request like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "$uri = $request->getUri();\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Then you can get various details from its methods:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getScheme()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getAuthority()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getUserInfo()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getHost()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getPort()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getPath()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getQuery()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getFragment()`" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md en/runtime/response.md +#, no-wrap +msgid "Headers" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "There are various methods to inspect request headers. To get all headers as an array:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"$headers = $request->getHeaders();\n" +"foreach ($headers as $name => $values) {\n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "To get a single header:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "$values = $request->getHeader('Accept-Encoding');\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Also, you could get value as a comma-separated string instead of an array. That's especially handy if a header has a single value:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"if ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') {\n" +" // This is an AJAX request made with jQuery.\n" +" // Note that header presence and name may vary depending on the library used. \n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "To check if a header is present in the request:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"if ($request->hasHeader('Accept-Encoding')) {\n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md en/runtime/response.md +#, no-wrap +msgid "Body" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "There are two methods to get body contents. The first is getting the body as it is without parsing:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "$body = $request->getBody();\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "The `$body` would be an instance of `Psr\\Http\\Message\\StreamInterface`." +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Also, you could get a parsed body:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "$bodyParameters = $request->getParsedBody();\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Parsing depends on PSR-7 implementation and may require middleware for custom body formats." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"getHeaderLine('Content-Type');\n" +"\n" +" if (strpos($contentType, 'application/json') !== false) {\n" +" $body = $request->getBody();\n" +" $parsedBody = $this->parse($body);\n" +" $request = $request->withParsedBody($parsedBody);\n" +" \n" +" }\n" +"\n" +" return $next->handle($request);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md +#, no-wrap +msgid "File uploads" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Uploaded files that user submitted from a form with `enctype` attribute equals to `multipart/form-data` are handled via special request method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"$files = $request->getUploadedFiles();\n" +"foreach ($files as $file) {\n" +" if ($file->getError() === UPLOAD_ERR_OK) {\n" +" $file->moveTo('path/to/uploads/new_filename.ext');\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md +#, no-wrap +msgid "Attributes" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Application middleware may set custom request attributes using `withAttribute()` method. You can get these attributes with `getAttribute()`." +msgstr "" diff --git a/guide/po/runtime_request.md/runtime_request.md.pot b/guide/po/runtime_request.md/runtime_request.md.pot new file mode 100644 index 00000000..5d791281 --- /dev/null +++ b/guide/po/runtime_request.md/runtime_request.md.pot @@ -0,0 +1,416 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/runtime/request.md +#, no-wrap +msgid "Request" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "HTTP request has a method, URI, a set of headers and a body:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/request.md +#, no-wrap +msgid "" +"POST /contact HTTP/1.1\n" +"Host: example.org\n" +"Accept-Language: en-us\n" +"Accept-Encoding: gzip, deflate\n" +"\n" +"{\n" +" \"subject\": \"Hello\",\n" +" \"body\": \"Hello there, we need to build Yii application together!\"\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "" +"The method is `POST`, URI is `/contact`. Extra headers are specifying host, " +"preferred language and encoding. The body could be anything. In this case, " +"it's a JSON payload." +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "" +"Yii uses [PSR-7 `ServerRequest`](https://www.php-fig.org/psr/psr-7/) as " +"request representation. The object is available in controller actions and " +"other types of middleware:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"public function view(ServerRequestInterface $request): ResponseInterface\n" +"{\n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md +#, no-wrap +msgid "Method" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "The method could be obtained from a request object:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "$method = $request->getMethod();\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Usually it's one of the:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "GET" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "POST" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "PUT" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "DELETE" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "HEAD" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "PATCH" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "OPTIONS" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "" +"In case you want to make sure the request method is of a certain type, there " +"is a special class with method names:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"use Yiisoft\\Http\\Method;\n" +"\n" +"if ($request->getMethod() === Method::POST) {\n" +" // method is POST\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md +#, no-wrap +msgid "URI" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "A URI has:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Scheme (`http`, `https`)" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Host (`yiiframework.com`)" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Port (`80`, `443`)" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Path (`/posts/1`)" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Query string (`page=1&sort=+id`)" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "Fragment (`#anchor`)" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "You can obtain `UriInterface` from request like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "$uri = $request->getUri();\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Then you can get various details from its methods:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getScheme()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getAuthority()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getUserInfo()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getHost()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getPort()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getPath()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getQuery()`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/request.md +msgid "`getFragment()`" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md en/runtime/response.md +#, no-wrap +msgid "Headers" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "" +"There are various methods to inspect request headers. To get all headers as " +"an array:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"$headers = $request->getHeaders();\n" +"foreach ($headers as $name => $values) {\n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "To get a single header:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "$values = $request->getHeader('Accept-Encoding');\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "" +"Also, you could get value as a comma-separated string instead of an array. " +"That's especially handy if a header has a single value:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"if ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') {\n" +" // This is an AJAX request made with jQuery.\n" +" // Note that header presence and name may vary depending on the library used. \n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "To check if a header is present in the request:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"if ($request->hasHeader('Accept-Encoding')) {\n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md en/runtime/response.md +#, no-wrap +msgid "Body" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "" +"There are two methods to get body contents. The first is getting the body as " +"it is without parsing:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "$body = $request->getBody();\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "" +"The `$body` would be an instance of `Psr\\Http\\Message\\StreamInterface`." +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "Also, you could get a parsed body:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "$bodyParameters = $request->getParsedBody();\n" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "" +"Parsing depends on PSR-7 implementation and may require middleware for " +"custom body formats." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"getHeaderLine('Content-Type');\n" +"\n" +" if (strpos($contentType, 'application/json') !== false) {\n" +" $body = $request->getBody();\n" +" $parsedBody = $this->parse($body);\n" +" $request = $request->withParsedBody($parsedBody);\n" +" \n" +" }\n" +"\n" +" return $next->handle($request);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md +#, no-wrap +msgid "File uploads" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "" +"Uploaded files that user submitted from a form with `enctype` attribute " +"equals to `multipart/form-data` are handled via special request method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/request.md +#, no-wrap +msgid "" +"$files = $request->getUploadedFiles();\n" +"foreach ($files as $file) {\n" +" if ($file->getError() === UPLOAD_ERR_OK) {\n" +" $file->moveTo('path/to/uploads/new_filename.ext');\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md +#, no-wrap +msgid "Attributes" +msgstr "" + +#. type: Plain text +#: en/runtime/request.md +msgid "" +"Application middleware may set custom request attributes using " +"`withAttribute()` method. You can get these attributes with " +"`getAttribute()`." +msgstr "" diff --git a/guide/po/runtime_response.md/ru/runtime_response.md.ru.po b/guide/po/runtime_response.md/ru/runtime_response.md.ru.po new file mode 100644 index 00000000..99f8c8b6 --- /dev/null +++ b/guide/po/runtime_response.md/ru/runtime_response.md.ru.po @@ -0,0 +1,212 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title ## +#: en/runtime/request.md en/runtime/response.md +#, no-wrap +msgid "Headers" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md en/runtime/response.md +#, no-wrap +msgid "Body" +msgstr "" + +#. type: Title # +#: en/runtime/response.md +#, no-wrap +msgid "Response" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "HTTP response has status code and message, a set of headers and a body:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/response.md +#, no-wrap +msgid "" +"HTTP/1.1 200 OK\n" +"Date: Mon, 27 Jul 2009 12:28:53 GMT\n" +"Server: Apache/2.2.14 (Win32)\n" +"Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT\n" +"Content-Length: 6 \n" +"Content-Type: text/html\n" +"Connection: Closed\n" +"\n" +"Hello!\n" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "Yii uses [PSR-7 `Response`](https://www.php-fig.org/psr/psr-7/) in the web application to represent response." +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "The object should be constructed and returned as a result of the execution of controller actions or other middleware. Usually, the middleware has a response factory injected into its constructor." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "" +"use Psr\\Http\\Message\\ResponseFactoryInterface;\n" +"use Psr\\Http\\Message\\ResponseInterface;\n" +"use Psr\\Http\\Message\\ServerRequestInterface;\n" +"\n" +"final readonly class PostAction\n" +"{\n" +" public function __construct(\n" +" private ResponseFactoryInterface $responseFactory\n" +" )\n" +" {\n" +" }\n" +"\n" +" public function view(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" $response = $this->responseFactory->createResponse();\n" +" $response->getBody()->write('Hello!');\n" +" return $response;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/response.md +#, no-wrap +msgid "Status code" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "You can set a status code like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "" +"use Yiisoft\\Http\\Status;\n" +"\n" +"$response = $response->withStatus(Status::NOT_FOUND);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "Majority of status codes are available from `Status` class for convenience and readability." +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "You can set headers like this:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "$response = $response->withHeader('Content-type', 'application/json');\n" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "If there is a need to append a header value to the existing header:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "$response = $response->withAddedHeader('Set-Cookie', 'qwerty=219ffwef9w0f; Domain=somecompany.co.uk; Path=/; Expires=Wed, 30 Aug 2019 00:00:00 GMT');\n" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "And, if needed, headers could be removed:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "$response = $response->withoutHeader('Set-Cookie');\n" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "Response body is an object implementing `Psr\\Http\\Message\\StreamInterface`." +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "You can write to it via the interface itself:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "" +"$body = $response->getBody();\n" +"$body->write('Hello');\n" +msgstr "" + +#. type: Title ## +#: en/runtime/response.md +#, no-wrap +msgid "Examples" +msgstr "" + +#. type: Title ### +#: en/runtime/response.md +#, no-wrap +msgid "Redirecting" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "" +"use Yiisoft\\Http\\Status;\n" +"\n" +"return $response\n" +" ->withStatus(Status::PERMANENT_REDIRECT)\n" +" ->withHeader('Location', 'https://www.example.com'); \n" +msgstr "" + +#. type: Title ### +#: en/runtime/response.md +#, no-wrap +msgid "Responding with JSON" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "" +"use Yiisoft\\Json\\Json;\n" +"\n" +"$data = [\n" +" 'account' => 'samdark',\n" +" 'value' => 42\n" +"];\n" +"\n" +"$response->getBody()->write(Json::encode($data));\n" +"return $response\n" +" ->withStatus(200)\n" +" ->withHeader('Content-Type', 'application/json');\n" +msgstr "" diff --git a/guide/po/runtime_response.md/runtime_response.md.pot b/guide/po/runtime_response.md/runtime_response.md.pot new file mode 100644 index 00000000..c99b39d5 --- /dev/null +++ b/guide/po/runtime_response.md/runtime_response.md.pot @@ -0,0 +1,221 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title ## +#: en/runtime/request.md en/runtime/response.md +#, no-wrap +msgid "Headers" +msgstr "" + +#. type: Title ## +#: en/runtime/request.md en/runtime/response.md +#, no-wrap +msgid "Body" +msgstr "" + +#. type: Title # +#: en/runtime/response.md +#, no-wrap +msgid "Response" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "HTTP response has status code and message, a set of headers and a body:" +msgstr "" + +#. type: Fenced code block +#: en/runtime/response.md +#, no-wrap +msgid "" +"HTTP/1.1 200 OK\n" +"Date: Mon, 27 Jul 2009 12:28:53 GMT\n" +"Server: Apache/2.2.14 (Win32)\n" +"Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT\n" +"Content-Length: 6 \n" +"Content-Type: text/html\n" +"Connection: Closed\n" +"\n" +"Hello!\n" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "" +"Yii uses [PSR-7 `Response`](https://www.php-fig.org/psr/psr-7/) in the web " +"application to represent response." +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "" +"The object should be constructed and returned as a result of the execution " +"of controller actions or other middleware. Usually, the middleware has a " +"response factory injected into its constructor." +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "" +"use Psr\\Http\\Message\\ResponseFactoryInterface;\n" +"use Psr\\Http\\Message\\ResponseInterface;\n" +"use Psr\\Http\\Message\\ServerRequestInterface;\n" +"\n" +"final readonly class PostAction\n" +"{\n" +" public function __construct(\n" +" private ResponseFactoryInterface $responseFactory\n" +" )\n" +" {\n" +" }\n" +"\n" +" public function view(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" $response = $this->responseFactory->createResponse();\n" +" $response->getBody()->write('Hello!');\n" +" return $response;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/response.md +#, no-wrap +msgid "Status code" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "You can set a status code like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "" +"use Yiisoft\\Http\\Status;\n" +"\n" +"$response = $response->withStatus(Status::NOT_FOUND);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "" +"Majority of status codes are available from `Status` class for convenience " +"and readability." +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "You can set headers like this:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "$response = $response->withHeader('Content-type', 'application/json');\n" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "If there is a need to append a header value to the existing header:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "$response = $response->withAddedHeader('Set-Cookie', 'qwerty=219ffwef9w0f; Domain=somecompany.co.uk; Path=/; Expires=Wed, 30 Aug 2019 00:00:00 GMT');\n" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "And, if needed, headers could be removed:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "$response = $response->withoutHeader('Set-Cookie');\n" +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "" +"Response body is an object implementing " +"`Psr\\Http\\Message\\StreamInterface`." +msgstr "" + +#. type: Plain text +#: en/runtime/response.md +msgid "You can write to it via the interface itself:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "" +"$body = $response->getBody();\n" +"$body->write('Hello');\n" +msgstr "" + +#. type: Title ## +#: en/runtime/response.md +#, no-wrap +msgid "Examples" +msgstr "" + +#. type: Title ### +#: en/runtime/response.md +#, no-wrap +msgid "Redirecting" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "" +"use Yiisoft\\Http\\Status;\n" +"\n" +"return $response\n" +" ->withStatus(Status::PERMANENT_REDIRECT)\n" +" ->withHeader('Location', 'https://www.example.com'); \n" +msgstr "" + +#. type: Title ### +#: en/runtime/response.md +#, no-wrap +msgid "Responding with JSON" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/response.md +#, no-wrap +msgid "" +"use Yiisoft\\Json\\Json;\n" +"\n" +"$data = [\n" +" 'account' => 'samdark',\n" +" 'value' => 42\n" +"];\n" +"\n" +"$response->getBody()->write(Json::encode($data));\n" +"return $response\n" +" ->withStatus(200)\n" +" ->withHeader('Content-Type', 'application/json');\n" +msgstr "" diff --git a/guide/po/runtime_routing.md/ru/runtime_routing.md.ru.po b/guide/po/runtime_routing.md/ru/runtime_routing.md.ru.po new file mode 100644 index 00000000..b7f365f9 --- /dev/null +++ b/guide/po/runtime_routing.md/ru/runtime_routing.md.ru.po @@ -0,0 +1,523 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/runtime/routing.md +#, no-wrap +msgid "Routing and URL generation" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "Usually, a Yii application processes certain requests with certain handlers. It selects a handler based on the request URL. The part of the application that does the job is a router, and the process of selecting a handler, instantiating it and running a handler method is *routing*." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "The reverse process of routing is *URL generation*, which creates a URL from a given named route and the associated query parameters. When you later request the created URL, the routing process can resolve it back into the original route and query parameters." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "Routing and URL generation are separate services, but they use a common set of routes for both URL matching and URL generation." +msgstr "" + +#. type: Title ## +#: en/runtime/routing.md +#, fuzzy, no-wrap +#| msgid "configuration could be:" +msgid "Configuring routes" +msgstr "конфигурация может быть:" + +#. type: Plain text +#: en/runtime/routing.md +msgid "By configuring routes, you can let your application recognize arbitrary URL formats without modifying your existing application code. You can configure routes in `/config/routes.php`. The structure of the file is the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"action([SiteController::class, 'index'])\n" +" ->name('site/index')\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "The file returns an array of routes. When defining a route, you start with a method corresponding to a certain HTTP request type:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "get" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "post" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "put" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "delete" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "patch" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "head" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "options" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "If you need many methods, you can use `methods()`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"action([SiteController::class, 'user'])\n" +" ->name('site/user')\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "All these methods accept a route pattern and a handler. The route pattern defines how the router matches the URL when routing and how it generates URL based on route name and parameters. You will learn about the actual syntax later in this guide. You could specify a handler as:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "[Middleware](../structure/middleware.md) class name." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "Handler action (an array of [HandlerClass, handlerMethod])." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "A callable." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "In case of a handler action, a class of type `HandlerClass` is instantiated and its `handlerMethod` is called:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"use Psr\\Http\\Message\\ServerRequestInterface;\n" +"use Psr\\Http\\Message\\ResponseInterface;\n" +"\n" +"final readonly class HandlerClass\n" +"{\n" +" public function handle(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" // ...\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "The callable is called as is:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"static function (ServerRequestInterface $request, RequestHandlerInterface $next) use ($responseFactory) {\n" +" $response = $responseFactory->createResponse();\n" +" $response->getBody()->write('You are at homepage.');\n" +" return $response;\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "For handler action and callable typed parameters are automatically injected using the dependency injection container passed to the route." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "Get current request and handler by type-hinting for `ServerRequestInterface` and `RequestHandlerInterface`. You could add extra handlers to wrap primary one with `middleware()` method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"action([DownloadController::class, 'download'])\n" +" ->name('download/id')\n" +" ->middleware(LimitDownloadRate::class)\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "Check [\"the middleware\"](../structure/middleware.md) guide to learn more about how to implement middleware." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "This is especially useful when grouping routes:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"middleware(ApiDataWrapper::class)\n" +" ->routes(\n" +" Route::get('/info/v2')\n" +" ->action(ApiInfo::class)\n" +" ->name('api/info/v2')\n" +" ->middleware(FormatDataResponseAsJson::class), \n" +" Route::get('/user')\n" +" ->action([ApiUserController::class, 'index'])\n" +" ->name('api/user/index'),\n" +" Route::get('/user/{login}')\n" +" ->action([ApiUserController::class, 'profile'])\n" +" ->middleware(FormatDataResponseAsJson::class)\n" +" ->name('api/user/profile'),\n" +" )\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "Router executes `ApiDataWrapper` before handling any URL starting with `/api`." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "You could name a route with a `name()` method. It's a good idea to choose a route name based on the handler's name." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "You can set a default value for a route parameter. For example:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"action([SiteController::class, 'user'])\n" +" ->name('site/user')\n" +" ->defaults(['id' => '42'])\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "This configuration would result in a match with both `/user` and `/user/123`. In both cases `CurrentRoute` service will contain `id` argument filled. In the first case it will be default `42` and in the second case it will be `123`." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "In cause URL should be valid for a single host, you can specify it with `host()`." +msgstr "" + +#. type: Title ## +#: en/runtime/routing.md +#, fuzzy, no-wrap +#| msgid "DI container " +msgid "Routing " +msgstr "Контейнер внедрения зависимостей " + +#. type: Plain text +#: en/runtime/routing.md +msgid "Yii routing is flexible, and internally it may use different routing implementations. The actual matching algorithm may vary, but the basic idea stays the same." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "Router matches routes defined in config from top to bottom. If there is a match, further matching isn't performed and the router executes the route handler to get the response. If there is no match at all, router passes handling to the next middleware in the [application middleware set](../structure/middleware.md)." +msgstr "" + +#. type: Title ## +#: en/runtime/routing.md +#, fuzzy, no-wrap +#| msgid "Defining aliases " +msgid "Generating URLs " +msgstr "Определение псевдонимов " + +#. type: Plain text +#: en/runtime/routing.md +msgid "To generate URL based on a route, a route should have a name:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"name('test/index'),\n" +" Route::post('/test/submit/{id}', [TestController::class, 'submit'])\n" +" ->name('test/submit')\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +#, fuzzy +#| msgid "That's equal to the following:" +msgid "The generation looks like the following:" +msgstr "Это соответствует:" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"generate('test/submit', ['id' => '42']);\n" +" // ...\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "In the above code, we get a generator instance with the help of [automatic dependency injection](../concept/di-container.md) that works with action handlers. In another service, you can get the instance with similar constructor injection. In views URL generator is available as `$url`." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "Then we use `generate()` method to get actual URL. It accepts a route name and an array of named query parameters. The code will return \"/test/submit/42.\" If you need absolute URL, use `generateAbsolute()` instead." +msgstr "" + +#. type: Title ## +#: en/runtime/routing.md +#, fuzzy, no-wrap +#| msgid "References " +msgid "Route patterns " +msgstr "Полезные ссылки " + +#. type: Plain text +#: en/runtime/routing.md +msgid "Route patterns used depend on the underlying implementation used. The default implementation is [nikic/FastRoute](https://github.com/nikic/FastRoute)." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "Basic patterns are static like `/test`. That means they must match exactly in order for a route match." +msgstr "" + +#. type: Title ### +#: en/runtime/routing.md +#, fuzzy, no-wrap +#| msgid "References " +msgid "Named Parameters " +msgstr "Полезные ссылки " + +#. type: Plain text +#: en/runtime/routing.md +msgid "A pattern can include one or more named parameters which are specified in the pattern in the format of `{ParamName:RegExp}`, where `ParamName` specifies the parameter name and `RegExp` is an optional regular expression used to match parameter values. If `RegExp` isn't specified, it means the parameter value should be a string without any slash." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> You can only use regular expressions inside parameters. The rest of the pattern is considered plain text.\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "You can't use capturing groups. For example `{lang:(en|de)}` isn't a valid placeholder, because `()` is a capturing group. Instead, you can use either `{lang:en|de}` or `{lang:(?:en|de)}`." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "On a route match router fills the associated request attributes with values matching the corresponding parts of the URL. When you use the rule to create a URL, it will take the values of the provided parameters and insert them at the places where the parameters are declared." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "Let's use some examples to illustrate how named parameters work. Assume you've declared the following three patterns:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/runtime/routing.md +msgid "`'posts/{year:\\d{4}}/{category}`" +msgstr "" + +#. type: Bullet: '2. ' +#: en/runtime/routing.md +msgid "`'posts'`" +msgstr "" + +#. type: Bullet: '3. ' +#: en/runtime/routing.md +msgid "`'post/{id:\\d+}'`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "`/posts` match the second pattern;" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "`/posts/2014/php` match a first pattern. Parameters are the `year` whose value is 2014 and the `category` whose value is `php`;" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "`/post/100` match a third pattern. The `id` parameter value is 100;" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "`/posts/php` doesn't match." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "When generating URLs, you should use the following parameters:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"echo $url->generate('first', ['year' => '2020', 'category' => 'Virology']);\n" +"echo $url->generate('second');\n" +"echo $url->generate('third', ['id' => '42']);\n" +msgstr "" + +#. type: Title ### +#: en/runtime/routing.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Optional parts " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/runtime/routing.md +msgid "You should wrap optional pattern parts with `[` and `]`. For example, `/posts[/{id}]` pattern would match both `http://example.com/posts` and `http://example.com/posts/42`. Router would fill `id` argument of `CurrentRoute` service in the second case only. In this case, you could specify the default value:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"use \\Yiisoft\\Router\\Route;\n" +"\n" +"Route::get('/posts[/{id}]')->defaults(['id' => '1']);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "Optional parts are only supported in a trailing position, not in the middle of a route." +msgstr "" diff --git a/guide/po/runtime_routing.md/runtime_routing.md.pot b/guide/po/runtime_routing.md/runtime_routing.md.pot new file mode 100644 index 00000000..942e8691 --- /dev/null +++ b/guide/po/runtime_routing.md/runtime_routing.md.pot @@ -0,0 +1,596 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/runtime/routing.md +#, no-wrap +msgid "Routing and URL generation" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Usually, a Yii application processes certain requests with certain " +"handlers. It selects a handler based on the request URL. The part of the " +"application that does the job is a router, and the process of selecting a " +"handler, instantiating it and running a handler method is *routing*." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"The reverse process of routing is *URL generation*, which creates a URL from " +"a given named route and the associated query parameters. When you later " +"request the created URL, the routing process can resolve it back into the " +"original route and query parameters." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Routing and URL generation are separate services, but they use a common set " +"of routes for both URL matching and URL generation." +msgstr "" + +#. type: Title ## +#: en/runtime/routing.md +#, no-wrap +msgid "Configuring routes" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"By configuring routes, you can let your application recognize arbitrary URL " +"formats without modifying your existing application code. You can configure " +"routes in `/config/routes.php`. The structure of the file is the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"action([SiteController::class, 'index'])\n" +" ->name('site/index')\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"The file returns an array of routes. When defining a route, you start with a " +"method corresponding to a certain HTTP request type:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "get" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "post" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "put" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "delete" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "patch" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "head" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "options" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "If you need many methods, you can use `methods()`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"action([SiteController::class, 'user'])\n" +" ->name('site/user')\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"All these methods accept a route pattern and a handler. The route pattern " +"defines how the router matches the URL when routing and how it generates URL " +"based on route name and parameters. You will learn about the actual syntax " +"later in this guide. You could specify a handler as:" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "[Middleware](../structure/middleware.md) class name." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "Handler action (an array of [HandlerClass, handlerMethod])." +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "A callable." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"In case of a handler action, a class of type `HandlerClass` is instantiated " +"and its `handlerMethod` is called:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"use Psr\\Http\\Message\\ServerRequestInterface;\n" +"use Psr\\Http\\Message\\ResponseInterface;\n" +"\n" +"final readonly class HandlerClass\n" +"{\n" +" public function handle(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" // ...\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "The callable is called as is:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"static function (ServerRequestInterface $request, RequestHandlerInterface $next) use ($responseFactory) {\n" +" $response = $responseFactory->createResponse();\n" +" $response->getBody()->write('You are at homepage.');\n" +" return $response;\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"For handler action and callable typed parameters are automatically injected " +"using the dependency injection container passed to the route." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Get current request and handler by type-hinting for `ServerRequestInterface` " +"and `RequestHandlerInterface`. You could add extra handlers to wrap primary " +"one with `middleware()` method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"action([DownloadController::class, 'download'])\n" +" ->name('download/id')\n" +" ->middleware(LimitDownloadRate::class)\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Check [\"the middleware\"](../structure/middleware.md) guide to learn more " +"about how to implement middleware." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "This is especially useful when grouping routes:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"middleware(ApiDataWrapper::class)\n" +" ->routes(\n" +" Route::get('/info/v2')\n" +" ->action(ApiInfo::class)\n" +" ->name('api/info/v2')\n" +" ->middleware(FormatDataResponseAsJson::class), \n" +" Route::get('/user')\n" +" ->action([ApiUserController::class, 'index'])\n" +" ->name('api/user/index'),\n" +" Route::get('/user/{login}')\n" +" ->action([ApiUserController::class, 'profile'])\n" +" ->middleware(FormatDataResponseAsJson::class)\n" +" ->name('api/user/profile'),\n" +" )\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Router executes `ApiDataWrapper` before handling any URL starting with `/" +"api`." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"You could name a route with a `name()` method. It's a good idea to choose a " +"route name based on the handler's name." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "You can set a default value for a route parameter. For example:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"action([SiteController::class, 'user'])\n" +" ->name('site/user')\n" +" ->defaults(['id' => '42'])\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"This configuration would result in a match with both `/user` and `/" +"user/123`. In both cases `CurrentRoute` service will contain `id` argument " +"filled. In the first case it will be default `42` and in the second case it " +"will be `123`." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"In cause URL should be valid for a single host, you can specify it with " +"`host()`." +msgstr "" + +#. type: Title ## +#: en/runtime/routing.md +#, no-wrap +msgid "Routing " +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Yii routing is flexible, and internally it may use different routing " +"implementations. The actual matching algorithm may vary, but the basic idea " +"stays the same." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Router matches routes defined in config from top to bottom. If there is a " +"match, further matching isn't performed and the router executes the route " +"handler to get the response. If there is no match at all, router passes " +"handling to the next middleware in the [application middleware set](../" +"structure/middleware.md)." +msgstr "" + +#. type: Title ## +#: en/runtime/routing.md +#, no-wrap +msgid "Generating URLs " +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "To generate URL based on a route, a route should have a name:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"name('test/index'),\n" +" Route::post('/test/submit/{id}', [TestController::class, 'submit'])\n" +" ->name('test/submit')\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "The generation looks like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"generate('test/submit', ['id' => '42']);\n" +" // ...\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"In the above code, we get a generator instance with the help of [automatic " +"dependency injection](../concept/di-container.md) that works with action " +"handlers. In another service, you can get the instance with similar " +"constructor injection. In views URL generator is available as `$url`." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Then we use `generate()` method to get actual URL. It accepts a route name " +"and an array of named query parameters. The code will return \"/test/" +"submit/42.\" If you need absolute URL, use `generateAbsolute()` instead." +msgstr "" + +#. type: Title ## +#: en/runtime/routing.md +#, no-wrap +msgid "Route patterns " +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Route patterns used depend on the underlying implementation used. The " +"default implementation is [nikic/FastRoute](https://github.com/nikic/" +"FastRoute)." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Basic patterns are static like `/test`. That means they must match exactly " +"in order for a route match." +msgstr "" + +#. type: Title ### +#: en/runtime/routing.md +#, no-wrap +msgid "Named Parameters " +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"A pattern can include one or more named parameters which are specified in " +"the pattern in the format of `{ParamName:RegExp}`, where `ParamName` " +"specifies the parameter name and `RegExp` is an optional regular expression " +"used to match parameter values. If `RegExp` isn't specified, it means the " +"parameter value should be a string without any slash." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> You can only use regular expressions inside parameters. The rest of the pattern is considered plain text.\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"You can't use capturing groups. For example `{lang:(en|de)}` isn't a valid " +"placeholder, because `()` is a capturing group. Instead, you can use either " +"`{lang:en|de}` or `{lang:(?:en|de)}`." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"On a route match router fills the associated request attributes with values " +"matching the corresponding parts of the URL. When you use the rule to " +"create a URL, it will take the values of the provided parameters and insert " +"them at the places where the parameters are declared." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Let's use some examples to illustrate how named parameters work. Assume " +"you've declared the following three patterns:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/runtime/routing.md +msgid "`'posts/{year:\\d{4}}/{category}`" +msgstr "" + +#. type: Bullet: '2. ' +#: en/runtime/routing.md +msgid "`'posts'`" +msgstr "" + +#. type: Bullet: '3. ' +#: en/runtime/routing.md +msgid "`'post/{id:\\d+}'`" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "`/posts` match the second pattern;" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "" +"`/posts/2014/php` match a first pattern. Parameters are the `year` whose " +"value is 2014 and the `category` whose value is `php`;" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "`/post/100` match a third pattern. The `id` parameter value is 100;" +msgstr "" + +#. type: Bullet: '- ' +#: en/runtime/routing.md +msgid "`/posts/php` doesn't match." +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "When generating URLs, you should use the following parameters:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"echo $url->generate('first', ['year' => '2020', 'category' => 'Virology']);\n" +"echo $url->generate('second');\n" +"echo $url->generate('third', ['id' => '42']);\n" +msgstr "" + +#. type: Title ### +#: en/runtime/routing.md +#, no-wrap +msgid "Optional parts " +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"You should wrap optional pattern parts with `[` and `]`. For example, `/" +"posts[/{id}]` pattern would match both `http://example.com/posts` and " +"`http://example.com/posts/42`. Router would fill `id` argument of " +"`CurrentRoute` service in the second case only. In this case, you could " +"specify the default value:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/routing.md +#, no-wrap +msgid "" +"use \\Yiisoft\\Router\\Route;\n" +"\n" +"Route::get('/posts[/{id}]')->defaults(['id' => '1']);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/routing.md +msgid "" +"Optional parts are only supported in a trailing position, not in the middle " +"of a route." +msgstr "" diff --git a/guide/po/runtime_sessions.md/ru/runtime_sessions.md.ru.po b/guide/po/runtime_sessions.md/ru/runtime_sessions.md.ru.po new file mode 100644 index 00000000..44f3e01a --- /dev/null +++ b/guide/po/runtime_sessions.md/ru/runtime_sessions.md.ru.po @@ -0,0 +1,255 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/runtime/sessions.md +#, fuzzy, no-wrap +#| msgid "Yii versions" +msgid "Sessions" +msgstr "Версии Yii" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "Sessions persist data between requests without passing them to the client and back. Yii has [a session package](https://github.com/yiisoft/session) to work with session data." +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "To add it to your application, use composer:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/runtime/sessions.md +#, fuzzy, no-wrap +#| msgid "composer install yiisoft/security\n" +msgid "composer require yiisoft/session\n" +msgstr "composer install yiisoft/security\n" + +#. type: Title ## +#: en/runtime/sessions.md +#, no-wrap +msgid "Configuring middleware" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "To keep a session between requests, you need to add `SessionMiddleware` to your route group or application middlewares. You should prefer a route group when you have both API with token-based authentication and regular web routes in the same application. Having it this way avoids starting the session for API endpoints." +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "To add a session for a certain group of routes, edit `config/routes.php` like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"middleware(SessionMiddleware::class)\n" +" ->routes(\n" +" // ...\n" +" )\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "To add a session to the whole application, edit `config/application.php` like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"return [\n" +" Yiisoft\\Yii\\Web\\Application::class => [\n" +" '__construct()' => [\n" +" 'dispatcher' => DynamicReference::to(static function (Injector $injector) {\n" +" return ($injector->make(MiddlewareDispatcher::class))\n" +" ->withMiddlewares(\n" +" [\n" +" Router::class,\n" +" CsrfMiddleware::class,\n" +" SessionMiddleware::class, // <-- add this\n" +" ErrorCatcher::class,\n" +" ]\n" +" );\n" +" }),\n" +" ],\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/runtime/sessions.md +#, no-wrap +msgid "Opening and closing session" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"public function actionProfile(\\Yiisoft\\Session\\SessionInterface $session)\n" +"{\n" +" // start a session if it's not yet started\n" +" $session->open();\n" +"\n" +" // work with session\n" +"\n" +" // write session values and then close it\n" +" $session->close();\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> Closing session as early as possible is a good practice since many session implementations are blocking other\n" +"> requests while the session is open.\n" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "There are two more ways to close a session:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"public function actionProfile(\\Yiisoft\\Session\\SessionInterface $session)\n" +"{\n" +" // discard changes and close the session\n" +" $session->discard();\n" +"\n" +" // destroy the session completely\n" +" $session->destroy(); \n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/sessions.md +#, no-wrap +msgid "Working with session data" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "Usually you will use the following methods to work with session data:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"public function actionProfile(\\Yiisoft\\Session\\SessionInterface $session)\n" +"{\n" +" // get a value\n" +" $lastAccessTime = $session->get('lastAccessTime');\n" +"\n" +" // get all values\n" +" $sessionData = $session->all();\n" +" \n" +" // set a value\n" +" $session->set('lastAccessTime', time());\n" +"\n" +" // check if the value exists\n" +" if ($session->has('lastAccessTime')) {\n" +" // ... \n" +" }\n" +" \n" +" // remove value\n" +" $session->remove('lastAccessTime');\n" +"\n" +" // get value and then remove it\n" +" $sessionData = $session->pull('lastAccessTime');\n" +"\n" +" // clear session data from runtime\n" +" $session->clear();\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/sessions.md +#, no-wrap +msgid "Flash messages" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "In case you need some data to remain in session until read, such as in case of displaying a message on the next page, \"flash\" messages are what you need. A flash message is a special type of data that's available only in the current request and the next request. After that, it will be deleted automatically." +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +#, fuzzy +#| msgid "That's equal to the following:" +msgid "`FlashInteface` usage is the following:" +msgstr "Это соответствует:" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"/** @var Yiisoft\\Session\\Flash\\FlashInterface $flash */\n" +"\n" +"// request 1\n" +"$flash->set('warning', 'Oh no, not again.');\n" +"\n" +"// request 2\n" +"$warning = $flash->get('warning');\n" +"if ($warning !== null) {\n" +" // do something with it\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/sessions.md +#, no-wrap +msgid "Custom session storage" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "When using `Yiisoft\\Session\\Session`, you can use your own storage implementation:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"$handler = new MySessionHandler();\n" +"$session = new \\Yiisoft\\Session\\Session([], $handler);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "Custom storage must implement `\\SessionHandlerInterface`." +msgstr "" diff --git a/guide/po/runtime_sessions.md/runtime_sessions.md.pot b/guide/po/runtime_sessions.md/runtime_sessions.md.pot new file mode 100644 index 00000000..4defba3a --- /dev/null +++ b/guide/po/runtime_sessions.md/runtime_sessions.md.pot @@ -0,0 +1,270 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/runtime/sessions.md +#, no-wrap +msgid "Sessions" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "" +"Sessions persist data between requests without passing them to the client " +"and back. Yii has [a session package](https://github.com/yiisoft/session) " +"to work with session data." +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "To add it to your application, use composer:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/runtime/sessions.md +#, no-wrap +msgid "composer require yiisoft/session\n" +msgstr "" + +#. type: Title ## +#: en/runtime/sessions.md +#, no-wrap +msgid "Configuring middleware" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "" +"To keep a session between requests, you need to add `SessionMiddleware` to " +"your route group or application middlewares. You should prefer a route " +"group when you have both API with token-based authentication and regular web " +"routes in the same application. Having it this way avoids starting the " +"session for API endpoints." +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "" +"To add a session for a certain group of routes, edit `config/routes.php` " +"like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"middleware(SessionMiddleware::class)\n" +" ->routes(\n" +" // ...\n" +" )\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "" +"To add a session to the whole application, edit `config/application.php` " +"like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"return [\n" +" Yiisoft\\Yii\\Web\\Application::class => [\n" +" '__construct()' => [\n" +" 'dispatcher' => DynamicReference::to(static function (Injector $injector) {\n" +" return ($injector->make(MiddlewareDispatcher::class))\n" +" ->withMiddlewares(\n" +" [\n" +" Router::class,\n" +" CsrfMiddleware::class,\n" +" SessionMiddleware::class, // <-- add this\n" +" ErrorCatcher::class,\n" +" ]\n" +" );\n" +" }),\n" +" ],\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/runtime/sessions.md +#, no-wrap +msgid "Opening and closing session" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"public function actionProfile(\\Yiisoft\\Session\\SessionInterface $session)\n" +"{\n" +" // start a session if it's not yet started\n" +" $session->open();\n" +"\n" +" // work with session\n" +"\n" +" // write session values and then close it\n" +" $session->close();\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> Closing session as early as possible is a good practice since many session implementations are blocking other\n" +"> requests while the session is open.\n" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "There are two more ways to close a session:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"public function actionProfile(\\Yiisoft\\Session\\SessionInterface $session)\n" +"{\n" +" // discard changes and close the session\n" +" $session->discard();\n" +"\n" +" // destroy the session completely\n" +" $session->destroy(); \n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/sessions.md +#, no-wrap +msgid "Working with session data" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "Usually you will use the following methods to work with session data:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"public function actionProfile(\\Yiisoft\\Session\\SessionInterface $session)\n" +"{\n" +" // get a value\n" +" $lastAccessTime = $session->get('lastAccessTime');\n" +"\n" +" // get all values\n" +" $sessionData = $session->all();\n" +" \n" +" // set a value\n" +" $session->set('lastAccessTime', time());\n" +"\n" +" // check if the value exists\n" +" if ($session->has('lastAccessTime')) {\n" +" // ... \n" +" }\n" +" \n" +" // remove value\n" +" $session->remove('lastAccessTime');\n" +"\n" +" // get value and then remove it\n" +" $sessionData = $session->pull('lastAccessTime');\n" +"\n" +" // clear session data from runtime\n" +" $session->clear();\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/sessions.md +#, no-wrap +msgid "Flash messages" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "" +"In case you need some data to remain in session until read, such as in case " +"of displaying a message on the next page, \"flash\" messages are what you " +"need. A flash message is a special type of data that's available only in " +"the current request and the next request. After that, it will be deleted " +"automatically." +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "`FlashInteface` usage is the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"/** @var Yiisoft\\Session\\Flash\\FlashInterface $flash */\n" +"\n" +"// request 1\n" +"$flash->set('warning', 'Oh no, not again.');\n" +"\n" +"// request 2\n" +"$warning = $flash->get('warning');\n" +"if ($warning !== null) {\n" +" // do something with it\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/runtime/sessions.md +#, no-wrap +msgid "Custom session storage" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "" +"When using `Yiisoft\\Session\\Session`, you can use your own storage " +"implementation:" +msgstr "" + +#. type: Fenced code block (php) +#: en/runtime/sessions.md +#, no-wrap +msgid "" +"$handler = new MySessionHandler();\n" +"$session = new \\Yiisoft\\Session\\Session([], $handler);\n" +msgstr "" + +#. type: Plain text +#: en/runtime/sessions.md +msgid "Custom storage must implement `\\SessionHandlerInterface`." +msgstr "" diff --git a/guide/po/security_authentication.md/ru/security_authentication.md.ru.po b/guide/po/security_authentication.md/ru/security_authentication.md.ru.po new file mode 100644 index 00000000..64920b21 --- /dev/null +++ b/guide/po/security_authentication.md/ru/security_authentication.md.ru.po @@ -0,0 +1,315 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/security/authentication.md +#, no-wrap +msgid "Authentication" +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "Authentication is the process of verifying the identity of a user. It usually uses an identifier (for example, a username or an email address) and a secret token (such as a password or an access token) to judge if the user is the one whom he claims as. Authentication is the basis of the login feature." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "Yii provides an authentication framework which wires up various components to support login. To use this framework, you mainly need to do the following work:" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "Configure the `Yiisoft\\Yii\\Web\\User\\User` service;" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "Create a class implementing the `\\Yiisoft\\Auth\\IdentityInterface` interface;" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "Create a class implementing the `\\Yiisoft\\Auth\\IdentityRepositoryInterface` interface;" +msgstr "" + +#. type: Title ## +#: en/security/authentication.md +#, fuzzy, no-wrap +#| msgid "Configuring container " +msgid "Configuring `Yiisoft\\Yii\\Web\\User\\User` " +msgstr "Конфигурирование контейнера " + +#. type: Plain text +#: en/security/authentication.md +msgid "The `Yiisoft\\Yii\\Web\\User\\User` application service manages the user authentication status. It depends on `Yiisoft\\Auth\\IdentityRepositoryInterface` that should return an instance of `\\Yiisoft\\Auth\\IdentityInterface` which has the actual authentication logic." +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"use Yiisoft\\Session\\Session;\n" +"use Yiisoft\\Session\\SessionInterface;\n" +"use Yiisoft\\Auth\\IdentityRepositoryInterface;\n" +"use Psr\\Container\\ContainerInterface;\n" +"\n" +"return [\n" +" // ...\n" +"\n" +" SessionInterface::class => [\n" +" 'class' => Session::class,\n" +" '__construct()' => [\n" +" $params['session']['options'] ?? [],\n" +" $params['session']['handler'] ?? null,\n" +" ],\n" +" ],\n" +" \n" +" \n" +" // User:\n" +" IdentityRepositoryInterface::class => static function (ContainerInterface $container) {\n" +" // instead of Cycle-based repository, you can use any implementation\n" +" return $container->get(\\Cycle\\ORM\\ORMInterface::class)->getRepository(\\App\\Entity\\User::class);\n" +" },\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/security/authentication.md +#, no-wrap +msgid "Implementing`\\Yiisoft\\Auth\\IdentityInterface` " +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "The identity class must implement the `\\Yiisoft\\Auth\\IdentityInterface` which has a single method:" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "[[yii\\web\\IdentityInterface::getId()|getId()]]: it returns the ID of the user represented by this identity instance." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "In the following example, an identity class implemented as a pure PHP object." +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"id;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/security/authentication.md +#, no-wrap +msgid "Implementing`\\Yiisoft\\Auth\\IdentityRepositoryInterface` " +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "The identity repository class must implement the `\\Yiisoft\\Auth\\IdentityRepositoryInterface` which has the following methods:" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "`findIdentity(string $id): ?IdentityInterface`: it looks for an instance of the identity class using the specified ID. This method is used when you need to keep the login status via session." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "`findIdentityByToken(string $token, string $type): ?IdentityInterface`: it looks for an instance of the identity class using the specified access token. This method is used when you need to authenticate a user by a single secret token (for example, in a stateless REST API)." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "A dummy implementation may look like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"namespace App\\User;\n" +"\n" +"use App\\User\\Identity;\n" +"use \\Yiisoft\\Auth\\IdentityInterface;\n" +"use \\Yiisoft\\Auth\\IdentityRepositoryInterface;\n" +"\n" +"final readonly class IdentityRepository implements IdentityRepositoryInterface\n" +"{\n" +" private const USERS = [\n" +" [\n" +" 'id' => 1,\n" +" 'token' => '12345' \n" +" ],\n" +" [\n" +" 'id' => 42,\n" +" 'token' => '54321'\n" +" ], \n" +" ];\n" +"\n" +" public function findIdentity(string $id) : ?IdentityInterface\n" +" {\n" +" foreach (self::USERS as $user) {\n" +" if ((string)$user['id'] === $id) {\n" +" return new Identity($id); \n" +" }\n" +" }\n" +" \n" +" return null;\n" +" }\n" +"\n" +" public function findIdentityByToken(string $token, string $type) : ?IdentityInterface\n" +" {\n" +" foreach (self::USERS as $user) {\n" +" if ($user['token'] === $token) {\n" +" return new Identity((string)$user['id']); \n" +" }\n" +" }\n" +" \n" +" return null;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/security/authentication.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Using `\\Yiisoft\\User\\User` " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/security/authentication.md +msgid "You can use `\\Yiisoft\\User\\User` service to obtain current user identity. As any service, it could be auto wired in either action handler constructor or method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"use \\Psr\\Http\\Message\\ServerRequestInterface;\n" +"use \\Yiisoft\\User\\User;\n" +"\n" +"final readonly class SiteController\n" +"{\n" +" public function actionIndex(ServerRequestInterface $request, User $user)\n" +" { \n" +" if ($user->isGuest()) {\n" +" // user is guest\n" +" } else {\n" +" $identity = $user->getIdentity();\n" +" // do something based on identity\n" +" } \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "`isGuest()` determines if user is logged in or not. `getIdentity()` returns an instance of identity." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "To log in a user, you may use the following code:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"$identity = $identityRepository->findByEmail($email);\n" +"\n" +"/* @var $user \\Yiisoft\\User\\User */\n" +"$user->login($identity);\n" +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "The `login()` method sets the identity to the User service. It stores identity into session so user authentication status is maintained." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "To logout a user, simply call" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"/* @var $user \\Yiisoft\\User\\User */\n" +"$user->logout();\n" +msgstr "" + +#. type: Title ## +#: en/security/authentication.md +#, fuzzy, no-wrap +#| msgid "References " +msgid "Authentication Events " +msgstr "Полезные ссылки " + +#. type: Plain text +#: en/security/authentication.md +msgid "The user service raises a few events during the login and logout processes." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "`\\Yiisoft\\User\\Event\\BeforeLogin`: raised at the beginning of `login()`. If the event handler calls `invalidate()` on an event object, the login process will be cancelled." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "`\\Yiisoft\\User\\Event\\AfterLogin`: raised after a successful login." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "`\\Yiisoft\\User\\Event\\BeforeLogout`: raised at the beginning of `logout()`. If the event handler calls `invalidate()` on an event object, the logout process will be cancelled." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "`\\Yiisoft\\User\\Event\\AfterLogout`: raised after a successful logout." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "You may respond to these events to implement features such as login audit, online user statistics. For example, in the handler for `\\Yiisoft\\User\\Event\\AfterLogin`, you may record the login time and IP address in the `user` database table." +msgstr "" diff --git a/guide/po/security_authentication.md/security_authentication.md.pot b/guide/po/security_authentication.md/security_authentication.md.pot new file mode 100644 index 00000000..c7d17197 --- /dev/null +++ b/guide/po/security_authentication.md/security_authentication.md.pot @@ -0,0 +1,363 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/security/authentication.md +#, no-wrap +msgid "Authentication" +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"Authentication is the process of verifying the identity of a user. It " +"usually uses an identifier (for example, a username or an email address) and " +"a secret token (such as a password or an access token) to judge if the user " +"is the one whom he claims as. Authentication is the basis of the login " +"feature." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"Yii provides an authentication framework which wires up various components " +"to support login. To use this framework, you mainly need to do the following " +"work:" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "Configure the `Yiisoft\\Yii\\Web\\User\\User` service;" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "" +"Create a class implementing the `\\Yiisoft\\Auth\\IdentityInterface` " +"interface;" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "" +"Create a class implementing the " +"`\\Yiisoft\\Auth\\IdentityRepositoryInterface` interface;" +msgstr "" + +#. type: Title ## +#: en/security/authentication.md +#, no-wrap +msgid "Configuring `Yiisoft\\Yii\\Web\\User\\User` " +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"The `Yiisoft\\Yii\\Web\\User\\User` application service manages the user " +"authentication status. It depends on " +"`Yiisoft\\Auth\\IdentityRepositoryInterface` that should return an instance " +"of `\\Yiisoft\\Auth\\IdentityInterface` which has the actual authentication " +"logic." +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"use Yiisoft\\Session\\Session;\n" +"use Yiisoft\\Session\\SessionInterface;\n" +"use Yiisoft\\Auth\\IdentityRepositoryInterface;\n" +"use Psr\\Container\\ContainerInterface;\n" +"\n" +"return [\n" +" // ...\n" +"\n" +" SessionInterface::class => [\n" +" 'class' => Session::class,\n" +" '__construct()' => [\n" +" $params['session']['options'] ?? [],\n" +" $params['session']['handler'] ?? null,\n" +" ],\n" +" ],\n" +" \n" +" \n" +" // User:\n" +" IdentityRepositoryInterface::class => static function (ContainerInterface $container) {\n" +" // instead of Cycle-based repository, you can use any implementation\n" +" return $container->get(\\Cycle\\ORM\\ORMInterface::class)->getRepository(\\App\\Entity\\User::class);\n" +" },\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/security/authentication.md +#, no-wrap +msgid "Implementing`\\Yiisoft\\Auth\\IdentityInterface` " +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"The identity class must implement the `\\Yiisoft\\Auth\\IdentityInterface` " +"which has a single method:" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "" +"[[yii\\web\\IdentityInterface::getId()|getId()]]: it returns the ID of the " +"user represented by this identity instance." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"In the following example, an identity class implemented as a pure PHP object." +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"id;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/security/authentication.md +#, no-wrap +msgid "Implementing`\\Yiisoft\\Auth\\IdentityRepositoryInterface` " +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"The identity repository class must implement the " +"`\\Yiisoft\\Auth\\IdentityRepositoryInterface` which has the following " +"methods:" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "" +"`findIdentity(string $id): ?IdentityInterface`: it looks for an instance of " +"the identity class using the specified ID. This method is used when you need " +"to keep the login status via session." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "" +"`findIdentityByToken(string $token, string $type): ?IdentityInterface`: it " +"looks for an instance of the identity class using the specified access " +"token. This method is used when you need to authenticate a user by a single " +"secret token (for example, in a stateless REST API)." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "A dummy implementation may look like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"namespace App\\User;\n" +"\n" +"use App\\User\\Identity;\n" +"use \\Yiisoft\\Auth\\IdentityInterface;\n" +"use \\Yiisoft\\Auth\\IdentityRepositoryInterface;\n" +"\n" +"final readonly class IdentityRepository implements IdentityRepositoryInterface\n" +"{\n" +" private const USERS = [\n" +" [\n" +" 'id' => 1,\n" +" 'token' => '12345' \n" +" ],\n" +" [\n" +" 'id' => 42,\n" +" 'token' => '54321'\n" +" ], \n" +" ];\n" +"\n" +" public function findIdentity(string $id) : ?IdentityInterface\n" +" {\n" +" foreach (self::USERS as $user) {\n" +" if ((string)$user['id'] === $id) {\n" +" return new Identity($id); \n" +" }\n" +" }\n" +" \n" +" return null;\n" +" }\n" +"\n" +" public function findIdentityByToken(string $token, string $type) : ?IdentityInterface\n" +" {\n" +" foreach (self::USERS as $user) {\n" +" if ($user['token'] === $token) {\n" +" return new Identity((string)$user['id']); \n" +" }\n" +" }\n" +" \n" +" return null;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/security/authentication.md +#, no-wrap +msgid "Using `\\Yiisoft\\User\\User` " +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"You can use `\\Yiisoft\\User\\User` service to obtain current user " +"identity. As any service, it could be auto wired in either action handler " +"constructor or method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"use \\Psr\\Http\\Message\\ServerRequestInterface;\n" +"use \\Yiisoft\\User\\User;\n" +"\n" +"final readonly class SiteController\n" +"{\n" +" public function actionIndex(ServerRequestInterface $request, User $user)\n" +" { \n" +" if ($user->isGuest()) {\n" +" // user is guest\n" +" } else {\n" +" $identity = $user->getIdentity();\n" +" // do something based on identity\n" +" } \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"`isGuest()` determines if user is logged in or not. `getIdentity()` returns " +"an instance of identity." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "To log in a user, you may use the following code:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"$identity = $identityRepository->findByEmail($email);\n" +"\n" +"/* @var $user \\Yiisoft\\User\\User */\n" +"$user->login($identity);\n" +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"The `login()` method sets the identity to the User service. It stores " +"identity into session so user authentication status is maintained." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "To logout a user, simply call" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authentication.md +#, no-wrap +msgid "" +"/* @var $user \\Yiisoft\\User\\User */\n" +"$user->logout();\n" +msgstr "" + +#. type: Title ## +#: en/security/authentication.md +#, no-wrap +msgid "Authentication Events " +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"The user service raises a few events during the login and logout processes." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "" +"`\\Yiisoft\\User\\Event\\BeforeLogin`: raised at the beginning of " +"`login()`. If the event handler calls `invalidate()` on an event object, " +"the login process will be cancelled." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "`\\Yiisoft\\User\\Event\\AfterLogin`: raised after a successful login." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "" +"`\\Yiisoft\\User\\Event\\BeforeLogout`: raised at the beginning of " +"`logout()`. If the event handler calls `invalidate()` on an event object, " +"the logout process will be cancelled." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/authentication.md +msgid "" +"`\\Yiisoft\\User\\Event\\AfterLogout`: raised after a successful logout." +msgstr "" + +#. type: Plain text +#: en/security/authentication.md +msgid "" +"You may respond to these events to implement features such as login audit, " +"online user statistics. For example, in the handler for " +"`\\Yiisoft\\User\\Event\\AfterLogin`, you may record the login time and IP " +"address in the `user` database table." +msgstr "" diff --git a/guide/po/security_authorization.md/ru/security_authorization.md.ru.po b/guide/po/security_authorization.md/ru/security_authorization.md.ru.po new file mode 100644 index 00000000..8215694f --- /dev/null +++ b/guide/po/security_authorization.md/ru/security_authorization.md.ru.po @@ -0,0 +1,686 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/security/authorization.md +#, no-wrap +msgid "Authorization" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Authorization is the process of verifying that a user has enough permission to do something." +msgstr "" + +#. type: Title ## +#: en/security/authorization.md +#, fuzzy, no-wrap +#| msgid "Injecting dependencies " +msgid "Checking for permission " +msgstr "Внедрение зависимостей " + +#. type: Plain text +#: en/security/authorization.md +msgid "You can check if a user has certain permissions by using `\\Yiisoft\\User\\User` service:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"namespace App\\Blog\\Post;\n" +"\n" +"use Yiisoft\\Router\\CurrentRoute;\n" +"use Yiisoft\\User\\User;\n" +"\n" +"final readonly class PostController\n" +"{\n" +" public function actionEdit(CurrentRoute $route, User $user, PostRepository $postRepository)\n" +" {\n" +" $postId = $route->getArgument('id');\n" +" if ($postId === null) {\n" +" // respond with 404 \n" +" }\n" +" \n" +" $post = $postRepository->findByPK($postId);\n" +" if ($post === null) {\n" +" // respond with 404 \n" +" }\n" +"\n" +" if (!$this->canEditPost($user, $post)) {\n" +" // respond with 403 \n" +" }\n" +" \n" +" // continue with editing a post\n" +" }\n" +" \n" +" private function canEditPost(User $user, Post $post): bool\n" +" {\n" +" return $post->getAuthorId() === $user->getId() || $user->can('updatePost'); \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Behind the scenes, `Yiisoft\\Yii\\Web\\User\\User::can()` method calls `\\Yiisoft\\Access\\AccessCheckerInterface::userHasPermission()` so you should provide an implementation in dependency container in order for it to work." +msgstr "" + +#. type: Title ## +#: en/security/authorization.md +#, no-wrap +msgid "Role-based access control (RBAC) " +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Role-Based Access Control (RBAC) provides a simple yet powerful centralized access control. Please refer to the [Wikipedia](https://en.wikipedia.org/wiki/Role-based_access_control) for details about comparing RBAC with other more traditional access control schemes." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Yii implements a General Hierarchical RBAC, following the [NIST RBAC model](https://csrc.nist.gov/CSRC/media/Publications/conference-paper/2000/07/26/the-nist-model-for-role-based-access-control-towards-a-unified-/documents/sandhu-ferraiolo-kuhn-00.pdf)." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Using RBAC involves two parts of work. The first part is to build up the RBAC authorization data, and the second part is to use the authorization data to perform access check in places where it's necessary. Since RBAC implements `\\Yiisoft\\Access\\AccessCheckerInterface`, using it's similar to using any other implementation of an access checker." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "To ease description next, there are some basic RBAC concepts first." +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, fuzzy, no-wrap +#| msgid "DI container " +msgid "Basic concepts " +msgstr "Контейнер внедрения зависимостей " + +#. type: Plain text +#: en/security/authorization.md +msgid "A role represents a collection of *permissions* (for example, creating posts, updating posts). You may assign a role to one or many users. To check if a user has a specified permission, you may check if the user has a role with that permission." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Associated with each role or permission, there may be a *rule*. A rule represents a piece of code that access checker will execute to decide if the corresponding role or permission applies to the current user. For example, the \"update post\" permission may have a rule that checks if the current user is the post creator. During access checking, if the user is NOT the post creator, there's no \"update post\" permission." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Both roles and permissions are in a hierarchy. In particular, a role may consist of other roles or permissions. And a permission may consist of other permissions. Yii implements a *partial order* hierarchy which includes the more special *tree* hierarchy. While a role can contain a permission, it isn't `true` vice versa." +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, fuzzy, no-wrap +#| msgid "Configuring container " +msgid "Configuring RBAC " +msgstr "Конфигурирование контейнера " + +#. type: Plain text +#: en/security/authorization.md +msgid "RBAC is available via `yiisoft/rbac` package, so you need to require it:" +msgstr "" + +#. type: Fenced code block +#: en/security/authorization.md +#, fuzzy, no-wrap +#| msgid "composer install yiisoft/security\n" +msgid "composer require yiisoft/rbac\n" +msgstr "composer install yiisoft/security\n" + +#. type: Plain text +#: en/security/authorization.md +msgid "Before we set off to define authorization data and perform access checking, you need to configure the `\\Yiisoft\\Access\\AccessCheckerInterface` in dependency container:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"use \\Psr\\Container\\ContainerInterface;\n" +"use Yiisoft\\Rbac\\Manager\\PhpManager;\n" +"use Yiisoft\\Rbac\\RuleFactory\\ClassNameRuleFactory;\n" +"\n" +"return [\n" +" \\Yiisoft\\Access\\AccessCheckerInterface::class => static function (ContainerInterface $container) {\n" +" $aliases = $container->get(\\Yiisoft\\Aliases\\Aliases::class);\n" +" return new PhpManager(new ClassNameRuleFactory(), $aliases->get('@rbac'));\n" +" }\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "`\\Yiisoft\\Rbac\\Manager\\PhpManager` uses a PHP script files to store authorization data. The files are under `@rbac` alias. Make sure the directory and all the files in it are writable by the Web server process if you want to change permission hierarchy online." +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, fuzzy, no-wrap +#| msgid "Defining aliases " +msgid "Building authorization data " +msgstr "Определение псевдонимов " + +#. type: Plain text +#: en/security/authorization.md +msgid "Building authorization data is all about the following tasks:" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/authorization.md +msgid "defining roles and permissions;" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/authorization.md +msgid "establishing relations between roles and permissions;" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/authorization.md +msgid "defining rules;" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/authorization.md +msgid "associating rules with roles and permissions;" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/authorization.md +msgid "assigning roles to users." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Depending on authorization flexibility requirements, you can do the tasks in different ways. If only developers change your permission hierarchy, you can use either migrations or a console command. Migration advantage is that you could execute it along with other migrations. The Console command advantage is that you have a good overview of the hierarchy in the code without a need to read many migrations." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Either way, in the end, you'll get the following RBAC hierarchy:" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "![Simple RBAC hierarchy](img/rbac-hierarchy-1.svg \"Simple RBAC hierarchy\")" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "In case you want to build permission hierarchy dynamically, you need a UI or a console command. The API used to build the hierarchy itself won't be different." +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, no-wrap +msgid "Using console command" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "If your permission hierarchy doesn't change at all, and you have a fixed number of users, you can create a [console command](../tutorial/console-applications.md) that will initialize authorization data once via APIs offered by `\\Yiisoft\\Rbac\\ManagerInterface`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"manager;\n" +"\n" +" $auth->removeAll(); \n" +" \n" +" $createPost = (new Permission('createPost'))->withDescription('Create a post'); \n" +" $auth->add($createPost);\n" +"\n" +" $updatePost = (new Permission('updatePost'))->withDescription('Update post');\n" +" $auth->add($updatePost);\n" +"\n" +" // add \"author\" role and give this role the \"createPost\" permission\n" +" $author = new Role('author');\n" +" $auth->add($author);\n" +" $auth->addChild($author, $createPost);\n" +"\n" +" // add the \"admin\" role and give this role the \"updatePost\" permission\n" +" // as well as the permissions of the \"author\" role\n" +" $admin = new Role('admin');\n" +" $auth->add($admin);\n" +" $auth->addChild($admin, $updatePost);\n" +" $auth->addChild($admin, $author);\n" +"\n" +" // Assign roles to users. 1 and 2 are IDs returned by IdentityInterface::getId()\n" +" // usually implemented in your User model.\n" +" $auth->assign($author, 2);\n" +" $auth->assign($admin, 1);\n" +" \n" +" return ExitCode::OK;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "You can execute the command above from the console the following way:" +msgstr "" + +#. type: Fenced code block +#: en/security/authorization.md +#, no-wrap +msgid "./yii rbac:init\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +#, no-wrap +msgid "" +"> If you don't want to hardcode what users have certain roles, don't put `->assign()` calls into the command. Instead,\n" +" create either UI or console command to manage assignments.\n" +msgstr "" + +#. type: Title #### +#: en/security/authorization.md +#, no-wrap +msgid "Using migrations" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +#, no-wrap +msgid "**TODO**: finish it when migrations are implemented.\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "You can use [migrations](../databases/db-migrations.md) to initialize and change hierarchy via APIs offered by `\\Yiisoft\\Rbac\\ManagerInterface`." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Create new migration using `./yii migrate:create init_rbac` then implement creating a hierarchy:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"removeAll(); \n" +" \n" +" $createPost = (new Permission('createPost'))->withDescription('Create a post'); \n" +" $auth->add($createPost);\n" +"\n" +" $updatePost = (new Permission('updatePost'))->withDescription('Update post');\n" +" $auth->add($updatePost);\n" +"\n" +" // add \"author\" role and give this role the \"createPost\" permission\n" +" $author = new Role('author');\n" +" $auth->add($author);\n" +" $auth->addChild($author, $createPost);\n" +"\n" +" // add the \"admin\" role and give this role the \"updatePost\" permission\n" +" // as well as the permissions of the \"author\" role\n" +" $admin = new Role('admin');\n" +" $auth->add($admin);\n" +" $auth->addChild($admin, $updatePost);\n" +" $auth->addChild($admin, $author);\n" +"\n" +" // Assign roles to users. 1 and 2 are IDs returned by IdentityInterface::getId()\n" +" // usually implemented in your User model.\n" +" $auth->assign($author, 2);\n" +" $auth->assign($admin, 1);\n" +" }\n" +" \n" +" public function down()\n" +" {\n" +" $auth = /* obtain auth */;\n" +"\n" +" $auth->removeAll();\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +#, no-wrap +msgid "" +"> If you don't want to hardcode which users have certain roles, don't put `->assign()` calls in migrations. Instead,\n" +" create either UI or console command to manage assignments.\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "You could apply migration by using `./yii migrate`." +msgstr "" + +#. type: Title ## +#: en/security/authorization.md +#, no-wrap +msgid "Assigning roles to users" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +#, no-wrap +msgid "TODO: update when signup implemented in demo / template.\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "The author can create a post, admin can update post and do everything the author can." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "If your application allows user signup, you need to assign roles to these new users once. For example, in order for all signed-up users to become authors in your advanced project template you need to change `frontend\\models\\SignupForm::signup()` as follows:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"public function signup()\n" +"{\n" +" if ($this->validate()) {\n" +" $user = new User();\n" +" $user->username = $this->username;\n" +" $user->email = $this->email;\n" +" $user->setPassword($this->password);\n" +" $user->generateAuthKey();\n" +" $user->save(false);\n" +"\n" +" // the following three lines were added:\n" +" $auth = \\Yii::$app->authManager;\n" +" $authorRole = $auth->getRole('author');\n" +" $auth->assign($authorRole, $user->getId());\n" +"\n" +" return $user;\n" +" }\n" +"\n" +" return null;\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "For applications that require complex access control with dynamically updated authorization data (such as an admin panel), you many need to develop special user interfaces using APIs offered by `authManager`." +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Using rules " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/security/authorization.md +msgid "As aforementioned, rules add extra constraint to roles and permissions. A rule is a class extending from `\\Yiisoft\\Rbac\\Rule`. It must implement the `execute()` method. In the hierarchy you've created before, the author can't edit his own post. Let's fix it. First, you need a rule to verify that the user is the post author:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"namespace App\\User\\Rbac;\n" +"\n" +"use Yiisoft\\Rbac\\Item;\n" +"use \\Yiisoft\\Rbac\\Rule;\n" +"\n" +"/**\n" +" * Checks if authorID matches user passed via params.\n" +" */\n" +"final readonly class AuthorRule extends Rule\n" +"{\n" +" private const NAME = 'isAuthor';\n" +"\n" +" public function __construct() {\n" +" parent::__construct(self::NAME);\n" +" }\n" +"\n" +" public function execute(string $userId, Item $item, array $parameters = []): bool\n" +" {\n" +" return isset($params['post']) ? $params['post']->getAuthorId() == $userId : false;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "The rule checks if user created the `post`. Create a special permission `updateOwnPost` in the command you've used before:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"/** @var \\Yiisoft\\Rbac\\ManagerInterface $auth */\n" +"\n" +"// add the rule\n" +"$rule = new AuthorRule();\n" +"$auth->add($rule);\n" +"\n" +"// add the \"updateOwnPost\" permission and associate the rule with it.\n" +"$updateOwnPost = (new \\Yiisoft\\Rbac\\Permission('updateOwnPost'))\n" +" ->withDescription('Update own post')\n" +" ->withRuleName($rule->getName());\n" +"$auth->add($updateOwnPost);\n" +"\n" +"// \"updateOwnPost\" will be used from \"updatePost\"\n" +"$auth->addChild($updateOwnPost, $updatePost);\n" +"\n" +"// allow \"author\" to update their own posts\n" +"$auth->addChild($author, $updateOwnPost);\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Now you've got the following hierarchy:" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "![RBAC hierarchy with a rule](img/rbac-hierarchy-2.svg \"RBAC hierarchy with a rule\")" +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, fuzzy, no-wrap +#| msgid "References " +msgid "Access check " +msgstr "Полезные ссылки " + +#. type: Plain text +#: en/security/authorization.md +msgid "The check is done similar to how it was done in the first section of this guide:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"namespace App\\Blog\\Post;\n" +"\n" +"use Psr\\Http\\Message\\ServerRequestInterface;\n" +"use Yiisoft\\User\\User;\n" +"\n" +"final readonly class PostController\n" +"{\n" +" public function actionEdit(ServerRequestInterface $request, User $user, PostRepository $postRepository)\n" +" {\n" +" $postId = $request->getAttribute('id');\n" +" if ($postId === null) {\n" +" // respond with 404 \n" +" }\n" +" \n" +" $post = $postRepository->findByPK($postId);\n" +" if ($post === null) {\n" +" // respond with 404 \n" +" }\n" +"\n" +" if (!$this->canEditPost($user, $post)) {\n" +" // respond with 403 \n" +" }\n" +" \n" +" // continue with editing a post\n" +" }\n" +" \n" +" private function canEditPost(User $user, Post $post): bool\n" +" {\n" +" return $user->can('updatePost', ['post' => $post]); \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "The difference is that now checking for user's own post is part of the RBAC." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "If the current user is Jane with `ID=1` you are starting at `createPost` and trying to get to `Jane`:" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "![Access check](img/rbac-access-check-1.svg \"Access check\")" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "To check if a user can update a post, you need to pass an extra parameter that's required by `AuthorRule` described before:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"if ($user->can('updatePost', ['post' => $post])) {\n" +" // update post\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Here is what happens if the current user is John:" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "![Access check](img/rbac-access-check-2.svg \"Access check\")" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +#, no-wrap +msgid "" +"You're starting with the `updatePost` and going through `updateOwnPost`. To pass the access check, `AuthorRule`\n" +"should return `true` from its `execute()` method. The method receives its `$params` from the `can()` method call, so the value is\n" +"`['post' => $post]`.\n" +"If everything is fine, you will get to `author` assigned to John.\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "In the case of Jane, it's a bit simpler since she is an admin:" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "![Access check](img/rbac-access-check-3.svg \"Access check\")" +msgstr "" + +#. type: Title ## +#: en/security/authorization.md +#, no-wrap +msgid "Implementing your own access checker" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "If RBAC doesn't suit your needs, you can implement your own access checker without changing the application code:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"namespace App\\User;\n" +"\n" +"use \\Yiisoft\\Access\\AccessCheckerInterface;\n" +"\n" +"final readonly class AccessChecker implements AccessCheckerInterface\n" +"{\n" +" private const PERMISSIONS = [\n" +" [\n" +" 1 => ['editPost'],\n" +" 42 => ['editPost', 'deletePost'],\n" +" ],\n" +" ];\n" +"\n" +" public function userHasPermission($userId, string $permissionName, array $parameters = []) : bool\n" +" {\n" +" if (!array_key_exists($userId, self::PERMISSIONS)) {\n" +" return false;\n" +" }\n" +"\n" +" return in_array($permissionName, self::PERMISSIONS[$userId], true); \n" +" }\n" +"}\n" +msgstr "" diff --git a/guide/po/security_authorization.md/security_authorization.md.pot b/guide/po/security_authorization.md/security_authorization.md.pot new file mode 100644 index 00000000..d14b9484 --- /dev/null +++ b/guide/po/security_authorization.md/security_authorization.md.pot @@ -0,0 +1,768 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/security/authorization.md +#, no-wrap +msgid "Authorization" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"Authorization is the process of verifying that a user has enough permission " +"to do something." +msgstr "" + +#. type: Title ## +#: en/security/authorization.md +#, no-wrap +msgid "Checking for permission " +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"You can check if a user has certain permissions by using " +"`\\Yiisoft\\User\\User` service:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"namespace App\\Blog\\Post;\n" +"\n" +"use Yiisoft\\Router\\CurrentRoute;\n" +"use Yiisoft\\User\\User;\n" +"\n" +"final readonly class PostController\n" +"{\n" +" public function actionEdit(CurrentRoute $route, User $user, PostRepository $postRepository)\n" +" {\n" +" $postId = $route->getArgument('id');\n" +" if ($postId === null) {\n" +" // respond with 404 \n" +" }\n" +" \n" +" $post = $postRepository->findByPK($postId);\n" +" if ($post === null) {\n" +" // respond with 404 \n" +" }\n" +"\n" +" if (!$this->canEditPost($user, $post)) {\n" +" // respond with 403 \n" +" }\n" +" \n" +" // continue with editing a post\n" +" }\n" +" \n" +" private function canEditPost(User $user, Post $post): bool\n" +" {\n" +" return $post->getAuthorId() === $user->getId() || $user->can('updatePost'); \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"Behind the scenes, `Yiisoft\\Yii\\Web\\User\\User::can()` method calls " +"`\\Yiisoft\\Access\\AccessCheckerInterface::userHasPermission()` so you " +"should provide an implementation in dependency container in order for it to " +"work." +msgstr "" + +#. type: Title ## +#: en/security/authorization.md +#, no-wrap +msgid "Role-based access control (RBAC) " +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"Role-Based Access Control (RBAC) provides a simple yet powerful centralized " +"access control. Please refer to the [Wikipedia](https://en.wikipedia.org/" +"wiki/Role-based_access_control) for details about comparing RBAC with other " +"more traditional access control schemes." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"Yii implements a General Hierarchical RBAC, following the [NIST RBAC model]" +"(https://csrc.nist.gov/CSRC/media/Publications/conference-paper/2000/07/26/" +"the-nist-model-for-role-based-access-control-towards-a-unified-/documents/" +"sandhu-ferraiolo-kuhn-00.pdf)." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"Using RBAC involves two parts of work. The first part is to build up the " +"RBAC authorization data, and the second part is to use the authorization " +"data to perform access check in places where it's necessary. Since RBAC " +"implements `\\Yiisoft\\Access\\AccessCheckerInterface`, using it's similar " +"to using any other implementation of an access checker." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "To ease description next, there are some basic RBAC concepts first." +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, no-wrap +msgid "Basic concepts " +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"A role represents a collection of *permissions* (for example, creating " +"posts, updating posts). You may assign a role to one or many users. To " +"check if a user has a specified permission, you may check if the user has a " +"role with that permission." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"Associated with each role or permission, there may be a *rule*. A rule " +"represents a piece of code that access checker will execute to decide if the " +"corresponding role or permission applies to the current user. For example, " +"the \"update post\" permission may have a rule that checks if the current " +"user is the post creator. During access checking, if the user is NOT the " +"post creator, there's no \"update post\" permission." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"Both roles and permissions are in a hierarchy. In particular, a role may " +"consist of other roles or permissions. And a permission may consist of " +"other permissions. Yii implements a *partial order* hierarchy which " +"includes the more special *tree* hierarchy. While a role can contain a " +"permission, it isn't `true` vice versa." +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, no-wrap +msgid "Configuring RBAC " +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"RBAC is available via `yiisoft/rbac` package, so you need to require it:" +msgstr "" + +#. type: Fenced code block +#: en/security/authorization.md +#, no-wrap +msgid "composer require yiisoft/rbac\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"Before we set off to define authorization data and perform access checking, " +"you need to configure the `\\Yiisoft\\Access\\AccessCheckerInterface` in " +"dependency container:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"use \\Psr\\Container\\ContainerInterface;\n" +"use Yiisoft\\Rbac\\Manager\\PhpManager;\n" +"use Yiisoft\\Rbac\\RuleFactory\\ClassNameRuleFactory;\n" +"\n" +"return [\n" +" \\Yiisoft\\Access\\AccessCheckerInterface::class => static function (ContainerInterface $container) {\n" +" $aliases = $container->get(\\Yiisoft\\Aliases\\Aliases::class);\n" +" return new PhpManager(new ClassNameRuleFactory(), $aliases->get('@rbac'));\n" +" }\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"`\\Yiisoft\\Rbac\\Manager\\PhpManager` uses a PHP script files to store " +"authorization data. The files are under `@rbac` alias. Make sure the " +"directory and all the files in it are writable by the Web server process if " +"you want to change permission hierarchy online." +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, no-wrap +msgid "Building authorization data " +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Building authorization data is all about the following tasks:" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/authorization.md +msgid "defining roles and permissions;" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/authorization.md +msgid "establishing relations between roles and permissions;" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/authorization.md +msgid "defining rules;" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/authorization.md +msgid "associating rules with roles and permissions;" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/authorization.md +msgid "assigning roles to users." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"Depending on authorization flexibility requirements, you can do the tasks in " +"different ways. If only developers change your permission hierarchy, you " +"can use either migrations or a console command. Migration advantage is that " +"you could execute it along with other migrations. The Console command " +"advantage is that you have a good overview of the hierarchy in the code " +"without a need to read many migrations." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Either way, in the end, you'll get the following RBAC hierarchy:" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"![Simple RBAC hierarchy](img/rbac-hierarchy-1.svg \"Simple RBAC hierarchy\")" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"In case you want to build permission hierarchy dynamically, you need a UI or " +"a console command. The API used to build the hierarchy itself won't be " +"different." +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, no-wrap +msgid "Using console command" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"If your permission hierarchy doesn't change at all, and you have a fixed " +"number of users, you can create a [console command](../tutorial/console-" +"applications.md) that will initialize authorization data once via APIs " +"offered by `\\Yiisoft\\Rbac\\ManagerInterface`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"manager;\n" +"\n" +" $auth->removeAll(); \n" +" \n" +" $createPost = (new Permission('createPost'))->withDescription('Create a post'); \n" +" $auth->add($createPost);\n" +"\n" +" $updatePost = (new Permission('updatePost'))->withDescription('Update post');\n" +" $auth->add($updatePost);\n" +"\n" +" // add \"author\" role and give this role the \"createPost\" permission\n" +" $author = new Role('author');\n" +" $auth->add($author);\n" +" $auth->addChild($author, $createPost);\n" +"\n" +" // add the \"admin\" role and give this role the \"updatePost\" permission\n" +" // as well as the permissions of the \"author\" role\n" +" $admin = new Role('admin');\n" +" $auth->add($admin);\n" +" $auth->addChild($admin, $updatePost);\n" +" $auth->addChild($admin, $author);\n" +"\n" +" // Assign roles to users. 1 and 2 are IDs returned by IdentityInterface::getId()\n" +" // usually implemented in your User model.\n" +" $auth->assign($author, 2);\n" +" $auth->assign($admin, 1);\n" +" \n" +" return ExitCode::OK;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "You can execute the command above from the console the following way:" +msgstr "" + +#. type: Fenced code block +#: en/security/authorization.md +#, no-wrap +msgid "./yii rbac:init\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +#, no-wrap +msgid "" +"> If you don't want to hardcode what users have certain roles, don't put `->assign()` calls into the command. Instead,\n" +" create either UI or console command to manage assignments.\n" +msgstr "" + +#. type: Title #### +#: en/security/authorization.md +#, no-wrap +msgid "Using migrations" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +#, no-wrap +msgid "**TODO**: finish it when migrations are implemented.\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"You can use [migrations](../databases/db-migrations.md) to initialize and " +"change hierarchy via APIs offered by `\\Yiisoft\\Rbac\\ManagerInterface`." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"Create new migration using `./yii migrate:create init_rbac` then implement " +"creating a hierarchy:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"removeAll(); \n" +" \n" +" $createPost = (new Permission('createPost'))->withDescription('Create a post'); \n" +" $auth->add($createPost);\n" +"\n" +" $updatePost = (new Permission('updatePost'))->withDescription('Update post');\n" +" $auth->add($updatePost);\n" +"\n" +" // add \"author\" role and give this role the \"createPost\" permission\n" +" $author = new Role('author');\n" +" $auth->add($author);\n" +" $auth->addChild($author, $createPost);\n" +"\n" +" // add the \"admin\" role and give this role the \"updatePost\" permission\n" +" // as well as the permissions of the \"author\" role\n" +" $admin = new Role('admin');\n" +" $auth->add($admin);\n" +" $auth->addChild($admin, $updatePost);\n" +" $auth->addChild($admin, $author);\n" +"\n" +" // Assign roles to users. 1 and 2 are IDs returned by IdentityInterface::getId()\n" +" // usually implemented in your User model.\n" +" $auth->assign($author, 2);\n" +" $auth->assign($admin, 1);\n" +" }\n" +" \n" +" public function down()\n" +" {\n" +" $auth = /* obtain auth */;\n" +"\n" +" $auth->removeAll();\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +#, no-wrap +msgid "" +"> If you don't want to hardcode which users have certain roles, don't put `->assign()` calls in migrations. Instead,\n" +" create either UI or console command to manage assignments.\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "You could apply migration by using `./yii migrate`." +msgstr "" + +#. type: Title ## +#: en/security/authorization.md +#, no-wrap +msgid "Assigning roles to users" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +#, no-wrap +msgid "TODO: update when signup implemented in demo / template.\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"The author can create a post, admin can update post and do everything the " +"author can." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"If your application allows user signup, you need to assign roles to these " +"new users once. For example, in order for all signed-up users to become " +"authors in your advanced project template you need to change " +"`frontend\\models\\SignupForm::signup()` as follows:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"public function signup()\n" +"{\n" +" if ($this->validate()) {\n" +" $user = new User();\n" +" $user->username = $this->username;\n" +" $user->email = $this->email;\n" +" $user->setPassword($this->password);\n" +" $user->generateAuthKey();\n" +" $user->save(false);\n" +"\n" +" // the following three lines were added:\n" +" $auth = \\Yii::$app->authManager;\n" +" $authorRole = $auth->getRole('author');\n" +" $auth->assign($authorRole, $user->getId());\n" +"\n" +" return $user;\n" +" }\n" +"\n" +" return null;\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"For applications that require complex access control with dynamically " +"updated authorization data (such as an admin panel), you many need to " +"develop special user interfaces using APIs offered by `authManager`." +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, no-wrap +msgid "Using rules " +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"As aforementioned, rules add extra constraint to roles and permissions. A " +"rule is a class extending from `\\Yiisoft\\Rbac\\Rule`. It must implement " +"the `execute()` method. In the hierarchy you've created before, the author " +"can't edit his own post. Let's fix it. First, you need a rule to verify " +"that the user is the post author:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"namespace App\\User\\Rbac;\n" +"\n" +"use Yiisoft\\Rbac\\Item;\n" +"use \\Yiisoft\\Rbac\\Rule;\n" +"\n" +"/**\n" +" * Checks if authorID matches user passed via params.\n" +" */\n" +"final readonly class AuthorRule extends Rule\n" +"{\n" +" private const NAME = 'isAuthor';\n" +"\n" +" public function __construct() {\n" +" parent::__construct(self::NAME);\n" +" }\n" +"\n" +" public function execute(string $userId, Item $item, array $parameters = []): bool\n" +" {\n" +" return isset($params['post']) ? $params['post']->getAuthorId() == $userId : false;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"The rule checks if user created the `post`. Create a special permission " +"`updateOwnPost` in the command you've used before:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"/** @var \\Yiisoft\\Rbac\\ManagerInterface $auth */\n" +"\n" +"// add the rule\n" +"$rule = new AuthorRule();\n" +"$auth->add($rule);\n" +"\n" +"// add the \"updateOwnPost\" permission and associate the rule with it.\n" +"$updateOwnPost = (new \\Yiisoft\\Rbac\\Permission('updateOwnPost'))\n" +" ->withDescription('Update own post')\n" +" ->withRuleName($rule->getName());\n" +"$auth->add($updateOwnPost);\n" +"\n" +"// \"updateOwnPost\" will be used from \"updatePost\"\n" +"$auth->addChild($updateOwnPost, $updatePost);\n" +"\n" +"// allow \"author\" to update their own posts\n" +"$auth->addChild($author, $updateOwnPost);\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Now you've got the following hierarchy:" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"![RBAC hierarchy with a rule](img/rbac-hierarchy-2.svg \"RBAC hierarchy with " +"a rule\")" +msgstr "" + +#. type: Title ### +#: en/security/authorization.md +#, no-wrap +msgid "Access check " +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"The check is done similar to how it was done in the first section of this " +"guide:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"namespace App\\Blog\\Post;\n" +"\n" +"use Psr\\Http\\Message\\ServerRequestInterface;\n" +"use Yiisoft\\User\\User;\n" +"\n" +"final readonly class PostController\n" +"{\n" +" public function actionEdit(ServerRequestInterface $request, User $user, PostRepository $postRepository)\n" +" {\n" +" $postId = $request->getAttribute('id');\n" +" if ($postId === null) {\n" +" // respond with 404 \n" +" }\n" +" \n" +" $post = $postRepository->findByPK($postId);\n" +" if ($post === null) {\n" +" // respond with 404 \n" +" }\n" +"\n" +" if (!$this->canEditPost($user, $post)) {\n" +" // respond with 403 \n" +" }\n" +" \n" +" // continue with editing a post\n" +" }\n" +" \n" +" private function canEditPost(User $user, Post $post): bool\n" +" {\n" +" return $user->can('updatePost', ['post' => $post]); \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"The difference is that now checking for user's own post is part of the RBAC." +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"If the current user is Jane with `ID=1` you are starting at `createPost` and " +"trying to get to `Jane`:" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "![Access check](img/rbac-access-check-1.svg \"Access check\")" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"To check if a user can update a post, you need to pass an extra parameter " +"that's required by `AuthorRule` described before:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"if ($user->can('updatePost', ['post' => $post])) {\n" +" // update post\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "Here is what happens if the current user is John:" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "![Access check](img/rbac-access-check-2.svg \"Access check\")" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +#, no-wrap +msgid "" +"You're starting with the `updatePost` and going through `updateOwnPost`. To pass the access check, `AuthorRule`\n" +"should return `true` from its `execute()` method. The method receives its `$params` from the `can()` method call, so the value is\n" +"`['post' => $post]`.\n" +"If everything is fine, you will get to `author` assigned to John.\n" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "In the case of Jane, it's a bit simpler since she is an admin:" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "![Access check](img/rbac-access-check-3.svg \"Access check\")" +msgstr "" + +#. type: Title ## +#: en/security/authorization.md +#, no-wrap +msgid "Implementing your own access checker" +msgstr "" + +#. type: Plain text +#: en/security/authorization.md +msgid "" +"If RBAC doesn't suit your needs, you can implement your own access checker " +"without changing the application code:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/authorization.md +#, no-wrap +msgid "" +"namespace App\\User;\n" +"\n" +"use \\Yiisoft\\Access\\AccessCheckerInterface;\n" +"\n" +"final readonly class AccessChecker implements AccessCheckerInterface\n" +"{\n" +" private const PERMISSIONS = [\n" +" [\n" +" 1 => ['editPost'],\n" +" 42 => ['editPost', 'deletePost'],\n" +" ],\n" +" ];\n" +"\n" +" public function userHasPermission($userId, string $permissionName, array $parameters = []) : bool\n" +" {\n" +" if (!array_key_exists($userId, self::PERMISSIONS)) {\n" +" return false;\n" +" }\n" +"\n" +" return in_array($permissionName, self::PERMISSIONS[$userId], true); \n" +" }\n" +"}\n" +msgstr "" diff --git a/guide/po/security_best-practices.md/ru/security_best-practices.md.ru.po b/guide/po/security_best-practices.md/ru/security_best-practices.md.ru.po new file mode 100644 index 00000000..11de6a1e --- /dev/null +++ b/guide/po/security_best-practices.md/ru/security_best-practices.md.ru.po @@ -0,0 +1,569 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2025-09-04 08:00+0500\n" +"PO-Revision-Date: 2025-09-04 08:31+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 3.7\n" + +#. type: Title ## +#: en/concept/autoloading.md en/security/best-practices.md +#, no-wrap +msgid "References" +msgstr "Ссылки" + +#. type: Title # +#: en/security/best-practices.md +#, no-wrap +msgid "Security best practices" +msgstr "Лучшие практики безопасности" + +#. type: Plain text +#: en/security/best-practices.md +msgid "Below, we'll review common security principles and describe how to avoid threats when developing applications using Yii. Most of these principles aren't unique to Yii alone but apply to website or software development in general, so you will also find links for further reading on the general ideas behind these." +msgstr "Ниже мы рассмотрим общие принципы безопасности и опишем, как избежать угроз при разработке приложений с использованием Yii. Большинство из этих принципов не являются уникальными только для Yii, но применимы к разработке веб-сайтов или программного обеспечения в целом, так что вы также найдете ссылки для дальнейшего чтения об общих идеях, лежащих в их основе." + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Basic principles" +msgstr "Основные принципы" + +#. type: Plain text +#: en/security/best-practices.md +msgid "There are two main principles when it comes to security no matter which application is being developed:" +msgstr "Независимо от того, какое приложение разрабатывается, существуют два основных принципа обеспечения безопасности:" + +#. type: Bullet: '1. ' +#: en/security/best-practices.md +msgid "Filter input." +msgstr "Фильтрация ввода." + +#. type: Bullet: '2. ' +#: en/security/best-practices.md +msgid "Escape output." +msgstr "Экранирование вывода." + +#. type: Title ### +#: en/security/best-practices.md +#, no-wrap +msgid "Filter input" +msgstr "Фильтрация ввода" + +#. type: Plain text +#: en/security/best-practices.md +msgid "Filter input means that you should never consider input safe, and you should always check if the value you've got is actually among allowed ones. For example, if you know that you sort by three fields `title`, `created_at` and `status` and the field came from user input, it's better to check the value you've got right where you're receiving it. In terms of basic PHP, that would look like the following:" +msgstr "" +"Фильтрация ввода означает, что входные данные никогда не должны считаться безопасными и вы всегда должны проверять, являются ли полученные данные допустимыми. \n" +"Например, если мы знаем, что сортировка может быть осуществлена только по трём полям `title`, `created_at` и `status`, и поле может передаваться через ввод пользователем, лучше проверить значение там, где мы его получили.\n" +"С точки зрения чистого PHP, это будет выглядеть следующим образом:" + +#. type: Fenced code block (php) +#: en/security/best-practices.md +#, no-wrap +msgid "" +"$sortBy = $_GET['sort'];\n" +"if (!in_array($sortBy, ['title', 'created_at', 'status'])) {\n" +"\tthrow new \\InvalidArgumentException('Invalid sort value.');\n" +"}\n" +msgstr "" +"$sortBy = $_GET['sort'];\n" +"if (!in_array($sortBy, ['title', 'created_at', 'status'])) {\n" +"\tthrow new \\InvalidArgumentException('Invalid sort value.');\n" +"}\n" + +#. type: Plain text +#: en/security/best-practices.md +msgid "In Yii, most probably you'll use [form validation](../input/validation.md) to do similar checks." +msgstr "В Yii, вы, скорее всего, будете использовать [валидацию форм](../input/validation.md), чтобы делать такие проверки." + +#. type: Plain text +#: en/security/best-practices.md +msgid "Further reading on the topic:" +msgstr "Дополнительная информация по теме:" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Title ### +#: en/security/best-practices.md +#, no-wrap +msgid "Escape output" +msgstr "Экранирование вывода" + +#. type: Plain text +#: en/security/best-practices.md +#, no-wrap +msgid "" +"Escape output means that, depending on the context where you're using data,\n" +"you should prepend it with special characters to negate its special meaning.\n" +"In context of HTML you should escape `<`, `>` and alike special characters.\n" +"In the context of JavaScript or SQL, it will be a different set of characters.\n" +"Since it's error-prone to escape manually, Yii provides various tools to perform escaping in different contexts.\n" +msgstr "" +"Экранирование вывода означает, что в зависимости от контекста, в котором вы используете данные, вам следует добавить \n" +"к ним специальные символы, чтобы экранировать их значение.\n" +"В контексте HTML вы должны экранировать `<`, `>` и похожие специальные символы.\n" +"В контексте JavaScript или SQL это будет другой набор символов.\n" +"Так как ручное экранирование чревато ошибками, Yii предоставляет различные утилиты для экранирования в различных контекстах.\n" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding SQL injections" +msgstr "Как избежать SQL-инъекций" + +#. type: Plain text +#: en/security/best-practices.md +msgid "SQL injection happens when you form a query text by concatenating unescaped strings such as the following:" +msgstr "SQL-инъекции происходят, когда текст запроса формируется склеиванием неэкранированных строк, как показано ниже:" + +#. type: Fenced code block (php) +#: en/security/best-practices.md +#, no-wrap +msgid "" +"$username = $_GET['username'];\n" +"$sql = \"SELECT * FROM user WHERE username = '$username'\";\n" +msgstr "" +"$username = $_GET['username'];\n" +"$sql = \"SELECT * FROM user WHERE username = '$username'\";\n" + +#. type: Plain text +#: en/security/best-practices.md +msgid "Instead of supplying correct username attacker could give your applications something like `'; DROP TABLE user; --`. The Resulting SQL will be the following:" +msgstr "" +"Вместо того чтобы подставлять корректное имя пользователя, злоумышленник может передать в ваше приложение что-то вроде\n" +"`'; DROP TABLE user; --`. В результате SQL будет следующий:" + +#. type: Fenced code block (sql) +#: en/security/best-practices.md +#, no-wrap +msgid "SELECT * FROM user WHERE username = ''; DROP TABLE user; --'\n" +msgstr "SELECT * FROM user WHERE username = ''; DROP TABLE user; --'\n" + +#. type: Plain text +#: en/security/best-practices.md +msgid "This is a valid query that will search for users with empty username and then will drop `user` table most probably resulting in a broken website and data loss (you've set up regular backups, right?)." +msgstr "Это валидный запрос, который сначала будет искать пользователей с пустым именем, а затем удалит таблицу user. Скорее всего будет сломано приложение и будут потеряны данные (вы ведь делаете регулярное резервное копирование?)." + +#. type: Plain text +#: en/security/best-practices.md +msgid "Make sure to either use PDO prepared statements directly or ensure that the library you prefer is doing it. In the case of prepared statements, it's impossible to manipulate the query as was demonstrated above." +msgstr "" +"Убедитесь, что либо вы напрямую используете подготовленные PDO запросы, либо это делает выбранная вами библиотека. \n" +"В случае подготовленных запросов невозможно манипулированть запросом, как было продемонстрировано выше." + +#. type: Plain text +#: en/security/best-practices.md +msgid "If you use data to specify column names or table names, the best thing to do is to allow only a predefined set of values:" +msgstr "Если вы используете данные для указания имен столбцов или таблиц, лучше всего разрешить только предопределенный набор значений:" + +#. type: Fenced code block (php) +#: en/security/best-practices.md +#, no-wrap +msgid "" +"function actionList($orderBy = null)\n" +"{\n" +" if (!in_array($orderBy, ['name', 'status'])) {\n" +" throw new \\InvalidArgumentException('Only name and status are allowed to order by.');\n" +" }\n" +" \n" +" // ...\n" +"}\n" +msgstr "" +"function actionList($orderBy = null)\n" +"{\n" +" if (!in_array($orderBy, ['name', 'status'])) {\n" +" throw new \\InvalidArgumentException('Only name and status are allowed to order by.');\n" +" }\n" +" \n" +" // ...\n" +"}\n" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding XSS" +msgstr "Как избежать XSS" + +#. type: Plain text +#: en/security/best-practices.md +#, no-wrap +msgid "" +"XSS or cross-site scripting happens when output isn't escaped properly when outputting HTML to the browser. For example,\n" +"if user can enter his name and instead of `Alexander` he enters ``, every page that\n" +"outputs username without escaping it will execute JavaScript `alert('Hello!');` resulting in alert box popping up\n" +"in a browser. Depending on the website instead of innocent alert, such a script could send messages using your name or even\n" +"perform bank transactions.\n" +msgstr "" +"XSS или кросс-сайтинговый скриптинг становится возможен, когда неэкранированный выходной HTML попадает в браузер. \n" +"Например, если пользователь должен ввести своё имя, но вместо `Alexander` он вводит `` то все страницы, которые его выводят без экранирования, будут выполнять JavaScript `alert('Hello!');`, и в результате будет выводиться окно сообщения в браузере.\n" +"В зависимости от сайта, вместо невинных скриптов с выводом всплывающего hello, злоумышленниками могут быть отправлены скрипты, похищающие личные данные пользователей сайта, либо выполняющие операции от их имени (например, банковские операции).\n" + +#. type: Plain text +#: en/security/best-practices.md +msgid "Avoiding XSS is quite easy in Yii. There are two cases:" +msgstr "В Yii избежать XSS легко. Существует два варианта:" + +#. type: Bullet: '1. ' +#: en/security/best-practices.md +msgid "You want to output data as plain text." +msgstr "Вы хотите вывести данные в виде обычного текста." + +#. type: Bullet: '2. ' +#: en/security/best-practices.md +msgid "You want to output data as HTML." +msgstr "Вы хотите вывести данные в виде HTML." + +#. type: Plain text +#: en/security/best-practices.md +msgid "If all you need is plain text, then escaping is as easy as the following:" +msgstr "Если вам нужно вывести простой текст, то экранировать лучше следующим образом:" + +#. type: Fenced code block (php) +#: en/security/best-practices.md +#, no-wrap +msgid "\n" +msgstr "\n" + +#. type: Plain text +#: en/security/best-practices.md +msgid "If it should be HTML, you could get some help from [HtmlPurifier](http://htmlpurifier.org/). Note that HtmlPurifier processing is quite heavy, so consider adding caching." +msgstr "" +"Если нужно вывести HTML, вам лучше воспользоваться [HtmlPurifier](http://htmlpurifier.org/).\n" +"Обратите внимание, что обработка с помощью HtmlPurifier довольно тяжела, поэтому рассмотрите возможность использования кеширования." + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding CSRF" +msgstr "Как избежать CSRF" + +#. type: Plain text +#: en/security/best-practices.md +msgid "CSRF is an abbreviation for cross-site request forgery. The idea is that many applications assume that requests coming from a user browser are made by the user themselves. This assumption could be false." +msgstr "" +"CSRF — это аббревиатура для межсайтинговой подмены запросов. Идея заключается в том, что многие приложения предполагают, \n" +"что запросы, приходящие от браузера, отправляются самим пользователем. Это может быть неправдой." + +#. type: Plain text +#: en/security/best-practices.md +#, no-wrap +msgid "" +"For example, the website `an.example.com` has a `/logout` URL that, when accessed using a simple GET request, logs the user out. As long\n" +"as it's requested by the user themselves everything is OK, but one day bad guys are somehow posting\n" +"`` on a forum the user often visits. The browser doesn't make any difference between\n" +"requesting an image or requesting a page so when the user opens a page with such a manipulated `` tag,\n" +"the browser will send the GET request to that URL and the user will be logged out from `an.example.com`.\n" +msgstr "" +"Например, сайт `an.example.com` имеет URL `/logout`, который, используя простой GET, разлогинивает пользователя. \n" +"Пока это запрос выполняется самим пользователем — всё в порядке, но в один прекрасный день злоумышленники размещают\n" +"код `` на форуме с большой посещаемостью. Браузер не делает никаких отличий\n" +"между запросом изображения и запросом страницы, так что когда пользователь откроет страницу с таким тегом ``,\n" +"браузер отправит GET-запрос на указанный адрес, и пользователь будет разлогинен с `an.example.com`.\n" + +#. type: Plain text +#: en/security/best-practices.md +#, no-wrap +msgid "" +"That's the basic idea of how a CSRF attack works. One can say that logging out a user isn't a serious thing.\n" +"However, this was just an example.\n" +"There are many more things one could do using this approach.\n" +"For example, triggering payments or changing data. Imagine that some website has a URL\n" +"`http://an.example.com/purse/transfer?to=anotherUser&amount=2000`. Accessing it using GET request, causes transfer of $2000\n" +"from an authorized user account to user `anotherUser`.\n" +"You know that the browser will always send a GET request to load an image,\n" +"so you can change the code to accept only POST requests on that URL.\n" +"Unfortunately, this won't save you, because an attacker\n" +"can put some JavaScript code instead of `` tag, which allows sending POST requests to that URL as well.\n" +msgstr "" +"Вот основная идея того, как работает CSRF-атака. \n" +"Можно сказать, что в разлогинивании пользователя нет ничего серьёзного. \n" +"Однако это был всего лишь пример.\n" +"С помощью этого подхода можно сделать гораздо больше опасных вещей.\n" +"Например, оплату или изменение данных.\n" +"Представьте, что существует страница `http://an.example.com/purse/transfer?to=anotherUser&amount=2000`, обращение\n" +"к которой с помощью GET-запроса, приводит к перечислению 2000 единиц валюты со счета авторизованного пользователя\n" +"на личный счёт пользователя с логином `anotherUser`. \n" +"Учитывая, что браузер для загрузки контента отправляет GET-запросы, можно подумать, что разрешение на выполнение такой\n" +"операции только POST-запросом на 100% обезопасит от проблем. \n" +"К сожалению, это не спасет вас, так как вместо тега ``, злоумышленник может внедрить JavaScript код, который будет\n" +"отправлять нужные POST-запросы на этот URL.\n" + +#. type: Plain text +#: en/security/best-practices.md +msgid "For this reason, Yii applies extra mechanisms to protect against CSRF attacks." +msgstr "По этой причине Yii применяет дополнительные механизмы защиты от CSRF-атак." + +#. type: Plain text +#: en/security/best-practices.md +msgid "To avoid CSRF, you should always:" +msgstr "Для того чтобы избежать CSRF вы должны всегда:" + +#. type: Bullet: '1. ' +#: en/security/best-practices.md +msgid "Follow HTTP specification. GET shouldn't change the application state. See [RFC2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) for more details." +msgstr "" +"Следовать спецификации HTTP. Например, GET-запрос не должен менять состояние приложения.\n" +" Дополнительные сведения см. в [RFC2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html)." + +#. type: Bullet: '2. ' +#: en/security/best-practices.md +msgid "Keep Yii CSRF protection enabled." +msgstr "Держите защиту CSRF в Yii включенной." + +#. type: Plain text +#: en/security/best-practices.md +msgid "Yii has CSRF protection as `Yiisoft\\Yii\\Web\\Middleware\\Csrf` middleware. Make sure it's in your application middleware stack." +msgstr "" +"Yii имеет защиту от CSRF в middleware `Yiisoft\\Yii\\Web\\Middleware\\Csrf`.\n" +"Убедитесь, что она используется в вашем приложении." + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding file exposure" +msgstr "Как избежать нежелательного доступа к файлам" + +#. type: Plain text +#: en/security/best-practices.md +#, no-wrap +msgid "" +"By default, server webroot is meant to be pointed to `public` directory where `index.php` is. In the case of shared hosting\n" +" environments, it could be impossible to achieve, so you'll end up with all the code, configs and logs in server webroot.\n" +msgstr "" +"По умолчанию, webroot сервера указывает на каталог `public`, где лежит `index.php`. \n" +"В случае использования виртуального хостинга это может быть недостижимо, в конечном итоге весь код, конфиги и логи могут оказаться в webroot сервера.\n" + +#. type: Plain text +#: en/security/best-practices.md +msgid "If so, remember to deny access to everything except `web`. If it's impossible, consider hosting your application elsewhere." +msgstr "" +"Если это так, то нужно запретить доступ ко всему, кроме директории `web`. \n" +"Если на вашем хостинге такое невозможно, рассмотрите возможность смены хостинга." + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding debug info and tools in production" +msgstr "Как избежать вывода отладочной информации и инструментов в боевом окружении" + +#. type: Plain text +#: en/security/best-practices.md +msgid "In debug mode, Yii shows quite verbose errors which are certainly helpful for development. The thing is that these verbose errors are handy for attacker as well since these could reveal database structure, configuration values and parts of your code." +msgstr "" +"В режиме отладки, Yii отображает довольно подробные ошибки, которые полезны во время разработки. Однако подробные ошибки\n" +"удобны и для нападающего, так как могут раскрыть структуру базы данных, параметров конфигурации и части вашего кода." + +#. type: Plain text +#: en/security/best-practices.md +msgid "Never run production applications with debugger or Gii accessible to everyone. One could use it to get information about database structure, code and to simply rewrite code with what's generated by Gii." +msgstr "" +"Вы никогда не должны оставлять Debug панель или Gii доступной для всех в боевом окружении. Это может быть использовано\n" +"для получения информации о структуре базы данных или коде, может позволить заменить файлы, генерируемые Gii автоматически." + +#. type: Plain text +#: en/security/best-practices.md +msgid "You should avoid the debug toolbar in production unless necessary. It exposes all the application and config details possible. If you absolutely need it, check twice you restrict access to your IP only." +msgstr "" +"Следует избегать включения в боевом окружении панели отладки, если только в этом нет острой необходимости.\n" +"Она раскрывает всё приложение и детали конфигурации. Если вам всё-таки нужно запустить панель отладки, проверьте дважды,\n" +"что доступ ограничен только вашими IP-адресами." + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Using secure connection over TLS" +msgstr "Использование безопасного подключения через TLS" + +#. type: Plain text +#: en/security/best-practices.md +msgid "Yii provides features that rely on cookies and/or PHP sessions. These can be vulnerable in case your connection is compromised. The risk is reduced if the app uses secure connection via TLS (often referred to as [SSL](https://en.wikipedia.org/wiki/Transport_Layer_Security))." +msgstr "" +"Yii предоставляет функции, которые зависят от куки-файлов и/или сессий PHP. \n" +"Они могут быть уязвимыми, если ваше соединение скомпрометировано. Риск снижается, если приложение использует безопасное соединение через TLS (часто называемое как [SSL](https://en.wikipedia.org/wiki/Transport_Layer_Security))." + +#. type: Plain text +#: en/security/best-practices.md +msgid "Nowadays, anyone can get a certificate for free and automatically update it thanks to [Let's Encrypt](https://letsencrypt.org/)." +msgstr "Сегодня любой желающий может бесплатно получить SSL-сертификат и автоматически обновлять его благодаря [Let's Encrypt](https://letsencrypt.org/)." + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Secure server configuration" +msgstr "Безопасная конфигурация сервера" + +#. type: Plain text +#: en/security/best-practices.md +msgid "The purpose of this section is to highlight risks that need to be considered when creating a server configuration for serving a Yii-based website. Besides the points covered here, there may be other security-related configuration options to be considered, so don't consider this section to be complete." +msgstr "" +"Цель этого раздела — выявить риски, которые необходимо учитывать при создании конфигурации сервера для обслуживания веб-сайта на основе Yii.\n" +"Помимо перечисленных здесь пунктов есть и другие параметры, связанные с безопасностью, которые необходимо учитывать, поэтому не рассматривайте этот раздел как завершенный." + +#. type: Title ### +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding `Host`-header attacks" +msgstr "Как избежать атаки типа `Host`-header" + +#. type: Plain text +#: en/security/best-practices.md +msgid "If the webserver is configured to serve the same site independent of the value of the `Host` header, this information mayn't be reliable and [may be faked by the user sending the HTTP request](https://www.acunetix.com/vulnerabilities/web/host-header-attack). In such situations, you should fix your webserver configuration to serve the site only for specified host names." +msgstr "" +"Если веб-сервер настроен на обслуживание одного и того же сайта независимо от значения заголовка `Host`, эта информация может быть ненадежной и [может быть подделана пользователем, отправляющим HTTP-запрос](https://www.acunetix.com/vulnerabilities/web/host-header-attack). \n" +"В таких ситуациях вам следует исправить конфигурацию вашего веб-сервера, чтобы он обслуживал сайт только для указанных имен хостов." + +#. type: Plain text +#: en/security/best-practices.md +msgid "For more information about the server configuration, please refer to the documentation of your webserver:" +msgstr "Дополнительные сведения о конфигурации сервера смотрите в документации вашего веб-сервера:" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "Apache 2: " +msgstr "Apache 2: " + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "Nginx: " +msgstr "Nginx: " + +#. type: Title ### +#: en/security/best-practices.md +#, no-wrap +msgid "Configuring SSL peer validation" +msgstr "Настройка проверки SSL-сертификата" + +#. type: Plain text +#: en/security/best-practices.md +msgid "There is a typical misconception about how to solve SSL certificate validation issues such as:" +msgstr "Существует типичное заблуждение о том, как решить проблемы с проверкой сертификата SSL, например:" + +#. type: Fenced code block +#: en/security/best-practices.md +#, no-wrap +msgid "cURL error 60: SSL certificate problem: unable to get local issuer certificate\n" +msgstr "cURL error 60: SSL certificate problem: unable to get local issuer certificate\n" + +#. type: Plain text +#: en/security/best-practices.md +msgid "or" +msgstr "или" + +#. type: Fenced code block +#: en/security/best-practices.md +#, no-wrap +msgid "stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed\n" +msgstr "stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed\n" + +#. type: Plain text +#: en/security/best-practices.md +msgid "Many sources wrongly suggest disabling SSL peer verification. That shouldn't be ever done since it enables man-in-the middle type of attacks. Instead, PHP should be configured properly:" +msgstr "" +"Многие источники ошибочно предлагают отключить проверку одноранговых соединений SSL.\n" +"Этого никогда не следует делать, поскольку это допускает атаки типа «man-in-the-middle».\n" +"Вместо этого PHP должен быть правильно настроен:" + +#. type: Bullet: '1. ' +#: en/security/best-practices.md +msgid "Download [https://curl.haxx.se/ca/cacert.pem](https://curl.haxx.se/ca/cacert.pem)." +msgstr "Скачайте файл [https://curl.haxx.se/ca/cacert.pem](https://curl.haxx.se/ca/cacert.pem)." + +#. type: Bullet: '2. ' +#: en/security/best-practices.md +msgid "Add the following to your php.ini:" +msgstr "Добавьте в свой php.ini следующее:" + +#. type: Fenced code block +#: en/security/best-practices.md +#, no-wrap +msgid "" +" openssl.cafile=\"/path/to/cacert.pem\"\n" +" curl.cainfo=\"/path/to/cacert.pem\".\n" +msgstr "" +" openssl.cafile=\"/path/to/cacert.pem\"\n" +" curl.cainfo=\"/path/to/cacert.pem\".\n" + +#. type: Plain text +#: en/security/best-practices.md +msgid "Note that you should keep the file up to date." +msgstr "Обратите внимание, что вам следует поддерживать файл в актуальном состоянии." + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "[OWASP top 10](https://owasp.org/Top10/)" +msgstr "[OWASP top 10](https://owasp.org/Top10/)" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "[The Basics of Web Application Security](https://martinfowler.com/articles/web-security-basics.html) by Martin Fowler" +msgstr "[The Basics of Web Application Security](https://martinfowler.com/articles/web-security-basics.html) Мартина Фаулера" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "[PHP manual: security](https://www.php.net/manual/en/security.php)" +msgstr "[Руководство по PHP: безопасность](https://www.php.net/manual/en/security.php)" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "[Information security at STackExchange](https://security.stackexchange.com/)" +msgstr "[Раздел \"Информационная безопасность\" на STackExchange](https://security.stackexchange.com/)" diff --git a/guide/po/security_best-practices.md/security_best-practices.md.pot b/guide/po/security_best-practices.md/security_best-practices.md.pot new file mode 100644 index 00000000..8e36ffa5 --- /dev/null +++ b/guide/po/security_best-practices.md/security_best-practices.md.pot @@ -0,0 +1,581 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 08:00+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title ## +#: en/concept/autoloading.md en/security/best-practices.md +#, no-wrap +msgid "References" +msgstr "" + +#. type: Title # +#: en/security/best-practices.md +#, no-wrap +msgid "Security best practices" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"Below, we'll review common security principles and describe how to avoid " +"threats when developing applications using Yii. Most of these principles " +"aren't unique to Yii alone but apply to website or software development in " +"general, so you will also find links for further reading on the general " +"ideas behind these." +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Basic principles" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"There are two main principles when it comes to security no matter which " +"application is being developed:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/security/best-practices.md +msgid "Filter input." +msgstr "" + +#. type: Bullet: '2. ' +#: en/security/best-practices.md +msgid "Escape output." +msgstr "" + +#. type: Title ### +#: en/security/best-practices.md +#, no-wrap +msgid "Filter input" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"Filter input means that you should never consider input safe, and you should " +"always check if the value you've got is actually among allowed ones. For " +"example, if you know that you sort by three fields `title`, `created_at` and " +"`status` and the field came from user input, it's better to check the value " +"you've got right where you're receiving it. In terms of basic PHP, that " +"would look like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/best-practices.md +#, no-wrap +msgid "" +"$sortBy = $_GET['sort'];\n" +"if (!in_array($sortBy, ['title', 'created_at', 'status'])) {\n" +"\tthrow new \\InvalidArgumentException('Invalid sort value.');\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"In Yii, most probably you'll use [form validation](../input/validation.md) " +"to do similar checks." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "Further reading on the topic:" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +"" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +"" +msgstr "" + +#. type: Title ### +#: en/security/best-practices.md +#, no-wrap +msgid "Escape output" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +#, no-wrap +msgid "" +"Escape output means that, depending on the context where you're using data,\n" +"you should prepend it with special characters to negate its special meaning.\n" +"In context of HTML you should escape `<`, `>` and alike special characters.\n" +"In the context of JavaScript or SQL, it will be a different set of characters.\n" +"Since it's error-prone to escape manually, Yii provides various tools to perform escaping in different contexts.\n" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding SQL injections" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"SQL injection happens when you form a query text by concatenating unescaped " +"strings such as the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/best-practices.md +#, no-wrap +msgid "" +"$username = $_GET['username'];\n" +"$sql = \"SELECT * FROM user WHERE username = '$username'\";\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"Instead of supplying correct username attacker could give your applications " +"something like `'; DROP TABLE user; --`. The Resulting SQL will be the " +"following:" +msgstr "" + +#. type: Fenced code block (sql) +#: en/security/best-practices.md +#, no-wrap +msgid "SELECT * FROM user WHERE username = ''; DROP TABLE user; --'\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"This is a valid query that will search for users with empty username and " +"then will drop `user` table most probably resulting in a broken website and " +"data loss (you've set up regular backups, right?)." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"Make sure to either use PDO prepared statements directly or ensure that the " +"library you prefer is doing it. In the case of prepared statements, it's " +"impossible to manipulate the query as was demonstrated above." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"If you use data to specify column names or table names, the best thing to do " +"is to allow only a predefined set of values:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/best-practices.md +#, no-wrap +msgid "" +"function actionList($orderBy = null)\n" +"{\n" +" if (!in_array($orderBy, ['name', 'status'])) {\n" +" throw new \\InvalidArgumentException('Only name and status are allowed to order by.');\n" +" }\n" +" \n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding XSS" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +#, no-wrap +msgid "" +"XSS or cross-site scripting happens when output isn't escaped properly when outputting HTML to the browser. For example,\n" +"if user can enter his name and instead of `Alexander` he enters ``, every page that\n" +"outputs username without escaping it will execute JavaScript `alert('Hello!');` resulting in alert box popping up\n" +"in a browser. Depending on the website instead of innocent alert, such a script could send messages using your name or even\n" +"perform bank transactions.\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "Avoiding XSS is quite easy in Yii. There are two cases:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/security/best-practices.md +msgid "You want to output data as plain text." +msgstr "" + +#. type: Bullet: '2. ' +#: en/security/best-practices.md +msgid "You want to output data as HTML." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"If all you need is plain text, then escaping is as easy as the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/best-practices.md +#, no-wrap +msgid "\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"If it should be HTML, you could get some help from [HtmlPurifier](http://" +"htmlpurifier.org/). Note that HtmlPurifier processing is quite heavy, so " +"consider adding caching." +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding CSRF" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"CSRF is an abbreviation for cross-site request forgery. The idea is that " +"many applications assume that requests coming from a user browser are made " +"by the user themselves. This assumption could be false." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +#, no-wrap +msgid "" +"For example, the website `an.example.com` has a `/logout` URL that, when accessed using a simple GET request, logs the user out. As long\n" +"as it's requested by the user themselves everything is OK, but one day bad guys are somehow posting\n" +"`` on a forum the user often visits. The browser doesn't make any difference between\n" +"requesting an image or requesting a page so when the user opens a page with such a manipulated `` tag,\n" +"the browser will send the GET request to that URL and the user will be logged out from `an.example.com`.\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +#, no-wrap +msgid "" +"That's the basic idea of how a CSRF attack works. One can say that logging out a user isn't a serious thing.\n" +"However, this was just an example.\n" +"There are many more things one could do using this approach.\n" +"For example, triggering payments or changing data. Imagine that some website has a URL\n" +"`http://an.example.com/purse/transfer?to=anotherUser&amount=2000`. Accessing it using GET request, causes transfer of $2000\n" +"from an authorized user account to user `anotherUser`.\n" +"You know that the browser will always send a GET request to load an image,\n" +"so you can change the code to accept only POST requests on that URL.\n" +"Unfortunately, this won't save you, because an attacker\n" +"can put some JavaScript code instead of `` tag, which allows sending POST requests to that URL as well.\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"For this reason, Yii applies extra mechanisms to protect against CSRF " +"attacks." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "To avoid CSRF, you should always:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/security/best-practices.md +msgid "" +"Follow HTTP specification. GET shouldn't change the application state. See " +"[RFC2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) for more " +"details." +msgstr "" + +#. type: Bullet: '2. ' +#: en/security/best-practices.md +msgid "Keep Yii CSRF protection enabled." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"Yii has CSRF protection as `Yiisoft\\Yii\\Web\\Middleware\\Csrf` " +"middleware. Make sure it's in your application middleware stack." +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding file exposure" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +#, no-wrap +msgid "" +"By default, server webroot is meant to be pointed to `public` directory where `index.php` is. In the case of shared hosting\n" +" environments, it could be impossible to achieve, so you'll end up with all the code, configs and logs in server webroot.\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"If so, remember to deny access to everything except `web`. If it's " +"impossible, consider hosting your application elsewhere." +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding debug info and tools in production" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"In debug mode, Yii shows quite verbose errors which are certainly helpful " +"for development. The thing is that these verbose errors are handy for " +"attacker as well since these could reveal database structure, configuration " +"values and parts of your code." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"Never run production applications with debugger or Gii accessible to " +"everyone. One could use it to get information about database structure, " +"code and to simply rewrite code with what's generated by Gii." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"You should avoid the debug toolbar in production unless necessary. It " +"exposes all the application and config details possible. If you absolutely " +"need it, check twice you restrict access to your IP only." +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Using secure connection over TLS" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"Yii provides features that rely on cookies and/or PHP sessions. These can be " +"vulnerable in case your connection is compromised. The risk is reduced if " +"the app uses secure connection via TLS (often referred to as [SSL](https://" +"en.wikipedia.org/wiki/Transport_Layer_Security))." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"Nowadays, anyone can get a certificate for free and automatically update it " +"thanks to [Let's Encrypt](https://letsencrypt.org/)." +msgstr "" + +#. type: Title ## +#: en/security/best-practices.md +#, no-wrap +msgid "Secure server configuration" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"The purpose of this section is to highlight risks that need to be considered " +"when creating a server configuration for serving a Yii-based website. " +"Besides the points covered here, there may be other security-related " +"configuration options to be considered, so don't consider this section to be " +"complete." +msgstr "" + +#. type: Title ### +#: en/security/best-practices.md +#, no-wrap +msgid "Avoiding `Host`-header attacks" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"If the webserver is configured to serve the same site independent of the " +"value of the `Host` header, this information mayn't be reliable and [may be " +"faked by the user sending the HTTP request](https://www.acunetix.com/" +"vulnerabilities/web/host-header-attack). In such situations, you should fix " +"your webserver configuration to serve the site only for specified host names." +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"For more information about the server configuration, please refer to the " +"documentation of your webserver:" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +"Apache 2: " +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +"Nginx: " +msgstr "" + +#. type: Title ### +#: en/security/best-practices.md +#, no-wrap +msgid "Configuring SSL peer validation" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"There is a typical misconception about how to solve SSL certificate " +"validation issues such as:" +msgstr "" + +#. type: Fenced code block +#: en/security/best-practices.md +#, no-wrap +msgid "cURL error 60: SSL certificate problem: unable to get local issuer certificate\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "or" +msgstr "" + +#. type: Fenced code block +#: en/security/best-practices.md +#, no-wrap +msgid "stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "" +"Many sources wrongly suggest disabling SSL peer verification. That " +"shouldn't be ever done since it enables man-in-the middle type of attacks. " +"Instead, PHP should be configured properly:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/security/best-practices.md +msgid "" +"Download [https://curl.haxx.se/ca/cacert.pem](https://curl.haxx.se/ca/cacert." +"pem)." +msgstr "" + +#. type: Bullet: '2. ' +#: en/security/best-practices.md +msgid "Add the following to your php.ini:" +msgstr "" + +#. type: Fenced code block +#: en/security/best-practices.md +#, no-wrap +msgid "" +" openssl.cafile=\"/path/to/cacert.pem\"\n" +" curl.cainfo=\"/path/to/cacert.pem\".\n" +msgstr "" + +#. type: Plain text +#: en/security/best-practices.md +msgid "Note that you should keep the file up to date." +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "[OWASP top 10](https://owasp.org/Top10/)" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +"[The Basics of Web Application Security](https://martinfowler.com/articles/" +"web-security-basics.html) by Martin Fowler" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "[PHP manual: security](https://www.php.net/manual/en/security.php)" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/best-practices.md +msgid "" +"[Information security at STackExchange](https://security.stackexchange.com/)" +msgstr "" diff --git a/guide/po/security_cryptography.md/ru/security_cryptography.md.ru.po b/guide/po/security_cryptography.md/ru/security_cryptography.md.ru.po new file mode 100644 index 00000000..46138996 --- /dev/null +++ b/guide/po/security_cryptography.md/ru/security_cryptography.md.ru.po @@ -0,0 +1,270 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2025-09-04 08:34+0500\n" +"PO-Revision-Date: 2025-09-04 08:44+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 3.7\n" + +#. type: Title # +#: en/security/cryptography.md +#, no-wrap +msgid "Cryptography" +msgstr "Криптография" + +#. type: Plain text +#: en/security/cryptography.md +msgid "In this section, we'll review the following security aspects:" +msgstr "В этом разделе мы рассмотрим следующие аспекты безопасности:" + +#. type: Bullet: '- ' +#: en/security/cryptography.md +msgid "Generating random data" +msgstr "Генерация случайных данных" + +#. type: Bullet: '- ' +#: en/security/cryptography.md +msgid "Encryption and Decryption" +msgstr "Шифрование и расшифровка" + +#. type: Bullet: '- ' +#: en/security/cryptography.md +msgid "Confirming Data Integrity" +msgstr "Проверка целостности данных" + +#. type: Plain text +#: en/security/cryptography.md +msgid "To use these features, you need to install `yiisoft/security` package:" +msgstr "Для использования этих функций, вам нужно установить пакет `yiisoft/security`:" + +#. type: Fenced code block +#: en/security/cryptography.md +#, no-wrap +msgid "composer install yiisoft/security\n" +msgstr "composer install yiisoft/security\n" + +#. type: Title ## +#: en/security/cryptography.md +#, no-wrap +msgid "Generating pseudorandom data" +msgstr "Генерация псевдослучайных данных" + +#. type: Plain text +#: en/security/cryptography.md +msgid "Pseudorandom data are useful in many situations. For example, when resetting a password via email, you need to generate a token, save it to the database, and send it via email to the end user, which in turn will allow them to prove ownership of that account. It's important that this token be unique and hard to guess, else there is a possibility that an attacker can predict the token's value and reset the user's password." +msgstr "" +"Псевдослучайные данные используются во многих ситуациях.\n" +"Например, при изменении пароля по email, вам необходимо сгенерировать токен, сохранить его в базу данных и отправить \n" +"по email пользователю, чтобы он с помощью него подтвердил владение аккаунтом.\n" +"Важно, чтобы этот токен был уникальным и его было трудно угадать, иначе есть вероятность, что атакующий может \n" +"предсказать значение токена и сбросить пароль пользователя." + +#. type: Plain text +#: en/security/cryptography.md +msgid "`\\Yiisoft\\Security\\Random` makes generating pseudorandom data simple:" +msgstr "Класс `\\Yiisoft\\Security\\Random` делает генерацию псевдослучайных данных простой:" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "$key = \\Yiisoft\\Security\\Random::string(42);\n" +msgstr "$key = \\Yiisoft\\Security\\Random::string(42);\n" + +#. type: Plain text +#: en/security/cryptography.md +msgid "The code above would give you a random string consisting of 42 characters." +msgstr "Код выше даст вам случайную строку, включающую 42 символа." + +#. type: Plain text +#: en/security/cryptography.md +msgid "If you need bytes or integers, use PHP functions directly:" +msgstr "Если вам нужны байты или целые числа, напрямую используйте функции PHP:" + +#. type: Bullet: '- ' +#: en/security/cryptography.md +msgid "`random_bytes()` for bytes. Note that the output may not be ASCII." +msgstr "`random_bytes()` для генерации байт. Обратите внимание, что вывод может быть не ASCII." + +#. type: Bullet: '- ' +#: en/security/cryptography.md +msgid "`random_int()` for integers." +msgstr "`random_int()` для генерации целых чисел." + +#. type: Title ## +#: en/security/cryptography.md +#, no-wrap +msgid "Encryption and decryption" +msgstr "Шифрование и расшифровка" + +#. type: Plain text +#: en/security/cryptography.md +msgid "Yii provides convenient helper functions to encrypt/decrypt data using a secret key. The data is passed through the encryption function so that only the person who has the secret key will be able to decrypt it. For example, you need to store some information in your database, but you need to make sure only the user who has the secret key can view it (even if one compromises the application database):" +msgstr "" +"Yii предоставляет удобные вспомогательные функции для шифрования/расшифровки данных с помощью секретного ключа.\n" +"Данные проходят через функцию шифрования таким образом, что только тот, кто знает секретный ключ, может расшифровать их.\n" +"Например, вам нужно сохранить некоторую информацию в вашей базе данных, но вы должны быть уверены, что только пользователь, который знает секретный ключ, сможет расшифровать их (даже если кто-нибудь скомпрометирует базу данных приложения):" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"$encryptedData = (new \\Yiisoft\\Security\\Crypt())->encryptByPassword($data, $password);\n" +"\n" +"// save data to a database or another storage\n" +"saveData($encryptedData);\n" +msgstr "" +"$encryptedData = (new \\Yiisoft\\Security\\Crypt())->encryptByPassword($data, $password);\n" +"\n" +"// сохранение данных в базу данных или другое хранилище\n" +"saveData($encryptedData);\n" + +#. type: Plain text +#: en/security/cryptography.md +msgid "Decrypting it:" +msgstr "Расшифровка:" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"// collect encrypted data from a database or another storage\n" +"$encryptedData = getEncryptedData();\n" +"\n" +"$data = (new \\Yiisoft\\Security\\Crypt())->decryptByPassword($encryptedData, $password);\n" +msgstr "" +"// получение зашифрованных данных из базы данных или другого хранилища\n" +"$encryptedData = getEncryptedData();\n" +"\n" +"$data = (new \\Yiisoft\\Security\\Crypt())->decryptByPassword($encryptedData, $password);\n" + +#. type: Plain text +#: en/security/cryptography.md +msgid "You could use a key instead of a password:" +msgstr "Вы можете использовать ключ вместо пароля:" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"$encryptedData = (new \\Yiisoft\\Security\\Crypt())->encryptByKey($data, $key);\n" +"\n" +"// save data to a database or another storage\n" +"saveData($encryptedData);\n" +msgstr "" +"$encryptedData = (new \\Yiisoft\\Security\\Crypt())->encryptByKey($data, $key);\n" +"\n" +"// сохранение данных в базу данных или другое хранилище\n" +"saveData($encryptedData);\n" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"// collect encrypted data from a database or another storage\n" +"$encryptedData = getEncryptedData();\n" +"\n" +"$data = (new \\Yiisoft\\Security\\Crypt())->decryptByKey($encryptedData, $key);\n" +msgstr "" +"// получение зашифрованных данных из базы данных или другого хранилища\n" +"$encryptedData = getEncryptedData();\n" +"\n" +"$data = (new \\Yiisoft\\Security\\Crypt())->decryptByKey($encryptedData, $key);\n" + +#. type: Title ## +#: en/security/cryptography.md +#, no-wrap +msgid "Confirming data integrity" +msgstr "Проверка целостности данных" + +#. type: Plain text +#: en/security/cryptography.md +msgid "There are situations in which you need to verify that your data hasn't been tampered with by a third party or even corrupted in some way. Yii provides a way to confirm data integrity by MAC signing." +msgstr "" +"Бывают ситуации, когда вам необходимо убедиться, что ваши данные не были подделаны третьей стороной или испорчены каким-то образом.\n" +"Yii предоставляет способ проверить целостность данных по MAC подписи." + +#. type: Plain text +#: en/security/cryptography.md +msgid "The `$key` should be present at both sending and receiving sides. On the sending side:" +msgstr "Ключ `$key` должен присутствовать как на отправляющей, так и на принимающей стороне. На отправляющей стороне:" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"$signedMessage = (new \\Yiisoft\\Security\\Mac())->sign($message, $key);\n" +"\n" +"sendMessage($signedMessage);\n" +msgstr "" +"$signedMessage = (new \\Yiisoft\\Security\\Mac())->sign($message, $key);\n" +"\n" +"sendMessage($signedMessage);\n" + +#. type: Plain text +#: en/security/cryptography.md +msgid "On the receiving side:" +msgstr "На принимающей стороне:" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"$signedMessage = receiveMessage($signedMessage);\n" +"\n" +"try {\n" +" $message = (new \\Yiisoft\\Security\\Mac())->getMessage($signedMessage, $key);\n" +"} catch (\\Yiisoft\\Security\\DataIsTamperedException $e) {\n" +" // data is tampered\n" +"}\n" +msgstr "" +"$signedMessage = receiveMessage($signedMessage);\n" +"\n" +"try {\n" +" $message = (new \\Yiisoft\\Security\\Mac())->getMessage($signedMessage, $key);\n" +"} catch (\\Yiisoft\\Security\\DataIsTamperedException $e) {\n" +" // данные подделаны\n" +"}\n" + +#. type: Title ## +#: en/security/cryptography.md +#, no-wrap +msgid "Masking token length" +msgstr "Маскировка длины токена" + +#. type: Plain text +#: en/security/cryptography.md +msgid "Masking a token helps to mitigate a BREACH attack by randomizing how the token outputted on each request. A random mask is applied to the token, making the string always unique." +msgstr "Маскировка токена помогает смягчить атаку BREACH за счет рандомизации способа вывода токена при каждом запросе. К токену применяется случайная маска, делающая строку всегда уникальной." + +#. type: Plain text +#: en/security/cryptography.md +msgid "To mask a token:" +msgstr "Для маскировки токена:" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "$maskedToken = \\Yiisoft\\Security\\TokenMask::apply($token);\n" +msgstr "$maskedToken = \\Yiisoft\\Security\\TokenMask::apply($token);\n" + +#. type: Plain text +#: en/security/cryptography.md +msgid "To get the original value from the masked one:" +msgstr "Получить исходное значение из замаскированного:" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "$token = \\Yiisoft\\Security\\TokenMask::remove($maskedToken);\n" +msgstr "$token = \\Yiisoft\\Security\\TokenMask::remove($maskedToken);\n" diff --git a/guide/po/security_cryptography.md/security_cryptography.md.pot b/guide/po/security_cryptography.md/security_cryptography.md.pot new file mode 100644 index 00000000..dc42ad2b --- /dev/null +++ b/guide/po/security_cryptography.md/security_cryptography.md.pot @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 08:34+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/security/cryptography.md +#, no-wrap +msgid "Cryptography" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "In this section, we'll review the following security aspects:" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/cryptography.md +msgid "Generating random data" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/cryptography.md +msgid "Encryption and Decryption" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/cryptography.md +msgid "Confirming Data Integrity" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "To use these features, you need to install `yiisoft/security` package:" +msgstr "" + +#. type: Fenced code block +#: en/security/cryptography.md +#, no-wrap +msgid "composer install yiisoft/security\n" +msgstr "" + +#. type: Title ## +#: en/security/cryptography.md +#, no-wrap +msgid "Generating pseudorandom data" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "" +"Pseudorandom data are useful in many situations. For example, when resetting " +"a password via email, you need to generate a token, save it to the database, " +"and send it via email to the end user, which in turn will allow them to " +"prove ownership of that account. It's important that this token be unique " +"and hard to guess, else there is a possibility that an attacker can predict " +"the token's value and reset the user's password." +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "" +"`\\Yiisoft\\Security\\Random` makes generating pseudorandom data simple:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "$key = \\Yiisoft\\Security\\Random::string(42);\n" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "" +"The code above would give you a random string consisting of 42 characters." +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "If you need bytes or integers, use PHP functions directly:" +msgstr "" + +#. type: Bullet: '- ' +#: en/security/cryptography.md +msgid "`random_bytes()` for bytes. Note that the output may not be ASCII." +msgstr "" + +#. type: Bullet: '- ' +#: en/security/cryptography.md +msgid "`random_int()` for integers." +msgstr "" + +#. type: Title ## +#: en/security/cryptography.md +#, no-wrap +msgid "Encryption and decryption" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "" +"Yii provides convenient helper functions to encrypt/decrypt data using a " +"secret key. The data is passed through the encryption function so that only " +"the person who has the secret key will be able to decrypt it. For example, " +"you need to store some information in your database, but you need to make " +"sure only the user who has the secret key can view it (even if one " +"compromises the application database):" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"$encryptedData = (new \\Yiisoft\\Security\\Crypt())->encryptByPassword($data, $password);\n" +"\n" +"// save data to a database or another storage\n" +"saveData($encryptedData);\n" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "Decrypting it:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"// collect encrypted data from a database or another storage\n" +"$encryptedData = getEncryptedData();\n" +"\n" +"$data = (new \\Yiisoft\\Security\\Crypt())->decryptByPassword($encryptedData, $password);\n" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "You could use a key instead of a password:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"$encryptedData = (new \\Yiisoft\\Security\\Crypt())->encryptByKey($data, $key);\n" +"\n" +"// save data to a database or another storage\n" +"saveData($encryptedData);\n" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"// collect encrypted data from a database or another storage\n" +"$encryptedData = getEncryptedData();\n" +"\n" +"$data = (new \\Yiisoft\\Security\\Crypt())->decryptByKey($encryptedData, $key);\n" +msgstr "" + +#. type: Title ## +#: en/security/cryptography.md +#, no-wrap +msgid "Confirming data integrity" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "" +"There are situations in which you need to verify that your data hasn't been " +"tampered with by a third party or even corrupted in some way. Yii provides a " +"way to confirm data integrity by MAC signing." +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "" +"The `$key` should be present at both sending and receiving sides. On the " +"sending side:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"$signedMessage = (new \\Yiisoft\\Security\\Mac())->sign($message, $key);\n" +"\n" +"sendMessage($signedMessage);\n" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "On the receiving side:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "" +"$signedMessage = receiveMessage($signedMessage);\n" +"\n" +"try {\n" +" $message = (new \\Yiisoft\\Security\\Mac())->getMessage($signedMessage, $key);\n" +"} catch (\\Yiisoft\\Security\\DataIsTamperedException $e) {\n" +" // data is tampered\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/security/cryptography.md +#, no-wrap +msgid "Masking token length" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "" +"Masking a token helps to mitigate a BREACH attack by randomizing how the " +"token outputted on each request. A random mask is applied to the token, " +"making the string always unique." +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "To mask a token:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "$maskedToken = \\Yiisoft\\Security\\TokenMask::apply($token);\n" +msgstr "" + +#. type: Plain text +#: en/security/cryptography.md +msgid "To get the original value from the masked one:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/cryptography.md +#, no-wrap +msgid "$token = \\Yiisoft\\Security\\TokenMask::remove($maskedToken);\n" +msgstr "" diff --git a/guide/po/security_overview.md/ru/security_overview.md.ru.po b/guide/po/security_overview.md/ru/security_overview.md.ru.po new file mode 100644 index 00000000..df7f4a9d --- /dev/null +++ b/guide/po/security_overview.md/ru/security_overview.md.ru.po @@ -0,0 +1,68 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/security/overview.md +#, no-wrap +msgid "Security" +msgstr "" + +#. type: Plain text +#: en/security/overview.md +msgid "Good security is vital to the health and success of any application. Unfortunately, many developers cut corners when it comes to security, either due to a lack of understanding or because implementation is too much of a hurdle. To make your Yii-powered application as secure as possible, Yii has included several excellent and easy-to-use security features." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Authentication](authentication.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Authorization](authorization.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Working with Passwords](passwords.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Cryptography](cryptography.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Best Practices](best-practices.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Trusted request](trusted-request.md)" +msgstr "" + +#. type: Plain text +#: en/security/overview.md +msgid "See also:" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Views security](../views/view.md#security)" +msgstr "" diff --git a/guide/po/security_overview.md/security_overview.md.pot b/guide/po/security_overview.md/security_overview.md.pot new file mode 100644 index 00000000..58bb2364 --- /dev/null +++ b/guide/po/security_overview.md/security_overview.md.pot @@ -0,0 +1,73 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/security/overview.md +#, no-wrap +msgid "Security" +msgstr "" + +#. type: Plain text +#: en/security/overview.md +msgid "" +"Good security is vital to the health and success of any application. " +"Unfortunately, many developers cut corners when it comes to security, either " +"due to a lack of understanding or because implementation is too much of a " +"hurdle. To make your Yii-powered application as secure as possible, Yii has " +"included several excellent and easy-to-use security features." +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Authentication](authentication.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Authorization](authorization.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Working with Passwords](passwords.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Cryptography](cryptography.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Best Practices](best-practices.md)" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Trusted request](trusted-request.md)" +msgstr "" + +#. type: Plain text +#: en/security/overview.md +msgid "See also:" +msgstr "" + +#. type: Bullet: '* ' +#: en/security/overview.md +msgid "[Views security](../views/view.md#security)" +msgstr "" diff --git a/guide/po/security_passwords.md/ru/security_passwords.md.ru.po b/guide/po/security_passwords.md/ru/security_passwords.md.ru.po new file mode 100644 index 00000000..878fe292 --- /dev/null +++ b/guide/po/security_passwords.md/ru/security_passwords.md.ru.po @@ -0,0 +1,88 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/security/passwords.md +#, no-wrap +msgid "Working with passwords" +msgstr "" + +#. type: Plain text +#: en/security/passwords.md +msgid "Most developers know that passwords can't be stored in plain text, but many developers believe it's still safe to hash passwords using `md5`, `sha1` or `sha256` etc. There was a time when using the aforementioned hashing algorithms was enough, but modern hardware makes it possible to reverse such hashes and even stronger ones using brute force attacks." +msgstr "" + +#. type: Plain text +#: en/security/passwords.md +msgid "To offer increased security for user passwords, even in the worst case scenario (when one breaches your application), you need to use a hashing algorithm that's resilient against brute force attacks. The best current choice is `argon2`. Yii `yiisoft/security` package make securely generate and verify hashes easier and ensure the best possible hashing solution used." +msgstr "" + +#. type: Plain text +#: en/security/passwords.md +msgid "To use it, you need to require the package first:" +msgstr "" + +#. type: Fenced code block +#: en/security/passwords.md +#, fuzzy, no-wrap +#| msgid "composer install yiisoft/security\n" +msgid "composer require yiisoft/security\n" +msgstr "composer install yiisoft/security\n" + +#. type: Plain text +#: en/security/passwords.md +msgid "When a user provides a password for the first time (e.g., upon registration), the password needs to be hashed and stored:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/passwords.md +#, fuzzy, no-wrap +#| msgid "" +#| "$encryptedData = (new \\Yiisoft\\Security\\Crypt())->encryptByPassword($data, $password);\n" +#| "\n" +#| "// save data to a database or another storage\n" +#| "saveData($encryptedData);\n" +msgid "" +"$hash = (new PasswordHasher())->hash($password);\n" +"\n" +"// save hash to a database or another storage\n" +"saveHash($hash); \n" +msgstr "" +"$encryptedData = (new \\Yiisoft\\Security\\Crypt())->encryptByPassword($data, $password);\n" +"\n" +"// сохранение данных в базу данных или другое хранилище\n" +"saveData($encryptedData);\n" + +#. type: Plain text +#: en/security/passwords.md +msgid "When a user attempts to log in, the submitted password must be verified against the previously hashed and stored password:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/passwords.md +#, no-wrap +msgid "" +"// get hash from a database or another storage\n" +"$hash = getHash();\n" +"\n" +"if ((new PasswordHasher())->validate($password, $hash)) {\n" +" // all good, logging in user\n" +"} else {\n" +" // wrong password\n" +"}\n" +msgstr "" diff --git a/guide/po/security_passwords.md/security_passwords.md.pot b/guide/po/security_passwords.md/security_passwords.md.pot new file mode 100644 index 00000000..5c62a178 --- /dev/null +++ b/guide/po/security_passwords.md/security_passwords.md.pot @@ -0,0 +1,92 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/security/passwords.md +#, no-wrap +msgid "Working with passwords" +msgstr "" + +#. type: Plain text +#: en/security/passwords.md +msgid "" +"Most developers know that passwords can't be stored in plain text, but many " +"developers believe it's still safe to hash passwords using `md5`, `sha1` or " +"`sha256` etc. There was a time when using the aforementioned hashing " +"algorithms was enough, but modern hardware makes it possible to reverse such " +"hashes and even stronger ones using brute force attacks." +msgstr "" + +#. type: Plain text +#: en/security/passwords.md +msgid "" +"To offer increased security for user passwords, even in the worst case " +"scenario (when one breaches your application), you need to use a hashing " +"algorithm that's resilient against brute force attacks. The best current " +"choice is `argon2`. Yii `yiisoft/security` package make securely generate " +"and verify hashes easier and ensure the best possible hashing solution used." +msgstr "" + +#. type: Plain text +#: en/security/passwords.md +msgid "To use it, you need to require the package first:" +msgstr "" + +#. type: Fenced code block +#: en/security/passwords.md +#, no-wrap +msgid "composer require yiisoft/security\n" +msgstr "" + +#. type: Plain text +#: en/security/passwords.md +msgid "" +"When a user provides a password for the first time (e.g., upon " +"registration), the password needs to be hashed and stored:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/passwords.md +#, no-wrap +msgid "" +"$hash = (new PasswordHasher())->hash($password);\n" +"\n" +"// save hash to a database or another storage\n" +"saveHash($hash); \n" +msgstr "" + +#. type: Plain text +#: en/security/passwords.md +msgid "" +"When a user attempts to log in, the submitted password must be verified " +"against the previously hashed and stored password:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/passwords.md +#, no-wrap +msgid "" +"// get hash from a database or another storage\n" +"$hash = getHash();\n" +"\n" +"if ((new PasswordHasher())->validate($password, $hash)) {\n" +" // all good, logging in user\n" +"} else {\n" +" // wrong password\n" +"}\n" +msgstr "" diff --git a/guide/po/security_trusted-request.md/ru/security_trusted-request.md.ru.po b/guide/po/security_trusted-request.md/ru/security_trusted-request.md.ru.po new file mode 100644 index 00000000..8cbe0bd4 --- /dev/null +++ b/guide/po/security_trusted-request.md/ru/security_trusted-request.md.ru.po @@ -0,0 +1,77 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/security/trusted-request.md +#, no-wrap +msgid "Trusted request" +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "Getting user information, like a host and IP address, will work out of the box in a normal setup where a single webserver is used to serve the website. If your Yii application, however, runs behind a reverse proxy, you need to add configuration to retrieve this information as the direct client is now the proxy, and the user IP address is passed to the Yii application by a header set by the proxy." +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "You shouldn't blindly trust headers provided by proxies unless you explicitly trust the proxy. Yii supports configuring trusted proxies via the `Yiisoft\\Yii\\Web\\Middleware\\TrustedHostsNetworkResolver`. You should add it to [middleware stack](../structure/middleware.md)." +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "The following is a request config for an application that runs behind an array of reverse proxies, which are located in the `10.0.2.0/24` IP network:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/trusted-request.md +#, no-wrap +msgid "" +"/** @var \\Yiisoft\\Yii\\Web\\Middleware\\TrustedHostsNetworkResolver $trustedHostsNetworkResolver */\n" +"$trustedHostsNetworkResolver = $trustedHostsNetworkResolver->withAddedTrustedHosts(['1.0.2.0/24']);\n" +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "The proxy sends the IP in the `X-Forwarded-For` header by default, and the protocol (`http` or `https`) is in `X-Forwarded-Proto`." +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "In case your proxies are using different headers, you can use the request configuration to adjust these, e.g.:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/trusted-request.md +#, no-wrap +msgid "" +"/** @var \\Yiisoft\\Yii\\Web\\Middleware\\TrustedHostsNetworkResolver $trustedHostsNetworkResolver */\n" +"$trustedHostsNetworkResolver = $trustedHostsNetworkResolver\n" +" ->withAddedTrustedHosts(\n" +" ['1.0.2.0/24'],\n" +" ['X-ProxyUser-Ip'],\n" +" ['Front-End-Https'],\n" +" [],\n" +" [],\n" +" ['X-Proxy-User-Ip']\n" +" );\n" +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "With the above configuration, `X-ProxyUser-Ip` and `Front-End-Https` headers are used to get user IP and protocol." +msgstr "" diff --git a/guide/po/security_trusted-request.md/security_trusted-request.md.pot b/guide/po/security_trusted-request.md/security_trusted-request.md.pot new file mode 100644 index 00000000..29dd42ec --- /dev/null +++ b/guide/po/security_trusted-request.md/security_trusted-request.md.pot @@ -0,0 +1,95 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/security/trusted-request.md +#, no-wrap +msgid "Trusted request" +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "" +"Getting user information, like a host and IP address, will work out of the " +"box in a normal setup where a single webserver is used to serve the website. " +"If your Yii application, however, runs behind a reverse proxy, you need to " +"add configuration to retrieve this information as the direct client is now " +"the proxy, and the user IP address is passed to the Yii application by a " +"header set by the proxy." +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "" +"You shouldn't blindly trust headers provided by proxies unless you " +"explicitly trust the proxy. Yii supports configuring trusted proxies via " +"the `Yiisoft\\Yii\\Web\\Middleware\\TrustedHostsNetworkResolver`. You " +"should add it to [middleware stack](../structure/middleware.md)." +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "" +"The following is a request config for an application that runs behind an " +"array of reverse proxies, which are located in the `10.0.2.0/24` IP network:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/trusted-request.md +#, no-wrap +msgid "" +"/** @var \\Yiisoft\\Yii\\Web\\Middleware\\TrustedHostsNetworkResolver $trustedHostsNetworkResolver */\n" +"$trustedHostsNetworkResolver = $trustedHostsNetworkResolver->withAddedTrustedHosts(['1.0.2.0/24']);\n" +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "" +"The proxy sends the IP in the `X-Forwarded-For` header by default, and the " +"protocol (`http` or `https`) is in `X-Forwarded-Proto`." +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "" +"In case your proxies are using different headers, you can use the request " +"configuration to adjust these, e.g.:" +msgstr "" + +#. type: Fenced code block (php) +#: en/security/trusted-request.md +#, no-wrap +msgid "" +"/** @var \\Yiisoft\\Yii\\Web\\Middleware\\TrustedHostsNetworkResolver $trustedHostsNetworkResolver */\n" +"$trustedHostsNetworkResolver = $trustedHostsNetworkResolver\n" +" ->withAddedTrustedHosts(\n" +" ['1.0.2.0/24'],\n" +" ['X-ProxyUser-Ip'],\n" +" ['Front-End-Https'],\n" +" [],\n" +" [],\n" +" ['X-Proxy-User-Ip']\n" +" );\n" +msgstr "" + +#. type: Plain text +#: en/security/trusted-request.md +msgid "" +"With the above configuration, `X-ProxyUser-Ip` and `Front-End-Https` headers " +"are used to get user IP and protocol." +msgstr "" diff --git a/guide/po/start_creating-project.md/ru/start_creating-project.md.ru.po b/guide/po/start_creating-project.md/ru/start_creating-project.md.ru.po new file mode 100644 index 00000000..0af7098b --- /dev/null +++ b/guide/po/start_creating-project.md/ru/start_creating-project.md.ru.po @@ -0,0 +1,128 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/start/creating-project.md +#, no-wrap +msgid "Creating a project" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "In this guide we'll provide commands for both [Docker](https://docs.docker.com/get-started/get-docker/) and the built-in dev server with everything installed locally." +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> If you want to use another web server,\n" +"> see [\"Configuring web servers\"](../../../cookbook/en/configuring-webservers/general.md).\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "We recommend starting with a project template that's a minimal working Yii project implementing some basic features. It can serve as a good starting point for your projects." +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "You can create a new project from a template using the [Composer](https://getcomposer.org) package manager:" +msgstr "" + +#. type: Fenced code block +#: en/start/creating-project.md +#, no-wrap +msgid "composer create-project yiisoft/app your_project\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "Docker users can run the following command:" +msgstr "" + +#. type: Fenced code block (sh) +#: en/start/creating-project.md +#, no-wrap +msgid "docker run --rm -it -v \"$(pwd):/app\" composer/composer create-project yiisoft/app your_project\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "This installs the latest stable version of the Yii project template in a directory named `your_project`. You can choose a different directory name if you want." +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +#, no-wrap +msgid "" +"> [!TIP]\n" +"> If you want to install the latest development version of Yii, you may add `--stability=dev` to the command.\n" +"> Don't use the development version of Yii for production because it may break your running code.\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "Go into the newly created directory and run:" +msgstr "" + +#. type: Fenced code block (sh) +#: en/start/creating-project.md +#, no-wrap +msgid "APP_ENV=dev ./yii serve --port=80\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "For Docker users, run:" +msgstr "" + +#. type: Fenced code block +#: en/start/creating-project.md +#, no-wrap +msgid "make up\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "Open your browser to the URL `http://localhost/`." +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> The HTTP server listens on port 80. If that port is already in use, specify the port via `--port` or, in case of Docker,\n" +"> `DEV_PORT` in the `docker/.env` file.\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "![Successful Installation of Yii](img/app-installed.png)" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← What do you need to know?](prerequisites.md) | \n" +"> [Running applications →](workflow.md)\n" +msgstr "" diff --git a/guide/po/start_creating-project.md/start_creating-project.md.pot b/guide/po/start_creating-project.md/start_creating-project.md.pot new file mode 100644 index 00000000..72d1d9e8 --- /dev/null +++ b/guide/po/start_creating-project.md/start_creating-project.md.pot @@ -0,0 +1,139 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/start/creating-project.md +#, no-wrap +msgid "Creating a project" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "" +"In this guide we'll provide commands for both [Docker](https://docs.docker." +"com/get-started/get-docker/) and the built-in dev server with everything " +"installed locally." +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> If you want to use another web server,\n" +"> see [\"Configuring web servers\"](../../../cookbook/en/configuring-webservers/general.md).\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "" +"We recommend starting with a project template that's a minimal working Yii " +"project implementing some basic features. It can serve as a good starting " +"point for your projects." +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "" +"You can create a new project from a template using the [Composer](https://" +"getcomposer.org) package manager:" +msgstr "" + +#. type: Fenced code block +#: en/start/creating-project.md +#, no-wrap +msgid "composer create-project yiisoft/app your_project\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "Docker users can run the following command:" +msgstr "" + +#. type: Fenced code block (sh) +#: en/start/creating-project.md +#, no-wrap +msgid "docker run --rm -it -v \"$(pwd):/app\" composer/composer create-project yiisoft/app your_project\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "" +"This installs the latest stable version of the Yii project template in a " +"directory named `your_project`. You can choose a different directory name " +"if you want." +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +#, no-wrap +msgid "" +"> [!TIP]\n" +"> If you want to install the latest development version of Yii, you may add `--stability=dev` to the command.\n" +"> Don't use the development version of Yii for production because it may break your running code.\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "Go into the newly created directory and run:" +msgstr "" + +#. type: Fenced code block (sh) +#: en/start/creating-project.md +#, no-wrap +msgid "APP_ENV=dev ./yii serve --port=80\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "For Docker users, run:" +msgstr "" + +#. type: Fenced code block +#: en/start/creating-project.md +#, no-wrap +msgid "make up\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "Open your browser to the URL `http://localhost/`." +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> The HTTP server listens on port 80. If that port is already in use, specify the port via `--port` or, in case of Docker,\n" +"> `DEV_PORT` in the `docker/.env` file.\n" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +msgid "![Successful Installation of Yii](img/app-installed.png)" +msgstr "" + +#. type: Plain text +#: en/start/creating-project.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← What do you need to know?](prerequisites.md) | \n" +"> [Running applications →](workflow.md)\n" +msgstr "" diff --git a/guide/po/start_databases.md/ru/start_databases.md.ru.po b/guide/po/start_databases.md/ru/start_databases.md.ru.po new file mode 100644 index 00000000..920857d0 --- /dev/null +++ b/guide/po/start_databases.md/ru/start_databases.md.ru.po @@ -0,0 +1,126 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/start/databases.md +#, no-wrap +msgid "Working with databases" +msgstr "" + +#. type: Plain text +#: en/start/databases.md +msgid "Yii doesn't dictate using a particular database or storage for your application. There are many ways you can work with relational databases:" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[Yii DB](https://github.com/yiisoft/db)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[Yii Active Record](https://github.com/yiisoft/active-record)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[Cycle](https://github.com/cycle) via [Yii Cycle package](https://github.com/yiisoft/yii-cycle)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[Doctrine](https://www.doctrine-project.org/) via [Yii Doctrine package](https://github.com/stargazer-team/yii-doctrine)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +#, fuzzy +#| msgid "[PHP manual: security](https://www.php.net/manual/en/security.php)" +msgid "[PDO](https://www.php.net/manual/en/book.pdo.php)" +msgstr "[Руководство по PHP: безопасность](https://www.php.net/manual/en/security.php)" + +#. type: Plain text +#: en/start/databases.md +msgid "For non-relational ones, there are usually official libraries available:" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[ElasticSearch](https://github.com/elastic/elasticsearch-php)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[Redis](https://redis.io/docs/clients/#php)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "..." +msgstr "" + +#. type: Plain text +#: en/start/databases.md +msgid "In this guide, we will focus on working with relational databases using Yii DB." +msgstr "" + +#. type: Title ## +#: en/start/databases.md +#, fuzzy, no-wrap +#| msgid "Configuring SSL peer validation" +msgid "Configuring connection" +msgstr "Настройка проверки SSL-сертификата" + +#. type: Title ## +#: en/start/databases.md +#, no-wrap +msgid "Creating and applying migration" +msgstr "" + +#. type: Title ## +#: en/start/databases.md +#, no-wrap +msgid "Inserting" +msgstr "" + +#. type: Title ## +#: en/start/databases.md +#, no-wrap +msgid "Selecting" +msgstr "" + +#. type: Title ## +#: en/start/databases.md +#, no-wrap +msgid "Using data package" +msgstr "" + +#. type: Title ### +#: en/start/databases.md +#, no-wrap +msgid "Pagination" +msgstr "" + +#. type: Plain text +#: en/start/databases.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Working with forms](forms.md) |\n" +"> [Generating code with Gii →](gii.md)\n" +msgstr "" diff --git a/guide/po/start_databases.md/start_databases.md.pot b/guide/po/start_databases.md/start_databases.md.pot new file mode 100644 index 00000000..d51e7af7 --- /dev/null +++ b/guide/po/start_databases.md/start_databases.md.pot @@ -0,0 +1,132 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/start/databases.md +#, no-wrap +msgid "Working with databases" +msgstr "" + +#. type: Plain text +#: en/start/databases.md +msgid "" +"Yii doesn't dictate using a particular database or storage for your " +"application. There are many ways you can work with relational databases:" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[Yii DB](https://github.com/yiisoft/db)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[Yii Active Record](https://github.com/yiisoft/active-record)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "" +"[Cycle](https://github.com/cycle) via [Yii Cycle package](https://github.com/" +"yiisoft/yii-cycle)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "" +"[Doctrine](https://www.doctrine-project.org/) via [Yii Doctrine package]" +"(https://github.com/stargazer-team/yii-doctrine)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[PDO](https://www.php.net/manual/en/book.pdo.php)" +msgstr "" + +#. type: Plain text +#: en/start/databases.md +msgid "" +"For non-relational ones, there are usually official libraries available:" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[ElasticSearch](https://github.com/elastic/elasticsearch-php)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "[Redis](https://redis.io/docs/clients/#php)" +msgstr "" + +#. type: Bullet: '- ' +#: en/start/databases.md +msgid "..." +msgstr "" + +#. type: Plain text +#: en/start/databases.md +msgid "" +"In this guide, we will focus on working with relational databases using Yii " +"DB." +msgstr "" + +#. type: Title ## +#: en/start/databases.md +#, no-wrap +msgid "Configuring connection" +msgstr "" + +#. type: Title ## +#: en/start/databases.md +#, no-wrap +msgid "Creating and applying migration" +msgstr "" + +#. type: Title ## +#: en/start/databases.md +#, no-wrap +msgid "Inserting" +msgstr "" + +#. type: Title ## +#: en/start/databases.md +#, no-wrap +msgid "Selecting" +msgstr "" + +#. type: Title ## +#: en/start/databases.md +#, no-wrap +msgid "Using data package" +msgstr "" + +#. type: Title ### +#: en/start/databases.md +#, no-wrap +msgid "Pagination" +msgstr "" + +#. type: Plain text +#: en/start/databases.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Working with forms](forms.md) |\n" +"> [Generating code with Gii →](gii.md)\n" +msgstr "" diff --git a/guide/po/start_forms.md/ru/start_forms.md.ru.po b/guide/po/start_forms.md/ru/start_forms.md.ru.po new file mode 100644 index 00000000..773a76a6 --- /dev/null +++ b/guide/po/start_forms.md/ru/start_forms.md.ru.po @@ -0,0 +1,349 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/start/forms.md +#, no-wrap +msgid "Working with forms" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "This section continues to improve on \"Saying Hello.\" Instead of using URL, you will now ask a user for a message via form." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "Through this tutorial, you will learn how to:" +msgstr "" + +#. type: Bullet: '* ' +#: en/start/forms.md +msgid "Create a form model to represent the data entered by a user through a form." +msgstr "" + +#. type: Bullet: '* ' +#: en/start/forms.md +msgid "Declare rules to validate the data entered." +msgstr "" + +#. type: Bullet: '* ' +#: en/start/forms.md +msgid "Build an HTML form in a view." +msgstr "" + +#. type: Title ## +#: en/start/forms.md +#, no-wrap +msgid "Installing form package" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "To install form package, issue the following command in your application directory:" +msgstr "" + +#. type: Fenced code block +#: en/start/forms.md +#, fuzzy, no-wrap +#| msgid "composer install yiisoft/security\n" +msgid "composer require yiisoft/form-model\n" +msgstr "composer install yiisoft/security\n" + +#. type: Plain text +#: en/start/forms.md +msgid "For Docker that would be:" +msgstr "" + +#. type: Fenced code block +#: en/start/forms.md +#, no-wrap +msgid "make composer require yiisoft/form-model\n" +msgstr "" + +#. type: Title ## +#: en/start/forms.md +#, fuzzy, no-wrap +#| msgid "Configuring container " +msgid "Creating a form " +msgstr "Конфигурирование контейнера " + +#. type: Plain text +#: en/start/forms.md +msgid "The data to be requested from the user will be represented by a `Form` class as shown below and saved in the file `/src/App/Controller/Echo/Form.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/forms.md +#, no-wrap +msgid "" +"" +msgid "Using the form " +msgstr "Конфигурирование контейнера " + +#. type: Plain text +#: en/start/forms.md +msgid "Now that you have a form, use it in your action from \"[Saying Hello](hello.md)\"." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "Here's what you end up with in `/src/Controller/Echo/Action.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/forms.md +#, no-wrap +msgid "" +"formHydrator->populateFromPostAndValidate($form, $request);\n" +"\n" +" return $this->viewRenderer->render(__DIR__ . '/template', [\n" +" 'form' => $form,\n" +" ]);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "Instead of reading from route, you fill your form from request's POST data and validate it with the help of `FormHydrator`. Next you pass the form to the view." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "For the form to function we need to allow both GET to render the form and POST to send the data. Adjust your route in `config/common/routes.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/forms.md +#, no-wrap +msgid "" +"routes(\n" +" Route::get('/')\n" +" ->action(\\App\\Controller\\HomePage\\Action::class)\n" +" ->name('home'),\n" +" Route::methods([Method::GET, Method::POST], '/say')\n" +" ->action(\\App\\Controller\\Echo\\Action::class)\n" +" ->name('echo/say'),\n" +" ),\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/start/forms.md +#, no-wrap +msgid "Adjusting view" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "To render a form, you need to change your view, `src/Controller/Echo/template.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/forms.md +#, no-wrap +msgid "" +"post($urlGenerator->generate('echo/say'))\n" +" ->csrf($csrf);\n" +"?>\n" +"\n" +"open() ?>\n" +" required() ?>\n" +" \n" +"close() ?>\n" +"\n" +"isValid()): ?>\n" +" Echo said: message) ?>\n" +"\n" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "If the form is valid, you display a message. The rest initializes and renders the form." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "First, you initialize `$htmlForm` with the POST type and the action URL generated with the help from the URL generator. You can access it as `$urlGenerator` in all views. You also need to pass the CSRF token to the form, which is also available in every view as `$csrf` thanks to the view injections listed in `config/common/params.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/forms.md +#, no-wrap +msgid "" +"'yiisoft/yii-view-renderer' => [\n" +" 'injections' => [\n" +" Reference::to(CsrfViewInjection::class),\n" +" ],\n" +"],\n" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "The template renders the CSRF token value as a hidden input to ensure that the request originates from the form page and not from another website. It will be submitted along with POST form data. Omitting it would result in [HTTP response code 422](https://tools.ietf.org/html/rfc4918#section-11.2)." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "You use `Field::text()` to output \"message\" field, so it takes care about filling the value, escaping it, rendering field label and validation errors." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "Now, in case you submit an empty message, you will get a validation error: \"The message to be echoed must contain at least 2 characters.\"" +msgstr "" + +#. type: Title ## +#: en/start/forms.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Trying it Out " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/start/forms.md +msgid "To see how it works, use your browser to access the following URL:" +msgstr "" + +#. type: Fenced code block +#: en/start/forms.md +#, no-wrap +msgid "http://localhost:8080/say\n" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "You will see a page with a form input field and a label that indicates what data to enter. Also, the form has a \"submit\" button labeled \"Say\". If you click the \"submit\" button without entering anything, you will see that the field is required. If you enter a single character, the form displays an error message next to the problematic input field." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "![Form with a validation error](img/form-error.png)" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "After you enter a valid message and click the \"submit\" button, the page echoes the data that you entered." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "![Form with a success message](img/form-success.png)" +msgstr "" + +#. type: Title ## +#: en/start/forms.md en/start/hello.md +#, fuzzy, no-wrap +msgid "Summary " +msgstr "Контейнер внедрения зависимостей " + +#. type: Plain text +#: en/start/forms.md +msgid "In this section of the guide, you've learned how to create a form model class to represent the user data and validate said data." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "You've also learned how to get data from users and how to display data back in the browser. This is a task that could take you a lot of time when developing an application, but Yii provides powerful widgets to make this task easy." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "In the next section, you will learn how to work with databases, which are needed in nearly every application." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Saying hello](hello.md) |\n" +"> [Working with databases →](databases.md)\n" +msgstr "" diff --git a/guide/po/start_forms.md/start_forms.md.pot b/guide/po/start_forms.md/start_forms.md.pot new file mode 100644 index 00000000..5774c009 --- /dev/null +++ b/guide/po/start_forms.md/start_forms.md.pot @@ -0,0 +1,394 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/start/forms.md +#, no-wrap +msgid "Working with forms" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"This section continues to improve on \"Saying Hello.\" Instead of using URL, " +"you will now ask a user for a message via form." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "Through this tutorial, you will learn how to:" +msgstr "" + +#. type: Bullet: '* ' +#: en/start/forms.md +msgid "" +"Create a form model to represent the data entered by a user through a form." +msgstr "" + +#. type: Bullet: '* ' +#: en/start/forms.md +msgid "Declare rules to validate the data entered." +msgstr "" + +#. type: Bullet: '* ' +#: en/start/forms.md +msgid "Build an HTML form in a view." +msgstr "" + +#. type: Title ## +#: en/start/forms.md +#, no-wrap +msgid "Installing form package" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"To install form package, issue the following command in your application " +"directory:" +msgstr "" + +#. type: Fenced code block +#: en/start/forms.md +#, no-wrap +msgid "composer require yiisoft/form-model\n" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "For Docker that would be:" +msgstr "" + +#. type: Fenced code block +#: en/start/forms.md +#, no-wrap +msgid "make composer require yiisoft/form-model\n" +msgstr "" + +#. type: Title ## +#: en/start/forms.md +#, no-wrap +msgid "Creating a form " +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"The data to be requested from the user will be represented by a `Form` class " +"as shown below and saved in the file `/src/App/Controller/Echo/Form.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/forms.md +#, no-wrap +msgid "" +" " +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"Now that you have a form, use it in your action from \"[Saying Hello](hello." +"md)\"." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "Here's what you end up with in `/src/Controller/Echo/Action.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/forms.md +#, no-wrap +msgid "" +"formHydrator->populateFromPostAndValidate($form, $request);\n" +"\n" +" return $this->viewRenderer->render(__DIR__ . '/template', [\n" +" 'form' => $form,\n" +" ]);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"Instead of reading from route, you fill your form from request's POST data " +"and validate it with the help of `FormHydrator`. Next you pass the form to " +"the view." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"For the form to function we need to allow both GET to render the form and " +"POST to send the data. Adjust your route in `config/common/routes.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/forms.md +#, no-wrap +msgid "" +"routes(\n" +" Route::get('/')\n" +" ->action(\\App\\Controller\\HomePage\\Action::class)\n" +" ->name('home'),\n" +" Route::methods([Method::GET, Method::POST], '/say')\n" +" ->action(\\App\\Controller\\Echo\\Action::class)\n" +" ->name('echo/say'),\n" +" ),\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/start/forms.md +#, no-wrap +msgid "Adjusting view" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"To render a form, you need to change your view, `src/Controller/Echo/" +"template.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/forms.md +#, no-wrap +msgid "" +"post($urlGenerator->generate('echo/say'))\n" +" ->csrf($csrf);\n" +"?>\n" +"\n" +"open() ?>\n" +" required() ?>\n" +" \n" +"close() ?>\n" +"\n" +"isValid()): ?>\n" +" Echo said: message) ?>\n" +"\n" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"If the form is valid, you display a message. The rest initializes and " +"renders the form." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"First, you initialize `$htmlForm` with the POST type and the action URL " +"generated with the help from the URL generator. You can access it as " +"`$urlGenerator` in all views. You also need to pass the CSRF token to the " +"form, which is also available in every view as `$csrf` thanks to the view " +"injections listed in `config/common/params.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/forms.md +#, no-wrap +msgid "" +"'yiisoft/yii-view-renderer' => [\n" +" 'injections' => [\n" +" Reference::to(CsrfViewInjection::class),\n" +" ],\n" +"],\n" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"The template renders the CSRF token value as a hidden input to ensure that " +"the request originates from the form page and not from another website. It " +"will be submitted along with POST form data. Omitting it would result in " +"[HTTP response code 422](https://tools.ietf.org/html/rfc4918#section-11.2)." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"You use `Field::text()` to output \"message\" field, so it takes care about " +"filling the value, escaping it, rendering field label and validation errors." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"Now, in case you submit an empty message, you will get a validation error: " +"\"The message to be echoed must contain at least 2 characters.\"" +msgstr "" + +#. type: Title ## +#: en/start/forms.md +#, no-wrap +msgid "Trying it Out " +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "To see how it works, use your browser to access the following URL:" +msgstr "" + +#. type: Fenced code block +#: en/start/forms.md +#, no-wrap +msgid "http://localhost:8080/say\n" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"You will see a page with a form input field and a label that indicates what " +"data to enter. Also, the form has a \"submit\" button labeled \"Say\". If " +"you click the \"submit\" button without entering anything, you will see that " +"the field is required. If you enter a single character, the form displays an " +"error message next to the problematic input field." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "![Form with a validation error](img/form-error.png)" +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"After you enter a valid message and click the \"submit\" button, the page " +"echoes the data that you entered." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "![Form with a success message](img/form-success.png)" +msgstr "" + +#. type: Title ## +#: en/start/forms.md en/start/hello.md +#, no-wrap +msgid "Summary " +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"In this section of the guide, you've learned how to create a form model " +"class to represent the user data and validate said data." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"You've also learned how to get data from users and how to display data back " +"in the browser. This is a task that could take you a lot of time when " +"developing an application, but Yii provides powerful widgets to make this " +"task easy." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +msgid "" +"In the next section, you will learn how to work with databases, which are " +"needed in nearly every application." +msgstr "" + +#. type: Plain text +#: en/start/forms.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Saying hello](hello.md) |\n" +"> [Working with databases →](databases.md)\n" +msgstr "" diff --git a/guide/po/start_gii.md/ru/start_gii.md.ru.po b/guide/po/start_gii.md/ru/start_gii.md.ru.po new file mode 100644 index 00000000..6d515a5c --- /dev/null +++ b/guide/po/start_gii.md/ru/start_gii.md.ru.po @@ -0,0 +1,33 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/start/gii.md +#, fuzzy, no-wrap +#| msgid "Generating random data" +msgid "Generating code with Gii" +msgstr "Генерация случайных данных" + +#. type: Plain text +#: en/start/gii.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Working with databases](databases.md) |\n" +"> [Looking ahead →](looking-ahead.md)\n" +msgstr "" diff --git a/guide/po/start_gii.md/start_gii.md.pot b/guide/po/start_gii.md/start_gii.md.pot new file mode 100644 index 00000000..b2889c8d --- /dev/null +++ b/guide/po/start_gii.md/start_gii.md.pot @@ -0,0 +1,32 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/start/gii.md +#, no-wrap +msgid "Generating code with Gii" +msgstr "" + +#. type: Plain text +#: en/start/gii.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Working with databases](databases.md) |\n" +"> [Looking ahead →](looking-ahead.md)\n" +msgstr "" diff --git a/guide/po/start_hello.md/ru/start_hello.md.ru.po b/guide/po/start_hello.md/ru/start_hello.md.ru.po new file mode 100644 index 00000000..e53be46f --- /dev/null +++ b/guide/po/start_hello.md/ru/start_hello.md.ru.po @@ -0,0 +1,293 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title ## +#: en/start/forms.md en/start/hello.md +#, fuzzy, no-wrap +msgid "Summary " +msgstr "Контейнер внедрения зависимостей " + +#. type: Title # +#: en/start/hello.md +#, no-wrap +msgid "Saying hello" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "This section describes how to create a new \"Hello\" page in your application. It's a simple page that will echo back whatever you pass to it or, if nothing passed, will just say \"Hello!\"." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "To achieve this goal, you will define a route and create [a handler](../structure/handler.md) that does the job and forms the response. Then you will improve it to use [view](../structure/views.md) for building the response." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "Through this tutorial, you will learn three things:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/start/hello.md +msgid "How to create a handler to respond to a request." +msgstr "" + +#. type: Bullet: '2. ' +#: en/start/hello.md +msgid "How to map URL to the handler." +msgstr "" + +#. type: Bullet: '3. ' +#: en/start/hello.md +msgid "How to create a [view](../structure/view.md) to compose the response's content." +msgstr "" + +#. type: Title ## +#: en/start/hello.md +#, fuzzy, no-wrap +#| msgid "Configuring container " +msgid "Creating a handler " +msgstr "Конфигурирование контейнера " + +#. type: Plain text +#: en/start/hello.md +msgid "For the \"Hello\" task, you will create a handler class that reads a `message` parameter from the request and displays that message back to the user. If the request doesn't provide a `message` parameter, the action will display the default \"Hello\" message." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "Create `src/Controller/Echo/Action.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/hello.md +#, no-wrap +msgid "" +"responseFactory->createResponse();\n" +" $response->getBody()->write('The message is: ' . Html::encode($message));\n" +" return $response;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "In your example, the `__invoke` method receives the `$message` parameter that with the help of `RouteArgument` attribute gets the message from URL. The value defaults to `\"Hello!\"`. If the request is made to `/say/Goodbye`, the action assigns the value \"Goodbye\" to the `$message` variable." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "The application passes the response through the [middleware stack](../structure/middleware.md) to the emitter that outputs the response to the end user." +msgstr "" + +#. type: Title ## +#: en/start/hello.md +#, fuzzy, no-wrap +#| msgid "configuration could be:" +msgid "Configuring router" +msgstr "конфигурация может быть:" + +#. type: Plain text +#: en/start/hello.md +msgid "Now, to map your handler to URL, you need to add a route in `config/common/routes.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/hello.md +#, no-wrap +msgid "" +"routes(\n" +" Route::get('/')\n" +" ->action(\\App\\Controller\\HomePage\\Action::class)\n" +" ->name('home'),\n" +" Route::get('/say[/{message}]')\n" +" ->action(\\App\\Controller\\Echo\\Action::class)\n" +" ->name('echo/say'),\n" +" ),\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "In the above, you map the `/say[/{message}]` pattern to `\\App\\Controller\\Echo\\Action`. For a request, the router creates an instance and calls the `__invoke()` method. The `{message}` part of the pattern writes anything specified in this place to the `message` request attribute. `[]` marks this part of the pattern as optional." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "You also give a `echo/say` name to this route to be able to generate URLs pointing to it." +msgstr "" + +#. type: Title ## +#: en/start/hello.md +#, fuzzy, no-wrap +#| msgid "Configuring container " +msgid "Trying it out " +msgstr "Конфигурирование контейнера " + +#. type: Plain text +#: en/start/hello.md +msgid "After creating the action and the view open `http://localhost/say/Hello+World` in your browser." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "This URL displays a page with \"The message is: Hello World\"." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "If you omit the `message` parameter in the URL, the page displays \"The message is: Hello!\"." +msgstr "" + +#. type: Title ## +#: en/start/hello.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Creating a View Template " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/start/hello.md +msgid "Usually, the task is more complicated than printing out \"hello world\" and involves rendering some complex HTML. For this task, it's handy to use view templates. They're scripts you write to generate a response's body." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "For the \"Hello\" task, create a `src/Controller/Echo/template.php` template that prints the `message` parameter received from the action method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/hello.md +#, no-wrap +msgid "" +"\n" +"\n" +"

The message is:

\n" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "In the above code, the `message` parameter uses HTML encoding before you print it. You need that because the parameter comes from an end user and is vulnerable to [cross-site scripting (XSS) attacks](https://en.wikipedia.org/wiki/Cross-site_scripting) by embedding malicious JavaScript in the parameter." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "Naturally, you may put more content in the `say` view. The content can consist of HTML tags, plain text, and even PHP statements. In fact, the view service executes the `say` view as a PHP script." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "To use the view, you need to change `src/Controller/Echo/Action.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/hello.md +#, no-wrap +msgid "" +"viewRenderer->render(__DIR__ . '/template', [\n" +" 'message' => $message,\n" +" ]);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "Now open your browser and check it again. You should see the similar text but with a layout applied." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "Also, you've separated the part about how it works and part of how it's presented. In the larger applications, it helps a lot to deal with complexity." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "In this section, you've touched the handler and template parts of the typical web application. You created a handler as part of a class to handle a specific request. You also created a view to compose the response's content. In this simple example, no data source was involved as the only data used was the `message` parameter." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "You've also learned about routing in Yii, which acts as the bridge between user requests and handlers." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "In the next section, you will learn how to fetch data and add a new page containing an HTML form." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Running applications](workflow.md) |\n" +"> [Working with forms →](forms.md)\n" +msgstr "" diff --git a/guide/po/start_hello.md/start_hello.md.pot b/guide/po/start_hello.md/start_hello.md.pot new file mode 100644 index 00000000..4bdcc47c --- /dev/null +++ b/guide/po/start_hello.md/start_hello.md.pot @@ -0,0 +1,350 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title ## +#: en/start/forms.md en/start/hello.md +#, no-wrap +msgid "Summary " +msgstr "" + +#. type: Title # +#: en/start/hello.md +#, no-wrap +msgid "Saying hello" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"This section describes how to create a new \"Hello\" page in your " +"application. It's a simple page that will echo back whatever you pass to it " +"or, if nothing passed, will just say \"Hello!\"." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"To achieve this goal, you will define a route and create [a handler](../" +"structure/handler.md) that does the job and forms the response. Then you " +"will improve it to use [view](../structure/views.md) for building the " +"response." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "Through this tutorial, you will learn three things:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/start/hello.md +msgid "How to create a handler to respond to a request." +msgstr "" + +#. type: Bullet: '2. ' +#: en/start/hello.md +msgid "How to map URL to the handler." +msgstr "" + +#. type: Bullet: '3. ' +#: en/start/hello.md +msgid "" +"How to create a [view](../structure/view.md) to compose the response's " +"content." +msgstr "" + +#. type: Title ## +#: en/start/hello.md +#, no-wrap +msgid "Creating a handler " +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"For the \"Hello\" task, you will create a handler class that reads a " +"`message` parameter from the request and displays that message back to the " +"user. If the request doesn't provide a `message` parameter, the action will " +"display the default \"Hello\" message." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "Create `src/Controller/Echo/Action.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/hello.md +#, no-wrap +msgid "" +"responseFactory->createResponse();\n" +" $response->getBody()->write('The message is: ' . Html::encode($message));\n" +" return $response;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"In your example, the `__invoke` method receives the `$message` parameter " +"that with the help of `RouteArgument` attribute gets the message from URL. " +"The value defaults to `\"Hello!\"`. If the request is made to `/say/" +"Goodbye`, the action assigns the value \"Goodbye\" to the `$message` " +"variable." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"The application passes the response through the [middleware stack](../" +"structure/middleware.md) to the emitter that outputs the response to the end " +"user." +msgstr "" + +#. type: Title ## +#: en/start/hello.md +#, no-wrap +msgid "Configuring router" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"Now, to map your handler to URL, you need to add a route in `config/common/" +"routes.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/hello.md +#, no-wrap +msgid "" +"routes(\n" +" Route::get('/')\n" +" ->action(\\App\\Controller\\HomePage\\Action::class)\n" +" ->name('home'),\n" +" Route::get('/say[/{message}]')\n" +" ->action(\\App\\Controller\\Echo\\Action::class)\n" +" ->name('echo/say'),\n" +" ),\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"In the above, you map the `/say[/{message}]` pattern to " +"`\\App\\Controller\\Echo\\Action`. For a request, the router creates an " +"instance and calls the `__invoke()` method. The `{message}` part of the " +"pattern writes anything specified in this place to the `message` request " +"attribute. `[]` marks this part of the pattern as optional." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"You also give a `echo/say` name to this route to be able to generate URLs " +"pointing to it." +msgstr "" + +#. type: Title ## +#: en/start/hello.md +#, no-wrap +msgid "Trying it out " +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"After creating the action and the view open `http://localhost/say/" +"Hello+World` in your browser." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "This URL displays a page with \"The message is: Hello World\"." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"If you omit the `message` parameter in the URL, the page displays \"The " +"message is: Hello!\"." +msgstr "" + +#. type: Title ## +#: en/start/hello.md +#, no-wrap +msgid "Creating a View Template " +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"Usually, the task is more complicated than printing out \"hello world\" and " +"involves rendering some complex HTML. For this task, it's handy to use view " +"templates. They're scripts you write to generate a response's body." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"For the \"Hello\" task, create a `src/Controller/Echo/template.php` template " +"that prints the `message` parameter received from the action method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/hello.md +#, no-wrap +msgid "" +"\n" +"\n" +"

The message is:

\n" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"In the above code, the `message` parameter uses HTML encoding before you " +"print it. You need that because the parameter comes from an end user and is " +"vulnerable to [cross-site scripting (XSS) attacks](https://en.wikipedia.org/" +"wiki/Cross-site_scripting) by embedding malicious JavaScript in the " +"parameter." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"Naturally, you may put more content in the `say` view. The content can " +"consist of HTML tags, plain text, and even PHP statements. In fact, the view " +"service executes the `say` view as a PHP script." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "To use the view, you need to change `src/Controller/Echo/Action.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/start/hello.md +#, no-wrap +msgid "" +"viewRenderer->render(__DIR__ . '/template', [\n" +" 'message' => $message,\n" +" ]);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"Now open your browser and check it again. You should see the similar text " +"but with a layout applied." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"Also, you've separated the part about how it works and part of how it's " +"presented. In the larger applications, it helps a lot to deal with " +"complexity." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"In this section, you've touched the handler and template parts of the " +"typical web application. You created a handler as part of a class to handle " +"a specific request. You also created a view to compose the response's " +"content. In this simple example, no data source was involved as the only " +"data used was the `message` parameter." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"You've also learned about routing in Yii, which acts as the bridge between " +"user requests and handlers." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +msgid "" +"In the next section, you will learn how to fetch data and add a new page " +"containing an HTML form." +msgstr "" + +#. type: Plain text +#: en/start/hello.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Running applications](workflow.md) |\n" +"> [Working with forms →](forms.md)\n" +msgstr "" diff --git a/guide/po/start_looking-ahead.md/ru/start_looking-ahead.md.ru.po b/guide/po/start_looking-ahead.md/ru/start_looking-ahead.md.ru.po new file mode 100644 index 00000000..9e431543 --- /dev/null +++ b/guide/po/start_looking-ahead.md/ru/start_looking-ahead.md.ru.po @@ -0,0 +1,36 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/start/looking-ahead.md +#, no-wrap +msgid "Looking ahead" +msgstr "" + +#. type: Plain text +#: en/start/looking-ahead.md +msgid "If you've read through the entire \"Getting Started\" chapter, you have now created a complete Yii application. In the process, you've learned how to implement some commonly necessary features, such as getting data from users via an HTML form, fetching data from a database, and displaying data in a paginated fashion. You've also learned how to use [Gii](gii.md) to generate code automatically. Using Gii for code generation turns the bulk of your Web development process into a task as simple as just filling out some forms." +msgstr "" + +#. type: Plain text +#: en/start/looking-ahead.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Generating code with Gii](gii.md)\n" +msgstr "" diff --git a/guide/po/start_looking-ahead.md/start_looking-ahead.md.pot b/guide/po/start_looking-ahead.md/start_looking-ahead.md.pot new file mode 100644 index 00000000..856473ed --- /dev/null +++ b/guide/po/start_looking-ahead.md/start_looking-ahead.md.pot @@ -0,0 +1,43 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/start/looking-ahead.md +#, no-wrap +msgid "Looking ahead" +msgstr "" + +#. type: Plain text +#: en/start/looking-ahead.md +msgid "" +"If you've read through the entire \"Getting Started\" chapter, you have now " +"created a complete Yii application. In the process, you've learned how to " +"implement some commonly necessary features, such as getting data from users " +"via an HTML form, fetching data from a database, and displaying data in a " +"paginated fashion. You've also learned how to use [Gii](gii.md) to generate " +"code automatically. Using Gii for code generation turns the bulk of your Web " +"development process into a task as simple as just filling out some forms." +msgstr "" + +#. type: Plain text +#: en/start/looking-ahead.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Generating code with Gii](gii.md)\n" +msgstr "" diff --git a/guide/po/start_prerequisites.md/ru/start_prerequisites.md.ru.po b/guide/po/start_prerequisites.md/ru/start_prerequisites.md.ru.po new file mode 100644 index 00000000..94876f85 --- /dev/null +++ b/guide/po/start_prerequisites.md/ru/start_prerequisites.md.ru.po @@ -0,0 +1,106 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title ## +#: en/intro/upgrade-from-v2.md en/start/prerequisites.md +#, no-wrap +msgid "Docker" +msgstr "" + +#. type: Title # +#: en/start/prerequisites.md +#, no-wrap +msgid "What do you need to know?" +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "The Yii learning curve isn't as steep as other PHP frameworks, but still, there are some things you should learn before starting with Yii." +msgstr "" + +#. type: Title ## +#: en/start/prerequisites.md +#, no-wrap +msgid "PHP" +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "Yii is a PHP framework, so make sure you [read and understand language reference](https://www.php.net/manual/en/langref.php)." +msgstr "" + +#. type: Title ## +#: en/start/prerequisites.md +#, no-wrap +msgid "Object-oriented programming" +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "You need a basic understanding of object-oriented programming. If you're not familiar with it, check one of the many tutorials available such as [the one from tuts+](https://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762)." +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "When you develop with Yii, you write code in an object-oriented fashion, so make sure you're familiar with [PHP OOP support](https://www.php.net/manual/en/language.oop5.php)." +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "Note that the more complicated your application is, the more advanced OOP concepts you should learn to successfully manage that complexity." +msgstr "" + +#. type: Title ## +#: en/start/prerequisites.md +#, no-wrap +msgid "Command line and Composer" +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "Yii extensively uses the de-facto standard PHP package manager, [Composer](https://getcomposer.org) so make sure you read and understand its [guide](https://getcomposer.org/doc/01-basic-usage.md). If you aren't familiar with using the command line, it's time to start trying. Once you learn the basics, you'll never want to work without it." +msgstr "" + +#. type: Title ## +#: en/start/prerequisites.md +#, no-wrap +msgid "HTTP" +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "Since Yii is a web framework and the web largely uses HTTP, it's a good idea to [learn more about it](https://developer.mozilla.org/en-US/docs/Web/HTTP)." +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "The default application template leverages Docker, so we recommend that you [read and understand the concepts](https://docs.docker.com/get-started/)." +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "Also, you will benefit from familiarizing yourself with [twelve-factor app](https://12factor.net/) principles." +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [Creating a project →](creating-project.md)\n" +msgstr "" diff --git a/guide/po/start_prerequisites.md/start_prerequisites.md.pot b/guide/po/start_prerequisites.md/start_prerequisites.md.pot new file mode 100644 index 00000000..0831bd9c --- /dev/null +++ b/guide/po/start_prerequisites.md/start_prerequisites.md.pot @@ -0,0 +1,130 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title ## +#: en/intro/upgrade-from-v2.md en/start/prerequisites.md +#, no-wrap +msgid "Docker" +msgstr "" + +#. type: Title # +#: en/start/prerequisites.md +#, no-wrap +msgid "What do you need to know?" +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "" +"The Yii learning curve isn't as steep as other PHP frameworks, but still, " +"there are some things you should learn before starting with Yii." +msgstr "" + +#. type: Title ## +#: en/start/prerequisites.md +#, no-wrap +msgid "PHP" +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "" +"Yii is a PHP framework, so make sure you [read and understand language " +"reference](https://www.php.net/manual/en/langref.php)." +msgstr "" + +#. type: Title ## +#: en/start/prerequisites.md +#, no-wrap +msgid "Object-oriented programming" +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "" +"You need a basic understanding of object-oriented programming. If you're not " +"familiar with it, check one of the many tutorials available such as [the one " +"from tuts+](https://code.tutsplus.com/tutorials/object-oriented-php-for-" +"beginners--net-12762)." +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "" +"When you develop with Yii, you write code in an object-oriented fashion, so " +"make sure you're familiar with [PHP OOP support](https://www.php.net/manual/" +"en/language.oop5.php)." +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "" +"Note that the more complicated your application is, the more advanced OOP " +"concepts you should learn to successfully manage that complexity." +msgstr "" + +#. type: Title ## +#: en/start/prerequisites.md +#, no-wrap +msgid "Command line and Composer" +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "" +"Yii extensively uses the de-facto standard PHP package manager, [Composer]" +"(https://getcomposer.org) so make sure you read and understand its [guide]" +"(https://getcomposer.org/doc/01-basic-usage.md). If you aren't familiar with " +"using the command line, it's time to start trying. Once you learn the " +"basics, you'll never want to work without it." +msgstr "" + +#. type: Title ## +#: en/start/prerequisites.md +#, no-wrap +msgid "HTTP" +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "" +"Since Yii is a web framework and the web largely uses HTTP, it's a good idea " +"to [learn more about it](https://developer.mozilla.org/en-US/docs/Web/HTTP)." +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "" +"The default application template leverages Docker, so we recommend that you " +"[read and understand the concepts](https://docs.docker.com/get-started/)." +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +msgid "" +"Also, you will benefit from familiarizing yourself with [twelve-factor app]" +"(https://12factor.net/) principles." +msgstr "" + +#. type: Plain text +#: en/start/prerequisites.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [Creating a project →](creating-project.md)\n" +msgstr "" diff --git a/guide/po/start_workflow.md/ru/start_workflow.md.ru.po b/guide/po/start_workflow.md/ru/start_workflow.md.ru.po new file mode 100644 index 00000000..04391d30 --- /dev/null +++ b/guide/po/start_workflow.md/ru/start_workflow.md.ru.po @@ -0,0 +1,224 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/start/workflow.md +#, no-wrap +msgid "Running applications" +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "After installing Yii, you have a working Yii application. This section introduces the application's built-in functionality, how the code is organized, and how the application handles requests in general." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "Note that unlike the framework itself, after you install a project template, it's all yours. You're free to add or delete code and overall change it as you need." +msgstr "" + +#. type: Title ## +#: en/start/workflow.md +#, fuzzy, no-wrap +#| msgid "Defining aliases " +msgid "Functionality " +msgstr "Определение псевдонимов " + +#. type: Plain text +#: en/start/workflow.md +msgid "The installed application has only the homepage, which displays when you access the URL `http://localhost/`. It shares a common layout that you can reuse on further pages." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +#, no-wrap +msgid "" +"\n" +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "In addition to the web application, you can access a console script via `APP_ENV=dev ./yii` or, in case of Docker, `make yii`. Use this script to run background and maintenance tasks for the application, which the [Console Application Section](../tutorial/console-applications.md) describes." +msgstr "" + +#. type: Title ## +#: en/start/workflow.md +#, no-wrap +msgid "Application structure " +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "The most important directories and files in your application are (assuming the application's root directory is `app`):" +msgstr "" + +#. type: Fenced code block +#: en/start/workflow.md +#, no-wrap +msgid "" +"assets/ Application assets to be published.\n" +"config/ Configuration.\n" +" common/ Configs applied to both console and web.\n" +" di/ DI container configuration.\n" +" aliasess.php Aliases.\n" +" application.php Application configuration.\n" +" bootstrap.php Bootstrap configuration.\n" +" params.php Various parameters used in DI configs.\n" +" routes.php Application routes.\n" +" console/ Configs applied to console.\n" +" commands.php Registered console commands.\n" +" params.php Various parameters used in DI configs.\n" +" web/ Configs applied to web.\n" +" di/ DI container configuration.\n" +" params.php Various parameters used in DI configs.\n" +" environments/ Environment-based configs.\n" +" dev/ Configs applied in dev environment.\n" +" params.php Various parameters used in DI configs.\n" +" prod/ Configs applied in prod environment.\n" +" params.php Various parameters used in DI configs.\n" +" test/ Configs applied in test environment.\n" +" params.php Various parameters used in DI configs. \n" +" configuration.php Defines how to read application configs.\n" +" .merge-plan.php Merge plan to assemble configs according to. Build using `configuration.php`.\n" +"docker/ Docker configuration.\n" +" dev/ Dev environment.\n" +" .env Environment variables.\n" +" compose.yml Services for dev environment.\n" +" prod/ Prod environment.\n" +" .env Environment variables.\n" +" compose.yml Services for prod environment.\n" +" test/ Test environment.\n" +" .env Environment variables.\n" +" compose.yml Services for test environment.\n" +" .env Common environment variables.\n" +" compose.yml Common services.\n" +" Dockerfile Images to use.\n" +"public/ Files publically accessible from the Internet.\n" +" assets/ Published assets.\n" +" index.php Entry script for web.\n" +"runtime/ Files generated during runtime.\n" +"src/ Application source code.\n" +" Command/ Console commands.\n" +" Controller/ Controllers.\n" +" Handler/ Custom handler for 404.\n" +" Layout/ Layouts.\n" +" autoload.php Autoloader.\n" +" Environment.php Environment helper.\n" +"tests/ A set of Codeception tests for the application. \n" +"vendor/ Installed Composer packages.\n" +".gitignore Files and directories to be ignored by Git.\n" +".php-cs-fixer.php PHP Coding Standards Fixer configuration.\n" +"c3.php Codeception code coverage script.\n" +"condeception.yml Codeception configuration.\n" +"composer.json Composer configuration.\n" +"composer.lock Composer lock file.\n" +"Makefile Makefile with shortcut commands.\n" +"psalm.xml Psalm configuration.\n" +"rector.php Rector configuration.\n" +"yii Console application entry point.\n" +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "In general, the files in the application fall into two groups: those under `app/public` and those under other directories. You can access the former directly via HTTP (i.e., in a browser), while you shouldn't expose the latter." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "Each application has an entry script `public/index.php`, the only web-accessible PHP script in the application. The entry script uses an [application runner](https://github.com/yiisoft/yii-runner) to create an instance of an incoming request with the help of one of PSR-7 packages and passes it to an [application](../structure/application.md) instance. The application executes a set of middleware sequentially to process the request. It then passes the result to the emitter, which sends the response to the browser." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "Depending on the middleware you use, the application may behave differently. By default, a router uses the requested URL and configuration to choose a handler and execute it to produce a response." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "You can learn more about the application template from the [yiisoft/app package documentation](https://github.com/yiisoft/app/blob/master/README.md)." +msgstr "" + +#. type: Title ## +#: en/start/workflow.md +#, fuzzy, no-wrap +#| msgid "References " +msgid "Request Lifecycle " +msgstr "Полезные ссылки " + +#. type: Plain text +#: en/start/workflow.md +msgid "The following diagram shows how an application handles a request." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "![Request Lifecycle](img/request-lifecycle.svg)" +msgstr "" + +#. type: Bullet: '1. ' +#: en/start/workflow.md +msgid "A user makes a request to the [entry script](../structure/entry-script.md) `public/index.php`." +msgstr "" + +#. type: Bullet: '2. ' +#: en/start/workflow.md +msgid "The entry script with the help of the application runner loads the container [configuration](../concept/configuration.md) and creates an [application](../structure/application.md) instance and services necessary to handle the request." +msgstr "" + +#. type: Bullet: '3. ' +#: en/start/workflow.md +msgid "Request factory creates a request object based on a raw request that came from a user." +msgstr "" + +#. type: Bullet: '4. ' +#: en/start/workflow.md +msgid "Application passes a request object through a middleware array configured. One of these is typically a router." +msgstr "" + +#. type: Bullet: '5. ' +#: en/start/workflow.md +msgid "The Router finds out what handler to execute based on request and configuration." +msgstr "" + +#. type: Bullet: '6. ' +#: en/start/workflow.md +msgid "The handler may load some data, possibly from a database." +msgstr "" + +#. type: Bullet: '7. ' +#: en/start/workflow.md +msgid "The handler forms a response by using data. Either directly or with the help of the view package." +msgstr "" + +#. type: Bullet: '8. ' +#: en/start/workflow.md +msgid "Emitter receives the response and takes care of sending the response to the user's browser." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Creating a project](creating-project.md) |\n" +"> [Saying hello →](hello.md)\n" +msgstr "" diff --git a/guide/po/start_workflow.md/start_workflow.md.pot b/guide/po/start_workflow.md/start_workflow.md.pot new file mode 100644 index 00000000..a6d3e8d8 --- /dev/null +++ b/guide/po/start_workflow.md/start_workflow.md.pot @@ -0,0 +1,270 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/start/workflow.md +#, no-wrap +msgid "Running applications" +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "" +"After installing Yii, you have a working Yii application. This section " +"introduces the application's built-in functionality, how the code is " +"organized, and how the application handles requests in general." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "" +"Note that unlike the framework itself, after you install a project template, " +"it's all yours. You're free to add or delete code and overall change it as " +"you need." +msgstr "" + +#. type: Title ## +#: en/start/workflow.md +#, no-wrap +msgid "Functionality " +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "" +"The installed application has only the homepage, which displays when you " +"access the URL `http://localhost/`. It shares a common layout that you can " +"reuse on further pages." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +#, no-wrap +msgid "" +"\n" +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "" +"In addition to the web application, you can access a console script via " +"`APP_ENV=dev ./yii` or, in case of Docker, `make yii`. Use this script to " +"run background and maintenance tasks for the application, which the [Console " +"Application Section](../tutorial/console-applications.md) describes." +msgstr "" + +#. type: Title ## +#: en/start/workflow.md +#, no-wrap +msgid "Application structure " +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "" +"The most important directories and files in your application are (assuming " +"the application's root directory is `app`):" +msgstr "" + +#. type: Fenced code block +#: en/start/workflow.md +#, no-wrap +msgid "" +"assets/ Application assets to be published.\n" +"config/ Configuration.\n" +" common/ Configs applied to both console and web.\n" +" di/ DI container configuration.\n" +" aliasess.php Aliases.\n" +" application.php Application configuration.\n" +" bootstrap.php Bootstrap configuration.\n" +" params.php Various parameters used in DI configs.\n" +" routes.php Application routes.\n" +" console/ Configs applied to console.\n" +" commands.php Registered console commands.\n" +" params.php Various parameters used in DI configs.\n" +" web/ Configs applied to web.\n" +" di/ DI container configuration.\n" +" params.php Various parameters used in DI configs.\n" +" environments/ Environment-based configs.\n" +" dev/ Configs applied in dev environment.\n" +" params.php Various parameters used in DI configs.\n" +" prod/ Configs applied in prod environment.\n" +" params.php Various parameters used in DI configs.\n" +" test/ Configs applied in test environment.\n" +" params.php Various parameters used in DI configs. \n" +" configuration.php Defines how to read application configs.\n" +" .merge-plan.php Merge plan to assemble configs according to. Build using `configuration.php`.\n" +"docker/ Docker configuration.\n" +" dev/ Dev environment.\n" +" .env Environment variables.\n" +" compose.yml Services for dev environment.\n" +" prod/ Prod environment.\n" +" .env Environment variables.\n" +" compose.yml Services for prod environment.\n" +" test/ Test environment.\n" +" .env Environment variables.\n" +" compose.yml Services for test environment.\n" +" .env Common environment variables.\n" +" compose.yml Common services.\n" +" Dockerfile Images to use.\n" +"public/ Files publically accessible from the Internet.\n" +" assets/ Published assets.\n" +" index.php Entry script for web.\n" +"runtime/ Files generated during runtime.\n" +"src/ Application source code.\n" +" Command/ Console commands.\n" +" Controller/ Controllers.\n" +" Handler/ Custom handler for 404.\n" +" Layout/ Layouts.\n" +" autoload.php Autoloader.\n" +" Environment.php Environment helper.\n" +"tests/ A set of Codeception tests for the application. \n" +"vendor/ Installed Composer packages.\n" +".gitignore Files and directories to be ignored by Git.\n" +".php-cs-fixer.php PHP Coding Standards Fixer configuration.\n" +"c3.php Codeception code coverage script.\n" +"condeception.yml Codeception configuration.\n" +"composer.json Composer configuration.\n" +"composer.lock Composer lock file.\n" +"Makefile Makefile with shortcut commands.\n" +"psalm.xml Psalm configuration.\n" +"rector.php Rector configuration.\n" +"yii Console application entry point.\n" +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "" +"In general, the files in the application fall into two groups: those under " +"`app/public` and those under other directories. You can access the former " +"directly via HTTP (i.e., in a browser), while you shouldn't expose the " +"latter." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "" +"Each application has an entry script `public/index.php`, the only web-" +"accessible PHP script in the application. The entry script uses an " +"[application runner](https://github.com/yiisoft/yii-runner) to create an " +"instance of an incoming request with the help of one of PSR-7 packages and " +"passes it to an [application](../structure/application.md) instance. The " +"application executes a set of middleware sequentially to process the " +"request. It then passes the result to the emitter, which sends the response " +"to the browser." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "" +"Depending on the middleware you use, the application may behave differently. " +"By default, a router uses the requested URL and configuration to choose a " +"handler and execute it to produce a response." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "" +"You can learn more about the application template from the [yiisoft/app " +"package documentation](https://github.com/yiisoft/app/blob/master/README.md)." +msgstr "" + +#. type: Title ## +#: en/start/workflow.md +#, no-wrap +msgid "Request Lifecycle " +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "The following diagram shows how an application handles a request." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +msgid "![Request Lifecycle](img/request-lifecycle.svg)" +msgstr "" + +#. type: Bullet: '1. ' +#: en/start/workflow.md +msgid "" +"A user makes a request to the [entry script](../structure/entry-script.md) " +"`public/index.php`." +msgstr "" + +#. type: Bullet: '2. ' +#: en/start/workflow.md +msgid "" +"The entry script with the help of the application runner loads the container " +"[configuration](../concept/configuration.md) and creates an [application](../" +"structure/application.md) instance and services necessary to handle the " +"request." +msgstr "" + +#. type: Bullet: '3. ' +#: en/start/workflow.md +msgid "" +"Request factory creates a request object based on a raw request that came " +"from a user." +msgstr "" + +#. type: Bullet: '4. ' +#: en/start/workflow.md +msgid "" +"Application passes a request object through a middleware array configured. " +"One of these is typically a router." +msgstr "" + +#. type: Bullet: '5. ' +#: en/start/workflow.md +msgid "" +"The Router finds out what handler to execute based on request and " +"configuration." +msgstr "" + +#. type: Bullet: '6. ' +#: en/start/workflow.md +msgid "The handler may load some data, possibly from a database." +msgstr "" + +#. type: Bullet: '7. ' +#: en/start/workflow.md +msgid "" +"The handler forms a response by using data. Either directly or with the help " +"of the view package." +msgstr "" + +#. type: Bullet: '8. ' +#: en/start/workflow.md +msgid "" +"Emitter receives the response and takes care of sending the response to the " +"user's browser." +msgstr "" + +#. type: Plain text +#: en/start/workflow.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> [← Creating a project](creating-project.md) |\n" +"> [Saying hello →](hello.md)\n" +msgstr "" diff --git a/guide/po/structure_action.md/ru/structure_action.md.ru.po b/guide/po/structure_action.md/ru/structure_action.md.ru.po new file mode 100644 index 00000000..3a4518fd --- /dev/null +++ b/guide/po/structure_action.md/ru/structure_action.md.ru.po @@ -0,0 +1,181 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/structure/action.md +#, no-wrap +msgid "Actions" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "In a web application, the request URL determines what's executed. Matching is made by a router configured with multiple routes. Each route can be attached to a middleware that, given request, produces a response. Since middleware overall could be chained and can pass actual handling to the next middleware, we call the middleware actually doing the job an action." +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "There are multiple ways to describe an action. The simplest one is using a closure:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use \\Psr\\Http\\Message\\ServerRequestInterface;\n" +"use \\Psr\\Http\\Message\\ResponseInterface;\n" +"use Yiisoft\\Router\\Route;\n" +"\n" +"Route::get('/')->action(function (ServerRequestInterface $request) use ($responseFactory): ResponseInterface {\n" +" $response = $responseFactory->createResponse();\n" +" $response->getBody()->write('You are at homepage.');\n" +" return $response;\n" +"});\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "It's fine for simple handling since any more complicated one would require getting dependencies, so a good idea would be moving the handling to a class method. Callback middleware could be used for the purpose:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use Yiisoft\\Router\\Route;\n" +"\n" +"Route::get('/')->action([FrontPageAction::class, 'run']),\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "The class itself would be like:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use \\Psr\\Http\\Message\\ServerRequestInterface;\n" +"use \\Psr\\Http\\Message\\ResponseInterface;\n" +"\n" +"final readonly class FrontPageAction\n" +"{\n" +" public function run(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" // build response for a front page \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "For many cases, it makes sense to group handling for many routes into a single class:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use Yiisoft\\Router\\Route;\n" +"\n" +"Route::get('/post/index')->action([PostController::class, 'actionIndex']),\n" +"Route::get('/post/view/{id:\\d+}')->action([PostController::class, 'actionView']),\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +#, fuzzy +#| msgid "That's equal to the following:" +msgid "The class itself would look like the following:" +msgstr "Это соответствует:" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use \\Psr\\Http\\Message\\ServerRequestInterface;\n" +"use \\Psr\\Http\\Message\\ResponseInterface;\n" +"\n" +"final readonly class PostController\n" +"{\n" +" public function actionIndex(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" // render posts list\n" +" }\n" +" \n" +" \n" +" public function actionView(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" // render a single post \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "We usually call such a class \"controller.\"" +msgstr "" + +#. type: Title ## +#: en/structure/action.md +#, no-wrap +msgid "Autowiring" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +#, no-wrap +msgid "" +"Both constructors of action-classes and action-methods are automatically getting services from\n" +" the dependency injection container:\n" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use \\Psr\\Http\\Message\\ServerRequestInterface;\n" +"use \\Psr\\Http\\Message\\ResponseInterface;\n" +"use Psr\\Log\\LoggerInterface;\n" +"\n" +"final readonly class PostController\n" +"{\n" +" public function __construct(\n" +" private PostRepository $postRepository\n" +" )\n" +" {\n" +" }\n" +"\n" +" public function actionIndex(ServerRequestInterface $request, LoggerInterface $logger): ResponseInterface\n" +" {\n" +" $logger->debug('Rendering posts list');\n" +" // render posts list\n" +" }\n" +" \n" +" \n" +" public function actionView(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" // render a single post \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "In the above example `PostRepository` is injected automatically via constructor. That means it is available in every action. Logger is injected into `index` action only." +msgstr "" diff --git a/guide/po/structure_action.md/structure_action.md.pot b/guide/po/structure_action.md/structure_action.md.pot new file mode 100644 index 00000000..9f92ef4a --- /dev/null +++ b/guide/po/structure_action.md/structure_action.md.pot @@ -0,0 +1,194 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/structure/action.md +#, no-wrap +msgid "Actions" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "" +"In a web application, the request URL determines what's executed. Matching " +"is made by a router configured with multiple routes. Each route can be " +"attached to a middleware that, given request, produces a response. Since " +"middleware overall could be chained and can pass actual handling to the next " +"middleware, we call the middleware actually doing the job an action." +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "" +"There are multiple ways to describe an action. The simplest one is using a " +"closure:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use \\Psr\\Http\\Message\\ServerRequestInterface;\n" +"use \\Psr\\Http\\Message\\ResponseInterface;\n" +"use Yiisoft\\Router\\Route;\n" +"\n" +"Route::get('/')->action(function (ServerRequestInterface $request) use ($responseFactory): ResponseInterface {\n" +" $response = $responseFactory->createResponse();\n" +" $response->getBody()->write('You are at homepage.');\n" +" return $response;\n" +"});\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "" +"It's fine for simple handling since any more complicated one would require " +"getting dependencies, so a good idea would be moving the handling to a class " +"method. Callback middleware could be used for the purpose:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use Yiisoft\\Router\\Route;\n" +"\n" +"Route::get('/')->action([FrontPageAction::class, 'run']),\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "The class itself would be like:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use \\Psr\\Http\\Message\\ServerRequestInterface;\n" +"use \\Psr\\Http\\Message\\ResponseInterface;\n" +"\n" +"final readonly class FrontPageAction\n" +"{\n" +" public function run(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" // build response for a front page \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "" +"For many cases, it makes sense to group handling for many routes into a " +"single class:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use Yiisoft\\Router\\Route;\n" +"\n" +"Route::get('/post/index')->action([PostController::class, 'actionIndex']),\n" +"Route::get('/post/view/{id:\\d+}')->action([PostController::class, 'actionView']),\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "The class itself would look like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use \\Psr\\Http\\Message\\ServerRequestInterface;\n" +"use \\Psr\\Http\\Message\\ResponseInterface;\n" +"\n" +"final readonly class PostController\n" +"{\n" +" public function actionIndex(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" // render posts list\n" +" }\n" +" \n" +" \n" +" public function actionView(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" // render a single post \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "We usually call such a class \"controller.\"" +msgstr "" + +#. type: Title ## +#: en/structure/action.md +#, no-wrap +msgid "Autowiring" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +#, no-wrap +msgid "" +"Both constructors of action-classes and action-methods are automatically getting services from\n" +" the dependency injection container:\n" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/action.md +#, no-wrap +msgid "" +"use \\Psr\\Http\\Message\\ServerRequestInterface;\n" +"use \\Psr\\Http\\Message\\ResponseInterface;\n" +"use Psr\\Log\\LoggerInterface;\n" +"\n" +"final readonly class PostController\n" +"{\n" +" public function __construct(\n" +" private PostRepository $postRepository\n" +" )\n" +" {\n" +" }\n" +"\n" +" public function actionIndex(ServerRequestInterface $request, LoggerInterface $logger): ResponseInterface\n" +" {\n" +" $logger->debug('Rendering posts list');\n" +" // render posts list\n" +" }\n" +" \n" +" \n" +" public function actionView(ServerRequestInterface $request): ResponseInterface\n" +" {\n" +" // render a single post \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/action.md +msgid "" +"In the above example `PostRepository` is injected automatically via " +"constructor. That means it is available in every action. Logger is injected " +"into `index` action only." +msgstr "" diff --git a/guide/po/structure_application.md/ru/structure_application.md.ru.po b/guide/po/structure_application.md/ru/structure_application.md.ru.po new file mode 100644 index 00000000..75353aae --- /dev/null +++ b/guide/po/structure_application.md/ru/structure_application.md.ru.po @@ -0,0 +1,48 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/structure/application.md +#, no-wrap +msgid "Application" +msgstr "" + +#. type: Plain text +#: en/structure/application.md +msgid "The primary purpose of the web application and its runner in Yii 3 is to process requests to get responses." +msgstr "" + +#. type: Plain text +#: en/structure/application.md +msgid "Typically, the runtime consists of:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/structure/application.md +msgid "Startup. Get config, create an instance of container and do additional environment initialization such as registering error handler, so it can handle errors occurring. Fire `ApplicationStartup` event." +msgstr "" + +#. type: Bullet: '2. ' +#: en/structure/application.md +msgid "Handle requests via passing request objects to middleware dispatcher to execute [middleware stack](middleware.md) and get a response object. In usual PHP applications, it's done once. In [environments such as RoadRunner](../tutorial/using-with-event-loop.md), it could be done multiple times with the same application instance. Response object is converted into an actual HTTP response by using emitter. Fire `AfterEmit` event." +msgstr "" + +#. type: Bullet: '3. ' +#: en/structure/application.md +msgid "Shutdown. Fire `ApplicationShutdown` event." +msgstr "" diff --git a/guide/po/structure_application.md/structure_application.md.pot b/guide/po/structure_application.md/structure_application.md.pot new file mode 100644 index 00000000..36058110 --- /dev/null +++ b/guide/po/structure_application.md/structure_application.md.pot @@ -0,0 +1,59 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/structure/application.md +#, no-wrap +msgid "Application" +msgstr "" + +#. type: Plain text +#: en/structure/application.md +msgid "" +"The primary purpose of the web application and its runner in Yii 3 is to " +"process requests to get responses." +msgstr "" + +#. type: Plain text +#: en/structure/application.md +msgid "Typically, the runtime consists of:" +msgstr "" + +#. type: Bullet: '1. ' +#: en/structure/application.md +msgid "" +"Startup. Get config, create an instance of container and do additional " +"environment initialization such as registering error handler, so it can " +"handle errors occurring. Fire `ApplicationStartup` event." +msgstr "" + +#. type: Bullet: '2. ' +#: en/structure/application.md +msgid "" +"Handle requests via passing request objects to middleware dispatcher to " +"execute [middleware stack](middleware.md) and get a response object. In " +"usual PHP applications, it's done once. In [environments such as RoadRunner]" +"(../tutorial/using-with-event-loop.md), it could be done multiple times with " +"the same application instance. Response object is converted into an actual " +"HTTP response by using emitter. Fire `AfterEmit` event." +msgstr "" + +#. type: Bullet: '3. ' +#: en/structure/application.md +msgid "Shutdown. Fire `ApplicationShutdown` event." +msgstr "" diff --git a/guide/po/structure_domain.md/ru/structure_domain.md.ru.po b/guide/po/structure_domain.md/ru/structure_domain.md.ru.po new file mode 100644 index 00000000..9e5bc4f1 --- /dev/null +++ b/guide/po/structure_domain.md/ru/structure_domain.md.ru.po @@ -0,0 +1,186 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title ## +#: en/concept/autoloading.md en/security/best-practices.md +#: en/structure/domain.md en/tutorial/console-applications.md +#, no-wrap +msgid "References" +msgstr "Ссылки" + +#. type: Title # +#: en/structure/domain.md +#, no-wrap +msgid "Domain" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +#, no-wrap +msgid "" +"The Domain or domain model is what makes the project unique. With requirements and terminology of the problem being solved\n" +"in mind (the problem context), you build an abstraction that consists of entities, their relationships, and logic that\n" +"operates these entities. To focus on the complex part of the problem, domain is, ideally, separated from\n" +" the infrastructure part of the system (that's how to save data into a database, how to form HTTP response, etc.).\n" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> Such isolation is suitable for complex systems. If your project domain is basically create/read/update/delete\n" +"> for a set of records with not much complex logic, it makes no sense to apply a complex solution to a simple problem.\n" +"> The individual concepts of domain design below could be applied separately, so make sure to check these even if your\n" +"> project isn't that complicated. \n" +msgstr "" + +#. type: Title ## +#: en/structure/domain.md +#, no-wrap +msgid "Bounded context" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "It's nearly impossible to build a model that solves multiple problems that aren't too complicated by itself. Therefore, it's a good practice to divide the domain into several use-cases and have a separate model for each use-case. Such separated models are called \"bounded contexts.\"" +msgstr "" + +#. type: Title ## +#: en/structure/domain.md +#, no-wrap +msgid "Building blocks" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "There are various building blocks that are typically used when describing domain models. It isn't mandatory to use them all." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md en/structure/service.md +#, no-wrap +msgid "Entity" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "Entity is a uniquely identifiable object such as user, product, payment, etc. When comparing them, you're checking ID, not the attribute values. If there are two objects with different attributes but the same ID, they're considered being the same thing." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Value object" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "Value object describes an object by its characteristics. For example, a price that consists of value and currency. When comparing such objects, you're checking actual values. If they match, an object is considered to be the same." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Aggregate" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "Aggregate is a set of domain objects such as entities and value objects and additional data that could be treated as a single unit. It usually represents a compound object from a domain model such as shop order or HR person dossier." +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "One of the components of an aggregate is called a root. The root identifies an aggregate as a whole and should be used to access it." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Domain event" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "An aggregate, while processed, may raise events. For example, when order is confirmed, `OrderConfirmed` event would be risen so other parts of the system may react on these." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Data transfer object" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "Data transfer object or DTO is an object whose only purpose is to hold data as it is. It's commonly used to pass data between different services." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Service" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "Service is a class that contains a standalone operation within the context of your domain model. See \"[service components](service.md)\"." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md en/structure/service.md +#, no-wrap +msgid "Repository" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "The repository task is to abstract away how domain objects are obtained. These are usually separated into two parts: an interface that stays in the domain layer and an implementation that's situated in the infrastructure layer. In such a way, domain doesn't care how data is obtained and saved and may be focused around the complicated business logic instead." +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "Repository is usually implemented as a service." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Instantiating building blocks" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "Entity, value object, aggregate, and domain events aren't services and shouldn't be instantiated through DI container. Using `new` is the way to go with these." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md +msgid "[BoundedContext by Martin Fowler](https://martinfowler.com/bliki/BoundedContext.html)" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md +msgid "[ValueObject by Martin Fowler](https://martinfowler.com/bliki/ValueObject.html)" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md +msgid "[Aggregate by Marting Fowler](https://martinfowler.com/bliki/DDD_Aggregate.html)" +msgstr "" diff --git a/guide/po/structure_domain.md/structure_domain.md.pot b/guide/po/structure_domain.md/structure_domain.md.pot new file mode 100644 index 00000000..22267195 --- /dev/null +++ b/guide/po/structure_domain.md/structure_domain.md.pot @@ -0,0 +1,227 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title ## +#: en/concept/autoloading.md en/security/best-practices.md +#: en/structure/domain.md en/tutorial/console-applications.md +#, no-wrap +msgid "References" +msgstr "" + +#. type: Title # +#: en/structure/domain.md +#, no-wrap +msgid "Domain" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +#, no-wrap +msgid "" +"The Domain or domain model is what makes the project unique. With requirements and terminology of the problem being solved\n" +"in mind (the problem context), you build an abstraction that consists of entities, their relationships, and logic that\n" +"operates these entities. To focus on the complex part of the problem, domain is, ideally, separated from\n" +" the infrastructure part of the system (that's how to save data into a database, how to form HTTP response, etc.).\n" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +#, no-wrap +msgid "" +"> [!NOTE]\n" +"> Such isolation is suitable for complex systems. If your project domain is basically create/read/update/delete\n" +"> for a set of records with not much complex logic, it makes no sense to apply a complex solution to a simple problem.\n" +"> The individual concepts of domain design below could be applied separately, so make sure to check these even if your\n" +"> project isn't that complicated. \n" +msgstr "" + +#. type: Title ## +#: en/structure/domain.md +#, no-wrap +msgid "Bounded context" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"It's nearly impossible to build a model that solves multiple problems that " +"aren't too complicated by itself. Therefore, it's a good practice to divide " +"the domain into several use-cases and have a separate model for each use-" +"case. Such separated models are called \"bounded contexts.\"" +msgstr "" + +#. type: Title ## +#: en/structure/domain.md +#, no-wrap +msgid "Building blocks" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"There are various building blocks that are typically used when describing " +"domain models. It isn't mandatory to use them all." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md en/structure/service.md +#, no-wrap +msgid "Entity" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"Entity is a uniquely identifiable object such as user, product, payment, " +"etc. When comparing them, you're checking ID, not the attribute values. If " +"there are two objects with different attributes but the same ID, they're " +"considered being the same thing." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Value object" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"Value object describes an object by its characteristics. For example, a " +"price that consists of value and currency. When comparing such objects, " +"you're checking actual values. If they match, an object is considered to be " +"the same." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Aggregate" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"Aggregate is a set of domain objects such as entities and value objects and " +"additional data that could be treated as a single unit. It usually " +"represents a compound object from a domain model such as shop order or HR " +"person dossier." +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"One of the components of an aggregate is called a root. The root identifies " +"an aggregate as a whole and should be used to access it." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Domain event" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"An aggregate, while processed, may raise events. For example, when order is " +"confirmed, `OrderConfirmed` event would be risen so other parts of the " +"system may react on these." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Data transfer object" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"Data transfer object or DTO is an object whose only purpose is to hold data " +"as it is. It's commonly used to pass data between different services." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Service" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"Service is a class that contains a standalone operation within the context " +"of your domain model. See \"[service components](service.md)\"." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md en/structure/service.md +#, no-wrap +msgid "Repository" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"The repository task is to abstract away how domain objects are obtained. " +"These are usually separated into two parts: an interface that stays in the " +"domain layer and an implementation that's situated in the infrastructure " +"layer. In such a way, domain doesn't care how data is obtained and saved and " +"may be focused around the complicated business logic instead." +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "Repository is usually implemented as a service." +msgstr "" + +#. type: Title ### +#: en/structure/domain.md +#, no-wrap +msgid "Instantiating building blocks" +msgstr "" + +#. type: Plain text +#: en/structure/domain.md +msgid "" +"Entity, value object, aggregate, and domain events aren't services and " +"shouldn't be instantiated through DI container. Using `new` is the way to " +"go with these." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md +msgid "" +"[BoundedContext by Martin Fowler](https://martinfowler.com/bliki/" +"BoundedContext.html)" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md +msgid "" +"[ValueObject by Martin Fowler](https://martinfowler.com/bliki/ValueObject." +"html)" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md +msgid "" +"[Aggregate by Marting Fowler](https://martinfowler.com/bliki/DDD_Aggregate." +"html)" +msgstr "" diff --git a/guide/po/structure_entry-script.md/ru/structure_entry-script.md.ru.po b/guide/po/structure_entry-script.md/ru/structure_entry-script.md.ru.po new file mode 100644 index 00000000..866ab3f8 --- /dev/null +++ b/guide/po/structure_entry-script.md/ru/structure_entry-script.md.ru.po @@ -0,0 +1,197 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/structure/entry-script.md +#, no-wrap +msgid "Entry scripts" +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "Entry scripts are the first step in the application bootstrapping process. An application (either Web application or console application) has a single entry script. End users make requests to entry scripts which instantiate application instances and forward the requests to them." +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "Entry scripts for Web applications must be stored under Web-accessible directories so that they can be accessed by end users. They're often named as `index.php`, but can also use any other names, provided Web servers can locate them." +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "Entry script for console application is `./yii`." +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "Entry scripts mainly perform the following work with the help of `ApplicationRunner`:" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +#, fuzzy +#| msgid "[Composer guide on autoloading](https://getcomposer.org/doc/01-basic-usage.md#autoloading)." +msgid "Register [Composer autoloader](https://getcomposer.org/doc/01-basic-usage.md#autoloading);" +msgstr "[Composer guide on autoloading](https://getcomposer.org/doc/01-basic-usage.md#autoloading)." + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "Obtain configuration;" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "Use configuration to initialize a dependency injection container;" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "Get an instance of the request." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "Pass it to `Application` to handle and get a response from it." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "With the help of an emitter that transforms a response object into an actual HTTP response that's sent to the client browser." +msgstr "" + +#. type: Title ## +#: en/structure/entry-script.md +#, fuzzy, no-wrap +#| msgid "Dependency injection " +msgid "Web Applications " +msgstr "Внедрение зависимостей " + +#. type: Plain text +#: en/structure/entry-script.md +msgid "The following is the code in the entry script for the application template:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/entry-script.md +#, no-wrap +msgid "" +"debug();\n" +"// Run application:\n" +"$runner->run();\n" +msgstr "" + +#. type: Title ## +#: en/structure/entry-script.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Console Applications " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/structure/entry-script.md +msgid "Similarly, the following is the code for the entry script of a console application:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/entry-script.md +#, no-wrap +msgid "" +"#!/usr/bin/env php\n" +"withDefinitions($config->get('console'))\n" +" ->withProviders($config->get('providers-console'));\n" +"$container = new Container($containerConfig);\n" +"\n" +"/** @var ContainerInterface $container */\n" +"$container = $container->get(ContainerInterface::class);\n" +"\n" +"$application = $container->get(Application::class);\n" +"$exitCode = 1;\n" +"\n" +"try {\n" +" $application->start();\n" +" $exitCode = $application->run(null, new ConsoleBufferedOutput());\n" +"} catch (\\Error $error) {\n" +" $application->renderThrowable($error, new ConsoleBufferedOutput());\n" +"} finally {\n" +" $application->shutdown($exitCode);\n" +" exit($exitCode);\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/structure/entry-script.md +#, no-wrap +msgid "Alternative runtimes" +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "For alternative runtimes such as RoadRunner or Swoole, special entry scripts should be used. See:" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/entry-script.md +msgid "[Using Yii with RoadRunner](../tutorial/using-yii-with-roadrunner.md)" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/entry-script.md +msgid "[Using Yii with Swoole](../tutorial/using-yii-with-swoole.md)" +msgstr "" diff --git a/guide/po/structure_entry-script.md/structure_entry-script.md.pot b/guide/po/structure_entry-script.md/structure_entry-script.md.pot new file mode 100644 index 00000000..863cddd1 --- /dev/null +++ b/guide/po/structure_entry-script.md/structure_entry-script.md.pot @@ -0,0 +1,212 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/structure/entry-script.md +#, no-wrap +msgid "Entry scripts" +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "" +"Entry scripts are the first step in the application bootstrapping process. " +"An application (either Web application or console application) has a single " +"entry script. End users make requests to entry scripts which instantiate " +"application instances and forward the requests to them." +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "" +"Entry scripts for Web applications must be stored under Web-accessible " +"directories so that they can be accessed by end users. They're often named " +"as `index.php`, but can also use any other names, provided Web servers can " +"locate them." +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "Entry script for console application is `./yii`." +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "" +"Entry scripts mainly perform the following work with the help of " +"`ApplicationRunner`:" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "" +"Register [Composer autoloader](https://getcomposer.org/doc/01-basic-usage." +"md#autoloading);" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "Obtain configuration;" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "Use configuration to initialize a dependency injection container;" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "Get an instance of the request." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "Pass it to `Application` to handle and get a response from it." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/entry-script.md +msgid "" +"With the help of an emitter that transforms a response object into an actual " +"HTTP response that's sent to the client browser." +msgstr "" + +#. type: Title ## +#: en/structure/entry-script.md +#, no-wrap +msgid "Web Applications " +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "" +"The following is the code in the entry script for the application template:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/entry-script.md +#, no-wrap +msgid "" +"debug();\n" +"// Run application:\n" +"$runner->run();\n" +msgstr "" + +#. type: Title ## +#: en/structure/entry-script.md +#, no-wrap +msgid "Console Applications " +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "" +"Similarly, the following is the code for the entry script of a console " +"application:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/entry-script.md +#, no-wrap +msgid "" +"#!/usr/bin/env php\n" +"withDefinitions($config->get('console'))\n" +" ->withProviders($config->get('providers-console'));\n" +"$container = new Container($containerConfig);\n" +"\n" +"/** @var ContainerInterface $container */\n" +"$container = $container->get(ContainerInterface::class);\n" +"\n" +"$application = $container->get(Application::class);\n" +"$exitCode = 1;\n" +"\n" +"try {\n" +" $application->start();\n" +" $exitCode = $application->run(null, new ConsoleBufferedOutput());\n" +"} catch (\\Error $error) {\n" +" $application->renderThrowable($error, new ConsoleBufferedOutput());\n" +"} finally {\n" +" $application->shutdown($exitCode);\n" +" exit($exitCode);\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/structure/entry-script.md +#, no-wrap +msgid "Alternative runtimes" +msgstr "" + +#. type: Plain text +#: en/structure/entry-script.md +msgid "" +"For alternative runtimes such as RoadRunner or Swoole, special entry scripts " +"should be used. See:" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/entry-script.md +msgid "[Using Yii with RoadRunner](../tutorial/using-yii-with-roadrunner.md)" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/entry-script.md +msgid "[Using Yii with Swoole](../tutorial/using-yii-with-swoole.md)" +msgstr "" diff --git a/guide/po/structure_handler.md/ru/structure_handler.md.ru.po b/guide/po/structure_handler.md/ru/structure_handler.md.ru.po new file mode 100644 index 00000000..2f3193c8 --- /dev/null +++ b/guide/po/structure_handler.md/ru/structure_handler.md.ru.po @@ -0,0 +1,23 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/structure/handler.md +#, no-wrap +msgid "Request handlers" +msgstr "" diff --git a/guide/po/structure_handler.md/structure_handler.md.pot b/guide/po/structure_handler.md/structure_handler.md.pot new file mode 100644 index 00000000..98caf8e3 --- /dev/null +++ b/guide/po/structure_handler.md/structure_handler.md.pot @@ -0,0 +1,23 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/structure/handler.md +#, no-wrap +msgid "Request handlers" +msgstr "" diff --git a/guide/po/structure_middleware.md/ru/structure_middleware.md.ru.po b/guide/po/structure_middleware.md/ru/structure_middleware.md.ru.po new file mode 100644 index 00000000..eea9be63 --- /dev/null +++ b/guide/po/structure_middleware.md/ru/structure_middleware.md.ru.po @@ -0,0 +1,313 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/structure/middleware.md +#, no-wrap +msgid "Middleware" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "Yii works with HTTP using the abstraction layer built around [PSR-7 HTTP message interfaces](https://www.php-fig.org/psr/psr-7/) and [PSR-15 request handler/middleware interfaces](https://www.php-fig.org/psr/psr-15/)." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "The application is composed of one or several middleware. Middleware runs between request and response. When the URL is requested, the request object is passed to the middleware dispatcher that starts executing middleware one after another. Each middleware, given the request, can:" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/middleware.md +msgid "Pass the request to the next middleware performing some work before / after it." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/middleware.md +msgid "Form the response and return it." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "Depending on middleware used, application behavior may vary significantly." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "![Middleware](img/middleware.svg)" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "In the above each next middleware wraps the previous middleware. Alternatively, it could be presented as follows:" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "![Middleware](img/middleware_alternative.svg)" +msgstr "" + +#. type: Title ## +#: en/structure/middleware.md +#, no-wrap +msgid "Using middleware" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "Any PSR-15 compatible middleware could be used with Yii and there are many. Say, you need to add basic authentication one of the application URLs. URL-dependent middleware is configured using router, so you need to change router factory." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "Authentication middleware is implemented by `middlewares/http-authentication` package so execute `composer require middlewares/http-authentication` in the application root directory." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "Now register the middleware in DI container configuration `config/web.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +" [\n" +" 'class' => \\Middlewares\\BasicAuthentication::class,\n" +" '__construct()' => [\n" +" 'users' => [\n" +" 'foo' => 'bar',\n" +" ],\n" +" ],\n" +" 'realm()' => ['Access to the staging site via basic auth'],\n" +" 'attribute()' => ['username'],\n" +"],\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "In the `config/routes.php`, add new route:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"([SiteController::class, 'auth'])\n" +" ->name('site/auth')\n" +" ->addMiddleware(BasicAuthentication::class)\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "When configuring routing, you're binding `/basic-auth` URL to a chain of middleware consisting of basic authentication, and the action itself. A chain is a special middleware that executes all the middleware it's configured with." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +#, fuzzy +#| msgid "That's equal to the following:" +msgid "The action itself may be the following:" +msgstr "Это соответствует:" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"public function auth(ServerRequestInterface $request): ResponseInterface\n" +"{\n" +" $response = $this->responseFactory->createResponse();\n" +" $response->getBody()->write('Hi ' . $request->getAttribute('username'));\n" +" return $response;\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "Basic authentication middleware wrote to request `username` attribute, so you can access the data if needed." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "To apply middleware to application overall regardless of URL, adjust `config/application.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"return [\n" +" Yiisoft\\Yii\\Http\\Application::class => [\n" +" '__construct()' => [\n" +" 'dispatcher' => DynamicReference::to(static function (Injector $injector) {\n" +" return ($injector->make(MiddlewareDispatcher::class))\n" +" ->withMiddlewares(\n" +" [\n" +" ErrorCatcher::class,\n" +" BasicAuthentication::class,\n" +" SessionMiddleware::class,\n" +" CsrfMiddleware::class,\n" +" Router::class,\n" +" ]\n" +" );\n" +" }),\n" +" 'fallbackHandler' => Reference::to(NotFoundHandler::class),\n" +" ],\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/structure/middleware.md +#, no-wrap +msgid "Creating your own middleware" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "To create middleware, you need to implement a single `process` method of `Psr\\Http\\Server\\MiddlewareInterface`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface;\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "There are multiple ways to handle request and choosing one depends on what the middleware should achieve." +msgstr "" + +#. type: Title ### +#: en/structure/middleware.md +#, no-wrap +msgid "Forming response directly" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "To respond directly, one needs a response factory passed via constructor:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"responseFactory->createResponse();\n" +" $response->getBody()->write('Hello!');\n" +" return $response;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ### +#: en/structure/middleware.md +#, no-wrap +msgid "Delegating handling to the next middleware" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +#, no-wrap +msgid "" +"If middleware either isn't intended form response / change request or can't do it this time, handling could be\n" +"left to the next middleware in the stack: \n" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "return $next->handle($request);\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "In case you need to pass data to the next middleware, you can use request attributes:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"$request = $request->withAttribute('answer', 42);\n" +"return $next->handle();\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "To get it in the next middleware:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "$answer = $request->getAttribute('answer');\n" +msgstr "" + +#. type: Title ### +#: en/structure/middleware.md +#, no-wrap +msgid "Capturing response to manipulate it" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "You may want to capture response to manipulate it. It could be useful for adding CORS headers, gzipping content etc." +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"$response = $next->handle($request);\n" +"// extra handing\n" +"return $response;\n" +msgstr "" diff --git a/guide/po/structure_middleware.md/structure_middleware.md.pot b/guide/po/structure_middleware.md/structure_middleware.md.pot new file mode 100644 index 00000000..41b83349 --- /dev/null +++ b/guide/po/structure_middleware.md/structure_middleware.md.pot @@ -0,0 +1,348 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/structure/middleware.md +#, no-wrap +msgid "Middleware" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"Yii works with HTTP using the abstraction layer built around [PSR-7 HTTP " +"message interfaces](https://www.php-fig.org/psr/psr-7/) and [PSR-15 request " +"handler/middleware interfaces](https://www.php-fig.org/psr/psr-15/)." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"The application is composed of one or several middleware. Middleware runs " +"between request and response. When the URL is requested, the request object " +"is passed to the middleware dispatcher that starts executing middleware one " +"after another. Each middleware, given the request, can:" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/middleware.md +msgid "" +"Pass the request to the next middleware performing some work before / after " +"it." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/middleware.md +msgid "Form the response and return it." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"Depending on middleware used, application behavior may vary significantly." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "![Middleware](img/middleware.svg)" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"In the above each next middleware wraps the previous middleware. " +"Alternatively, it could be presented as follows:" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "![Middleware](img/middleware_alternative.svg)" +msgstr "" + +#. type: Title ## +#: en/structure/middleware.md +#, no-wrap +msgid "Using middleware" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"Any PSR-15 compatible middleware could be used with Yii and there are many. " +"Say, you need to add basic authentication one of the application URLs. URL-" +"dependent middleware is configured using router, so you need to change " +"router factory." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"Authentication middleware is implemented by `middlewares/http-" +"authentication` package so execute `composer require middlewares/http-" +"authentication` in the application root directory." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"Now register the middleware in DI container configuration `config/web.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +" [\n" +" 'class' => \\Middlewares\\BasicAuthentication::class,\n" +" '__construct()' => [\n" +" 'users' => [\n" +" 'foo' => 'bar',\n" +" ],\n" +" ],\n" +" 'realm()' => ['Access to the staging site via basic auth'],\n" +" 'attribute()' => ['username'],\n" +"],\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "In the `config/routes.php`, add new route:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"([SiteController::class, 'auth'])\n" +" ->name('site/auth')\n" +" ->addMiddleware(BasicAuthentication::class)\n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"When configuring routing, you're binding `/basic-auth` URL to a chain of " +"middleware consisting of basic authentication, and the action itself. A " +"chain is a special middleware that executes all the middleware it's " +"configured with." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "The action itself may be the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"public function auth(ServerRequestInterface $request): ResponseInterface\n" +"{\n" +" $response = $this->responseFactory->createResponse();\n" +" $response->getBody()->write('Hi ' . $request->getAttribute('username'));\n" +" return $response;\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"Basic authentication middleware wrote to request `username` attribute, so " +"you can access the data if needed." +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"To apply middleware to application overall regardless of URL, adjust `config/" +"application.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"return [\n" +" Yiisoft\\Yii\\Http\\Application::class => [\n" +" '__construct()' => [\n" +" 'dispatcher' => DynamicReference::to(static function (Injector $injector) {\n" +" return ($injector->make(MiddlewareDispatcher::class))\n" +" ->withMiddlewares(\n" +" [\n" +" ErrorCatcher::class,\n" +" BasicAuthentication::class,\n" +" SessionMiddleware::class,\n" +" CsrfMiddleware::class,\n" +" Router::class,\n" +" ]\n" +" );\n" +" }),\n" +" 'fallbackHandler' => Reference::to(NotFoundHandler::class),\n" +" ],\n" +" ],\n" +"];\n" +msgstr "" + +#. type: Title ## +#: en/structure/middleware.md +#, no-wrap +msgid "Creating your own middleware" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"To create middleware, you need to implement a single `process` method of " +"`Psr\\Http\\Server\\MiddlewareInterface`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface;\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"There are multiple ways to handle request and choosing one depends on what " +"the middleware should achieve." +msgstr "" + +#. type: Title ### +#: en/structure/middleware.md +#, no-wrap +msgid "Forming response directly" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"To respond directly, one needs a response factory passed via constructor:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"responseFactory->createResponse();\n" +" $response->getBody()->write('Hello!');\n" +" return $response;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ### +#: en/structure/middleware.md +#, no-wrap +msgid "Delegating handling to the next middleware" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +#, no-wrap +msgid "" +"If middleware either isn't intended form response / change request or can't do it this time, handling could be\n" +"left to the next middleware in the stack: \n" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "return $next->handle($request);\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"In case you need to pass data to the next middleware, you can use request " +"attributes:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"$request = $request->withAttribute('answer', 42);\n" +"return $next->handle();\n" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "To get it in the next middleware:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "$answer = $request->getAttribute('answer');\n" +msgstr "" + +#. type: Title ### +#: en/structure/middleware.md +#, no-wrap +msgid "Capturing response to manipulate it" +msgstr "" + +#. type: Plain text +#: en/structure/middleware.md +msgid "" +"You may want to capture response to manipulate it. It could be useful for " +"adding CORS headers, gzipping content etc." +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/middleware.md +#, no-wrap +msgid "" +"$response = $next->handle($request);\n" +"// extra handing\n" +"return $response;\n" +msgstr "" diff --git a/guide/po/structure_overview.md/ru/structure_overview.md.ru.po b/guide/po/structure_overview.md/ru/structure_overview.md.ru.po new file mode 100644 index 00000000..a4648ffd --- /dev/null +++ b/guide/po/structure_overview.md/ru/structure_overview.md.ru.po @@ -0,0 +1,160 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/structure/overview.md +#, no-wrap +msgid "Overview" +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "Yii applications code is typically grouped into modules by context. In each module there could be grouping by type." +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "For example, if the application is an online store, the context could be:" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/overview.md +msgid "Customer" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Profile" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Products list" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Checkout" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/overview.md +msgid "Logistics" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/overview.md +msgid "Delivery" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Addresses" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/overview.md +msgid "Helpdesk" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Support" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Claims" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Returns" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/overview.md +msgid "Accounting" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Transactions" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Taxes" +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "For a \"Customer\" context, residing under `App\\Customer` namespace, structure would be:" +msgstr "" + +#. type: Fenced code block +#: en/structure/overview.md +#, no-wrap +msgid "" +"App/\n" +" Customer/ <-- module namespace\n" +" Entity/\n" +" Customer.php <-- entity shared by \"Profile\" and \"Checkout\"\n" +" Profile/\n" +" Widget/\n" +" Gravatar.php\n" +" ProfileRepository.php <-- repository is usually specific to context\n" +" ProfileController.php <-- \"Customer\\Profile\" entry point\n" +" ProductList/ <-- module namespace \n" +" Entity/ <-- entities specific to \"Customer\\ProductList\"\n" +" Category.php\n" +" Product.php\n" +" ProductsListController.php <-- \"Customer\\ProductList\" entry point\n" +" Checkout/ <-- module namespace\n" +" CheckoutController.php\n" +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "A context may include sub-contexts. If a class is shared by multiple contexts, it's moved to the ancestor of both contexts." +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "A context may have [an entry point known as \"action\" or \"controller\"](action.md). Its job is to take [a request instance](../runtime/request.md), pass it to [domain layer](domain.md) in a suitable format, and create [a response](../runtime/response.md) based on domain layer return." +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "Besides, Yii applications also have the following:" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/overview.md +msgid "[entry scripts](entry-script.md): they're PHP scripts that are directly accessible by end users. They're responsible for starting a request handling cycle. Typically, a single entry script is handling the whole application." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/overview.md +msgid "[services](service.md): they're typically stateless objects registered within dependency container and provide various action methods." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/overview.md +msgid "[middleware](middleware.md): they represent a code that needs to be invoked before and after the actual handling of each request by action handlers." +msgstr "" diff --git a/guide/po/structure_overview.md/structure_overview.md.pot b/guide/po/structure_overview.md/structure_overview.md.pot new file mode 100644 index 00000000..57f9b49b --- /dev/null +++ b/guide/po/structure_overview.md/structure_overview.md.pot @@ -0,0 +1,179 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/structure/overview.md +#, no-wrap +msgid "Overview" +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "" +"Yii applications code is typically grouped into modules by context. In each " +"module there could be grouping by type." +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "" +"For example, if the application is an online store, the context could be:" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/overview.md +msgid "Customer" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Profile" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Products list" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Checkout" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/overview.md +msgid "Logistics" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/overview.md +msgid "Delivery" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Addresses" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/overview.md +msgid "Helpdesk" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Support" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Claims" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Returns" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/overview.md +msgid "Accounting" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Transactions" +msgstr "" + +#. type: Bullet: ' - ' +#: en/structure/overview.md +msgid "Taxes" +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "" +"For a \"Customer\" context, residing under `App\\Customer` namespace, " +"structure would be:" +msgstr "" + +#. type: Fenced code block +#: en/structure/overview.md +#, no-wrap +msgid "" +"App/\n" +" Customer/ <-- module namespace\n" +" Entity/\n" +" Customer.php <-- entity shared by \"Profile\" and \"Checkout\"\n" +" Profile/\n" +" Widget/\n" +" Gravatar.php\n" +" ProfileRepository.php <-- repository is usually specific to context\n" +" ProfileController.php <-- \"Customer\\Profile\" entry point\n" +" ProductList/ <-- module namespace \n" +" Entity/ <-- entities specific to \"Customer\\ProductList\"\n" +" Category.php\n" +" Product.php\n" +" ProductsListController.php <-- \"Customer\\ProductList\" entry point\n" +" Checkout/ <-- module namespace\n" +" CheckoutController.php\n" +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "" +"A context may include sub-contexts. If a class is shared by multiple " +"contexts, it's moved to the ancestor of both contexts." +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "" +"A context may have [an entry point known as \"action\" or \"controller\"]" +"(action.md). Its job is to take [a request instance](../runtime/request.md), " +"pass it to [domain layer](domain.md) in a suitable format, and create [a " +"response](../runtime/response.md) based on domain layer return." +msgstr "" + +#. type: Plain text +#: en/structure/overview.md +msgid "Besides, Yii applications also have the following:" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/overview.md +msgid "" +"[entry scripts](entry-script.md): they're PHP scripts that are directly " +"accessible by end users. They're responsible for starting a request " +"handling cycle. Typically, a single entry script is handling the whole " +"application." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/overview.md +msgid "" +"[services](service.md): they're typically stateless objects registered " +"within dependency container and provide various action methods." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/overview.md +msgid "" +"[middleware](middleware.md): they represent a code that needs to be invoked " +"before and after the actual handling of each request by action handlers." +msgstr "" diff --git a/guide/po/structure_package.md/ru/structure_package.md.ru.po b/guide/po/structure_package.md/ru/structure_package.md.ru.po new file mode 100644 index 00000000..cab2323b --- /dev/null +++ b/guide/po/structure_package.md/ru/structure_package.md.ru.po @@ -0,0 +1,367 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/structure/package.md +#, no-wrap +msgid "Packages" +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "Reusable code could be released as [a Composer package](https://getcomposer.org/doc/05-repositories.md#package). It could be an infrastructure library, a module representing one of the application contexts or, basically, any reusable code." +msgstr "" + +#. type: Title ## +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Using packages " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/structure/package.md +msgid "By default, Composer installs packages registered on [Packagist](https://packagist.org/) — the biggest repository for open source PHP packages. You can look for packages on Packagist. You may also [create your own repository](https://getcomposer.org/doc/05-repositories.md#repository) and configure Composer to use it. This is useful if you're developing private packages that you want to share within your projects only." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "Packages installed by Composer are stored in the `vendor` directory of your project. Because the Composer is a dependency manager, when it installs a package, it will also install all its dependent packages." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +#, no-wrap +msgid "" +"> [!WARNING]\n" +"> `vendor` directory of your application should never be modified.\n" +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "A package could be installed with the following command:" +msgstr "" + +#. type: Fenced code block +#: en/structure/package.md +#, no-wrap +msgid "composer install vendor-name/package-name\n" +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "After it's done, Composer modifies `composer.json` and `composer.lock`. The former defines what packages to install, and their version constraints the latter stores a snapshot of exact versions actually installed." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "Classes from the package will be available immediately via [autoloading](../concept/autoloading.md)." +msgstr "" + +#. type: Title ## +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Creating packages " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/structure/package.md +msgid "You may consider creating a package when you feel the need to share with other people your great code. A package can contain any code you like, such as a helper class, a widget, a service, middleware, the whole module, etc." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "Below are the basic steps you may follow." +msgstr "" + +#. type: Bullet: '1. ' +#: en/structure/package.md +msgid "Create a project for your package and host it on a VCS repository, such as [GitHub.com](https://github.com). The development and maintenance work for the package should be done on this repository." +msgstr "" + +#. type: Bullet: '2. ' +#: en/structure/package.md +msgid "Under the root directory of the project, create a file named `composer.json` as required by Composer. Please refer to the next subsection for more details." +msgstr "" + +#. type: Bullet: '3. ' +#: en/structure/package.md +msgid "Register your package with a Composer repository, such as [Packagist](https://packagist.org/), so that other users can find and install your package using Composer." +msgstr "" + +#. type: Title ### +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "DI container " +msgid "`composer.json` " +msgstr "Контейнер внедрения зависимостей " + +#. type: Plain text +#: en/structure/package.md +msgid "Each Composer package must have a `composer.json` file in its root directory. The file contains the metadata about the package. You may find the complete specification about this file in the [Composer Manual](https://getcomposer.org/doc/01-basic-usage.md#composer-json-project-setup). The following example shows the `composer.json` file for the `yiisoft/yii-widgets` package:" +msgstr "" + +#. type: Fenced code block (json) +#: en/structure/package.md +#, no-wrap +msgid "" +"{\n" +" \"name\": \"yiisoft/yii-widgets\",\n" +" \"type\": \"library\",\n" +" \"description\": \"Yii widgets collection\",\n" +" \"keywords\": [\n" +" \"yii\",\n" +" \"widgets\"\n" +" ],\n" +" \"homepage\": \"https://www.yiiframework.com/\",\n" +" \"license\": \"BSD-3-Clause\",\n" +" \"support\": {\n" +" \"issues\": \"https://github.com/yiisoft/yii-widgets/issues?state=open\",\n" +" \"forum\": \"https://www.yiiframework.com/forum/\",\n" +" \"wiki\": \"https://www.yiiframework.com/wiki/\",\n" +" \"irc\": \"ircs://irc.libera.chat:6697/yii\",\n" +" \"chat\": \"https://t.me/yii3en\",\n" +" \"source\": \"https://github.com/yiisoft/yii-widgets\"\n" +" },\n" +" \"funding\": [\n" +" {\n" +" \"type\": \"opencollective\",\n" +" \"url\": \"https://opencollective.com/yiisoft\"\n" +" },\n" +" {\n" +" \"type\": \"github\",\n" +" \"url\": \"https://github.com/sponsors/yiisoft\"\n" +" }\n" +" ],\n" +" \"require\": {\n" +" \"php\": \"^7.4|^8.0\",\n" +" \"yiisoft/aliases\": \"^1.1|^2.0\",\n" +" \"yiisoft/cache\": \"^1.0\",\n" +" \"yiisoft/html\": \"^2.0\",\n" +" \"yiisoft/view\": \"^4.0\",\n" +" \"yiisoft/widget\": \"^1.0\"\n" +" },\n" +" \"require-dev\": {\n" +" \"phpunit/phpunit\": \"^9.5\",\n" +" \"roave/infection-static-analysis-plugin\": \"^1.16\",\n" +" \"spatie/phpunit-watcher\": \"^1.23\",\n" +" \"vimeo/psalm\": \"^4.18\",\n" +" \"yiisoft/psr-dummy-provider\": \"^1.0\",\n" +" \"yiisoft/test-support\": \"^1.3\"\n" +" },\n" +" \"autoload\": {\n" +" \"psr-4\": {\n" +" \"Yiisoft\\\\Yii\\\\Widgets\\\\\": \"src\"\n" +" }\n" +" },\n" +" \"autoload-dev\": {\n" +" \"psr-4\": {\n" +" \"Yiisoft\\\\Yii\\\\Widgets\\\\Tests\\\\\": \"tests\"\n" +" }\n" +" },\n" +" \"extra\": {\n" +" \"branch-alias\": {\n" +" \"dev-master\": \"3.0.x-dev\"\n" +" }\n" +" },\n" +" \"scripts\": {\n" +" \"test\": \"phpunit --testdox --no-interaction\",\n" +" \"test-watch\": \"phpunit-watcher watch\"\n" +" },\n" +" \"config\": {\n" +" \"sort-packages\": true,\n" +" \"allow-plugins\": {\n" +" \"infection/extension-installer\": true,\n" +" \"composer/package-versions-deprecated\": true\n" +" }\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "DI container " +msgid "Package Name " +msgstr "Контейнер внедрения зависимостей " + +#. type: Plain text +#: en/structure/package.md +msgid "Each Composer package should have a package name which uniquely identifies the package among all others. The format of package names is `vendorName/projectName`. For example, in the package name `yiisoft/queue`, the vendor name, and the project name are `yiisoft` and `queue`, respectively." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +#, no-wrap +msgid "" +"> [!WARNING]\n" +"> Don't use `yiisoft` as your vendor name as it's reserved for use by the Yii itself.\n" +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "We recommend you prefix `yii-` to the project name for packages that aren't able to work as general PHP packages and require Yii application. This will allow users to more easily tell whether a package is Yii specific." +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "References " +msgid "Dependencies " +msgstr "Полезные ссылки " + +#. type: Plain text +#: en/structure/package.md +msgid "If your extension depends on other packages, you should list them in `require` section of `composer.json`. Make sure you also list appropriate version constraints (e.g. `^1.0`, `@stable`) for each dependent package. Use stable dependencies when your extension is released in a stable version." +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "DI container " +msgid "Class Autoloading " +msgstr "Контейнер внедрения зависимостей " + +#. type: Plain text +#: en/structure/package.md +msgid "In order for your classes to be autoloaded, you should specify the `autoload` entry in the `composer.json` file, like shown below:" +msgstr "" + +#. type: Fenced code block (json) +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "" +#| "{\n" +#| " \"autoload\": {\n" +#| " \"psr-4\": {\n" +#| " \"App\\\\\": \"src/\"\n" +#| " }\n" +#| " }\n" +#| "}\n" +msgid "" +"{\n" +" // ....\n" +"\n" +" \"autoload\": {\n" +" \"psr-4\": {\n" +" \"MyVendorName\\\\MyPackageName\\\\\": \"src\"\n" +" }\n" +" }\n" +"}\n" +msgstr "" +"{\n" +" \"autoload\": {\n" +" \"psr-4\": {\n" +" \"App\\\\\": \"src/\"\n" +" }\n" +" }\n" +"}\n" + +#. type: Plain text +#: en/structure/package.md +msgid "You may list one or multiple root namespaces and their corresponding file paths." +msgstr "" + +#. type: Title ### +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "Predefined aliases " +msgid "Recommended Practices " +msgstr "Предопределенные псевдонимы " + +#. type: Plain text +#: en/structure/package.md +msgid "Because packages are meant to be used by other people, you often need to make an extra effort during development. Below, we introduce some common and recommended practices in creating high-quality extensions." +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Testing " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/structure/package.md +msgid "You want your package to run flawlessly without bringing problems to other people. To reach this goal, you should test your extension before releasing it to the public." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "It's recommended that you create various test cases to cover your extension code rather than relying on manual tests. Each time before you release a new version of your package, you may run these test cases to make sure everything is in good shape. For more details, please refer to the [Testing](../testing/overview.md) section." +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "Defining aliases " +msgid "Versioning " +msgstr "Определение псевдонимов " + +#. type: Plain text +#: en/structure/package.md +msgid "You should give each release of your extension a version number (e.g. `1.0.1`). We recommend you follow the [semantic versioning](https://semver.org) practice when determining what version numbers should be used." +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, fuzzy, no-wrap +#| msgid "References " +msgid "Releasing " +msgstr "Полезные ссылки " + +#. type: Plain text +#: en/structure/package.md +msgid "To let other people know about your package, you need to release it to the public." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "If it's the first time you're releasing a package, you should register it in a Composer repository, such as [Packagist](https://packagist.org/). After that, all you need to do is create a release tag (for example, `v1.0.1`) on the VCS repository of your extension and notify the Composer repository about the new release. People will then be able to find the new release and install or update the package through the Composer repository." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "In the release of your package, in addition to code files, you should also consider including the following to help other people learn about and use your extension:" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/package.md +msgid "A readme file in the package root directory: it describes what your extension does and how to install and use it. We recommend you write it in [Markdown](https://daringfireball.net/projects/markdown/) format and name the file as `README.md`." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/package.md +msgid "A changelog file in the package root directory: it lists what changes are made in each release. The file may be written in Markdown format and named as `CHANGELOG.md`." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/package.md +msgid "An upgrade file in the package root directory: it gives the instructions on how to upgrade from older releases of the extension. The file may be written in Markdown format and named as `UPGRADE.md`." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/package.md +msgid "Tutorials, demos, screenshots, etc.: these are needed if your extension provides many features that can't be fully covered in the readme file." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/package.md +msgid "API documentation: your code should be well-documented to allow other people to more easily read and understand it." +msgstr "" diff --git a/guide/po/structure_package.md/structure_package.md.pot b/guide/po/structure_package.md/structure_package.md.pot new file mode 100644 index 00000000..c0520351 --- /dev/null +++ b/guide/po/structure_package.md/structure_package.md.pot @@ -0,0 +1,432 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/structure/package.md +#, no-wrap +msgid "Packages" +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"Reusable code could be released as [a Composer package](https://getcomposer." +"org/doc/05-repositories.md#package). It could be an infrastructure library, " +"a module representing one of the application contexts or, basically, any " +"reusable code." +msgstr "" + +#. type: Title ## +#: en/structure/package.md +#, no-wrap +msgid "Using packages " +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"By default, Composer installs packages registered on [Packagist](https://" +"packagist.org/) — the biggest repository for open source PHP packages. You " +"can look for packages on Packagist. You may also [create your own repository]" +"(https://getcomposer.org/doc/05-repositories.md#repository) and configure " +"Composer to use it. This is useful if you're developing private packages " +"that you want to share within your projects only." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"Packages installed by Composer are stored in the `vendor` directory of your " +"project. Because the Composer is a dependency manager, when it installs a " +"package, it will also install all its dependent packages." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +#, no-wrap +msgid "" +"> [!WARNING]\n" +"> `vendor` directory of your application should never be modified.\n" +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "A package could be installed with the following command:" +msgstr "" + +#. type: Fenced code block +#: en/structure/package.md +#, no-wrap +msgid "composer install vendor-name/package-name\n" +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"After it's done, Composer modifies `composer.json` and `composer.lock`. The " +"former defines what packages to install, and their version constraints the " +"latter stores a snapshot of exact versions actually installed." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"Classes from the package will be available immediately via [autoloading](../" +"concept/autoloading.md)." +msgstr "" + +#. type: Title ## +#: en/structure/package.md +#, no-wrap +msgid "Creating packages " +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"You may consider creating a package when you feel the need to share with " +"other people your great code. A package can contain any code you like, such " +"as a helper class, a widget, a service, middleware, the whole module, etc." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "Below are the basic steps you may follow." +msgstr "" + +#. type: Bullet: '1. ' +#: en/structure/package.md +msgid "" +"Create a project for your package and host it on a VCS repository, such as " +"[GitHub.com](https://github.com). The development and maintenance work for " +"the package should be done on this repository." +msgstr "" + +#. type: Bullet: '2. ' +#: en/structure/package.md +msgid "" +"Under the root directory of the project, create a file named `composer.json` " +"as required by Composer. Please refer to the next subsection for more " +"details." +msgstr "" + +#. type: Bullet: '3. ' +#: en/structure/package.md +msgid "" +"Register your package with a Composer repository, such as [Packagist]" +"(https://packagist.org/), so that other users can find and install your " +"package using Composer." +msgstr "" + +#. type: Title ### +#: en/structure/package.md +#, no-wrap +msgid "`composer.json` " +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"Each Composer package must have a `composer.json` file in its root " +"directory. The file contains the metadata about the package. You may find " +"the complete specification about this file in the [Composer Manual](https://" +"getcomposer.org/doc/01-basic-usage.md#composer-json-project-setup). The " +"following example shows the `composer.json` file for the `yiisoft/yii-" +"widgets` package:" +msgstr "" + +#. type: Fenced code block (json) +#: en/structure/package.md +#, no-wrap +msgid "" +"{\n" +" \"name\": \"yiisoft/yii-widgets\",\n" +" \"type\": \"library\",\n" +" \"description\": \"Yii widgets collection\",\n" +" \"keywords\": [\n" +" \"yii\",\n" +" \"widgets\"\n" +" ],\n" +" \"homepage\": \"https://www.yiiframework.com/\",\n" +" \"license\": \"BSD-3-Clause\",\n" +" \"support\": {\n" +" \"issues\": \"https://github.com/yiisoft/yii-widgets/issues?state=open\",\n" +" \"forum\": \"https://www.yiiframework.com/forum/\",\n" +" \"wiki\": \"https://www.yiiframework.com/wiki/\",\n" +" \"irc\": \"ircs://irc.libera.chat:6697/yii\",\n" +" \"chat\": \"https://t.me/yii3en\",\n" +" \"source\": \"https://github.com/yiisoft/yii-widgets\"\n" +" },\n" +" \"funding\": [\n" +" {\n" +" \"type\": \"opencollective\",\n" +" \"url\": \"https://opencollective.com/yiisoft\"\n" +" },\n" +" {\n" +" \"type\": \"github\",\n" +" \"url\": \"https://github.com/sponsors/yiisoft\"\n" +" }\n" +" ],\n" +" \"require\": {\n" +" \"php\": \"^7.4|^8.0\",\n" +" \"yiisoft/aliases\": \"^1.1|^2.0\",\n" +" \"yiisoft/cache\": \"^1.0\",\n" +" \"yiisoft/html\": \"^2.0\",\n" +" \"yiisoft/view\": \"^4.0\",\n" +" \"yiisoft/widget\": \"^1.0\"\n" +" },\n" +" \"require-dev\": {\n" +" \"phpunit/phpunit\": \"^9.5\",\n" +" \"roave/infection-static-analysis-plugin\": \"^1.16\",\n" +" \"spatie/phpunit-watcher\": \"^1.23\",\n" +" \"vimeo/psalm\": \"^4.18\",\n" +" \"yiisoft/psr-dummy-provider\": \"^1.0\",\n" +" \"yiisoft/test-support\": \"^1.3\"\n" +" },\n" +" \"autoload\": {\n" +" \"psr-4\": {\n" +" \"Yiisoft\\\\Yii\\\\Widgets\\\\\": \"src\"\n" +" }\n" +" },\n" +" \"autoload-dev\": {\n" +" \"psr-4\": {\n" +" \"Yiisoft\\\\Yii\\\\Widgets\\\\Tests\\\\\": \"tests\"\n" +" }\n" +" },\n" +" \"extra\": {\n" +" \"branch-alias\": {\n" +" \"dev-master\": \"3.0.x-dev\"\n" +" }\n" +" },\n" +" \"scripts\": {\n" +" \"test\": \"phpunit --testdox --no-interaction\",\n" +" \"test-watch\": \"phpunit-watcher watch\"\n" +" },\n" +" \"config\": {\n" +" \"sort-packages\": true,\n" +" \"allow-plugins\": {\n" +" \"infection/extension-installer\": true,\n" +" \"composer/package-versions-deprecated\": true\n" +" }\n" +" }\n" +"}\n" +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, no-wrap +msgid "Package Name " +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"Each Composer package should have a package name which uniquely identifies " +"the package among all others. The format of package names is `vendorName/" +"projectName`. For example, in the package name `yiisoft/queue`, the vendor " +"name, and the project name are `yiisoft` and `queue`, respectively." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +#, no-wrap +msgid "" +"> [!WARNING]\n" +"> Don't use `yiisoft` as your vendor name as it's reserved for use by the Yii itself.\n" +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"We recommend you prefix `yii-` to the project name for packages that aren't " +"able to work as general PHP packages and require Yii application. This will " +"allow users to more easily tell whether a package is Yii specific." +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, no-wrap +msgid "Dependencies " +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"If your extension depends on other packages, you should list them in " +"`require` section of `composer.json`. Make sure you also list appropriate " +"version constraints (e.g. `^1.0`, `@stable`) for each dependent package. " +"Use stable dependencies when your extension is released in a stable version." +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, no-wrap +msgid "Class Autoloading " +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"In order for your classes to be autoloaded, you should specify the " +"`autoload` entry in the `composer.json` file, like shown below:" +msgstr "" + +#. type: Fenced code block (json) +#: en/structure/package.md +#, no-wrap +msgid "" +"{\n" +" // ....\n" +"\n" +" \"autoload\": {\n" +" \"psr-4\": {\n" +" \"MyVendorName\\\\MyPackageName\\\\\": \"src\"\n" +" }\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"You may list one or multiple root namespaces and their corresponding file " +"paths." +msgstr "" + +#. type: Title ### +#: en/structure/package.md +#, no-wrap +msgid "Recommended Practices " +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"Because packages are meant to be used by other people, you often need to " +"make an extra effort during development. Below, we introduce some common " +"and recommended practices in creating high-quality extensions." +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, no-wrap +msgid "Testing " +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"You want your package to run flawlessly without bringing problems to other " +"people. To reach this goal, you should test your extension before releasing " +"it to the public." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"It's recommended that you create various test cases to cover your extension " +"code rather than relying on manual tests. Each time before you release a " +"new version of your package, you may run these test cases to make sure " +"everything is in good shape. For more details, please refer to the [Testing]" +"(../testing/overview.md) section." +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, no-wrap +msgid "Versioning " +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"You should give each release of your extension a version number (e.g. " +"`1.0.1`). We recommend you follow the [semantic versioning](https://semver." +"org) practice when determining what version numbers should be used." +msgstr "" + +#. type: Title #### +#: en/structure/package.md +#, no-wrap +msgid "Releasing " +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"To let other people know about your package, you need to release it to the " +"public." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"If it's the first time you're releasing a package, you should register it in " +"a Composer repository, such as [Packagist](https://packagist.org/). After " +"that, all you need to do is create a release tag (for example, `v1.0.1`) on " +"the VCS repository of your extension and notify the Composer repository " +"about the new release. People will then be able to find the new release and " +"install or update the package through the Composer repository." +msgstr "" + +#. type: Plain text +#: en/structure/package.md +msgid "" +"In the release of your package, in addition to code files, you should also " +"consider including the following to help other people learn about and use " +"your extension:" +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/package.md +msgid "" +"A readme file in the package root directory: it describes what your " +"extension does and how to install and use it. We recommend you write it in " +"[Markdown](https://daringfireball.net/projects/markdown/) format and name " +"the file as `README.md`." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/package.md +msgid "" +"A changelog file in the package root directory: it lists what changes are " +"made in each release. The file may be written in Markdown format and named " +"as `CHANGELOG.md`." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/package.md +msgid "" +"An upgrade file in the package root directory: it gives the instructions on " +"how to upgrade from older releases of the extension. The file may be written " +"in Markdown format and named as `UPGRADE.md`." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/package.md +msgid "" +"Tutorials, demos, screenshots, etc.: these are needed if your extension " +"provides many features that can't be fully covered in the readme file." +msgstr "" + +#. type: Bullet: '* ' +#: en/structure/package.md +msgid "" +"API documentation: your code should be well-documented to allow other people " +"to more easily read and understand it." +msgstr "" diff --git a/guide/po/structure_service.md/ru/structure_service.md.ru.po b/guide/po/structure_service.md/ru/structure_service.md.ru.po new file mode 100644 index 00000000..36bd193d --- /dev/null +++ b/guide/po/structure_service.md/ru/structure_service.md.ru.po @@ -0,0 +1,218 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Bullet: '- ' +#: en/structure/domain.md en/structure/service.md +#, no-wrap +msgid "Entity" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md en/structure/service.md +#, no-wrap +msgid "Repository" +msgstr "" + +#. type: Title # +#: en/structure/service.md +#, no-wrap +msgid "Service components" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "Application may get complicated, so it makes sense to extract focused parts of business logic or infrastructure into service components. They're typically injected into other components or action handlers. It's usually done via autowiring:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/service.md +#, no-wrap +msgid "" +"public function actionIndex(CurrentRoute $route, MyService $myService): ResponseInterface\n" +"{\n" +" $id = $route->getArgument('id');\n" +" \n" +" // ...\n" +" $extraData = $myService->getExtraData($id);\n" +" \n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "Yii3 doesn't technically imply any limitations on how you build services. In general, there's no need to extend from a base class or implement a certain interface:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/service.md +#, no-wrap +msgid "" +"final readonly class MyService\n" +"{\n" +" public function __construct(\n" +" private ExtraDataStorage $extraDataStorage\n" +" )\n" +" {\n" +" }\n" +"\n" +" public function getExtraData(string $id): array\n" +" {\n" +" return $this->extraDataStorage->get($id);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "Services either perform a task or return data. They're created once, put into a DI container and then could be used multiple times. Because of that, it's a good idea to keep your services stateless that's both service itself and any of its dependencies shouldn't hold state. You can ensure it by using `readonly` PHP keyword at class level." +msgstr "" + +#. type: Title ## +#: en/structure/service.md +#, fuzzy, no-wrap +#| msgid "Secure server configuration" +msgid "Service dependencies and configuration" +msgstr "Безопасная конфигурация сервера" + +#. type: Plain text +#: en/structure/service.md +msgid "Services should always define all their dependencies on other services via `__construct()`. It both allows you to use a service right away after it's created and serves as an indicator of a service doing too much if there are too many dependencies." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/service.md +msgid "After the service is created, it shouldn't be re-configured in runtime." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/service.md +msgid "DI container instance usually **shouldn't** be injected as a dependency. Prefer concrete interfaces." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/service.md +msgid "In case of complicated or \"heavy\" initialization, try to postpone it until the service method is called." +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "The same is valid for configuration values. They should be provided as a constructor argument. Related values could be grouped together into value objects. For example, database connection usually requires DSN string, username and password. These three could be combined into Dsn class:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/service.md +#, no-wrap +msgid "" +"final readonly class Dsn\n" +"{\n" +" public function __construct(\n" +" public string $dsn,\n" +" public string $username,\n" +" public string $password\n" +" )\n" +" {\n" +" if (!$this->isValidDsn($dsn)) {\n" +" throw new \\InvalidArgumentException('DSN provided is not valid.');\n" +" }\n" +" }\n" +" \n" +" private function isValidDsn(string $dsn): bool\n" +" {\n" +" // check DSN validity \n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/structure/service.md +#, no-wrap +msgid "Service methods" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "Service method usually does something. It could be a simple thing repeated exactly, but usually it depends on the context. For example:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/service.md +#, fuzzy, no-wrap +#| msgid "" +#| "final class MyService implements MyServiceInterface\n" +#| "{\n" +#| " public function __construct(int $amount)\n" +#| " {\n" +#| " }\n" +#| "\n" +#| " public function setDiscount(int $discount): void\n" +#| " {\n" +#| " \n" +#| " }\n" +#| "}\n" +msgid "" +"final readonly class PostPersister\n" +"{\n" +" public function __construct(\n" +" private Storage $db\n" +" )\n" +" {\n" +" }\n" +" \n" +" public function persist(Post $post)\n" +" {\n" +" $this->db->insertOrUpdate('post', $post); \n" +" }\n" +"}\n" +msgstr "" +"class MyService implements MyServiceInterface\n" +"{\n" +" public function __construct(int $amount)\n" +" {\n" +" }\n" +"\n" +" public function setDiscount(int $discount): void\n" +" {\n" +" \n" +" }\n" + +#. type: Plain text +#: en/structure/service.md +msgid "There's a service that is saving posts into permanent storage such as a database. An object allowing communication with a concrete storage is always the same, so it's injected using constructor while the post saved could vary, so it's passed as a method argument." +msgstr "" + +#. type: Title ## +#: en/structure/service.md +#, no-wrap +msgid "Is everything a service?" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "Often it makes sense to choose another class type to place your code into. Check:" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/service.md +msgid "Widget" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/service.md +msgid "[Middleware](middleware.md)" +msgstr "" diff --git a/guide/po/structure_service.md/structure_service.md.pot b/guide/po/structure_service.md/structure_service.md.pot new file mode 100644 index 00000000..fe8bd0a5 --- /dev/null +++ b/guide/po/structure_service.md/structure_service.md.pot @@ -0,0 +1,227 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Bullet: '- ' +#: en/structure/domain.md en/structure/service.md +#, no-wrap +msgid "Entity" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/domain.md en/structure/service.md +#, no-wrap +msgid "Repository" +msgstr "" + +#. type: Title # +#: en/structure/service.md +#, no-wrap +msgid "Service components" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "" +"Application may get complicated, so it makes sense to extract focused parts " +"of business logic or infrastructure into service components. They're " +"typically injected into other components or action handlers. It's usually " +"done via autowiring:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/service.md +#, no-wrap +msgid "" +"public function actionIndex(CurrentRoute $route, MyService $myService): ResponseInterface\n" +"{\n" +" $id = $route->getArgument('id');\n" +" \n" +" // ...\n" +" $extraData = $myService->getExtraData($id);\n" +" \n" +" // ...\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "" +"Yii3 doesn't technically imply any limitations on how you build services. In " +"general, there's no need to extend from a base class or implement a certain " +"interface:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/service.md +#, no-wrap +msgid "" +"final readonly class MyService\n" +"{\n" +" public function __construct(\n" +" private ExtraDataStorage $extraDataStorage\n" +" )\n" +" {\n" +" }\n" +"\n" +" public function getExtraData(string $id): array\n" +" {\n" +" return $this->extraDataStorage->get($id);\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "" +"Services either perform a task or return data. They're created once, put " +"into a DI container and then could be used multiple times. Because of that, " +"it's a good idea to keep your services stateless that's both service itself " +"and any of its dependencies shouldn't hold state. You can ensure it by using " +"`readonly` PHP keyword at class level." +msgstr "" + +#. type: Title ## +#: en/structure/service.md +#, no-wrap +msgid "Service dependencies and configuration" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "" +"Services should always define all their dependencies on other services via " +"`__construct()`. It both allows you to use a service right away after it's " +"created and serves as an indicator of a service doing too much if there are " +"too many dependencies." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/service.md +msgid "After the service is created, it shouldn't be re-configured in runtime." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/service.md +msgid "" +"DI container instance usually **shouldn't** be injected as a dependency. " +"Prefer concrete interfaces." +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/service.md +msgid "" +"In case of complicated or \"heavy\" initialization, try to postpone it until " +"the service method is called." +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "" +"The same is valid for configuration values. They should be provided as a " +"constructor argument. Related values could be grouped together into value " +"objects. For example, database connection usually requires DSN string, " +"username and password. These three could be combined into Dsn class:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/service.md +#, no-wrap +msgid "" +"final readonly class Dsn\n" +"{\n" +" public function __construct(\n" +" public string $dsn,\n" +" public string $username,\n" +" public string $password\n" +" )\n" +" {\n" +" if (!$this->isValidDsn($dsn)) {\n" +" throw new \\InvalidArgumentException('DSN provided is not valid.');\n" +" }\n" +" }\n" +" \n" +" private function isValidDsn(string $dsn): bool\n" +" {\n" +" // check DSN validity \n" +" }\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/structure/service.md +#, no-wrap +msgid "Service methods" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "" +"Service method usually does something. It could be a simple thing repeated " +"exactly, but usually it depends on the context. For example:" +msgstr "" + +#. type: Fenced code block (php) +#: en/structure/service.md +#, no-wrap +msgid "" +"final readonly class PostPersister\n" +"{\n" +" public function __construct(\n" +" private Storage $db\n" +" )\n" +" {\n" +" }\n" +" \n" +" public function persist(Post $post)\n" +" {\n" +" $this->db->insertOrUpdate('post', $post); \n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "" +"There's a service that is saving posts into permanent storage such as a " +"database. An object allowing communication with a concrete storage is always " +"the same, so it's injected using constructor while the post saved could " +"vary, so it's passed as a method argument." +msgstr "" + +#. type: Title ## +#: en/structure/service.md +#, no-wrap +msgid "Is everything a service?" +msgstr "" + +#. type: Plain text +#: en/structure/service.md +msgid "" +"Often it makes sense to choose another class type to place your code into. " +"Check:" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/service.md +msgid "Widget" +msgstr "" + +#. type: Bullet: '- ' +#: en/structure/service.md +msgid "[Middleware](middleware.md)" +msgstr "" diff --git a/guide/po/tutorial_console-applications.md/ru/tutorial_console-applications.md.ru.po b/guide/po/tutorial_console-applications.md/ru/tutorial_console-applications.md.ru.po new file mode 100644 index 00000000..94b764fd --- /dev/null +++ b/guide/po/tutorial_console-applications.md/ru/tutorial_console-applications.md.ru.po @@ -0,0 +1,142 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title ## +#: en/concept/autoloading.md en/security/best-practices.md +#: en/structure/domain.md en/tutorial/console-applications.md +#, no-wrap +msgid "References" +msgstr "Ссылки" + +#. type: Title # +#: en/tutorial/console-applications.md +#, no-wrap +msgid "Console applications" +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "Console applications are mainly used to create utility, background processing and maintenance tasks." +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "To get support for console application in your project, get `yiisoft/yii-console` via composer:" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/console-applications.md +#, fuzzy, no-wrap +#| msgid "composer install yiisoft/security\n" +msgid "composer require yiisoft/yii-console\n" +msgstr "composer install yiisoft/security\n" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "After it's installed, you can access the entry point as" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/console-applications.md +#, no-wrap +msgid "./yii\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "Out of the box only `serve` command is available. It's starting PHP built-in web server to serve the application locally." +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "Commands are executed with `symfony/console`. To create your own console command, you need to define a command:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/console-applications.md +#, no-wrap +msgid "" +"setHelp('This command serves for demo purpose')\n" +" ->addArgument('name', InputArgument::OPTIONAL, 'Name to greet', 'anonymous');\n" +" }\n" +"\n" +" protected function execute(InputInterface $input, OutputInterface $output): int\n" +" {\n" +" $io = new SymfonyStyle($input, $output);\n" +"\n" +" $name = $input->getArgument('name');\n" +" $io->success(\"Hello, $name!\");\n" +" return ExitCode::OK;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "Now register the command in `config/params.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/console-applications.md +#, no-wrap +msgid "" +"return [\n" +" 'console' => [\n" +" 'commands' => [\n" +" 'demo/hello' => App\\Demo\\HelloCommand::class,\n" +" ],\n" +" ], \n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "After it's done, the command could be executed as" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/console-applications.md +#, no-wrap +msgid "./yii demo:hello Alice\n" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/console-applications.md +msgid "[Symfony Console component guide](https://symfony.com/doc/current/components/console.html)" +msgstr "" diff --git a/guide/po/tutorial_console-applications.md/tutorial_console-applications.md.pot b/guide/po/tutorial_console-applications.md/tutorial_console-applications.md.pot new file mode 100644 index 00000000..4c79890e --- /dev/null +++ b/guide/po/tutorial_console-applications.md/tutorial_console-applications.md.pot @@ -0,0 +1,151 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title ## +#: en/concept/autoloading.md en/security/best-practices.md +#: en/structure/domain.md en/tutorial/console-applications.md +#, no-wrap +msgid "References" +msgstr "" + +#. type: Title # +#: en/tutorial/console-applications.md +#, no-wrap +msgid "Console applications" +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "" +"Console applications are mainly used to create utility, background " +"processing and maintenance tasks." +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "" +"To get support for console application in your project, get `yiisoft/yii-" +"console` via composer:" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/console-applications.md +#, no-wrap +msgid "composer require yiisoft/yii-console\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "After it's installed, you can access the entry point as" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/console-applications.md +#, no-wrap +msgid "./yii\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "" +"Out of the box only `serve` command is available. It's starting PHP built-in " +"web server to serve the application locally." +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "" +"Commands are executed with `symfony/console`. To create your own console " +"command, you need to define a command:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/console-applications.md +#, no-wrap +msgid "" +"setHelp('This command serves for demo purpose')\n" +" ->addArgument('name', InputArgument::OPTIONAL, 'Name to greet', 'anonymous');\n" +" }\n" +"\n" +" protected function execute(InputInterface $input, OutputInterface $output): int\n" +" {\n" +" $io = new SymfonyStyle($input, $output);\n" +"\n" +" $name = $input->getArgument('name');\n" +" $io->success(\"Hello, $name!\");\n" +" return ExitCode::OK;\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "Now register the command in `config/params.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/console-applications.md +#, no-wrap +msgid "" +"return [\n" +" 'console' => [\n" +" 'commands' => [\n" +" 'demo/hello' => App\\Demo\\HelloCommand::class,\n" +" ],\n" +" ], \n" +"];\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/console-applications.md +msgid "After it's done, the command could be executed as" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/console-applications.md +#, no-wrap +msgid "./yii demo:hello Alice\n" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/console-applications.md +msgid "" +"[Symfony Console component guide](https://symfony.com/doc/current/components/" +"console.html)" +msgstr "" diff --git a/guide/po/tutorial_mailing.md/ru/tutorial_mailing.md.ru.po b/guide/po/tutorial_mailing.md/ru/tutorial_mailing.md.ru.po new file mode 100644 index 00000000..900c0539 --- /dev/null +++ b/guide/po/tutorial_mailing.md/ru/tutorial_mailing.md.ru.po @@ -0,0 +1,608 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/tutorial/mailing.md +#, no-wrap +msgid "Mailing" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "Yii simplifies the composition and sending of email messages using the [yiisoft/mailer](https://github.com/yiisoft/mailer) package. This package provides content composition functionality and a basic interface for sending emails. By default, the package includes a file mailer that writes email contents into a file instead of sending them. This is particularly useful during the initial stages of application development." +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "To send actual emails, you can use the [Symfony Mailer](https://github.com/yiisoft/mailer-symfony) implementation, which is used in the examples below." +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, fuzzy, no-wrap +#| msgid "Confirming data integrity" +msgid "Configuring the Mailer" +msgstr "Проверка целостности данных" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "The mailer service allows you to create a message instance, populate it with data, and send it. Typically, you get an instance from the DI container as `Yiisoft\\Mailer\\MailerInterface`." +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "You can also create an instance manually as follows:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"\n" +"use Yiisoft\\Mailer\\Symfony\\Mailer;\n" +"\n" +"/**\n" +" * @var \\Symfony\\Component\\Mailer\\Transport\\TransportInterface $transport\n" +" */\n" +"\n" +"$mailer = new \\Yiisoft\\Mailer\\Symfony\\Mailer(\n" +" $transport,\n" +");\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "The `Yiisoft\\Mailer\\MailerInterface` provides two main methods:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`send()` - Sends the given email message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`sendMultiple()` - Sends many messages at once." +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Creating a Message" +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "Simple Text Message" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "To create a simple message with a text body, use `Yiisoft\\Mailer\\Message`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"$message = new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Message subject',\n" +" textBody: 'Plain text content'\n" +");\n" +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "Simple HTML Message" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"$message = new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Message subject',\n" +" htmlBody: 'HTML content'\n" +");\n" +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "HTML Message from template" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "For this example, we will use package rendering package [view](https://github.com/yiisoft/view)." +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"/**\n" +" * @var \\Yiisoft\\View\\View $view\n" +" */\n" +"\n" +"$content = $view->render('path/to/view.php', [\n" +" 'name' => 'name',\n" +" 'code' => 'code',\n" +"]);\n" +"\n" +"$message = new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Subject',\n" +" htmlBody: $content\n" +");\n" +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "Using Layouts" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "You can also pass parameters to layouts from your template message:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"/**\n" +" * @var \\Yiisoft\\View\\View $view\n" +" * @var array $layoutParameters\n" +" */\n" +"\n" +"$messageBody = $view->render('path/to/view.php', [\n" +" 'name' => 'name',\n" +" 'code' => 'code',\n" +"]);\n" +"\n" +"$layoutParameters['content'] = $messageBody;\n" +"\n" +"$content = $view->render('path/to/layout.php', $layoutParameters);\n" +"\n" +"$message = new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Subject',\n" +" htmlBody: $content\n" +");\n" +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "Layout Example" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "You can wrap the view rendering result in a layout, similar to how layouts work in web applications. This is useful for setting up shared content like CSS styles:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"\n" +"\n" +"\n" +"\n" +" \n" +"\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"--
\n" +"Mailed by Yii\n" +"
\n" +"\n" +"\n" +"\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Adding More Data" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "The `Yiisoft\\Mailer\\MessageInterface` provides several methods to customize your message:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withCharset()` - Returns a new instance with the specified charset." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withFrom()` - Returns a new instance with the specified sender email address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withTo()` - Returns a new instance with the specified recipient(s) email address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withReplyTo()` - Returns a new instance with the specified reply-to address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withCc()` - Returns a new instance with the specified Cc (extra copy receiver) addresses." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withBcc()` - Returns a new instance with the specified Bcc (hidden copy receiver) addresses." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withSubject()` - Returns a new instance with the specified message subject." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withDate()` - Returns a new instance with the specified date when the message was sent." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withPriority()` - Returns a new instance with the specified priority of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withReturnPath()` - Returns a new instance with the specified return-path (the bounce address) of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withSender()` - Returns a new instance with the specified actual sender email address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withHtmlBody()` - Returns a new instance with the specified message HTML content." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withTextBody()` - Returns a new instance with the specified message plain text content." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withAddedHeader()` - Returns a new instance with the specified added custom header value." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withHeader()` - Returns a new instance with the specified custom header value." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withHeaders()` - Returns a new instance with the specified custom header values." +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "These methods are immutable, meaning they return a new instance of the message with the updated data." +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "Note `with` prefix. It indicates that the method is immutable and returns a new instance of the class with the changed data." +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "Getters" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "The following getters are available to retrieve message data:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getCharset()` - Returns the charset of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getFrom()` - Returns the message sender email address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getTo()` - Returns the message recipient(s) email address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getReplyTo()` - Returns the reply-to address of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getCc()` - Returns the Cc (extra copy receiver) addresses of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getBcc()` - Returns the Bcc (hidden copy receiver) addresses of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getSubject()` - Returns the message subject." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getDate()` - Returns the date when the message was sent, or null if it wasn't set." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getPriority()` - Returns the priority of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getReturnPath()` - Returns the return-path (the bounce address) of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getSender()` - Returns the message actual sender email address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getHtmlBody()` - Returns the message HTML body." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getTextBody()` - Returns the message text body." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getHeader()` - Returns all values for the specified header." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`__toString()` - Returns string representation of this message." +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Attaching Files" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "You can attach files to your message using the `withAttached()` method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"use Yiisoft\\Mailer\\File;\n" +"\n" +"// Attach a file from the local file system\n" +"$message = $message->withAttached(\n" +" File::fromPath('/path/to/source/file.pdf'),\n" +");\n" +"\n" +"// Create an attachment on-the-fly\n" +"$message = $message->withAttached(\n" +" File::fromContent('Attachment content', 'attach.txt', 'text/plain'),\n" +");\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Embedding Images" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "You can embed images into the message content using the `withEmbedded()` method. This is particularly useful when composing messages with views:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"$logo = 'path/to/logo';\n" +"$htmlBody = $this->view->render(\n" +" __DIR__ . 'template.php',\n" +" [\n" +" 'content' => $content,\n" +" 'logoCid' => $logo->cid(),\n" +" ],\n" +");\n" +"return new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Message subject',\n" +" htmlBody: $htmlBody,\n" +" embeddings: $logo\n" +" );\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "In your view or layout template, you can reference the embedded image using its CID:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "\">\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Sending a Message" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "To send an email message:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"/**\n" +" * @var \\Yiisoft\\View\\View $view\n" +" */\n" +"\n" +"$content = $view->render('path/to/view.php', [\n" +" 'name' => 'name',\n" +" 'code' => 'code',\n" +"]);\n" +"\n" +"$message = new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Subject',\n" +" htmlBody: $content\n" +");\n" +"\n" +"$mailer->send($message);\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Sending Multiple Messages" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "You can send multiple messages at once:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"$messages = [];\n" +"\n" +"foreach ($users as $user) {\n" +" $messages[] = (new \\Yiisoft\\Mailer\\Message())\n" +" // ...\n" +" ->withTo($user->email);\n" +"}\n" +"\n" +"$result = $mailer->sendMultiple($messages);\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "The `sendMultiple()` method returns a `Yiisoft\\Mailer\\SendResults` object containing arrays of successfully sent and failed messages." +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Implementing your own mail driver" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "To create a custom mail solution, implement the `Yiisoft\\Mailer\\MailerInterface` and `Yiisoft\\Mailer\\MessageInterface` interfaces." +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "For Development" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "For local or test development, you can use simplified implementations of the mailer that does not send emails. The package provides these implementations:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`Yiisoft\\Mailer\\StubMailer` - A simple mailer that stores messages in a local array." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`Yiisoft\\Mailer\\FileMailer` - A mock mailer that saves email messages as files instead of sending them." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`Yiisoft\\Mailer\\NullMailer` - A mailer that discards messages without sending or storing them." +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "To use one of these mailers, configure it in your development environment file Example: `environments/local/di.php`" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"return [\n" +" Yiisoft\\Mailer\\MailerInterface::class => Yiisoft\\Mailer\\StubMailer::class, //or any other\n" +"];\n" +"\n" +msgstr "" diff --git a/guide/po/tutorial_mailing.md/tutorial_mailing.md.pot b/guide/po/tutorial_mailing.md/tutorial_mailing.md.pot new file mode 100644 index 00000000..03fc575c --- /dev/null +++ b/guide/po/tutorial_mailing.md/tutorial_mailing.md.pot @@ -0,0 +1,685 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/tutorial/mailing.md +#, no-wrap +msgid "Mailing" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"Yii simplifies the composition and sending of email messages using the " +"[yiisoft/mailer](https://github.com/yiisoft/mailer) package. This package " +"provides content composition functionality and a basic interface for sending " +"emails. By default, the package includes a file mailer that writes email " +"contents into a file instead of sending them. This is particularly useful " +"during the initial stages of application development." +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"To send actual emails, you can use the [Symfony Mailer](https://github.com/" +"yiisoft/mailer-symfony) implementation, which is used in the examples below." +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Configuring the Mailer" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"The mailer service allows you to create a message instance, populate it with " +"data, and send it. Typically, you get an instance from the DI container as " +"`Yiisoft\\Mailer\\MailerInterface`." +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "You can also create an instance manually as follows:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"\n" +"use Yiisoft\\Mailer\\Symfony\\Mailer;\n" +"\n" +"/**\n" +" * @var \\Symfony\\Component\\Mailer\\Transport\\TransportInterface $transport\n" +" */\n" +"\n" +"$mailer = new \\Yiisoft\\Mailer\\Symfony\\Mailer(\n" +" $transport,\n" +");\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "The `Yiisoft\\Mailer\\MailerInterface` provides two main methods:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`send()` - Sends the given email message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`sendMultiple()` - Sends many messages at once." +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Creating a Message" +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "Simple Text Message" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"To create a simple message with a text body, use `Yiisoft\\Mailer\\Message`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"$message = new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Message subject',\n" +" textBody: 'Plain text content'\n" +");\n" +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "Simple HTML Message" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"$message = new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Message subject',\n" +" htmlBody: 'HTML content'\n" +");\n" +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "HTML Message from template" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"For this example, we will use package rendering package [view](https://" +"github.com/yiisoft/view)." +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"/**\n" +" * @var \\Yiisoft\\View\\View $view\n" +" */\n" +"\n" +"$content = $view->render('path/to/view.php', [\n" +" 'name' => 'name',\n" +" 'code' => 'code',\n" +"]);\n" +"\n" +"$message = new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Subject',\n" +" htmlBody: $content\n" +");\n" +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "Using Layouts" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "You can also pass parameters to layouts from your template message:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"/**\n" +" * @var \\Yiisoft\\View\\View $view\n" +" * @var array $layoutParameters\n" +" */\n" +"\n" +"$messageBody = $view->render('path/to/view.php', [\n" +" 'name' => 'name',\n" +" 'code' => 'code',\n" +"]);\n" +"\n" +"$layoutParameters['content'] = $messageBody;\n" +"\n" +"$content = $view->render('path/to/layout.php', $layoutParameters);\n" +"\n" +"$message = new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Subject',\n" +" htmlBody: $content\n" +");\n" +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "Layout Example" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"You can wrap the view rendering result in a layout, similar to how layouts " +"work in web applications. This is useful for setting up shared content like " +"CSS styles:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"\n" +"\n" +"\n" +"\n" +" \n" +"\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"--
\n" +"Mailed by Yii\n" +"
\n" +"\n" +"\n" +"\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Adding More Data" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"The `Yiisoft\\Mailer\\MessageInterface` provides several methods to " +"customize your message:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`withCharset()` - Returns a new instance with the specified charset." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withFrom()` - Returns a new instance with the specified sender email " +"address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withTo()` - Returns a new instance with the specified recipient(s) email " +"address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withReplyTo()` - Returns a new instance with the specified reply-to address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withCc()` - Returns a new instance with the specified Cc (extra copy " +"receiver) addresses." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withBcc()` - Returns a new instance with the specified Bcc (hidden copy " +"receiver) addresses." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withSubject()` - Returns a new instance with the specified message subject." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withDate()` - Returns a new instance with the specified date when the " +"message was sent." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withPriority()` - Returns a new instance with the specified priority of " +"this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withReturnPath()` - Returns a new instance with the specified return-path " +"(the bounce address) of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withSender()` - Returns a new instance with the specified actual sender " +"email address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withHtmlBody()` - Returns a new instance with the specified message HTML " +"content." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withTextBody()` - Returns a new instance with the specified message plain " +"text content." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withAddedHeader()` - Returns a new instance with the specified added custom " +"header value." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withHeader()` - Returns a new instance with the specified custom header " +"value." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`withHeaders()` - Returns a new instance with the specified custom header " +"values." +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"These methods are immutable, meaning they return a new instance of the " +"message with the updated data." +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"Note `with` prefix. It indicates that the method is immutable and returns a " +"new instance of the class with the changed data." +msgstr "" + +#. type: Title ### +#: en/tutorial/mailing.md +#, no-wrap +msgid "Getters" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "The following getters are available to retrieve message data:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getCharset()` - Returns the charset of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getFrom()` - Returns the message sender email address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getTo()` - Returns the message recipient(s) email address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getReplyTo()` - Returns the reply-to address of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`getCc()` - Returns the Cc (extra copy receiver) addresses of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`getBcc()` - Returns the Bcc (hidden copy receiver) addresses of this " +"message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getSubject()` - Returns the message subject." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`getDate()` - Returns the date when the message was sent, or null if it " +"wasn't set." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getPriority()` - Returns the priority of this message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`getReturnPath()` - Returns the return-path (the bounce address) of this " +"message." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getSender()` - Returns the message actual sender email address." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getHtmlBody()` - Returns the message HTML body." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getTextBody()` - Returns the message text body." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`getHeader()` - Returns all values for the specified header." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "`__toString()` - Returns string representation of this message." +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Attaching Files" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "You can attach files to your message using the `withAttached()` method:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"use Yiisoft\\Mailer\\File;\n" +"\n" +"// Attach a file from the local file system\n" +"$message = $message->withAttached(\n" +" File::fromPath('/path/to/source/file.pdf'),\n" +");\n" +"\n" +"// Create an attachment on-the-fly\n" +"$message = $message->withAttached(\n" +" File::fromContent('Attachment content', 'attach.txt', 'text/plain'),\n" +");\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Embedding Images" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"You can embed images into the message content using the `withEmbedded()` " +"method. This is particularly useful when composing messages with views:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"$logo = 'path/to/logo';\n" +"$htmlBody = $this->view->render(\n" +" __DIR__ . 'template.php',\n" +" [\n" +" 'content' => $content,\n" +" 'logoCid' => $logo->cid(),\n" +" ],\n" +");\n" +"return new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Message subject',\n" +" htmlBody: $htmlBody,\n" +" embeddings: $logo\n" +" );\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"In your view or layout template, you can reference the embedded image using " +"its CID:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "\">\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Sending a Message" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "To send an email message:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"/**\n" +" * @var \\Yiisoft\\View\\View $view\n" +" */\n" +"\n" +"$content = $view->render('path/to/view.php', [\n" +" 'name' => 'name',\n" +" 'code' => 'code',\n" +"]);\n" +"\n" +"$message = new \\Yiisoft\\Mailer\\Message(\n" +" from: 'from@domain.com',\n" +" to: 'to@domain.com',\n" +" subject: 'Subject',\n" +" htmlBody: $content\n" +");\n" +"\n" +"$mailer->send($message);\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Sending Multiple Messages" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "You can send multiple messages at once:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"$messages = [];\n" +"\n" +"foreach ($users as $user) {\n" +" $messages[] = (new \\Yiisoft\\Mailer\\Message())\n" +" // ...\n" +" ->withTo($user->email);\n" +"}\n" +"\n" +"$result = $mailer->sendMultiple($messages);\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"The `sendMultiple()` method returns a `Yiisoft\\Mailer\\SendResults` object " +"containing arrays of successfully sent and failed messages." +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "Implementing your own mail driver" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"To create a custom mail solution, implement the " +"`Yiisoft\\Mailer\\MailerInterface` and `Yiisoft\\Mailer\\MessageInterface` " +"interfaces." +msgstr "" + +#. type: Title ## +#: en/tutorial/mailing.md +#, no-wrap +msgid "For Development" +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"For local or test development, you can use simplified implementations of the " +"mailer that does not send emails. The package provides these " +"implementations:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`Yiisoft\\Mailer\\StubMailer` - A simple mailer that stores messages in a " +"local array." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`Yiisoft\\Mailer\\FileMailer` - A mock mailer that saves email messages as " +"files instead of sending them." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/mailing.md +msgid "" +"`Yiisoft\\Mailer\\NullMailer` - A mailer that discards messages without " +"sending or storing them." +msgstr "" + +#. type: Plain text +#: en/tutorial/mailing.md +msgid "" +"To use one of these mailers, configure it in your development environment " +"file Example: `environments/local/di.php`" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/mailing.md +#, no-wrap +msgid "" +"return [\n" +" Yiisoft\\Mailer\\MailerInterface::class => Yiisoft\\Mailer\\StubMailer::class, //or any other\n" +"];\n" +"\n" +msgstr "" diff --git a/guide/po/tutorial_performance-tuning.md/ru/tutorial_performance-tuning.md.ru.po b/guide/po/tutorial_performance-tuning.md/ru/tutorial_performance-tuning.md.ru.po new file mode 100644 index 00000000..b773f66f --- /dev/null +++ b/guide/po/tutorial_performance-tuning.md/ru/tutorial_performance-tuning.md.ru.po @@ -0,0 +1,326 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Performance tuning" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "There are many factors affecting the performance of your application. Some are environmental, some are related to your code, while some others are related to Yii itself. In this section, we will count most of these factors and explain how you can improve your application performance by adjusting these factors." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Optimizing your PHP Environment " +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "A well-configured PHP environment is important. To get maximum performance:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "Use the latest stable PHP version. Major releases of PHP may bring significant performance improvements." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "Enable bytecode caching with [Opcache](https://secure.php.net/opcache). Bytecode caching avoids the time spent in parsing and including PHP scripts for every incoming request." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "[Tune `realpath()` cache](https://github.com/samdark/realpath_cache_tuner)." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "Make sure [XDebug](https://xdebug.org/) isn't installed in the production environment." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "Try [PHP 7 preloading](https://wiki.php.net/rfc/preload)." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, fuzzy, no-wrap +#| msgid "Injecting dependencies " +msgid "Using caching techniques " +msgstr "Внедрение зависимостей " + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "You can use various caching techniques to significantly improve the performance of your application. For example, if your application allows users to enter text in Markdown format, you may consider caching the parsed Markdown content to avoid parsing the same Markdown text repeatedly in every request. Please refer to the [Caching](../caching/overview.md) section to learn about the caching support provided by Yii." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, fuzzy, no-wrap +#| msgid "Configuring container " +msgid "Optimizing session storage " +msgstr "Конфигурирование контейнера " + +#. type: Plain text +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "" +"By default, session data is stored in files. The implementation is locking a file from opening a session to the point it's\n" +"closed either by `$session->close()` or at the end of request.\n" +"While the session file is locked, all other requests that are trying to use the same session are blocked. That's waiting for the\n" +"initial request to release a session file. This is fine for development and probably small projects. But when it comes \n" +"to handling massive concurrent requests, it's better to use more sophisticated storage, such as Redis.\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "It could be done either by [configuring PHP via php.ini](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-redis-server-as-a-session-handler-for-php-on-ubuntu-14-04) or [implementing SessionHandlerInterface](https://www.sitepoint.com/saving-php-sessions-in-redis/) and configuring session service as follows:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/performance-tuning.md +#, fuzzy, no-wrap +#| msgid "" +#| "return [\n" +#| " MyServiceInterface::class => [\n" +#| " 'class' => MyService::class,\n" +#| " '__construct()' => [42],\n" +#| " 'setDiscount()' => [10],\n" +#| " ],\n" +#| "];\n" +msgid "" +"\\Yiisoft\\Session\\SessionInterface::class => [\n" +" 'class' => \\Yiisoft\\Session\\Session::class,\n" +" '__construct()' => [[], $myCustomSessionHandler],\n" +"],\n" +msgstr "" +"return [\n" +" MyServiceInterface::class => [\n" +" 'class' => MyService::class,\n" +" '__construct()' => [42],\n" +" 'setDiscount()' => [10],\n" +" ],\n" +"];\n" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, fuzzy, no-wrap +#| msgid "Defining aliases " +msgid "Optimizing databases " +msgstr "Определение псевдонимов " + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "Executing DB queries and fetching data from databases are often the main performance bottleneck in a Web application. Although using [data caching](../caching/data.md) techniques may ease the performance hit, it doesn't fully solve the problem. When the database has enormous amounts of data and the cached data are invalid, fetching the latest data could be prohibitively expensive without a proper database and query design." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "A general technique to improve the performance of DB queries is to create indices for table columns that need to be filtered by. For example, if you need to look for a user record by `username`, you should create an index on `username`. Note that while indexing can make SELECT queries much faster, it will slow down INSERT, UPDATE and DELETE queries." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "For complex DB queries, it's recommended that you create database views to save the query parsing and preparation time." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "Last but not least, use `LIMIT` in your `SELECT` queries. This avoids fetching an overwhelming amount of data from the database and exhausting the memory allocated to PHP." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, fuzzy, no-wrap +#| msgid "Defining aliases " +msgid "Optimizing composer autoloader " +msgstr "Определение псевдонимов " + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "Because Composer autoloader is used to include most third-party class files, you should consider optimizing it by executing the following command:" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "composer dumpautoload -o\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "Additionally, you may consider using [authoritative class maps](https://getcomposer.org/doc/articles/autoloader-optimization.md#optimization-level-2-a-authoritative-class-maps) and [APCu cache](https://getcomposer.org/doc/articles/autoloader-optimization.md#optimization-level-2-b-apcu-cache). Note that both optimizations may or may not be suitable for your particular case." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, fuzzy, no-wrap +#| msgid "Resolving aliases " +msgid "Processing data offline " +msgstr "Разрешение псевдонимов " + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "When a request involves some resource-intensive operations, you should think of ways to perform those operations in offline mode without having users wait for them to finish." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "There are two methods to process data offline: pull and push." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "In the pull method, whenever a request involves some complex operation, you create a task and save it in a persistent storage, such as a database. You then use a separate process (such as a cron job) to pull the tasks and process them. This method is straightforward to implement, but it has some drawbacks. For example, the task process needs to periodically pull from the task storage. If the pull frequency is too low, the tasks may be processed with great delay, but if the frequency is too high, it will introduce high overhead." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "In the push method, you would use a message queue (e.g., RabbitMQ, ActiveMQ, Amazon SQS, etc.) to manage the tasks. Whenever a new task is put in the queue, it will initiate or notify the task handling process to trigger the task processing." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Using preloading" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "As of PHP 7.4.0, PHP can be configured to preload scripts into the opcache when the engine starts. You can read more in the [documentation](https://www.php.net/manual/en/opcache.preloading.php) and the corresponding [RFC](https://wiki.php.net/rfc/preload)." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "Note that the optimal tradeoff between performance and memory may vary with the application. \"Preload everything\" may be the easiest strategy, but not necessarily the best strategy." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "For example, we conducted a simple [yiisoft/app](https://github.com/yiisoft/app) application template benchmark. Without preloading and with preloading of the entire composer class map." +msgstr "" + +#. type: Title ### +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Preloading benchmarks" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "The application template benchmark includes configuring classes to injected dependencies in the bootstrap script." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "For both variants, [ApacheBench](https://httpd.apache.org/docs/2.4/programs/ab.html) was used with the following run parameters:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "ab -n 1000 -c 10 -t 10\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "Also, the debug mode was disabled. And an optimized autoloader of the [Composer](https://getcomposer.org) was used and development dependencies weren't used:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "composer install --optimize-autoloader --no-dev\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "With preloading enabled, the entire composer class map (825 files) was used:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "" +"$files = require 'vendor/composer/autoload_classmap.php';\n" +"\n" +"foreach (array_unique($files) as $file) {\n" +" opcache_compile_file($file);\n" +"}\n" +msgstr "" + +#. type: Title #### +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Test results" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "" +"| Benchmark | Preloaded files | Opcache memory used | Per request memory used | Time per request | Requests per second |\n" +"|--------------------|-----------------|---------------------|-------------------------|------------------|---------------------|\n" +"| Without preloading | 0 | 12.32 mb | 1.71 mb | 27.63 ms | 36.55 rq/s |\n" +"| With preloading | 825 | 17.86 mb | 1.82 mb | 26.21 ms | 38.42 rq/s |\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "As you can see, the test results aren't much different, since this is just a clean application template that contains a few classes. More discussion of preloading, including benchmarks, can be found in the [composer's issue](https://github.com/composer/composer/issues/7777)." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, fuzzy, no-wrap +#| msgid "References " +msgid "Performance profiling " +msgstr "Полезные ссылки " + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "You should profile your code to find out the performance bottlenecks and take appropriate measures accordingly. The following profiling tools may be useful:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "[Yii debug toolbar and debugger](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide/README.md)" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "[Blackfire](https://blackfire.io/)" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +#, fuzzy +#| msgid "[PHP manual: security](https://www.php.net/manual/en/security.php)" +msgid "[XHProf](https://secure.php.net/manual/en/book.xhprof.php)" +msgstr "[Руководство по PHP: безопасность](https://www.php.net/manual/en/security.php)" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "[XDebug profiler](https://xdebug.org/docs/profiler)" +msgstr "" diff --git a/guide/po/tutorial_performance-tuning.md/tutorial_performance-tuning.md.pot b/guide/po/tutorial_performance-tuning.md/tutorial_performance-tuning.md.pot new file mode 100644 index 00000000..5e27f538 --- /dev/null +++ b/guide/po/tutorial_performance-tuning.md/tutorial_performance-tuning.md.pot @@ -0,0 +1,394 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Performance tuning" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"There are many factors affecting the performance of your application. Some " +"are environmental, some are related to your code, while some others are " +"related to Yii itself. In this section, we will count most of these factors " +"and explain how you can improve your application performance by adjusting " +"these factors." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Optimizing your PHP Environment " +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"A well-configured PHP environment is important. To get maximum performance:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "" +"Use the latest stable PHP version. Major releases of PHP may bring " +"significant performance improvements." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "" +"Enable bytecode caching with [Opcache](https://secure.php.net/opcache). " +"Bytecode caching avoids the time spent in parsing and including PHP scripts " +"for every incoming request." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "" +"[Tune `realpath()` cache](https://github.com/samdark/realpath_cache_tuner)." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "" +"Make sure [XDebug](https://xdebug.org/) isn't installed in the production " +"environment." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "Try [PHP 7 preloading](https://wiki.php.net/rfc/preload)." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Using caching techniques " +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"You can use various caching techniques to significantly improve the " +"performance of your application. For example, if your application allows " +"users to enter text in Markdown format, you may consider caching the parsed " +"Markdown content to avoid parsing the same Markdown text repeatedly in every " +"request. Please refer to the [Caching](../caching/overview.md) section to " +"learn about the caching support provided by Yii." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Optimizing session storage " +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "" +"By default, session data is stored in files. The implementation is locking a file from opening a session to the point it's\n" +"closed either by `$session->close()` or at the end of request.\n" +"While the session file is locked, all other requests that are trying to use the same session are blocked. That's waiting for the\n" +"initial request to release a session file. This is fine for development and probably small projects. But when it comes \n" +"to handling massive concurrent requests, it's better to use more sophisticated storage, such as Redis.\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"It could be done either by [configuring PHP via php.ini](https://www." +"digitalocean.com/community/tutorials/how-to-set-up-a-redis-server-as-a-" +"session-handler-for-php-on-ubuntu-14-04) or [implementing " +"SessionHandlerInterface](https://www.sitepoint.com/saving-php-sessions-in-" +"redis/) and configuring session service as follows:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "" +"\\Yiisoft\\Session\\SessionInterface::class => [\n" +" 'class' => \\Yiisoft\\Session\\Session::class,\n" +" '__construct()' => [[], $myCustomSessionHandler],\n" +"],\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Optimizing databases " +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"Executing DB queries and fetching data from databases are often the main " +"performance bottleneck in a Web application. Although using [data caching]" +"(../caching/data.md) techniques may ease the performance hit, it doesn't " +"fully solve the problem. When the database has enormous amounts of data and " +"the cached data are invalid, fetching the latest data could be prohibitively " +"expensive without a proper database and query design." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"A general technique to improve the performance of DB queries is to create " +"indices for table columns that need to be filtered by. For example, if you " +"need to look for a user record by `username`, you should create an index on " +"`username`. Note that while indexing can make SELECT queries much faster, it " +"will slow down INSERT, UPDATE and DELETE queries." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"For complex DB queries, it's recommended that you create database views to " +"save the query parsing and preparation time." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"Last but not least, use `LIMIT` in your `SELECT` queries. This avoids " +"fetching an overwhelming amount of data from the database and exhausting the " +"memory allocated to PHP." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Optimizing composer autoloader " +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"Because Composer autoloader is used to include most third-party class files, " +"you should consider optimizing it by executing the following command:" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "composer dumpautoload -o\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"Additionally, you may consider using [authoritative class maps](https://" +"getcomposer.org/doc/articles/autoloader-optimization.md#optimization-level-2-" +"a-authoritative-class-maps) and [APCu cache](https://getcomposer.org/doc/" +"articles/autoloader-optimization.md#optimization-level-2-b-apcu-cache). " +"Note that both optimizations may or may not be suitable for your particular " +"case." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Processing data offline " +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"When a request involves some resource-intensive operations, you should think " +"of ways to perform those operations in offline mode without having users " +"wait for them to finish." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "There are two methods to process data offline: pull and push." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"In the pull method, whenever a request involves some complex operation, you " +"create a task and save it in a persistent storage, such as a database. You " +"then use a separate process (such as a cron job) to pull the tasks and " +"process them. This method is straightforward to implement, but it has some " +"drawbacks. For example, the task process needs to periodically pull from the " +"task storage. If the pull frequency is too low, the tasks may be processed " +"with great delay, but if the frequency is too high, it will introduce high " +"overhead." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"In the push method, you would use a message queue (e.g., RabbitMQ, ActiveMQ, " +"Amazon SQS, etc.) to manage the tasks. Whenever a new task is put in the " +"queue, it will initiate or notify the task handling process to trigger the " +"task processing." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Using preloading" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"As of PHP 7.4.0, PHP can be configured to preload scripts into the opcache " +"when the engine starts. You can read more in the [documentation](https://" +"www.php.net/manual/en/opcache.preloading.php) and the corresponding [RFC]" +"(https://wiki.php.net/rfc/preload)." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"Note that the optimal tradeoff between performance and memory may vary with " +"the application. \"Preload everything\" may be the easiest strategy, but not " +"necessarily the best strategy." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"For example, we conducted a simple [yiisoft/app](https://github.com/yiisoft/" +"app) application template benchmark. Without preloading and with preloading " +"of the entire composer class map." +msgstr "" + +#. type: Title ### +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Preloading benchmarks" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"The application template benchmark includes configuring classes to injected " +"dependencies in the bootstrap script." +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"For both variants, [ApacheBench](https://httpd.apache.org/docs/2.4/programs/" +"ab.html) was used with the following run parameters:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "ab -n 1000 -c 10 -t 10\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"Also, the debug mode was disabled. And an optimized autoloader of the " +"[Composer](https://getcomposer.org) was used and development dependencies " +"weren't used:" +msgstr "" + +#. type: Fenced code block (shell) +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "composer install --optimize-autoloader --no-dev\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"With preloading enabled, the entire composer class map (825 files) was used:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "" +"$files = require 'vendor/composer/autoload_classmap.php';\n" +"\n" +"foreach (array_unique($files) as $file) {\n" +" opcache_compile_file($file);\n" +"}\n" +msgstr "" + +#. type: Title #### +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Test results" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "" +"| Benchmark | Preloaded files | Opcache memory used | Per request memory used | Time per request | Requests per second |\n" +"|--------------------|-----------------|---------------------|-------------------------|------------------|---------------------|\n" +"| Without preloading | 0 | 12.32 mb | 1.71 mb | 27.63 ms | 36.55 rq/s |\n" +"| With preloading | 825 | 17.86 mb | 1.82 mb | 26.21 ms | 38.42 rq/s |\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"As you can see, the test results aren't much different, since this is just a " +"clean application template that contains a few classes. More discussion of " +"preloading, including benchmarks, can be found in the [composer's issue]" +"(https://github.com/composer/composer/issues/7777)." +msgstr "" + +#. type: Title ## +#: en/tutorial/performance-tuning.md +#, no-wrap +msgid "Performance profiling " +msgstr "" + +#. type: Plain text +#: en/tutorial/performance-tuning.md +msgid "" +"You should profile your code to find out the performance bottlenecks and " +"take appropriate measures accordingly. The following profiling tools may be " +"useful:" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "" +"[Yii debug toolbar and debugger](https://github.com/yiisoft/yii2-debug/blob/" +"master/docs/guide/README.md)" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "[Blackfire](https://blackfire.io/)" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "[XHProf](https://secure.php.net/manual/en/book.xhprof.php)" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/performance-tuning.md +msgid "[XDebug profiler](https://xdebug.org/docs/profiler)" +msgstr "" diff --git a/guide/po/tutorial_using-with-event-loop.md/ru/tutorial_using-with-event-loop.md.ru.po b/guide/po/tutorial_using-with-event-loop.md/ru/tutorial_using-with-event-loop.md.ru.po new file mode 100644 index 00000000..d2aebd19 --- /dev/null +++ b/guide/po/tutorial_using-with-event-loop.md/ru/tutorial_using-with-event-loop.md.ru.po @@ -0,0 +1,132 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title # +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "Using Yii with event loop" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "" +"A normal PHP web request execution cycle consists of setting up an environment, getting a request, processing it to form a response\n" +"and sending the result. After the response is sent, execution is terminated and its context is lost. So, for the further \n" +" request, the whole sequence is repeated. Such an approach has a big advantage in ease of development since a developer doesn't\n" +"have to take much care about memory leaks or properly clean up context. On the other side, initializing everything for\n" +"every request takes time and overall consumes up to 50% of processing resources.\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "There is an alternative way of running an application. Event loop. The idea is to initialize everything possible at once and then process a number of requests using it. Such an approach is usually called event loop." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "There are multiple tools that could be used to achieve it. Notably, [FrankenPHP](https://frankenphp.dev/), [RoadRunner](https://roadrunner.dev/) and [Swoole](https://www.swoole.co.uk/)." +msgstr "" + +#. type: Title ## +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "Event loop implications" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "Event loop worker basically looks like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "" +"initializeContext();\n" +"while ($request = getRequest()) {\n" +" $response = process($request);\n" +" emit($response);\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "Usually, there are multiple workers processing requests at the same time as with traditional php-fpm." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "That means that there's more to consider when developing applications." +msgstr "" + +#. type: Title ### +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "Processing is blocking" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "Worker process requests one by one that's current processing is blocking processing next request. That means that long-running processes, same as in general PHP applications, should be put into a background via using a queue." +msgstr "" + +#. type: Title ### +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "Services and state" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "Since the context in the event loop is shared between all request-responses processed by a single worker, all changes in the state of a service made by the previous request may affect the current request. Moreover, it can be a security problem if data from one user is available to another user." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "There are two ways of dealing with it. First, you can avoid having state by making services stateless. PHP's `readonly` keyword may be handy for it. Second, you can reset services state at the end of the request processing. In this case, a state resetter will help you:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "" +"initializeContext();\n" +"$resetter = $container->get(\\Yiisoft\\Di\\StateResetter::class);\n" +"while ($request = getRequest()) {\n" +" $response = process($request);\n" +" emit($response);\n" +" $resetter->reset(); // We should reset the state of such services on every request.\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "Integrations" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/using-with-event-loop.md +msgid "[RoadRunner](using-yii-with-roadrunner.md)" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/using-with-event-loop.md +msgid "[Swoole](using-yii-with-swoole.md)" +msgstr "" diff --git a/guide/po/tutorial_using-with-event-loop.md/tutorial_using-with-event-loop.md.pot b/guide/po/tutorial_using-with-event-loop.md/tutorial_using-with-event-loop.md.pot new file mode 100644 index 00000000..2b6bddc8 --- /dev/null +++ b/guide/po/tutorial_using-with-event-loop.md/tutorial_using-with-event-loop.md.pot @@ -0,0 +1,151 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title # +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "Using Yii with event loop" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "" +"A normal PHP web request execution cycle consists of setting up an environment, getting a request, processing it to form a response\n" +"and sending the result. After the response is sent, execution is terminated and its context is lost. So, for the further \n" +" request, the whole sequence is repeated. Such an approach has a big advantage in ease of development since a developer doesn't\n" +"have to take much care about memory leaks or properly clean up context. On the other side, initializing everything for\n" +"every request takes time and overall consumes up to 50% of processing resources.\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "" +"There is an alternative way of running an application. Event loop. The idea " +"is to initialize everything possible at once and then process a number of " +"requests using it. Such an approach is usually called event loop." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "" +"There are multiple tools that could be used to achieve it. Notably, " +"[FrankenPHP](https://frankenphp.dev/), [RoadRunner](https://roadrunner.dev/) " +"and [Swoole](https://www.swoole.co.uk/)." +msgstr "" + +#. type: Title ## +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "Event loop implications" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "Event loop worker basically looks like the following:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "" +"initializeContext();\n" +"while ($request = getRequest()) {\n" +" $response = process($request);\n" +" emit($response);\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "" +"Usually, there are multiple workers processing requests at the same time as " +"with traditional php-fpm." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "That means that there's more to consider when developing applications." +msgstr "" + +#. type: Title ### +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "Processing is blocking" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "" +"Worker process requests one by one that's current processing is blocking " +"processing next request. That means that long-running processes, same as in " +"general PHP applications, should be put into a background via using a queue." +msgstr "" + +#. type: Title ### +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "Services and state" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "" +"Since the context in the event loop is shared between all request-responses " +"processed by a single worker, all changes in the state of a service made by " +"the previous request may affect the current request. Moreover, it can be a " +"security problem if data from one user is available to another user." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-with-event-loop.md +msgid "" +"There are two ways of dealing with it. First, you can avoid having state by " +"making services stateless. PHP's `readonly` keyword may be handy for it. " +"Second, you can reset services state at the end of the request processing. " +"In this case, a state resetter will help you:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "" +"initializeContext();\n" +"$resetter = $container->get(\\Yiisoft\\Di\\StateResetter::class);\n" +"while ($request = getRequest()) {\n" +" $response = process($request);\n" +" emit($response);\n" +" $resetter->reset(); // We should reset the state of such services on every request.\n" +"}\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-with-event-loop.md +#, no-wrap +msgid "Integrations" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/using-with-event-loop.md +msgid "[RoadRunner](using-yii-with-roadrunner.md)" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/using-with-event-loop.md +msgid "[Swoole](using-yii-with-swoole.md)" +msgstr "" diff --git a/guide/po/tutorial_using-yii-with-roadrunner.md/ru/tutorial_using-yii-with-roadrunner.md.ru.po b/guide/po/tutorial_using-yii-with-roadrunner.md/ru/tutorial_using-yii-with-roadrunner.md.ru.po new file mode 100644 index 00000000..3003d389 --- /dev/null +++ b/guide/po/tutorial_using-yii-with-roadrunner.md/ru/tutorial_using-yii-with-roadrunner.md.ru.po @@ -0,0 +1,183 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title ## +#: en/concept/configuration.md en/tutorial/using-yii-with-roadrunner.md +#: en/views/view-injections.md +#, fuzzy, no-wrap +msgid "Configuration" +msgstr "конфигурация может быть:" + +#. type: Title # +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "Using Yii with RoadRunner" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "" +"[RoadRunner](https://roadrunner.dev/) is a Golang-powered application server that integrates well with PHP. It runs\n" +"it as workers and each worker may handle multiple requests. Such an operation mode is often called\n" +"[event loop](using-with-event-loop.md) and allows not re-initializing a framework for each request that improves\n" +"performance significantly.\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Installation" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "RoadRunner works on Linux, macOS and Windows. The best way to install it is to use a Composer:" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "composer require yiisoft/yii-runner-roadrunner\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "After installation is done, run" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "./vendor/bin/rr get\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "That would download ready to use RoadRunner server `rr` binary." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "First, we need to configure the server itself. Create `/.rr.yaml` and add the following config:" +msgstr "" + +#. type: Fenced code block (yaml) +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "" +"server:\n" +" command: \"php worker.php\"\n" +"\n" +"rpc:\n" +" listen: tcp://127.0.0.1:6001\n" +"\n" +"http:\n" +" address: :8080\n" +" pool:\n" +" num_workers: 4\n" +" max_jobs: 64\n" +" middleware: [\"static\", \"headers\"]\n" +" static:\n" +" dir: \"public\"\n" +" forbid: [\".php\", \".htaccess\"]\n" +" headers:\n" +" response:\n" +" \"Cache-Control\": \"no-cache\"\n" +"\n" +"reload:\n" +" interval: 1s\n" +" patterns: [ \".php\" ]\n" +" services:\n" +" http:\n" +" recursive: true\n" +" dirs: [ \".\" ]\n" +"\n" +"logs:\n" +" mode: production\n" +" level: warn\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "We're specifying that entry script is `worker.php`, there should be three workers on port 8080, `public` directory files are static ones except `.php` and `.htaccess`. Also, we're sending an additional header." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "Create `/worker.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "" +"run();\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Starting a server" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +msgid "To start a server, execute the following command:" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "./rr serve -d\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "On worker scope" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/using-yii-with-roadrunner.md +msgid "Each worker's scope is isolated from other workers. Memory isn't shared." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/using-yii-with-roadrunner.md +msgid "A single worker serves multiple requests where the scope is shared." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/using-yii-with-roadrunner.md +msgid "At each iteration of the event loop, every service that depends on state should be reset." +msgstr "" diff --git a/guide/po/tutorial_using-yii-with-roadrunner.md/tutorial_using-yii-with-roadrunner.md.pot b/guide/po/tutorial_using-yii-with-roadrunner.md/tutorial_using-yii-with-roadrunner.md.pot new file mode 100644 index 00000000..c5c79fd8 --- /dev/null +++ b/guide/po/tutorial_using-yii-with-roadrunner.md/tutorial_using-yii-with-roadrunner.md.pot @@ -0,0 +1,193 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title ## +#: en/concept/configuration.md en/tutorial/using-yii-with-roadrunner.md +#: en/views/view-injections.md +#, no-wrap +msgid "Configuration" +msgstr "" + +#. type: Title # +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "Using Yii with RoadRunner" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "" +"[RoadRunner](https://roadrunner.dev/) is a Golang-powered application server that integrates well with PHP. It runs\n" +"it as workers and each worker may handle multiple requests. Such an operation mode is often called\n" +"[event loop](using-with-event-loop.md) and allows not re-initializing a framework for each request that improves\n" +"performance significantly.\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Installation" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "" +"RoadRunner works on Linux, macOS and Windows. The best way to install it is " +"to use a Composer:" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "composer require yiisoft/yii-runner-roadrunner\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "After installation is done, run" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "./vendor/bin/rr get\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "That would download ready to use RoadRunner server `rr` binary." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "" +"First, we need to configure the server itself. Create `/.rr.yaml` and add " +"the following config:" +msgstr "" + +#. type: Fenced code block (yaml) +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "" +"server:\n" +" command: \"php worker.php\"\n" +"\n" +"rpc:\n" +" listen: tcp://127.0.0.1:6001\n" +"\n" +"http:\n" +" address: :8080\n" +" pool:\n" +" num_workers: 4\n" +" max_jobs: 64\n" +" middleware: [\"static\", \"headers\"]\n" +" static:\n" +" dir: \"public\"\n" +" forbid: [\".php\", \".htaccess\"]\n" +" headers:\n" +" response:\n" +" \"Cache-Control\": \"no-cache\"\n" +"\n" +"reload:\n" +" interval: 1s\n" +" patterns: [ \".php\" ]\n" +" services:\n" +" http:\n" +" recursive: true\n" +" dirs: [ \".\" ]\n" +"\n" +"logs:\n" +" mode: production\n" +" level: warn\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "" +"We're specifying that entry script is `worker.php`, there should be three " +"workers on port 8080, `public` directory files are static ones except `.php` " +"and `.htaccess`. Also, we're sending an additional header." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +msgid "Create `/worker.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "" +"run();\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Starting a server" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +msgid "To start a server, execute the following command:" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "./rr serve -d\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-roadrunner.md +#, no-wrap +msgid "On worker scope" +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/using-yii-with-roadrunner.md +msgid "" +"Each worker's scope is isolated from other workers. Memory isn't shared." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/using-yii-with-roadrunner.md +msgid "A single worker serves multiple requests where the scope is shared." +msgstr "" + +#. type: Bullet: '- ' +#: en/tutorial/using-yii-with-roadrunner.md +msgid "" +"At each iteration of the event loop, every service that depends on state " +"should be reset." +msgstr "" diff --git a/guide/po/tutorial_using-yii-with-swoole.md/ru/tutorial_using-yii-with-swoole.md.ru.po b/guide/po/tutorial_using-yii-with-swoole.md/ru/tutorial_using-yii-with-swoole.md.ru.po new file mode 100644 index 00000000..733a911e --- /dev/null +++ b/guide/po/tutorial_using-yii-with-swoole.md/ru/tutorial_using-yii-with-swoole.md.ru.po @@ -0,0 +1,197 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title ## +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Installation" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Starting a server" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +msgid "To start a server, execute the following command:" +msgstr "" + +#. type: Title # +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Using Yii with Swoole" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "" +"[Swoole](https://www.swoole.co.uk/) is a PHP network framework distributed as a PECL extension. It allows you built-in async,\n" +"multiple threads I/O modules. Developers can use sync or async, coroutine API to write the applications.\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +msgid "In the context of Yii, it allows running request handlers as workers. Each worker may handle multiple requests. Such an operation mode is often called [event loop](using-with-event-loop.md) and allows not to re-initialize a framework for each request that improves performance significantly." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +msgid "Swoole works on Linux and macOS and can be installed via pecl:" +msgstr "" + +#. type: Fenced code block (bash) +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "pecl install swoole\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Putting up a server" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +msgid "Since Swoole doesn't have built-in PSR-7 support, you need a package fixing so:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "composer require ilexn/swoole-convent-psr7\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +msgid "Create an entry script, `server.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "" +"withDefinitions($config->get('web'))\n" +" ->withProviders($config->get('providers-web'));\n" +"$container = new Container($containerConfig);\n" +"\n" +"$bootstrapList = $config->get('bootstrap-web');\n" +"foreach ($bootstrapList as $callback) {\n" +" if (!(is_callable($callback))) {\n" +" $type = is_object($callback) ? get_class($callback) : gettype($callback);\n" +"\n" +" throw new \\RuntimeException(\"Bootstrap callback must be callable, $type given.\");\n" +" }\n" +" $callback($container);\n" +"}\n" +"\n" +"$application = $container->get(Application::class);\n" +"\n" +"$serverRequestFactory = new \\Ilex\\SwoolePsr7\\SwooleServerRequestConverter(\n" +" $container->get(ServerRequestFactoryInterface::class),\n" +" $container->get(UriFactoryInterface::class),\n" +" $container->get(UploadedFileFactoryInterface::class),\n" +" $container->get(StreamFactoryInterface::class)\n" +");\n" +"\n" +"$server = new Swoole\\HTTP\\Server('0.0.0.0', 9501);\n" +"\n" +"$server->on('start', static function (Swoole\\Http\\Server $server) use ($application) {\n" +" $application->start();\n" +" echo \"Swoole http server is started at http://127.0.0.1:9501\\n\";\n" +"});\n" +"\n" +"$server->on('request', static function (Swoole\\Http\\Request $request, Swoole\\Http\\Response $response) use ($serverRequestFactory, $application, $container) {\n" +" $psr7Response = null;\n" +" try {\n" +" $requestContainer = clone $container;\n" +" $psr7Request = $serverRequestFactory->createFromSwoole($request);\n" +" $psr7Response = $application->handle($psr7Request);\n" +" \n" +" $converter = new \\Ilex\\SwoolePsr7\\SwooleResponseConverter($response);\n" +" $converter->send($psr7Response);\n" +" } catch (\\Throwable $t) {\n" +" // TODO: render it properly\n" +" $response->end($t->getMessage());\n" +" } finally {\n" +" $application->afterEmit($psr7Response ?? null);\n" +" $container->get(\\Yiisoft\\Di\\StateResetter::class)->reset();\n" +" $container = $requestContainer; \n" +" }\n" +"});\n" +"\n" +"$server->on('shutdown', static function (Swoole\\Http\\Server $server) use ($application) {\n" +" $application->shutdown();\n" +"});\n" +"\n" +"$server->start();\n" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "php server.php\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "On scope" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +msgid "A scope is shared, so at each iteration of the event loop every service that depends on state should be reset." +msgstr "" diff --git a/guide/po/tutorial_using-yii-with-swoole.md/tutorial_using-yii-with-swoole.md.pot b/guide/po/tutorial_using-yii-with-swoole.md/tutorial_using-yii-with-swoole.md.pot new file mode 100644 index 00000000..1b2a4269 --- /dev/null +++ b/guide/po/tutorial_using-yii-with-swoole.md/tutorial_using-yii-with-swoole.md.pot @@ -0,0 +1,205 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title ## +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Installation" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Starting a server" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-roadrunner.md +#: en/tutorial/using-yii-with-swoole.md +msgid "To start a server, execute the following command:" +msgstr "" + +#. type: Title # +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Using Yii with Swoole" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "" +"[Swoole](https://www.swoole.co.uk/) is a PHP network framework distributed as a PECL extension. It allows you built-in async,\n" +"multiple threads I/O modules. Developers can use sync or async, coroutine API to write the applications.\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +msgid "" +"In the context of Yii, it allows running request handlers as workers. Each " +"worker may handle multiple requests. Such an operation mode is often called " +"[event loop](using-with-event-loop.md) and allows not to re-initialize a " +"framework for each request that improves performance significantly." +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +msgid "Swoole works on Linux and macOS and can be installed via pecl:" +msgstr "" + +#. type: Fenced code block (bash) +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "pecl install swoole\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "Putting up a server" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +msgid "" +"Since Swoole doesn't have built-in PSR-7 support, you need a package fixing " +"so:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "composer require ilexn/swoole-convent-psr7\n" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +msgid "Create an entry script, `server.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "" +"withDefinitions($config->get('web'))\n" +" ->withProviders($config->get('providers-web'));\n" +"$container = new Container($containerConfig);\n" +"\n" +"$bootstrapList = $config->get('bootstrap-web');\n" +"foreach ($bootstrapList as $callback) {\n" +" if (!(is_callable($callback))) {\n" +" $type = is_object($callback) ? get_class($callback) : gettype($callback);\n" +"\n" +" throw new \\RuntimeException(\"Bootstrap callback must be callable, $type given.\");\n" +" }\n" +" $callback($container);\n" +"}\n" +"\n" +"$application = $container->get(Application::class);\n" +"\n" +"$serverRequestFactory = new \\Ilex\\SwoolePsr7\\SwooleServerRequestConverter(\n" +" $container->get(ServerRequestFactoryInterface::class),\n" +" $container->get(UriFactoryInterface::class),\n" +" $container->get(UploadedFileFactoryInterface::class),\n" +" $container->get(StreamFactoryInterface::class)\n" +");\n" +"\n" +"$server = new Swoole\\HTTP\\Server('0.0.0.0', 9501);\n" +"\n" +"$server->on('start', static function (Swoole\\Http\\Server $server) use ($application) {\n" +" $application->start();\n" +" echo \"Swoole http server is started at http://127.0.0.1:9501\\n\";\n" +"});\n" +"\n" +"$server->on('request', static function (Swoole\\Http\\Request $request, Swoole\\Http\\Response $response) use ($serverRequestFactory, $application, $container) {\n" +" $psr7Response = null;\n" +" try {\n" +" $requestContainer = clone $container;\n" +" $psr7Request = $serverRequestFactory->createFromSwoole($request);\n" +" $psr7Response = $application->handle($psr7Request);\n" +" \n" +" $converter = new \\Ilex\\SwoolePsr7\\SwooleResponseConverter($response);\n" +" $converter->send($psr7Response);\n" +" } catch (\\Throwable $t) {\n" +" // TODO: render it properly\n" +" $response->end($t->getMessage());\n" +" } finally {\n" +" $application->afterEmit($psr7Response ?? null);\n" +" $container->get(\\Yiisoft\\Di\\StateResetter::class)->reset();\n" +" $container = $requestContainer; \n" +" }\n" +"});\n" +"\n" +"$server->on('shutdown', static function (Swoole\\Http\\Server $server) use ($application) {\n" +" $application->shutdown();\n" +"});\n" +"\n" +"$server->start();\n" +msgstr "" + +#. type: Fenced code block +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "php server.php\n" +msgstr "" + +#. type: Title ## +#: en/tutorial/using-yii-with-swoole.md +#, no-wrap +msgid "On scope" +msgstr "" + +#. type: Plain text +#: en/tutorial/using-yii-with-swoole.md +msgid "" +"A scope is shared, so at each iteration of the event loop every service that " +"depends on state should be reset." +msgstr "" diff --git a/guide/po/views_view-injections.md/ru/views_view-injections.md.ru.po b/guide/po/views_view-injections.md/ru/views_view-injections.md.ru.po new file mode 100644 index 00000000..8684aa66 --- /dev/null +++ b/guide/po/views_view-injections.md/ru/views_view-injections.md.ru.po @@ -0,0 +1,191 @@ +# Russian translations for PACKAGE package +# Copyright (C) 2025 Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# Automatically generated, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: 2025-09-04 11:19+0500\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#. type: Title ## +#: en/concept/configuration.md en/tutorial/using-yii-with-roadrunner.md +#: en/views/view-injections.md +#, fuzzy, no-wrap +msgid "Configuration" +msgstr "конфигурация может быть:" + +#. type: Title # +#: en/views/view-injections.md +#, fuzzy, no-wrap +#| msgid "Avoiding SQL injections" +msgid "View injections" +msgstr "Как избежать SQL-инъекций" + +#. type: Plain text +#: en/views/view-injections.md +msgid "The view injections are designed to provide a standardized way to pass parameters to the common layer of views in an application. Implementing this interface allows developers to manage the data that will be available across various views, ensuring flexibility and reusability of code." +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "In config `params.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/views/view-injections.md +#, no-wrap +msgid "" +"...\n" +"'yiisoft/yii-view' => [\n" +" 'injections' => [\n" +" Reference::to(ContentViewInjection::class),\n" +" Reference::to(CsrfViewInjection::class),\n" +" Reference::to(LayoutViewInjection::class),\n" +" ],\n" +" ],\n" +msgstr "" + +#. type: Title ## +#: en/views/view-injections.md +#, no-wrap +msgid "New injections" +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "Start by defining a class that will implement the `Yiisoft\\Yii\\View\\Renderer\\CommonParametersInjectionInterface`. This class will be responsible for providing the parameters you want to inject into your view templates and layouts." +msgstr "" + +#. type: Fenced code block (php) +#: en/views/view-injections.md +#, no-wrap +msgid "" +"class MyCustomParametersInjection implements Yiisoft\\Yii\\View\\Renderer\\CommonParametersInjectionInterface\n" +"{\n" +" // Class properties and methods will go here\n" +"\n" +" public function __construct(UserService $userService)\n" +" {\n" +" $this->userService = $userService;\n" +" }\n" +"\n" +" public function getCommonParameters(): array\n" +" {\n" +" return [\n" +" 'siteName' => 'My Awesome Site',\n" +" 'currentYear' => date('Y'),\n" +" 'user' => $this->userService->getCurrentUser(),\n" +" ];\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "Add your new Injection to `params.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/views/view-injections.md +#, no-wrap +msgid "" +"'yiisoft/yii-view' => [\n" +" 'injections' => [\n" +" ...,\n" +" Reference::to(MyCustomParametersInjection::class),\n" +" ],\n" +" ],\n" +msgstr "" + +#. type: Title ## +#: en/views/view-injections.md +#, no-wrap +msgid "Using Separate Injections for Different Layouts" +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "If your application has multiple layouts, you can create separate parameter injections for each layout. This approach allows you to tailor the parameters injected into each layout according to its specific needs, enhancing the flexibility and maintainability of your application." +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "Create your custom ViewInjection for a specific layout:" +msgstr "" + +#. type: Fenced code block (php) +#: en/views/view-injections.md +#, fuzzy, no-wrap +#| msgid "" +#| "final class MyService implements MyServiceInterface\n" +#| "{\n" +#| " public function __construct(int $amount)\n" +#| " {\n" +#| " }\n" +#| "\n" +#| " public function setDiscount(int $discount): void\n" +#| " {\n" +#| " \n" +#| " }\n" +#| "}\n" +msgid "" +"readonly final class CartViewInjection implements CommonParametersInjectionInterface\n" +"{\n" +" public function __construct(private Cart $cart)\n" +" {\n" +" }\n" +"\n" +" public function getCommonParameters(): array\n" +" {\n" +" return [\n" +" 'cart' => $this->cart,\n" +" ];\n" +" }\n" +"}\n" +msgstr "" +"class MyService implements MyServiceInterface\n" +"{\n" +" public function __construct(int $amount)\n" +" {\n" +" }\n" +"\n" +" public function setDiscount(int $discount): void\n" +" {\n" +" \n" +" }\n" + +#. type: Plain text +#: en/views/view-injections.md +msgid "Add your new injection to `params.php` under specific layout name. In the following example, it is `@layout/cart`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/views/view-injections.md +#, no-wrap +msgid "" +"'yiisoft/yii-view' => [\n" +" 'injections' => [\n" +" ...,\n" +" Reference::to(MyCustomParametersInjection::class),\n" +" DynamicReference::to(static function (ContainerInterface $container) {\n" +" $cart = $container\n" +" ->get(Cart::class);\n" +"\n" +" return new LayoutSpecificInjections(\n" +" '@layout/cart', // layout name for injection\n" +"\n" +" new CartViewInjection($cart)\n" +" );\n" +" }),\n" +" ],\n" +" ],\n" +msgstr "" diff --git a/guide/po/views_view-injections.md/views_view-injections.md.pot b/guide/po/views_view-injections.md/views_view-injections.md.pot new file mode 100644 index 00000000..f9344fd4 --- /dev/null +++ b/guide/po/views_view-injections.md/views_view-injections.md.pot @@ -0,0 +1,182 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR Free Software Foundation, Inc. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-09-04 11:19+0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title ## +#: en/concept/configuration.md en/tutorial/using-yii-with-roadrunner.md +#: en/views/view-injections.md +#, no-wrap +msgid "Configuration" +msgstr "" + +#. type: Title # +#: en/views/view-injections.md +#, no-wrap +msgid "View injections" +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "" +"The view injections are designed to provide a standardized way to pass " +"parameters to the common layer of views in an application. Implementing this " +"interface allows developers to manage the data that will be available across " +"various views, ensuring flexibility and reusability of code." +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "In config `params.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/views/view-injections.md +#, no-wrap +msgid "" +"...\n" +"'yiisoft/yii-view' => [\n" +" 'injections' => [\n" +" Reference::to(ContentViewInjection::class),\n" +" Reference::to(CsrfViewInjection::class),\n" +" Reference::to(LayoutViewInjection::class),\n" +" ],\n" +" ],\n" +msgstr "" + +#. type: Title ## +#: en/views/view-injections.md +#, no-wrap +msgid "New injections" +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "" +"Start by defining a class that will implement the " +"`Yiisoft\\Yii\\View\\Renderer\\CommonParametersInjectionInterface`. This " +"class will be responsible for providing the parameters you want to inject " +"into your view templates and layouts." +msgstr "" + +#. type: Fenced code block (php) +#: en/views/view-injections.md +#, no-wrap +msgid "" +"class MyCustomParametersInjection implements Yiisoft\\Yii\\View\\Renderer\\CommonParametersInjectionInterface\n" +"{\n" +" // Class properties and methods will go here\n" +"\n" +" public function __construct(UserService $userService)\n" +" {\n" +" $this->userService = $userService;\n" +" }\n" +"\n" +" public function getCommonParameters(): array\n" +" {\n" +" return [\n" +" 'siteName' => 'My Awesome Site',\n" +" 'currentYear' => date('Y'),\n" +" 'user' => $this->userService->getCurrentUser(),\n" +" ];\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "Add your new Injection to `params.php`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/views/view-injections.md +#, no-wrap +msgid "" +"'yiisoft/yii-view' => [\n" +" 'injections' => [\n" +" ...,\n" +" Reference::to(MyCustomParametersInjection::class),\n" +" ],\n" +" ],\n" +msgstr "" + +#. type: Title ## +#: en/views/view-injections.md +#, no-wrap +msgid "Using Separate Injections for Different Layouts" +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "" +"If your application has multiple layouts, you can create separate parameter " +"injections for each layout. This approach allows you to tailor the " +"parameters injected into each layout according to its specific needs, " +"enhancing the flexibility and maintainability of your application." +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "Create your custom ViewInjection for a specific layout:" +msgstr "" + +#. type: Fenced code block (php) +#: en/views/view-injections.md +#, no-wrap +msgid "" +"readonly final class CartViewInjection implements CommonParametersInjectionInterface\n" +"{\n" +" public function __construct(private Cart $cart)\n" +" {\n" +" }\n" +"\n" +" public function getCommonParameters(): array\n" +" {\n" +" return [\n" +" 'cart' => $this->cart,\n" +" ];\n" +" }\n" +"}\n" +msgstr "" + +#. type: Plain text +#: en/views/view-injections.md +msgid "" +"Add your new injection to `params.php` under specific layout name. In the " +"following example, it is `@layout/cart`:" +msgstr "" + +#. type: Fenced code block (php) +#: en/views/view-injections.md +#, no-wrap +msgid "" +"'yiisoft/yii-view' => [\n" +" 'injections' => [\n" +" ...,\n" +" Reference::to(MyCustomParametersInjection::class),\n" +" DynamicReference::to(static function (ContainerInterface $container) {\n" +" $cart = $container\n" +" ->get(Cart::class);\n" +"\n" +" return new LayoutSpecificInjections(\n" +" '@layout/cart', // layout name for injection\n" +"\n" +" new CartViewInjection($cart)\n" +" );\n" +" }),\n" +" ],\n" +" ],\n" +msgstr "" diff --git a/guide/po4a.cfg b/guide/po4a.cfg new file mode 100644 index 00000000..a23a33ea --- /dev/null +++ b/guide/po4a.cfg @@ -0,0 +1,69 @@ +[po4a_langs] ru + + + +[po4a_paths] po/$master/$master.pot $lang:po/$master/$lang/$master.$lang.po +[options] opt:"--verbose" opt:"--addendum-charset=UTF-8" opt:"--localized-charset=UTF-8" opt:"--master-charset=UTF-8" opt:"--master-language=en_US" opt:"--porefs=file" opt:"--msgmerge-opt='--no-wrap'" opt:"--wrap-po=newlines" +[po4a_alias:markdown] text opt:"--option markdown" opt:"--option keyvalue" opt:"--option yfm_keys=title,description,menu_title" opt:"--addendum-charset=UTF-8" opt:"--localized-charset=UTF-8" opt:"--master-charset=UTF-8" opt:"--keep=5" + + +[type: markdown] en/README.md $lang:$lang/README.md + +[type: markdown] en/caching/data.md $lang:$lang/caching/data.md pot=caching_data.md +[type: markdown] en/caching/overview.md $lang:$lang/caching/overview.md pot=caching_overview.md + +[type: markdown] en/concept/aliases.md $lang:$lang/concept/aliases.md pot=concept_aliases.md +[type: markdown] en/concept/autoloading.md $lang:$lang/concept/autoloading.md pot=concept_autoloading.md +[type: markdown] en/concept/configuration.md $lang:$lang/concept/configuration.md pot=concept_configuration.md +[type: markdown] en/concept/di-container.md $lang:$lang/concept/di-container.md pot=concept_di-container.md +[type: markdown] en/concept/events.md $lang:$lang/concept/events.md pot=concept_events.md +[type: markdown] en/concept/immutability.md $lang:$lang/concept/immutability.md pot=concept_immutability.md + +[type: markdown] en/databases/db-migrations.md $lang:$lang/databases/db-migrations.md pot=databases_db-migrations.md + +[type: markdown] en/intro/upgrade-from-v2.md $lang:$lang/intro/upgrade-from-v2.md pot=intro_upgrade-from-v2.md +[type: markdown] en/intro/what-is-yii.md $lang:$lang/intro/what-is-yii.md pot=intro_what-is-yii.md + +[type: markdown] en/runtime/cookies.md $lang:$lang/runtime/cookies.md pot=runtime_cookies.md +[type: markdown] en/runtime/handling-errors.md $lang:$lang/runtime/handling-errors.md pot=runtime_handling-errors.md +[type: markdown] en/runtime/logging.md $lang:$lang/runtime/logging.md pot=runtime_logging.md +[type: markdown] en/runtime/request.md $lang:$lang/runtime/request.md pot=runtime_request.md +[type: markdown] en/runtime/response.md $lang:$lang/runtime/response.md pot=runtime_response.md +[type: markdown] en/runtime/routing.md $lang:$lang/runtime/routing.md pot=runtime_routing.md +[type: markdown] en/runtime/sessions.md $lang:$lang/runtime/sessions.md pot=runtime_sessions.md + +[type: markdown] en/security/authentication.md $lang:$lang/security/authentication.md pot=security_authentication.md +[type: markdown] en/security/authorization.md $lang:$lang/security/authorization.md pot=security_authorization.md +[type: markdown] en/security/best-practices.md $lang:$lang/security/best-practices.md pot=security_best-practices.md +[type: markdown] en/security/cryptography.md $lang:$lang/security/cryptography.md pot=security_cryptography.md +[type: markdown] en/security/overview.md $lang:$lang/security/overview.md pot=security_overview.md +[type: markdown] en/security/passwords.md $lang:$lang/security/passwords.md pot=security_passwords.md +[type: markdown] en/security/trusted-request.md $lang:$lang/security/trusted-request.md pot=security_trusted-request.md + +[type: markdown] en/start/creating-project.md $lang:$lang/start/creating-project.md pot=start_creating-project.md +[type: markdown] en/start/databases.md $lang:$lang/start/databases.md pot=start_databases.md +[type: markdown] en/start/forms.md $lang:$lang/start/forms.md pot=start_forms.md +[type: markdown] en/start/gii.md $lang:$lang/start/gii.md pot=start_gii.md +[type: markdown] en/start/hello.md $lang:$lang/start/hello.md pot=start_hello.md +[type: markdown] en/start/looking-ahead.md $lang:$lang/start/looking-ahead.md pot=start_looking-ahead.md +[type: markdown] en/start/prerequisites.md $lang:$lang/start/prerequisites.md pot=start_prerequisites.md +[type: markdown] en/start/workflow.md $lang:$lang/start/workflow.md pot=start_workflow.md + +[type: markdown] en/structure/action.md $lang:$lang/structure/action.md pot=structure_action.md +[type: markdown] en/structure/application.md $lang:$lang/structure/application.md pot=structure_application.md +[type: markdown] en/structure/domain.md $lang:$lang/structure/domain.md pot=structure_domain.md +[type: markdown] en/structure/entry-script.md $lang:$lang/structure/entry-script.md pot=structure_entry-script.md +[type: markdown] en/structure/handler.md $lang:$lang/structure/handler.md pot=structure_handler.md +[type: markdown] en/structure/middleware.md $lang:$lang/structure/middleware.md pot=structure_middleware.md +[type: markdown] en/structure/overview.md $lang:$lang/structure/overview.md pot=structure_overview.md +[type: markdown] en/structure/package.md $lang:$lang/structure/package.md pot=structure_package.md +[type: markdown] en/structure/service.md $lang:$lang/structure/service.md pot=structure_service.md + +[type: markdown] en/tutorial/console-applications.md $lang:$lang/tutorial/console-applications.md pot=tutorial_console-applications.md +[type: markdown] en/tutorial/mailing.md $lang:$lang/tutorial/mailing.md pot=tutorial_mailing.md +[type: markdown] en/tutorial/performance-tuning.md $lang:$lang/tutorial/performance-tuning.md pot=tutorial_performance-tuning.md +[type: markdown] en/tutorial/using-with-event-loop.md $lang:$lang/tutorial/using-with-event-loop.md pot=tutorial_using-with-event-loop.md +[type: markdown] en/tutorial/using-yii-with-roadrunner.md $lang:$lang/tutorial/using-yii-with-roadrunner.md pot=tutorial_using-yii-with-roadrunner.md +[type: markdown] en/tutorial/using-yii-with-swoole.md $lang:$lang/tutorial/using-yii-with-swoole.md pot=tutorial_using-yii-with-swoole.md + +[type: markdown] en/views/view-injections.md $lang:$lang/views/view-injections.md pot=views_view-injections.md diff --git a/guide/ru/concept/aliases.md b/guide/ru/concept/aliases.md index fb355121..a4190740 100644 --- a/guide/ru/concept/aliases.md +++ b/guide/ru/concept/aliases.md @@ -1,16 +1,20 @@ # Псевдонимы (алиасы) -Вы можете использовать псевдонимы для представления путей к файлам или URL-адресов, чтобы вам не приходилось жестко -указывать абсолютные пути или URL-адреса в вашем проекте. Каждый псевдоним должен начинаться с символа `@`, чтобы -отличаться от обычных файловых путей или URL. Алиас, определенный без предшествующего `@` будет префиксироваться -с помощью символа `@`. +Вы можете использовать псевдонимы для представления путей к файлам или +URL-адресов, чтобы вам не приходилось жестко указывать абсолютные пути или +URL-адреса в вашем проекте. Каждый псевдоним должен начинаться с символа +`@`, чтобы отличаться от обычных файловых путей или URL. Алиас, определенный +без предшествующего `@` будет префиксироваться с помощью символа `@`. -По умолчанию Yii-приложение имеет несколько алисов, предопределенных в `config/params.php`. Например, алиас `@public` -представляет корневой путь для web; `@baseUrl` представляет базовый URL для запущенного в текущий момент Web-приложения. +По умолчанию Yii-приложение имеет несколько алисов, предопределенных в +`config/params.php`. Например, алиас `@public` представляет корневой путь +для web; `@baseUrl` представляет базовый URL для запущенного в текущий +момент Web-приложения. ## Определение псевдонимов -Вы можете определить какой-либо псевдоним через `config/params.php` приложения: +Вы можете определить какой-либо псевдоним через `config/params.php` +приложения: ```php return [ @@ -36,17 +40,22 @@ return [ > Примечание: Псевдонимизированный файловый путь или URL *не обязательно* может ссылаться на существующий файл или > ресурс. -Учитывая определенный псевдоним, вы можете создать новый, добавив слэш `/`, за которым следует один или несколько -сегментов пути. Например, `@foo` - это корневой псевдоним, а `@foo/bar/file.php` - производный псевдоним. +Учитывая определенный псевдоним, вы можете создать новый, добавив слэш `/`, +за которым следует один или несколько +сегментов пути. Например, `@foo` - это корневой псевдоним, а +`@foo/bar/file.php` - производный псевдоним. -Вы можете определить псевдоним, используя другой псевдоним (корневой или производный): +Вы можете определить псевдоним, используя другой псевдоним (корневой или +производный): ```php '@foobar' => '@foo/bar', ``` -Параметр `yiisoft/aliases` инициализирует сервис `Aliases` из [пакета](https://github.com/yiisoft/aliases) -`yiisoft/aliases`. Используя этот сервис, вы можете установить дополнительные псевдонимы времени выполнения: +Параметр `yiisoft/aliases` инициализирует сервис `Aliases` из +[пакета](https://github.com/yiisoft/aliases) +`yiisoft/aliases`. Используя этот сервис, вы можете установить +дополнительные псевдонимы времени выполнения: ```php use \Yiisoft\Aliases\Aliases; @@ -57,9 +66,10 @@ public function actionIndex(Aliases $aliases) } ``` -## Использование псевдонимов в конфигурации +## Использование псевдонимов в конфигурации -Предпочтительно разрешать псевдонимы на уровне конфигурации, чтобы сервисы получали URL-адреса и пути как готовые к +Предпочтительно разрешать псевдонимы на уровне конфигурации, чтобы сервисы +получали URL-адреса и пути как готовые к использованию строки: ```php @@ -81,7 +91,8 @@ return [ ## Разрешение псевдонимов -Вы можете использовать сервис `Aliases`, чтобы преобразовать псевдоним или производный псевдоним в путь к файлу или URL, +Вы можете использовать сервис `Aliases`, чтобы преобразовать псевдоним или +производный псевдоним в путь к файлу или URL, который он представляет: ```php @@ -95,13 +106,17 @@ public function actionIndex(Aliases $aliases) } ``` -Путь/URL, представленный производным псевдонимом, определяется путем замены части корневого псевдонима на +Путь/URL, представленный производным псевдонимом, определяется путем замены +части корневого псевдонима на соответствующий путь/URL в производном псевдониме. > Примечание: Метод `get()` не проверяет, относится ли результирующий путь/URL-адрес к существующему файлу или ресурсу. -Псевдоним root также может содержать символы косой черты `/`. Метод `get()` достаточно интеллектуален, чтобы определить, -какая часть псевдонима является корневым псевдонимом, и, таким образом, правильно определить путь к соответствующему + +Псевдоним root также может содержать символы косой черты `/`. Метод `get()` +достаточно интеллектуален, чтобы определить, +какая часть псевдонима является корневым псевдонимом, и, таким образом, +правильно определить путь к соответствующему файлу или URL-адрес: ```php @@ -117,24 +132,31 @@ public function actionIndex(Aliases $aliases) } ``` -Если бы `@foo/bar` не был бы определен как корневой псевдоним, то последний оператор отобразил бы +Если бы `@foo/bar` не был бы определен как корневой псевдоним, то последний +оператор отобразил бы `/path/to/foo/bar/file.php`. ## Предопределенные псевдонимы -[Yii приложение](https://github.com/yiisoft/app) предопределяет набор псевдонимов, чтобы ссылаться на часто используемые +[Yii приложение](https://github.com/yiisoft/app) предопределяет набор +псевдонимов, чтобы ссылаться на часто используемые файловые пути и URL-адреса: - `@root` - базовая директория для приложения запущенного в текущий момент. -- `@assets` - публичная директория приложения, где оно публикует ресурсы (assets). +- `@assets` - публичная директория приложения, где оно публикует ресурсы + (assets). - `@assetsUrl` - URL базовой директории с опубликованными ресурсами. -- `@baseUrl` - базовый URL запущенного в текущий момент Web приложения. По умолчанию - `/`. +- `@baseUrl` - базовый URL запущенного в текущий момент Web приложения. По + умолчанию - `/`. - `@npm` - директория пакетов Node JS. - `@bower` - директория пакетов Bower. - `@vendor` - директория `vendor` Composer'а . -- `@public` - публично доступная директория приложения, которая содержит `index.php`. -- `@runtime` - путь времени выполнения текущего запущенного приложения. По умолчанию - `@root/runtime`. +- `@public` - публично доступная директория приложения, которая содержит + `index.php`. +- `@runtime` - путь времени выполнения текущего запущенного приложения. По + умолчанию - `@root/runtime`. - `@layout` - директория с макетами. -- `@resources` - директория с представлениями, исходниками ресурсов (asset) и другими ресурсами. +- `@resources` - директория с представлениями, исходниками ресурсов (asset) + и другими ресурсами. - `@views` - базовая директория шаблонов представлений приложения. diff --git a/guide/ru/concept/autoloading.md b/guide/ru/concept/autoloading.md index f6ff254f..f9ef338a 100644 --- a/guide/ru/concept/autoloading.md +++ b/guide/ru/concept/autoloading.md @@ -1,10 +1,17 @@ # Автозагрузка класоов -Поскольку Yii использует [Composer](https://getcomposer.org) для управления пакетами, он автоматически загружает классы из пакетов без необходимости явно подключать их через `require`. -При установке пакетов он создает [автозагрузчик, совместимый с PSR-4](https://www.php-fig.org/psr/psr-4/). -Чтобы использовать его, подключите `/vendor/autoload.php` через `require_once` в ваш входной скрипт `index.php` +Поскольку Yii использует [Composer](https://getcomposer.org) для управления +пакетами, он автоматически загружает классы из пакетов без необходимости +явно подключать их через `require`. +При установке пакетов он создает [автозагрузчик, совместимый с +PSR-4](https://www.php-fig.org/psr/psr-4/). +Чтобы использовать его, подключите `/vendor/autoload.php` через +`require_once` в ваш входной скрипт `index.php`. -Вы можете использовать автозагрузчик не только для установленных пакетов, но и для всего вашего приложения, поскольку оно тоже является пакетом. Чтобы загрузить классы определенного пространства имен, добавьте в `composer.json`: +Вы можете использовать автозагрузчик не только для установленных пакетов, но +и для всего вашего приложения, поскольку оно тоже является пакетом. Чтобы +загрузить классы определенного пространства имен, добавьте в +`composer.json`: ```json { @@ -16,11 +23,18 @@ } ``` -Здесь `App\\` это корневое пространство имен, а `src/` - директория, где вы храните ваши классы. При необходимости, вы можете добавить несколько корневых директорий. После изменения `composer.json` выполните `composer dump-autoload` или `composer du` и классы из соответствующих пространств имен начнут загружаться автоматически. +Здесь `App\\` это корневое пространство имен, а `src/` - директория, где вы +храните ваши классы. При необходимости, вы можете добавить несколько +корневых директорий. После изменения `composer.json` выполните `composer +dump-autoload` или `composer du` и классы из соответствующих пространств +имен начнут загружаться автоматически. -Если вам нужна специфичная для разработки автозагрузка, которая не используется при запуске Composer с флагом `--no-dev`, добавьте ее в секцию `autoload-dev` вместо `autoload`. +Если вам нужна специфичная для разработки автозагрузка, которая не +используется при запуске Composer с флагом `--no-dev`, добавьте ее в секцию +`autoload-dev` вместо `autoload`. ## Ссылки - [PSR-4: Autoloader](https://www.php-fig.org/psr/psr-4/). -- [Composer guide on autoloading](https://getcomposer.org/doc/01-basic-usage.md#autoloading). +- [Composer guide on + autoloading](https://getcomposer.org/doc/01-basic-usage.md#autoloading). diff --git a/guide/ru/concept/di-container.md b/guide/ru/concept/di-container.md index e1a17114..5e94d739 100644 --- a/guide/ru/concept/di-container.md +++ b/guide/ru/concept/di-container.md @@ -2,7 +2,8 @@ ## Внедрение зависимостей -В ООП существует два способа повторного использования кода: наследование и композиция. +В ООП существует два способа повторного использования кода: наследование и +композиция. Наследование — это просто: @@ -28,7 +29,8 @@ class CachedWidget extends Cache } ``` -Проблема здесь в том, что эти два класса становятся излишне сопряженными или взаимозависимыми, что делает их более хрупкими. +Проблема здесь в том, что эти два класса становятся излишне сопряженными или +взаимозависимыми, что делает их более хрупкими. Есть способ справиться с этой проблемой — композиция: @@ -66,27 +68,39 @@ final class CachedWidget } ``` -Мы избежали ненужного наследования и использовали интерфейс, чтобы уменьшить сопряженность. -Вы можете заменить реализацию кэша без изменения класса `CachedWidget`, поэтому он становится более стабильным. +Мы избежали ненужного наследования и использовали интерфейс, чтобы уменьшить +сопряженность. +Вы можете заменить реализацию кэша без изменения класса `CachedWidget`, +поэтому он становится более стабильным. -Здесь `CacheInterface` это зависимость — объект, от которого зависит другой объект. -Процесс помещения экземпляра объекта зависимости в объект (`CachedWidget`) называется внедрением зависимости. +Здесь `CacheInterface` это зависимость — объект, от которого зависит другой +объект. +Процесс помещения экземпляра объекта зависимости в объект (`CachedWidget`) +называется внедрением зависимости. Существует множество способов его +реализации: -Существует множество способов его реализации: - -- Внедрение через конструктор. Лучше всего подходит для обязательных зависимостей. +- Внедрение через конструктор. Лучше всего подходит для обязательных + зависимостей. - Через метод. Лучше использовать для необязательных зависимостей. -- Через свойство. Лучше избегать использования в PHP, за исключением, может быть, объектов передачи данных (DTO) +- Через свойство. Лучше избегать использования в PHP, за исключением, может + быть, объектов передачи данных (DTO) + ## Контейнер внедрения зависимостей Внедрять базовые зависимости просто и легко. -Вы выбираете место, где вас не волнуют зависимости, которые обычно являются обработчиками действий и которые вы не собираетесь тестировать, создаете экземпляры необходимых зависимостей и передаете их в зависимые классы. - -Это хорошо работает, когда в целом зависимостей немного и нет вложенных зависимостей. -Когда их много, и каждая зависимость сама имеет зависимости, создание всей иерархии становится утомительным процессом, который требует большого количества кода и может привести к трудно отлаживаемым ошибкам. - -Кроме того, многие зависимости, такие как некоторые сторонние обертки API, одинаковы для любого класса, использующего его. +Вы выбираете место, где вас не волнуют зависимости, которые обычно являются +обработчиками действий и которые вы не собираетесь тестировать, создаете +экземпляры необходимых зависимостей и передаете их в зависимые классы. + +Это хорошо работает, когда в целом зависимостей немного и нет вложенных +зависимостей. +Когда их много, и каждая зависимость сама имеет зависимости, создание всей +иерархии становится утомительным процессом, который требует большого +количества кода и может привести к трудно отлаживаемым ошибкам. + +Кроме того, многие зависимости, такие как некоторые сторонние обертки API, +одинаковы для любого класса, использующего его. Поэтому имеет смысл: - Определить, как создать экземпляр такой обертки API один раз. @@ -94,15 +108,21 @@ final class CachedWidget Именно для этого нужны контейнеры зависимостей. -Контейнер внедрения зависимостей (DI-контейнер) — это объект, который знает, как создавать и настраивать объекты и все зависимые от них объекты. -[Статья Мартина Фаулера](https://martinfowler.com/articles/injection.html) хорошо объясняет почему DI-контейнер полезен. -Здесь мы в основном поясним использование DI-контейнера, предоставляемого Yii. +Контейнер внедрения зависимостей (DI-контейнер) — это объект, который знает, +как создавать и настраивать объекты и все зависимые от них объекты. +[Статья Мартина Фаулера](https://martinfowler.com/articles/injection.html) +хорошо объясняет почему DI-контейнер полезен. +Здесь мы в основном поясним использование DI-контейнера, предоставляемого +Yii. -Yii реализует DI-контейнер через пакет [yiisoft/di](https://github.com/yiisoft/di) и [yiisoft/injector](https://github.com/yiisoft/injector). +Yii реализует DI-контейнер через пакет +[yiisoft/di](https://github.com/yiisoft/di) и +[yiisoft/injector](https://github.com/yiisoft/injector). ### Конфигурирование контейнера -Поскольку для создания нового объекта вам нужны его зависимости, вам следует зарегестрировать их как можно раньше. +Поскольку для создания нового объекта вам нужны его зависимости, вам следует +зарегестрировать их как можно раньше. Вы можете сделать это в конфигурации приложения, `config/web.php`. Например, для следующего сервиса: @@ -117,10 +137,9 @@ class MyService implements MyServiceInterface { } -} ``` -Конфигурация может быть: +конфигурация может быть: ```php return [ @@ -169,9 +188,11 @@ return [ ### Внедрение зависимостей -Непосредственное обращение к контейнеру в классе — плохая идея, так как код становится не универсальным, сопряжен с интерфейсом контейнера и, что еще хуже, зависимости становятся скрытыми. - -Поэтому Yii инвертирует управление, автоматически вводя объекты из контейнера в конструкторы и методы, основываясь на типах аргументов. +Непосредственное обращение к контейнеру в классе — плохая идея, так как код +становится не универсальным, сопряжен с интерфейсом контейнера и, что еще +хуже, зависимости становятся скрытыми. Поэтому Yii инвертирует управление, +автоматически вводя объекты из контейнера в конструкторы и методы, +основываясь на типах аргументов. В основном это делается в конструкторе и методе, обрабатывающем действие: @@ -199,11 +220,19 @@ class MyController } ``` -Поскольку именно [yiisoft/injector](https://github.com/yiisoft/injector) создает экземпляр и вызывает обработчик действий - он проверяет типы аргументов конструктора и метода, получает зависимости этих типов из контейнера и передает их как аргументы. +Поскольку именно [yiisoft/injector](https://github.com/yiisoft/injector) +создает экземпляр и вызывает обработчик действий - он проверяет типы +аргументов конструктора и метода, получает зависимости этих типов из +контейнера и передает их как аргументы. Обычно это называется автоматическим разрешением зависимостей. -Это происходит и с дополнительными зависимостями - если вы явно не указываете зависимость, контейнер сначала проверит, есть ли у него такая зависимость. -Достаточно объявить нужную вам зависимость, и она будет получена из контейнера автоматически. +Это происходит и с дополнительными зависимостями - если вы явно не +указываете зависимость, контейнер сначала проверит, есть ли у него такая +зависимость. +Достаточно объявить нужную вам зависимость, и она будет получена из +контейнера автоматически. + ## Полезные ссылки -- [Inversion of Control Containers and the Dependency Injection pattern Мартина Фаулера](https://martinfowler.com/articles/injection.html) +- [Inversion of Control Containers and the Dependency Injection pattern + Мартина Фаулера](https://martinfowler.com/articles/injection.html) diff --git a/guide/ru/intro/what-is-yii.md b/guide/ru/intro/what-is-yii.md index d9d24b41..b44fdd6c 100644 --- a/guide/ru/intro/what-is-yii.md +++ b/guide/ru/intro/what-is-yii.md @@ -1,19 +1,27 @@ # Что такое Yii? -Yii – это высокопроизводительный пакетный PHP фреймворк, предназначенный для разработки современных веб-приложений. -Слово Yii (произносится как `Йии` или `[ji:]`) в китайском языке означает «простой и эволюционирующий». + +Yii – это высокопроизводительный пакетный PHP фреймворк, предназначенный для +разработки современных веб-приложений. +Слово Yii (произносится как `Йии` или `[ji:]`) в китайском языке означает +«простой и эволюционирующий». Также Yii может расшифровываться как акроним **Yes It Is**! ## Для каких задач больше всего подходит Yii? Yii – это универсальный веб-фреймворк. Вы можете использовать его для разработки всех типов веб-приложений. -Благодаря его архитектуре и отличной поддержке кеширования, фреймворк особенно подходит для разработки таких крупных проектов, как порталы, CMS, магазины или RESTful-приложения. +Благодаря его архитектуре и отличной поддержке кеширования, фреймворк +особенно подходит для разработки таких крупных проектов, как порталы, CMS, +магазины или RESTful-приложения. ## Сравнение Yii с другими фреймворками -Если вы уже знакомы с другими фреймворками, вам наверняка будет интересно сравнить их с Yii: +Если вы уже знакомы с другими фреймворками, вам наверняка будет интересно +сравнить их с Yii: -- Yii придерживается [философии практичности и полезности] (https://github.com/yiisoft/docs/blob/master/001-yii-values.md), достигая следующего: +- Yii придерживается [философии практичности и полезности] + (https://github.com/yiisoft/docs/blob/master/001-yii-values.md), достигая + следующего: - Производительность как в разработке, так и во время выполнения. - Удобные изменяемые настройки по-умолчанию. - Практикоориентированность. @@ -28,20 +36,35 @@ Yii – это универсальный веб-фреймворк. - Yii расширяем. Вы можете настроить или заменить практически любую часть основного кода. Используя пакетную архитектуру, легко делиться кодом или использовать код сообщества. - Одна из главных целей Yii – производительность. -Yii разрабатывается [сильной командой разработчиков](https://www.yiiframework.com/team/), финансируемой [фондом OpenCollective](https://opencollective.com/yiisoft), и большим сообществом, которое ей помогает. Авторы фреймворка следят за тенденциями веб-разработки и развитием других проектов. Наиболее подходящие возможности и лучшие практики регулярно внедряются во фреймворк в виде простых и элегантных интерфейсов. +Yii разрабатывается [сильной командой +разработчиков](https://www.yiiframework.com/team/), финансируемой [фондом +OpenCollective](https://opencollective.com/yiisoft), и большим сообществом, +которое ей помогает. Авторы фреймворка следят за тенденциями веб-разработки +и развитием других проектов. Наиболее подходящие возможности и лучшие +практики регулярно внедряются во фреймворк в виде простых и элегантных +интерфейсов. + ## Версии Yii В настоящее время доступны три основные ветки: 1.1, 2.0 и 3.0. -- Ветка 1.1 является предыдущим поколением и находится в состоянии исправления ошибок и заморозки добавления новой функциональности. -- Ветка 2.0 — текущая стабильная версия. Находится в состоянии исправления ошибок и заморозки добавления новой функциональности. -- Ветка 3.0 — текущая разрабатываемая версия. Данное руководство именно о версии 3.0. +- Ветка 1.1 является предыдущим поколением и находится в состоянии + исправления ошибок и заморозки добавления новой функциональности. +- Ветка 2.0 — текущая стабильная версия. Находится в состоянии исправления + ошибок и заморозки добавления новой функциональности. +- Ветка 3.0 — текущая разрабатываемая версия. Данное руководство именно о + версии 3.0. + ## Требования к ПО и знаниям -Yii3 требует PHP 8.2 или выше, но некоторые пакеты также поддерживают PHP 7.4. +Yii3 требует PHP 8.2 или выше, но некоторые пакеты также поддерживают PHP +7.4. -Для разработки на Yii потребуется общее понимание объектно-ориентированного программирования (ООП), так как фреймворк -полностью следует этой парадигме. Yii3 также использует новейшие возможности PHP, такие, как декларация типов и генераторы. +Для разработки на Yii потребуется общее понимание объектно-ориентированного +программирования (ООП), так как фреймворк +полностью следует этой парадигме. Yii3 также использует новейшие возможности +PHP, такие, как декларация типов и генераторы. Понимание этих концепций поможет вам быстрее разобраться с Yii3. + diff --git a/guide/ru/security/best-practices.md b/guide/ru/security/best-practices.md index 513a5dad..e4dbd77d 100644 --- a/guide/ru/security/best-practices.md +++ b/guide/ru/security/best-practices.md @@ -1,18 +1,29 @@ # Лучшие практики безопасности -Ниже мы рассмотрим общие принципы безопасности и опишем, как избежать угроз при разработке приложений с использованием Yii. Большинство из этих принципов не являются уникальными только для Yii, но применимы к разработке веб-сайтов или программного обеспечения в целом, так что вы также найдете ссылки для дальнейшего чтения об общих идеях, лежащих в их основе. +Ниже мы рассмотрим общие принципы безопасности и опишем, как избежать угроз +при разработке приложений с использованием Yii. Большинство из этих +принципов не являются уникальными только для Yii, но применимы к разработке +веб-сайтов или программного обеспечения в целом, так что вы также найдете +ссылки для дальнейшего чтения об общих идеях, лежащих в их основе. + ## Основные принципы -Независимо от того, какое приложение разрабатывается, существуют два основных принципа обеспечения безопасности: +Независимо от того, какое приложение разрабатывается, существуют два +основных принципа обеспечения безопасности: 1. Фильтрация ввода. 2. Экранирование вывода. + ### Фильтрация ввода -Фильтрация ввода означает, что входные данные никогда не должны считаться безопасными и вы всегда должны проверять, являются ли полученные данные допустимыми. -Например, если мы знаем, что сортировка может быть осуществлена только по трём полям `title`, `created_at` и `status`, и поле может передаваться через ввод пользователем, лучше проверить значение там, где мы его получили. +Фильтрация ввода означает, что входные данные никогда не должны считаться +безопасными и вы всегда должны проверять, являются ли полученные данные +допустимыми. +Например, если мы знаем, что сортировка может быть осуществлена только по +трём полям `title`, `created_at` и `status`, и поле может передаваться через +ввод пользователем, лучше проверить значение там, где мы его получили. С точки зрения чистого PHP, это будет выглядеть следующим образом: ```php @@ -22,13 +33,15 @@ if (!in_array($sortBy, ['title', 'created_at', 'status'])) { } ``` -В Yii, вы, скорее всего, будете использовать [валидацию форм](../input/validation.md), чтобы делать такие проверки. +В Yii, вы, скорее всего, будете использовать [валидацию +форм](../input/validation.md), чтобы делать такие проверки. Дополнительная информация по теме: - - + ### Экранирование вывода Экранирование вывода означает, что в зависимости от контекста, в котором вы используете данные, вам следует добавить @@ -43,29 +56,37 @@ if (!in_array($sortBy, ['title', 'created_at', 'status'])) { - - + ## Как избежать SQL-инъекций -SQL-инъекции происходят, когда текст запроса формируется склеиванием неэкранированных строк, как показано ниже: +SQL-инъекции происходят, когда текст запроса формируется склеиванием +неэкранированных строк, как показано ниже: ```php $username = $_GET['username']; $sql = "SELECT * FROM user WHERE username = '$username'"; ``` -Вместо того чтобы подставлять корректное имя пользователя, злоумышленник может передать в ваше приложение что-то вроде +Вместо того чтобы подставлять корректное имя пользователя, злоумышленник +может передать в ваше приложение что-то вроде `'; DROP TABLE user; --`. В результате SQL будет следующий: ```sql SELECT * FROM user WHERE username = ''; DROP TABLE user; --' ``` -Это валидный запрос, который сначала будет искать пользователей с пустым именем, а затем удалит таблицу user. Скорее всего будет сломано приложение и будут потеряны данные (вы ведь делаете регулярное резервное копирование?). - -Убедитесь, что-либо вы напрямую используете подготовленные PDO запросы, либо это делает выбранная вами библиотека. -В случае подготовленных запросов невозможно манипулированть запросом, как было продемонстрировано выше. +Это валидный запрос, который сначала будет искать пользователей с пустым +именем, а затем удалит таблицу user. Скорее всего будет сломано приложение и +будут потеряны данные (вы ведь делаете регулярное резервное копирование?). -Если вы используете данные для указания имен столбцов или таблиц, лучше всего разрешить только предопределенный набор значений: +Убедитесь, что либо вы напрямую используете подготовленные PDO запросы, либо +это делает выбранная вами библиотека. +В случае подготовленных запросов невозможно манипулированть запросом, как +было продемонстрировано выше. +Если вы используете данные для указания имен столбцов или таблиц, лучше +всего разрешить только предопределенный набор значений: + ```php function actionList($orderBy = null) { @@ -81,6 +102,7 @@ function actionList($orderBy = null) - + ## Как избежать XSS XSS или кросс-сайтинговый скриптинг становится возможен, когда неэкранированный выходной HTML попадает в браузер. @@ -92,34 +114,40 @@ XSS или кросс-сайтинговый скриптинг становит 1. Вы хотите вывести данные в виде обычного текста. 2. Вы хотите вывести данные в виде HTML. -Если вам нужно вывести простой текст, то экранировать лучше следующим образом: +Если вам нужно вывести простой текст, то экранировать лучше следующим +образом: + ```php ``` -Если нужно вывести HTML, вам лучше воспользоваться [HtmlPurifier](http://htmlpurifier.org/). -Обратите внимание, что обработка с помощью HtmlPurifier довольно тяжела, поэтому рассмотрите возможность использования кеширования. +Если нужно вывести HTML, вам лучше воспользоваться +[HtmlPurifier](http://htmlpurifier.org/). +Обратите внимание, что обработка с помощью HtmlPurifier довольно тяжела, +поэтому рассмотрите возможность использования кеширования. Дополнительная информация по теме: - + ## Как избежать CSRF -CSRF — это аббревиатура для межсайтинговой подмены запросов. Идея заключается в том, что многие приложения предполагают, -что запросы, приходящие от браузера, отправляются самим пользователем. Это может быть неправдой. +CSRF — это аббревиатура для межсайтинговой подмены запросов. Идея +заключается в том, что многие приложения предполагают, +что запросы, приходящие от браузера, отправляются самим пользователем. Это +может быть неправдой. Например, сайт `an.example.com` имеет URL `/logout`, который, используя простой GET, разлогинивает пользователя. Пока это запрос выполняется самим пользователем — всё в порядке, но в один прекрасный день злоумышленники размещают -код '' на форуме с большой посещаемостью. Браузер не делает никаких отличий +код `` на форуме с большой посещаемостью. Браузер не делает никаких отличий между запросом изображения и запросом страницы, так что когда пользователь откроет страницу с таким тегом ``, браузер отправит GET-запрос на указанный адрес, и пользователь будет разлогинен с `an.example.com`. - + Вот основная идея того, как работает CSRF-атака. Можно сказать, что в разлогинивании пользователя нет ничего серьёзного. Однако это был всего лишь пример. - С помощью этого подхода можно сделать гораздо больше опасных вещей. Например, оплату или изменение данных. Представьте, что существует страница `http://an.example.com/purse/transfer?to=anotherUser&amount=2000`, обращение @@ -134,36 +162,47 @@ CSRF — это аббревиатура для межсайтинговой п Для того чтобы избежать CSRF вы должны всегда: -1. Следовать спецификации HTTP. Например, GET-запрос не должен менять состояние приложения. - Дополнительные сведения см. в [RFC2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) +1. Следовать спецификации HTTP. Например, GET-запрос не должен менять + состояние приложения. + Дополнительные сведения см. в + [RFC2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html). 2. Держите защиту CSRF в Yii включенной. Yii имеет защиту от CSRF в middleware `Yiisoft\Yii\Web\Middleware\Csrf`. -Убедитесь, что он используется в вашем приложении. +Убедитесь, что она используется в вашем приложении. Дополнительная информация по теме: - - + ## Как избежать нежелательного доступа к файлам По умолчанию, webroot сервера указывает на каталог `public`, где лежит `index.php`. В случае использования виртуального хостинга это может быть недостижимо, в конечном итоге весь код, конфиги и логи могут оказаться в webroot сервера. -Если это так, то нужно запретить доступ ко всему, кроме директории `web`. -Если на вашем хостинге такое невозможно, рассмотрите возможность смены хостинга. +Если это так, то нужно запретить доступ ко всему, кроме директории `web`. +Если на вашем хостинге такое невозможно, рассмотрите возможность смены +хостинга. + ## Как избежать вывода отладочной информации и инструментов в боевом окружении -В режиме отладки, Yii отображает довольно подробные ошибки, которые полезны во время разработки. Однако подробные ошибки -удобны и для нападающего, так как могут раскрыть структуру базы данных, параметров конфигурации и части вашего кода. +В режиме отладки, Yii отображает довольно подробные ошибки, которые полезны +во время разработки. Однако подробные ошибки +удобны и для нападающего, так как могут раскрыть структуру базы данных, +параметров конфигурации и части вашего кода. -Вы никогда не должны оставлять Debug панель или Gii доступной для всех в боевом окружении. Это может быть использовано -для получения информации о структуре базы данных или коде, может позволить заменить файлы, генерируемые Gii автоматически. +Вы никогда не должны оставлять Debug панель или Gii доступной для всех в +боевом окружении. Это может быть использовано +для получения информации о структуре базы данных или коде, может позволить +заменить файлы, генерируемые Gii автоматически. -Следует избегать включения в боевом окружении панели отладки, если только в этом нет острой необходимости. -Она раскрывает всё приложение и детали конфигурации. Если вам всё-таки нужно запустить панель отладки, проверьте дважды, +Следует избегать включения в боевом окружении панели отладки, если только в +этом нет острой необходимости. +Она раскрывает всё приложение и детали конфигурации. Если вам всё-таки нужно +запустить панель отладки, проверьте дважды, что доступ ограничен только вашими IP-адресами. Дополнительная информация по теме: @@ -171,33 +210,49 @@ Yii имеет защиту от CSRF в middleware `Yiisoft\Yii\Web\Middleware\ - - -## Использование безопасного подключения через TLS -Yii предоставляет функции, которые зависят от куки-файлов и/или сессий PHP. -Они могут быть уязвимыми, если ваше соединение скомпрометировано. +## Использование безопасного подключения через TLS -Риск снижается, если приложение использует безопасное соединение через TLS (часто называемое как [SSL](https://en.wikipedia.org/wiki/Transport_Layer_Security)). +Yii предоставляет функции, которые зависят от куки-файлов и/или сессий PHP. +Они могут быть уязвимыми, если ваше соединение скомпрометировано. Риск +снижается, если приложение использует безопасное соединение через TLS (часто +называемое как +[SSL](https://en.wikipedia.org/wiki/Transport_Layer_Security)). -Сегодня любой желающий может бесплатно получить SSL-сертификат и автоматически обновлять его благодаря [Let's Encrypt](https://letsencrypt.org/). +Сегодня любой желающий может бесплатно получить SSL-сертификат и +автоматически обновлять его благодаря [Let's +Encrypt](https://letsencrypt.org/). ## Безопасная конфигурация сервера -Цель этого раздела — выявить риски, которые необходимо учитывать при создании конфигурации сервера для обслуживания веб-сайта на основе Yii. -Помимо перечисленных здесь пунктов есть и другие параметры, связанные с безопасностью, которые необходимо учитывать, поэтому не рассматривайте этот раздел как завершенный. +Цель этого раздела — выявить риски, которые необходимо учитывать при +создании конфигурации сервера для обслуживания веб-сайта на основе Yii. +Помимо перечисленных здесь пунктов есть и другие параметры, связанные с +безопасностью, которые необходимо учитывать, поэтому не рассматривайте этот +раздел как завершенный. ### Как избежать атаки типа `Host`-header -Если веб-сервер настроен на обслуживание одного и того же сайта независимо от значения заголовка `Host`, эта информация может быть ненадежной и [может быть подделана пользователем, отправляющим HTTP-запрос](https://www.acunetix.com/vulnerabilities/web/host-header-attack). -В таких ситуациях вам следует исправить конфигурацию вашего веб-сервера, чтобы он обслуживал сайт только для указанных имен хостов. +Если веб-сервер настроен на обслуживание одного и того же сайта независимо +от значения заголовка `Host`, эта информация может быть ненадежной и [может +быть подделана пользователем, отправляющим +HTTP-запрос](https://www.acunetix.com/vulnerabilities/web/host-header-attack). + +В таких ситуациях вам следует исправить конфигурацию вашего веб-сервера, +чтобы он обслуживал сайт только для указанных имен хостов. -Дополнительные сведения о конфигурации сервера смотрите в документации вашего веб-сервера: +Дополнительные сведения о конфигурации сервера смотрите в документации +вашего веб-сервера: -- Apache 2: -- Nginx: +- Apache 2: + +- Nginx: + ### Настройка проверки SSL-сертификата -Существует типичное заблуждение о том, как решить проблемы с проверкой сертификата SSL, например: +Существует типичное заблуждение о том, как решить проблемы с проверкой +сертификата SSL, например: ``` cURL error 60: SSL certificate problem: unable to get local issuer certificate @@ -209,11 +264,14 @@ cURL error 60: SSL certificate problem: unable to get local issuer certificate stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed ``` -Многие источники ошибочно предлагают отключить проверку одноранговых соединений SSL. -Этого никогда не следует делать, поскольку это допускает атаки типа «man-in-the-middle». +Многие источники ошибочно предлагают отключить проверку одноранговых +соединений SSL. +Этого никогда не следует делать, поскольку это допускает атаки типа +«man-in-the-middle». Вместо этого PHP должен быть правильно настроен: -1. Скачайте файл [https://curl.haxx.se/ca/cacert.pem](https://curl.haxx.se/ca/cacert.pem). +1. Скачайте файл + [https://curl.haxx.se/ca/cacert.pem](https://curl.haxx.se/ca/cacert.pem). 2. Добавьте в свой php.ini следующее: ``` openssl.cafile="/path/to/cacert.pem" @@ -225,7 +283,11 @@ stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error m ## Ссылки - [OWASP top 10](https://owasp.org/Top10/) -- [The Basics of Web Application Security](https://martinfowler.com/articles/web-security-basics.html) Мартина Фаулера -- [Руководство по PHP: безопасность](https://www.php.net/manual/en/security.php) -- [Раздел "Информационная безопасность" на STackExchange](https://security.stackexchange.com/) +- [The Basics of Web Application + Security](https://martinfowler.com/articles/web-security-basics.html) + Мартина Фаулера +- [Руководство по PHP: + безопасность](https://www.php.net/manual/en/security.php) +- [Раздел "Информационная безопасность" на + STackExchange](https://security.stackexchange.com/) diff --git a/guide/ru/security/cryptography.md b/guide/ru/security/cryptography.md index cd7ee59d..fd1fde4c 100644 --- a/guide/ru/security/cryptography.md +++ b/guide/ru/security/cryptography.md @@ -6,7 +6,8 @@ - Шифрование и расшифровка - Проверка целостности данных -Для использования этих функций, вам нужно установить пакет `yiisoft/security`: +Для использования этих функций, вам нужно установить пакет +`yiisoft/security`: ``` composer install yiisoft/security @@ -15,12 +16,16 @@ composer install yiisoft/security ## Генерация псевдослучайных данных Псевдослучайные данные используются во многих ситуациях. -Например, при изменении пароля по email, вам необходимо сгенерировать токен, сохранить его в базу данных и отправить -по email пользователю, чтобы он с помощью него подтвердил владение аккаунтом. -Важно, чтобы этот токен был уникальным и его было трудно угадать, иначе есть вероятность, что атакующий может +Например, при изменении пароля по email, вам необходимо сгенерировать токен, +сохранить его в базу данных и отправить +по email пользователю, чтобы он с помощью него подтвердил владение +аккаунтом. +Важно, чтобы этот токен был уникальным и его было трудно угадать, иначе есть +вероятность, что атакующий может предсказать значение токена и сбросить пароль пользователя. -Класс `\Yiisoft\Security\Random` делает генерацию псевдослучайных данных простой: +Класс `\Yiisoft\Security\Random` делает генерацию псевдослучайных данных +простой: ```php $key = \Yiisoft\Security\Random::string(42); @@ -30,14 +35,20 @@ $key = \Yiisoft\Security\Random::string(42); Если вам нужны байты или целые числа, напрямую используйте функции PHP: -- `random_bytes()` для генерации байт. Обратите внимание, что вывод может быть не ASCII. +- `random_bytes()` для генерации байт. Обратите внимание, что вывод может + быть не ASCII. - `random_int()` для генерации целых чисел. ## Шифрование и расшифровка -Yii предоставляет удобные вспомогательные функции для шифрования/расшифровки данных с помощью секретного ключа. -Данные проходят через функцию шифрования таким образом, что только тот, кто знает секретный ключ, может расшифровать их. -Например, вам нужно сохранить некоторую информацию в вашей базе данных, но вы должны быть уверены, что только пользователь, который знает секретный ключ, сможет расшифровать их (даже если кто-нибудь скомпрометирует базу данных приложения) +Yii предоставляет удобные вспомогательные функции для шифрования/расшифровки +данных с помощью секретного ключа. +Данные проходят через функцию шифрования таким образом, что только тот, кто +знает секретный ключ, может расшифровать их. +Например, вам нужно сохранить некоторую информацию в вашей базе данных, но +вы должны быть уверены, что только пользователь, который знает секретный +ключ, сможет расшифровать их (даже если кто-нибудь скомпрометирует базу +данных приложения): ```php $encryptedData = (new \Yiisoft\Security\Crypt())->encryptByPassword($data, $password); @@ -75,10 +86,12 @@ $data = (new \Yiisoft\Security\Crypt())->decryptByKey($encryptedData, $key); ## Проверка целостности данных -Бывают ситуации, когда вам необходимо убедиться, что ваши данные не были подделаны третьей стороной или испорчены каким-то образом. +Бывают ситуации, когда вам необходимо убедиться, что ваши данные не были +подделаны третьей стороной или испорчены каким-то образом. Yii предоставляет способ проверить целостность данных по MAC подписи. -Ключ `$key` должен присутствовать как на отправляющей, так и на принимающей стороне. На отправляющей стороне: +Ключ `$key` должен присутствовать как на отправляющей, так и на принимающей +стороне. На отправляющей стороне: ```php $signedMessage = (new \Yiisoft\Security\Mac())->sign($message, $key); @@ -100,7 +113,9 @@ try { ## Маскировка длины токена -Маскировка токена помогает смягчить атаку BREACH за счет рандомизации способа вывода токена при каждом запросе. К токену применяется случайная маска, делающая строку всегда уникальной. +Маскировка токена помогает смягчить атаку BREACH за счет рандомизации +способа вывода токена при каждом запросе. К токену применяется случайная +маска, делающая строку всегда уникальной. Для маскировки токена: diff --git a/guide/ru/tutorial/console-applications.md b/guide/ru/tutorial/console-applications.md new file mode 100644 index 00000000..47b23c46 --- /dev/null +++ b/guide/ru/tutorial/console-applications.md @@ -0,0 +1,85 @@ +# Console applications + +Console applications are mainly used to create utility, background +processing and maintenance tasks. + +To get support for console application in your project, get +`yiisoft/yii-console` via composer: + + +``` +composer require yiisoft/yii-console +``` + +After it's installed, you can access the entry point as + +``` +./yii +``` + +Out of the box only `serve` command is available. It's starting PHP built-in +web server to serve the application locally. + +Commands are executed with `symfony/console`. To create your own console +command, you need to define a command: + +```php +setHelp('This command serves for demo purpose') + ->addArgument('name', InputArgument::OPTIONAL, 'Name to greet', 'anonymous'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $name = $input->getArgument('name'); + $io->success("Hello, $name!"); + return ExitCode::OK; + } +} +``` + +Now register the command in `config/params.php`: + +```php +return [ + 'console' => [ + 'commands' => [ + 'demo/hello' => App\Demo\HelloCommand::class, + ], + ], +]; +``` + +After it's done, the command could be executed as + +``` +./yii demo:hello Alice +``` + + +## Ссылки + +- [Symfony Console component + guide](https://symfony.com/doc/current/components/console.html)